aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/Xext
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/Xext')
-rw-r--r--xorg-server/Xext/EVI.c200
-rw-r--r--xorg-server/Xext/EVIstruct.h58
-rw-r--r--xorg-server/Xext/Makefile.am181
-rw-r--r--xorg-server/Xext/Makefile.in908
-rw-r--r--xorg-server/Xext/appgroup.c775
-rw-r--r--xorg-server/Xext/appgroup.h67
-rw-r--r--xorg-server/Xext/bigreq.c90
-rw-r--r--xorg-server/Xext/cup.c342
-rw-r--r--xorg-server/Xext/dpms.c439
-rw-r--r--xorg-server/Xext/dpmsproc.h17
-rw-r--r--xorg-server/Xext/dpmsstubs.c50
-rw-r--r--xorg-server/Xext/fontcache.c323
-rw-r--r--xorg-server/Xext/mbuf.c1763
-rw-r--r--xorg-server/Xext/mbufbf.c1011
-rw-r--r--xorg-server/Xext/mbufpx.c650
-rw-r--r--xorg-server/Xext/mitmisc.c155
-rw-r--r--xorg-server/Xext/panoramiX.c1283
-rw-r--r--xorg-server/Xext/panoramiX.h100
-rw-r--r--xorg-server/Xext/panoramiXSwap.c142
-rw-r--r--xorg-server/Xext/panoramiXh.h74
-rw-r--r--xorg-server/Xext/panoramiXprocs.c2377
-rw-r--r--xorg-server/Xext/panoramiXsrv.h56
-rw-r--r--xorg-server/Xext/sampleEVI.c123
-rw-r--r--xorg-server/Xext/saver.c1570
-rw-r--r--xorg-server/Xext/security.c1149
-rw-r--r--xorg-server/Xext/securitysrv.h83
-rw-r--r--xorg-server/Xext/shape.c1329
-rw-r--r--xorg-server/Xext/shm.c1309
-rw-r--r--xorg-server/Xext/shmint.h42
-rw-r--r--xorg-server/Xext/sleepuntil.c237
-rw-r--r--xorg-server/Xext/sleepuntil.h46
-rw-r--r--xorg-server/Xext/sync.c2642
-rw-r--r--xorg-server/Xext/xace.c341
-rw-r--r--xorg-server/Xext/xace.h126
-rw-r--r--xorg-server/Xext/xacestr.h147
-rw-r--r--xorg-server/Xext/xcalibrate.c305
-rw-r--r--xorg-server/Xext/xcmisc.c236
-rw-r--r--xorg-server/Xext/xevie.c744
-rw-r--r--xorg-server/Xext/xf86bigfont.c771
-rw-r--r--xorg-server/Xext/xprint.c2617
-rw-r--r--xorg-server/Xext/xres.c390
-rw-r--r--xorg-server/Xext/xselinux.c2037
-rw-r--r--xorg-server/Xext/xselinux.h159
-rw-r--r--xorg-server/Xext/xtest.c591
-rw-r--r--xorg-server/Xext/xvdisp.c2055
-rw-r--r--xorg-server/Xext/xvdisp.h2
-rw-r--r--xorg-server/Xext/xvdix.h287
-rw-r--r--xorg-server/Xext/xvmain.c1187
-rw-r--r--xorg-server/Xext/xvmc.c792
-rw-r--r--xorg-server/Xext/xvmcext.h115
50 files changed, 32493 insertions, 0 deletions
diff --git a/xorg-server/Xext/EVI.c b/xorg-server/Xext/EVI.c
new file mode 100644
index 000000000..a637bae5d
--- /dev/null
+++ b/xorg-server/Xext/EVI.c
@@ -0,0 +1,200 @@
+/************************************************************
+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.
+********************************************************/
+
+#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"
+
+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 (AddExtension(EVINAME, 0, 0,
+ ProcEVIDispatch, SProcEVIDispatch,
+ EVIResetProc, StandardMinorOpcode)) {
+ eviPriv = eviDDXInit();
+ }
+}
diff --git a/xorg-server/Xext/EVIstruct.h b/xorg-server/Xext/EVIstruct.h
new file mode 100644
index 000000000..e6581909f
--- /dev/null
+++ b/xorg-server/Xext/EVIstruct.h
@@ -0,0 +1,58 @@
+/************************************************************
+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.
+********************************************************/
+
+#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/xorg-server/Xext/Makefile.am b/xorg-server/Xext/Makefile.am
new file mode 100644
index 000000000..648736d95
--- /dev/null
+++ b/xorg-server/Xext/Makefile.am
@@ -0,0 +1,181 @@
+# libXext.la: includes all extensions and should be linked into Xvfb,
+# Xnest, Xdmx and Xprt
+# libXextbuiltin.la: includes those extensions that are built directly into
+# Xorg by default
+# libXextmodule.la: includes those extensions that are built into a module
+# that Xorg loads
+if XORG
+noinst_LTLIBRARIES = libXext.la libXextbuiltin.la libXextmodule.la
+else
+noinst_LTLIBRARIES = libXext.la
+endif
+
+INCLUDES = -I$(top_srcdir)/hw/xfree86/dixmods/extmod
+
+AM_CFLAGS = $(DIX_CFLAGS)
+
+if XORG
+sdk_HEADERS = xvdix.h xvmcext.h
+endif
+
+# Sources always included in libXextbuiltin.la & libXext.la
+BUILTIN_SRCS = \
+ shape.c \
+ sleepuntil.c \
+ sleepuntil.h \
+ xtest.c
+
+# Sources always included in libXextmodule.la & libXext.la
+MODULE_SRCS = \
+ bigreq.c \
+ mitmisc.c \
+ shape.c \
+ sync.c \
+ xcmisc.c
+
+# Optional sources included if extension enabled by configure.ac rules
+
+# MIT Shared Memory extension
+MITSHM_SRCS = shm.c shmint.h
+if MITSHM
+BUILTIN_SRCS += $(MITSHM_SRCS)
+endif
+
+# XVideo extension
+XV_SRCS = xvmain.c xvdisp.c xvmc.c xvdix.h xvmcext.h xvdisp.h
+if XV
+MODULE_SRCS += $(XV_SRCS)
+endif
+
+# XResource extension: lets clients get data about per-client resource usage
+RES_SRCS = xres.c
+if RES
+MODULE_SRCS += $(RES_SRCS)
+endif
+
+# MIT ScreenSaver extension
+SCREENSAVER_SRCS = saver.c
+if SCREENSAVER
+MODULE_SRCS += $(SCREENSAVER_SRCS)
+endif
+
+# Xinerama extension: making multiple video devices act as one virtual screen
+XINERAMA_SRCS = panoramiX.c panoramiX.h panoramiXh.h panoramiXsrv.h panoramiXprocs.c panoramiXSwap.c
+if XINERAMA
+BUILTIN_SRCS += $(XINERAMA_SRCS)
+endif
+
+# X-ACE extension: provides hooks for building security policy extensions
+# like XC-Security, X-SELinux & XTSol
+XACE_SRCS = xace.c xace.h xacestr.h
+if XACE
+BUILTIN_SRCS += $(XACE_SRCS)
+endif
+
+# SELinux extension: provides SELinux policy support for X objects
+# requires X-ACE extension
+XSELINUX_SRCS = xselinux.c xselinux.h
+if XSELINUX
+MODULE_SRCS += $(XSELINUX_SRCS)
+endif
+
+# Security extension: multi-level security to protect clients from each other
+XCSECURITY_SRCS = security.c securitysrv.h
+if XCSECURITY
+BUILTIN_SRCS += $(XCSECURITY_SRCS)
+endif
+
+XCALIBRATE_SRCS = xcalibrate.c
+if XCALIBRATE
+BUILTIN_SRCS += $(XCALIBRATE_SRCS)
+# XCalibrate needs tslib
+endif
+
+# X EVent Interception Extension: allows accessibility helpers & composite
+# managers to intercept events from input devices and transform as needed
+# before the clients see them.
+XEVIE_SRCS = xevie.c
+if XEVIE
+BUILTIN_SRCS += $(XEVIE_SRCS)
+endif
+
+# XPrint: Printing via X Protocol
+XPRINT_SRCS = xprint.c
+if XPRINT
+BUILTIN_SRCS += $(XPRINT_SRCS)
+endif
+
+# AppGroup
+APPGROUP_SRCS = appgroup.c appgroup.h
+if APPGROUP
+BUILTIN_SRCS += $(APPGROUP_SRCS)
+endif
+
+# Colormap Utilization Protocol: Less flashing when switching between
+# PsuedoColor apps and better sharing of limited colormap slots
+CUP_SRCS = cup.c
+if CUP
+MODULE_SRCS += $(CUP_SRCS)
+endif
+
+# Extended Visual Information
+EVI_SRCS = EVI.c sampleEVI.c EVIstruct.h
+if EVI
+MODULE_SRCS += $(EVI_SRCS)
+endif
+
+# Multi-buffering extension
+MULTIBUFFER_SRCS = mbuf.c
+EXTRA_MULTIBUFFER_SRCS = mbufbf.c mbufpx.c
+if MULTIBUFFER
+MODULE_SRCS += $(MULTIBUFFER_SRCS)
+endif
+
+# Font Cache extension
+FONTCACHE_SRCS = fontcache.c
+if FONTCACHE
+MODULE_SRCS += $(FONTCACHE_SRCS)
+endif
+
+# XF86 Big Font extension
+BIGFONT_SRCS = xf86bigfont.c
+if XF86BIGFONT
+BUILTIN_SRCS += $(BIGFONT_SRCS)
+endif
+
+# DPMS extension
+DPMS_SRCS = dpms.c dpmsproc.h
+if DPMSExtension
+MODULE_SRCS += $(DPMS_SRCS)
+endif
+
+# Now take all of the above, mix well, bake for 10 minutes and get libXext*.la
+
+libXext_la_SOURCES = $(BUILTIN_SRCS) $(MODULE_SRCS)
+
+if XORG
+libXextbuiltin_la_SOURCES = $(BUILTIN_SRCS)
+
+libXextmodule_la_SOURCES = $(MODULE_SRCS)
+endif
+
+EXTRA_DIST = \
+ $(MITSHM_SRCS) \
+ $(XV_SRCS) \
+ $(RES_SRCS) \
+ $(SCREENSAVER_SRCS) \
+ $(XACE_SRCS) \
+ $(XCSECURITY_SRCS) \
+ $(XCALIBRATE_SRCS) \
+ $(XINERAMA_SRCS) \
+ $(XEVIE_SRCS) \
+ $(XPRINT_SRCS) \
+ $(APPGROUP_SRCS) \
+ $(CUP_SRCS) \
+ $(EVI_SRCS) \
+ $(MULTIBUFFER_SRCS) \
+ $(EXTRA_MULTIBUFFER_SRCS) \
+ $(FONTCACHE_SRCS) \
+ $(BIGFONT_SRCS) \
+ $(DPMS_SRCS)
+
diff --git a/xorg-server/Xext/Makefile.in b/xorg-server/Xext/Makefile.in
new file mode 100644
index 000000000..11af6324e
--- /dev/null
+++ b/xorg-server/Xext/Makefile.in
@@ -0,0 +1,908 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@MITSHM_TRUE@am__append_1 = $(MITSHM_SRCS)
+@XV_TRUE@am__append_2 = $(XV_SRCS)
+@RES_TRUE@am__append_3 = $(RES_SRCS)
+@SCREENSAVER_TRUE@am__append_4 = $(SCREENSAVER_SRCS)
+@XINERAMA_TRUE@am__append_5 = $(XINERAMA_SRCS)
+@XACE_TRUE@am__append_6 = $(XACE_SRCS)
+@XSELINUX_TRUE@am__append_7 = $(XSELINUX_SRCS)
+@XCSECURITY_TRUE@am__append_8 = $(XCSECURITY_SRCS)
+@XCALIBRATE_TRUE@am__append_9 = $(XCALIBRATE_SRCS)
+@XEVIE_TRUE@am__append_10 = $(XEVIE_SRCS)
+@XPRINT_TRUE@am__append_11 = $(XPRINT_SRCS)
+@APPGROUP_TRUE@am__append_12 = $(APPGROUP_SRCS)
+@CUP_TRUE@am__append_13 = $(CUP_SRCS)
+@EVI_TRUE@am__append_14 = $(EVI_SRCS)
+@MULTIBUFFER_TRUE@am__append_15 = $(MULTIBUFFER_SRCS)
+@FONTCACHE_TRUE@am__append_16 = $(FONTCACHE_SRCS)
+@XF86BIGFONT_TRUE@am__append_17 = $(BIGFONT_SRCS)
+@DPMSExtension_TRUE@am__append_18 = $(DPMS_SRCS)
+subdir = Xext
+DIST_COMMON = $(am__sdk_HEADERS_DIST) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/do-not-use-config.h \
+ $(top_builddir)/include/xorg-server.h \
+ $(top_builddir)/include/dix-config.h \
+ $(top_builddir)/include/xgl-config.h \
+ $(top_builddir)/include/xorg-config.h \
+ $(top_builddir)/include/xkb-config.h \
+ $(top_builddir)/include/xwin-config.h \
+ $(top_builddir)/include/kdrive-config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libXext_la_LIBADD =
+am__libXext_la_SOURCES_DIST = shape.c sleepuntil.c sleepuntil.h \
+ xtest.c shm.c shmint.h panoramiX.c panoramiX.h panoramiXh.h \
+ panoramiXsrv.h panoramiXprocs.c panoramiXSwap.c xace.c xace.h \
+ xacestr.h security.c securitysrv.h xcalibrate.c xevie.c \
+ xprint.c appgroup.c appgroup.h xf86bigfont.c bigreq.c \
+ mitmisc.c sync.c xcmisc.c xvmain.c xvdisp.c xvmc.c xvdix.h \
+ xvmcext.h xvdisp.h xres.c saver.c xselinux.c xselinux.h cup.c \
+ EVI.c sampleEVI.c EVIstruct.h mbuf.c fontcache.c dpms.c \
+ dpmsproc.h
+am__objects_1 = shm.lo
+@MITSHM_TRUE@am__objects_2 = $(am__objects_1)
+am__objects_3 = panoramiX.lo panoramiXprocs.lo panoramiXSwap.lo
+@XINERAMA_TRUE@am__objects_4 = $(am__objects_3)
+am__objects_5 = xace.lo
+@XACE_TRUE@am__objects_6 = $(am__objects_5)
+am__objects_7 = security.lo
+@XCSECURITY_TRUE@am__objects_8 = $(am__objects_7)
+am__objects_9 = xcalibrate.lo
+@XCALIBRATE_TRUE@am__objects_10 = $(am__objects_9)
+am__objects_11 = xevie.lo
+@XEVIE_TRUE@am__objects_12 = $(am__objects_11)
+am__objects_13 = xprint.lo
+@XPRINT_TRUE@am__objects_14 = $(am__objects_13)
+am__objects_15 = appgroup.lo
+@APPGROUP_TRUE@am__objects_16 = $(am__objects_15)
+am__objects_17 = xf86bigfont.lo
+@XF86BIGFONT_TRUE@am__objects_18 = $(am__objects_17)
+am__objects_19 = shape.lo sleepuntil.lo xtest.lo $(am__objects_2) \
+ $(am__objects_4) $(am__objects_6) $(am__objects_8) \
+ $(am__objects_10) $(am__objects_12) $(am__objects_14) \
+ $(am__objects_16) $(am__objects_18)
+am__objects_20 = xvmain.lo xvdisp.lo xvmc.lo
+@XV_TRUE@am__objects_21 = $(am__objects_20)
+am__objects_22 = xres.lo
+@RES_TRUE@am__objects_23 = $(am__objects_22)
+am__objects_24 = saver.lo
+@SCREENSAVER_TRUE@am__objects_25 = $(am__objects_24)
+am__objects_26 = xselinux.lo
+@XSELINUX_TRUE@am__objects_27 = $(am__objects_26)
+am__objects_28 = cup.lo
+@CUP_TRUE@am__objects_29 = $(am__objects_28)
+am__objects_30 = EVI.lo sampleEVI.lo
+@EVI_TRUE@am__objects_31 = $(am__objects_30)
+am__objects_32 = mbuf.lo
+@MULTIBUFFER_TRUE@am__objects_33 = $(am__objects_32)
+am__objects_34 = fontcache.lo
+@FONTCACHE_TRUE@am__objects_35 = $(am__objects_34)
+am__objects_36 = dpms.lo
+@DPMSExtension_TRUE@am__objects_37 = $(am__objects_36)
+am__objects_38 = bigreq.lo mitmisc.lo shape.lo sync.lo xcmisc.lo \
+ $(am__objects_21) $(am__objects_23) $(am__objects_25) \
+ $(am__objects_27) $(am__objects_29) $(am__objects_31) \
+ $(am__objects_33) $(am__objects_35) $(am__objects_37)
+am_libXext_la_OBJECTS = $(am__objects_19) $(am__objects_38)
+libXext_la_OBJECTS = $(am_libXext_la_OBJECTS)
+@XORG_FALSE@am_libXext_la_rpath =
+@XORG_TRUE@am_libXext_la_rpath =
+libXextbuiltin_la_LIBADD =
+am__libXextbuiltin_la_SOURCES_DIST = shape.c sleepuntil.c sleepuntil.h \
+ xtest.c shm.c shmint.h panoramiX.c panoramiX.h panoramiXh.h \
+ panoramiXsrv.h panoramiXprocs.c panoramiXSwap.c xace.c xace.h \
+ xacestr.h security.c securitysrv.h xcalibrate.c xevie.c \
+ xprint.c appgroup.c appgroup.h xf86bigfont.c
+@XORG_TRUE@am_libXextbuiltin_la_OBJECTS = $(am__objects_19)
+libXextbuiltin_la_OBJECTS = $(am_libXextbuiltin_la_OBJECTS)
+@XORG_TRUE@am_libXextbuiltin_la_rpath =
+libXextmodule_la_LIBADD =
+am__libXextmodule_la_SOURCES_DIST = bigreq.c mitmisc.c shape.c sync.c \
+ xcmisc.c xvmain.c xvdisp.c xvmc.c xvdix.h xvmcext.h xvdisp.h \
+ xres.c saver.c xselinux.c xselinux.h cup.c EVI.c sampleEVI.c \
+ EVIstruct.h mbuf.c fontcache.c dpms.c dpmsproc.h
+@XORG_TRUE@am_libXextmodule_la_OBJECTS = $(am__objects_38)
+libXextmodule_la_OBJECTS = $(am_libXextmodule_la_OBJECTS)
+@XORG_TRUE@am_libXextmodule_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libXext_la_SOURCES) $(libXextbuiltin_la_SOURCES) \
+ $(libXextmodule_la_SOURCES)
+DIST_SOURCES = $(am__libXext_la_SOURCES_DIST) \
+ $(am__libXextbuiltin_la_SOURCES_DIST) \
+ $(am__libXextmodule_la_SOURCES_DIST)
+am__sdk_HEADERS_DIST = xvdix.h xvmcext.h
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(sdkdir)"
+sdkHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(sdk_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADMIN_MAN_DIR = @ADMIN_MAN_DIR@
+ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+APPDEFAULTDIR = @APPDEFAULTDIR@
+APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@
+APP_MAN_DIR = @APP_MAN_DIR@
+APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASE_FONT_PATH = @BASE_FONT_PATH@
+BUILD_DATE = @BUILD_DATE@
+BUILD_TIME = @BUILD_TIME@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DARWIN_LIBS = @DARWIN_LIBS@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DEFAULT_LIBRARY_PATH = @DEFAULT_LIBRARY_PATH@
+DEFAULT_LOGPREFIX = @DEFAULT_LOGPREFIX@
+DEFAULT_MODULE_PATH = @DEFAULT_MODULE_PATH@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DGA_CFLAGS = @DGA_CFLAGS@
+DGA_LIBS = @DGA_LIBS@
+DIX_CFLAGS = @DIX_CFLAGS@
+DLLTOOL = @DLLTOOL@
+DMXEXAMPLES_DEP_CFLAGS = @DMXEXAMPLES_DEP_CFLAGS@
+DMXEXAMPLES_DEP_LIBS = @DMXEXAMPLES_DEP_LIBS@
+DMXMODULES_CFLAGS = @DMXMODULES_CFLAGS@
+DMXMODULES_LIBS = @DMXMODULES_LIBS@
+DMXXIEXAMPLES_DEP_CFLAGS = @DMXXIEXAMPLES_DEP_CFLAGS@
+DMXXIEXAMPLES_DEP_LIBS = @DMXXIEXAMPLES_DEP_LIBS@
+DMXXMUEXAMPLES_DEP_CFLAGS = @DMXXMUEXAMPLES_DEP_CFLAGS@
+DMXXMUEXAMPLES_DEP_LIBS = @DMXXMUEXAMPLES_DEP_LIBS@
+DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@
+DRI2PROTO_LIBS = @DRI2PROTO_LIBS@
+DRIPROTO_CFLAGS = @DRIPROTO_CFLAGS@
+DRIPROTO_LIBS = @DRIPROTO_LIBS@
+DRIVER_MAN_DIR = @DRIVER_MAN_DIR@
+DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
+DRI_DRIVER_PATH = @DRI_DRIVER_PATH@
+DSYMUTIL = @DSYMUTIL@
+DTRACE = @DTRACE@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FILE_MAN_DIR = @FILE_MAN_DIR@
+FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@
+GLX_DEFINES = @GLX_DEFINES@
+GL_CFLAGS = @GL_CFLAGS@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KDRIVE_CFLAGS = @KDRIVE_CFLAGS@
+KDRIVE_INCS = @KDRIVE_INCS@
+KDRIVE_LIBS = @KDRIVE_LIBS@
+KDRIVE_LOCAL_LIBS = @KDRIVE_LOCAL_LIBS@
+KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@
+KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@
+LAUNCHD = @LAUNCHD@
+LDFLAGS = @LDFLAGS@
+LD_EXPORT_SYMBOLS_FLAG = @LD_EXPORT_SYMBOLS_FLAG@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBDRM_CFLAGS = @LIBDRM_CFLAGS@
+LIBDRM_LIBS = @LIBDRM_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MAN_DIR = @LIB_MAN_DIR@
+LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
+LINUXDOC = @LINUXDOC@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAKE_HTML = @MAKE_HTML@
+MAKE_PDF = @MAKE_PDF@
+MAKE_PS = @MAKE_PS@
+MAKE_TEXT = @MAKE_TEXT@
+MESA_SOURCE = @MESA_SOURCE@
+MISC_MAN_DIR = @MISC_MAN_DIR@
+MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
+MKDIR_P = @MKDIR_P@
+MKFONTDIR = @MKFONTDIR@
+MKFONTSCALE = @MKFONTSCALE@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCCLD = @OBJCCLD@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJCFLAGS = @OBJCFLAGS@
+OBJCLINK = @OBJCLINK@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@
+PCIACCESS_LIBS = @PCIACCESS_LIBS@
+PCI_TXT_IDS_PATH = @PCI_TXT_IDS_PATH@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PROJECTROOT = @PROJECTROOT@
+PS2PDF = @PS2PDF@
+RANLIB = @RANLIB@
+RAWCPP = @RAWCPP@
+RAWCPPFLAGS = @RAWCPPFLAGS@
+SED = @SED@
+SERVER_MISC_CONFIG_PATH = @SERVER_MISC_CONFIG_PATH@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOLARIS_ASM_CFLAGS = @SOLARIS_ASM_CFLAGS@
+SOLARIS_INOUT_ARCH = @SOLARIS_INOUT_ARCH@
+STRIP = @STRIP@
+TSLIB_CFLAGS = @TSLIB_CFLAGS@
+TSLIB_LIBS = @TSLIB_LIBS@
+UTILS_SYS_LIBS = @UTILS_SYS_LIBS@
+VENDOR_MAN_VERSION = @VENDOR_MAN_VERSION@
+VENDOR_NAME = @VENDOR_NAME@
+VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@
+VENDOR_RELEASE = @VENDOR_RELEASE@
+VERSION = @VERSION@
+X11APP_ARCHS = @X11APP_ARCHS@
+X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@
+X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@
+XDMCP_CFLAGS = @XDMCP_CFLAGS@
+XDMCP_LIBS = @XDMCP_LIBS@
+XDMXCONFIG_DEP_CFLAGS = @XDMXCONFIG_DEP_CFLAGS@
+XDMXCONFIG_DEP_LIBS = @XDMXCONFIG_DEP_LIBS@
+XDMX_CFLAGS = @XDMX_CFLAGS@
+XDMX_LIBS = @XDMX_LIBS@
+XDMX_SYS_LIBS = @XDMX_SYS_LIBS@
+XEGLMODULES_CFLAGS = @XEGLMODULES_CFLAGS@
+XEGL_LIBS = @XEGL_LIBS@
+XEGL_SYS_LIBS = @XEGL_SYS_LIBS@
+XEPHYR_CFLAGS = @XEPHYR_CFLAGS@
+XEPHYR_DRI_LIBS = @XEPHYR_DRI_LIBS@
+XEPHYR_INCS = @XEPHYR_INCS@
+XEPHYR_LIBS = @XEPHYR_LIBS@
+XF86CONFIGFILE = @XF86CONFIGFILE@
+XF86MISC_CFLAGS = @XF86MISC_CFLAGS@
+XF86MISC_LIBS = @XF86MISC_LIBS@
+XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@
+XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@
+XGLMODULES_CFLAGS = @XGLMODULES_CFLAGS@
+XGLMODULES_LIBS = @XGLMODULES_LIBS@
+XGLXMODULES_CFLAGS = @XGLXMODULES_CFLAGS@
+XGLXMODULES_LIBS = @XGLXMODULES_LIBS@
+XGLX_LIBS = @XGLX_LIBS@
+XGLX_SYS_LIBS = @XGLX_SYS_LIBS@
+XGL_LIBS = @XGL_LIBS@
+XGL_MODULE_PATH = @XGL_MODULE_PATH@
+XGL_SYS_LIBS = @XGL_SYS_LIBS@
+XKB_BASE_DIRECTORY = @XKB_BASE_DIRECTORY@
+XKB_BIN_DIRECTORY = @XKB_BIN_DIRECTORY@
+XKB_COMPILED_DIR = @XKB_COMPILED_DIR@
+XKM_OUTPUT_DIR = @XKM_OUTPUT_DIR@
+XLIB_CFLAGS = @XLIB_CFLAGS@
+XLIB_LIBS = @XLIB_LIBS@
+XNESTMODULES_CFLAGS = @XNESTMODULES_CFLAGS@
+XNESTMODULES_LIBS = @XNESTMODULES_LIBS@
+XNEST_LIBS = @XNEST_LIBS@
+XNEST_SYS_LIBS = @XNEST_SYS_LIBS@
+XORGCFG_DEP_CFLAGS = @XORGCFG_DEP_CFLAGS@
+XORGCFG_DEP_LIBS = @XORGCFG_DEP_LIBS@
+XORGCONFIG_DEP_CFLAGS = @XORGCONFIG_DEP_CFLAGS@
+XORGCONFIG_DEP_LIBS = @XORGCONFIG_DEP_LIBS@
+XORG_CFLAGS = @XORG_CFLAGS@
+XORG_INCS = @XORG_INCS@
+XORG_LIBS = @XORG_LIBS@
+XORG_MODULES_CFLAGS = @XORG_MODULES_CFLAGS@
+XORG_MODULES_LIBS = @XORG_MODULES_LIBS@
+XORG_OS = @XORG_OS@
+XORG_OS_SUBDIR = @XORG_OS_SUBDIR@
+XORG_SYS_LIBS = @XORG_SYS_LIBS@
+XPRINTMODULES_CFLAGS = @XPRINTMODULES_CFLAGS@
+XPRINTMODULES_LIBS = @XPRINTMODULES_LIBS@
+XPRINTPROTO_CFLAGS = @XPRINTPROTO_CFLAGS@
+XPRINTPROTO_LIBS = @XPRINTPROTO_LIBS@
+XPRINT_CFLAGS = @XPRINT_CFLAGS@
+XPRINT_LIBS = @XPRINT_LIBS@
+XPRINT_SYS_LIBS = @XPRINT_SYS_LIBS@
+XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@
+XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@
+XSDL_INCS = @XSDL_INCS@
+XSDL_LIBS = @XSDL_LIBS@
+XSERVERCFLAGS_CFLAGS = @XSERVERCFLAGS_CFLAGS@
+XSERVERCFLAGS_LIBS = @XSERVERCFLAGS_LIBS@
+XSERVERLIBS_CFLAGS = @XSERVERLIBS_CFLAGS@
+XSERVERLIBS_LIBS = @XSERVERLIBS_LIBS@
+XSERVER_LIBS = @XSERVER_LIBS@
+XSERVER_SYS_LIBS = @XSERVER_SYS_LIBS@
+XTSTEXAMPLES_DEP_CFLAGS = @XTSTEXAMPLES_DEP_CFLAGS@
+XTSTEXAMPLES_DEP_LIBS = @XTSTEXAMPLES_DEP_LIBS@
+XVFB_LIBS = @XVFB_LIBS@
+XVFB_SYS_LIBS = @XVFB_SYS_LIBS@
+XWINMODULES_CFLAGS = @XWINMODULES_CFLAGS@
+XWINMODULES_LIBS = @XWINMODULES_LIBS@
+XWIN_LIBS = @XWIN_LIBS@
+XWIN_SERVER_NAME = @XWIN_SERVER_NAME@
+XWIN_SYS_LIBS = @XWIN_SYS_LIBS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+__XCONFIGFILE__ = @__XCONFIGFILE__@
+abi_ansic = @abi_ansic@
+abi_extension = @abi_extension@
+abi_font = @abi_font@
+abi_videodrv = @abi_videodrv@
+abi_xinput = @abi_xinput@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+driverdir = @driverdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+extdir = @extdir@
+ft_config = @ft_config@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+launchagentsdir = @launchagentsdir@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+logdir = @logdir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sdkdir = @sdkdir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+xglmoduledir = @xglmoduledir@
+xpconfigdir = @xpconfigdir@
+@XORG_FALSE@noinst_LTLIBRARIES = libXext.la
+
+# libXext.la: includes all extensions and should be linked into Xvfb,
+# Xnest, Xdmx and Xprt
+# libXextbuiltin.la: includes those extensions that are built directly into
+# Xorg by default
+# libXextmodule.la: includes those extensions that are built into a module
+# that Xorg loads
+@XORG_TRUE@noinst_LTLIBRARIES = libXext.la libXextbuiltin.la libXextmodule.la
+INCLUDES = -I$(top_srcdir)/hw/xfree86/dixmods/extmod
+AM_CFLAGS = $(DIX_CFLAGS)
+@XORG_TRUE@sdk_HEADERS = xvdix.h xvmcext.h
+
+# Sources always included in libXextbuiltin.la & libXext.la
+BUILTIN_SRCS = shape.c sleepuntil.c sleepuntil.h xtest.c \
+ $(am__append_1) $(am__append_5) $(am__append_6) \
+ $(am__append_8) $(am__append_9) $(am__append_10) \
+ $(am__append_11) $(am__append_12) $(am__append_17)
+
+# Sources always included in libXextmodule.la & libXext.la
+MODULE_SRCS = bigreq.c mitmisc.c shape.c sync.c xcmisc.c \
+ $(am__append_2) $(am__append_3) $(am__append_4) \
+ $(am__append_7) $(am__append_13) $(am__append_14) \
+ $(am__append_15) $(am__append_16) $(am__append_18)
+
+# Optional sources included if extension enabled by configure.ac rules
+
+# MIT Shared Memory extension
+MITSHM_SRCS = shm.c shmint.h
+
+# XVideo extension
+XV_SRCS = xvmain.c xvdisp.c xvmc.c xvdix.h xvmcext.h xvdisp.h
+
+# XResource extension: lets clients get data about per-client resource usage
+RES_SRCS = xres.c
+
+# MIT ScreenSaver extension
+SCREENSAVER_SRCS = saver.c
+
+# Xinerama extension: making multiple video devices act as one virtual screen
+XINERAMA_SRCS = panoramiX.c panoramiX.h panoramiXh.h panoramiXsrv.h panoramiXprocs.c panoramiXSwap.c
+
+# X-ACE extension: provides hooks for building security policy extensions
+# like XC-Security, X-SELinux & XTSol
+XACE_SRCS = xace.c xace.h xacestr.h
+
+# SELinux extension: provides SELinux policy support for X objects
+# requires X-ACE extension
+XSELINUX_SRCS = xselinux.c xselinux.h
+
+# Security extension: multi-level security to protect clients from each other
+XCSECURITY_SRCS = security.c securitysrv.h
+XCALIBRATE_SRCS = xcalibrate.c
+# XCalibrate needs tslib
+
+# X EVent Interception Extension: allows accessibility helpers & composite
+# managers to intercept events from input devices and transform as needed
+# before the clients see them.
+XEVIE_SRCS = xevie.c
+
+# XPrint: Printing via X Protocol
+XPRINT_SRCS = xprint.c
+
+# AppGroup
+APPGROUP_SRCS = appgroup.c appgroup.h
+
+# Colormap Utilization Protocol: Less flashing when switching between
+# PsuedoColor apps and better sharing of limited colormap slots
+CUP_SRCS = cup.c
+
+# Extended Visual Information
+EVI_SRCS = EVI.c sampleEVI.c EVIstruct.h
+
+# Multi-buffering extension
+MULTIBUFFER_SRCS = mbuf.c
+EXTRA_MULTIBUFFER_SRCS = mbufbf.c mbufpx.c
+
+# Font Cache extension
+FONTCACHE_SRCS = fontcache.c
+
+# XF86 Big Font extension
+BIGFONT_SRCS = xf86bigfont.c
+
+# DPMS extension
+DPMS_SRCS = dpms.c dpmsproc.h
+
+# Now take all of the above, mix well, bake for 10 minutes and get libXext*.la
+libXext_la_SOURCES = $(BUILTIN_SRCS) $(MODULE_SRCS)
+@XORG_TRUE@libXextbuiltin_la_SOURCES = $(BUILTIN_SRCS)
+@XORG_TRUE@libXextmodule_la_SOURCES = $(MODULE_SRCS)
+EXTRA_DIST = \
+ $(MITSHM_SRCS) \
+ $(XV_SRCS) \
+ $(RES_SRCS) \
+ $(SCREENSAVER_SRCS) \
+ $(XACE_SRCS) \
+ $(XCSECURITY_SRCS) \
+ $(XCALIBRATE_SRCS) \
+ $(XINERAMA_SRCS) \
+ $(XEVIE_SRCS) \
+ $(XPRINT_SRCS) \
+ $(APPGROUP_SRCS) \
+ $(CUP_SRCS) \
+ $(EVI_SRCS) \
+ $(MULTIBUFFER_SRCS) \
+ $(EXTRA_MULTIBUFFER_SRCS) \
+ $(FONTCACHE_SRCS) \
+ $(BIGFONT_SRCS) \
+ $(DPMS_SRCS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Xext/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Xext/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libXext.la: $(libXext_la_OBJECTS) $(libXext_la_DEPENDENCIES)
+ $(LINK) $(am_libXext_la_rpath) $(libXext_la_OBJECTS) $(libXext_la_LIBADD) $(LIBS)
+libXextbuiltin.la: $(libXextbuiltin_la_OBJECTS) $(libXextbuiltin_la_DEPENDENCIES)
+ $(LINK) $(am_libXextbuiltin_la_rpath) $(libXextbuiltin_la_OBJECTS) $(libXextbuiltin_la_LIBADD) $(LIBS)
+libXextmodule.la: $(libXextmodule_la_OBJECTS) $(libXextmodule_la_DEPENDENCIES)
+ $(LINK) $(am_libXextmodule_la_rpath) $(libXextmodule_la_OBJECTS) $(libXextmodule_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/EVI.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/appgroup.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bigreq.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cup.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dpms.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fontcache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbuf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mitmisc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panoramiX.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panoramiXSwap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/panoramiXprocs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sampleEVI.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/saver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/security.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shape.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shm.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sleepuntil.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xace.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xcalibrate.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xcmisc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xevie.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86bigfont.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xprint.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xres.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xselinux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xtest.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xvdisp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xvmain.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xvmc.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-sdkHEADERS: $(sdk_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(sdkdir)" || $(MKDIR_P) "$(DESTDIR)$(sdkdir)"
+ @list='$(sdk_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(sdkHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(sdkdir)/$$f'"; \
+ $(sdkHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(sdkdir)/$$f"; \
+ done
+
+uninstall-sdkHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sdk_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(sdkdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(sdkdir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(sdkdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-sdkHEADERS
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-sdkHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-sdkHEADERS install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-sdkHEADERS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/xorg-server/Xext/appgroup.c b/xorg-server/Xext/appgroup.c
new file mode 100644
index 000000000..c40782df5
--- /dev/null
+++ b/xorg-server/Xext/appgroup.c
@@ -0,0 +1,775 @@
+/*
+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.
+*/
+
+#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 "xacestr.h"
+#include "securitysrv.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);
+
+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++) {
+ if (pAppGrp->clients[i] == NULL) continue;
+ 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)
+{
+ NewClientInfoRec* pci = (NewClientInfoRec*) calldata;
+ ClientPtr pClient = pci->client;
+ AppGroupPtr pAppGrp = pClient->appgroup;
+ int slot;
+
+ if (!pAppGrp)
+ return;
+
+ switch (pClient->clientState) {
+ case ClientStateAuthenticating:
+ case ClientStateRunning:
+ case ClientStateCheckingSecurity:
+ break;
+
+ case ClientStateInitial:
+ case ClientStateCheckedSecurity:
+ slot = -1;
+ /* see the comment above about Initial vs. CheckedSecurity */
+ if (pAppGrp->nclients != 0) {
+ /* 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;
+ if (slot == -1 && pAppGrp->clients[i] == NULL)
+ slot = i;
+ }
+ if (slot == -1) {
+ slot = pAppGrp->nclients++;
+ pAppGrp->clients = (ClientPtr*) xrealloc (pAppGrp->clients,
+ pAppGrp->nclients * sizeof (ClientPtr));
+ }
+ pAppGrp->clients[slot] = 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;
+ }
+ }
+ pClient->appgroup = NULL; /* redundant, pClient will be freed */
+ break;
+ }
+}
+
+/*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, rc;
+ ScreenPtr pScreen;
+ DepthPtr pDepth;
+ ColormapPtr pColormap;
+
+ rc = dixLookupWindow(&pWin, pAppGrp->default_root, client,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ 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) {
+
+ rc = dixLookupResource((pointer *)&pColormap, pAppGrp->default_colormap,
+ RT_COLORMAP, client, DixUseAccess);
+ if (rc != Success)
+ return rc;
+ 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, DixReadAccess);
+ 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, DixReadAccess);
+ 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, rc;
+
+ REQUEST_SIZE_MATCH (xXagQueryReq);
+ rc = dixLookupClient(&pClient, stuff->resource, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ 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);
+}
+
+static void XagCallClientStateChange(
+ CallbackListPtr *pcbl,
+ pointer nulldata,
+ pointer calldata)
+{
+ XaceAuthAvailRec* rec = (XaceAuthAvailRec*) calldata;
+ ClientPtr pClient = rec->client;
+
+ if (!pClient->appgroup) {
+ SecurityAuthorizationPtr pAuth;
+ XID authId = rec->authId;
+
+ /* can't use SecurityLookupIDByType here -- client
+ * security state hasn't been setup yet.
+ */
+ pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId,
+ SecurityAuthorizationResType);
+ if (!pAuth)
+ return;
+
+ pClient->appgroup = (AppGroupPtr)LookupIDByType(pAuth->group,
+ RT_APPGROUP);
+ }
+
+ if (pClient->appgroup) {
+ NewClientInfoRec clientinfo;
+
+ clientinfo.client = pClient;
+ XagClientStateChange (NULL, NULL, (pointer)&clientinfo);
+ }
+}
+
+void
+XagExtensionInit(INITARGS)
+{
+ if (AddExtension (XAGNAME,
+ 0,
+ XagNumberErrors,
+ ProcXagDispatch,
+ SProcXagDispatch,
+ XagResetProc,
+ StandardMinorOpcode)) {
+ RT_APPGROUP = CreateNewResourceType (XagAppGroupFree);
+ XaceRegisterCallback(XACE_AUTH_AVAIL, XagCallClientStateChange, NULL);
+ }
+}
diff --git a/xorg-server/Xext/appgroup.h b/xorg-server/Xext/appgroup.h
new file mode 100644
index 000000000..778da5de6
--- /dev/null
+++ b/xorg-server/Xext/appgroup.h
@@ -0,0 +1,67 @@
+/*
+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.
+*/
+
+#ifndef _APPGROUP_SRV_H_
+#define _APPGROUP_SRV_H_
+
+#include <X11/Xfuncproto.h>
+
+_XFUNCPROTOBEGIN
+
+extern void XagConnectionInfo(
+ ClientPtr /* client */,
+ xConnSetupPrefix** /* conn_prefix */,
+ char** /* conn_info */,
+ int* /* num_screens */
+);
+
+extern VisualID XagRootVisual(
+ ClientPtr /* client */
+);
+
+extern Colormap XagDefaultColormap(
+ ClientPtr /* client */
+);
+
+extern ClientPtr XagLeader(
+ ClientPtr /* client */
+);
+
+extern Bool XagIsControlledRoot (
+ ClientPtr /* client */,
+ WindowPtr /* pParent */
+);
+
+extern XID XagId (
+ ClientPtr /* client */
+);
+
+_XFUNCPROTOEND
+
+#endif /* _APPGROUP_SRV_H_ */
+
+
+
diff --git a/xorg-server/Xext/bigreq.c b/xorg-server/Xext/bigreq.c
new file mode 100644
index 000000000..4f0724bc1
--- /dev/null
+++ b/xorg-server/Xext/bigreq.c
@@ -0,0 +1,90 @@
+/*
+
+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.
+
+*/
+
+#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"
+
+static void BigReqResetProc(
+ ExtensionEntry * /* extEntry */
+);
+
+static DISPATCH_PROC(ProcBigReqDispatch);
+
+void
+BigReqExtensionInit(INITARGS)
+{
+ AddExtension(XBigReqExtensionName, 0, 0,
+ ProcBigReqDispatch, ProcBigReqDispatch,
+ BigReqResetProc, StandardMinorOpcode);
+}
+
+/*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/xorg-server/Xext/cup.c b/xorg-server/Xext/cup.c
new file mode 100644
index 000000000..fd1409e33
--- /dev/null
+++ b/xorg-server/Xext/cup.c
@@ -0,0 +1,342 @@
+/*
+
+Copyright 1997, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#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>
+
+#include "../os/osdep.h"
+
+#include "modinit.h"
+
+static int ProcDispatch(ClientPtr client);
+static int SProcDispatch(ClientPtr client);
+static void ResetProc(ExtensionEntry* extEntry);
+
+#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)
+{
+ (void) AddExtension (XCUPNAME,
+ 0,
+ XcupNumberErrors,
+ ProcDispatch,
+ SProcDispatch,
+ ResetProc,
+ StandardMinorOpcode);
+
+ /* 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;
+ int rc;
+
+ REQUEST_AT_LEAST_SIZE (xXcupStoreColorsReq);
+ rc = dixLookupResource((pointer *)&pcmp, stuff->cmap, RT_COLORMAP,
+ client, DixAddAccess);
+
+ if (rc == Success) {
+ 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 (rc == BadValue) ? BadColor : rc;
+ }
+}
+
+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/xorg-server/Xext/dpms.c b/xorg-server/Xext/dpms.c
new file mode 100644
index 000000000..e3204febb
--- /dev/null
+++ b/xorg-server/Xext/dpms.c
@@ -0,0 +1,439 @@
+/*****************************************************************
+
+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
+ */
+
+
+#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"
+
+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)
+{
+ AddExtension(DPMSExtensionName, 0, 0,
+ ProcDPMSDispatch, SProcDPMSDispatch,
+ DPMSResetProc, StandardMinorOpcode);
+}
+
+/*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;
+ SetScreenSaverTimer();
+
+ return(client->noClientException);
+}
+
+static int
+ProcDPMSEnable(client)
+ register ClientPtr client;
+{
+ Bool was_enabled = DPMSEnabled;
+
+ REQUEST_SIZE_MATCH(xDPMSEnableReq);
+
+ if (DPMSCapableFlag) {
+ DPMSEnabled = TRUE;
+ if (!was_enabled)
+ SetScreenSaverTimer();
+ }
+
+ return(client->noClientException);
+}
+
+static int
+ProcDPMSDisable(client)
+ register ClientPtr client;
+{
+ /* REQUEST(xDPMSDisableReq); */
+
+ REQUEST_SIZE_MATCH(xDPMSDisableReq);
+
+ DPMSSet(client, 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(client, 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/xorg-server/Xext/dpmsproc.h b/xorg-server/Xext/dpmsproc.h
new file mode 100644
index 000000000..d57f57318
--- /dev/null
+++ b/xorg-server/Xext/dpmsproc.h
@@ -0,0 +1,17 @@
+
+/* Prototypes for functions that the DDX must provide */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef _DPMSPROC_H_
+#define _DPMSPROC_H_
+
+#include "dixstruct.h"
+
+int DPMSSet(ClientPtr client, int level);
+int DPMSGet(int *plevel);
+Bool DPMSSupported(void);
+
+#endif
diff --git a/xorg-server/Xext/dpmsstubs.c b/xorg-server/Xext/dpmsstubs.c
new file mode 100644
index 000000000..0f59d5160
--- /dev/null
+++ b/xorg-server/Xext/dpmsstubs.c
@@ -0,0 +1,50 @@
+/*****************************************************************
+
+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.
+
+******************************************************************/
+
+#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;
+}
+
+int DPMSSet(ClientPtr client, int level)
+{
+ return Success;
+}
diff --git a/xorg-server/Xext/fontcache.c b/xorg-server/Xext/fontcache.c
new file mode 100644
index 000000000..0338d4a0f
--- /dev/null
+++ b/xorg-server/Xext/fontcache.c
@@ -0,0 +1,323 @@
+/*-
+ * 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.
+ */
+
+/* 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 <X11/extensions/fontcacheP.h>
+#include <X11/extensions/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);
+
+void
+FontCacheExtensionInit(INITARGS)
+{
+ ExtensionEntry* extEntry;
+
+ if (
+ (extEntry = AddExtension(FONTCACHENAME,
+ FontCacheNumberEvents,
+ FontCacheNumberErrors,
+ ProcFontCacheDispatch,
+ SProcFontCacheDispatch,
+ FontCacheResetProc,
+ StandardMinorOpcode))) {
+ 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/xorg-server/Xext/mbuf.c b/xorg-server/Xext/mbuf.c
new file mode 100644
index 000000000..0b5b91ea9
--- /dev/null
+++ b/xorg-server/Xext/mbuf.c
@@ -0,0 +1,1763 @@
+/************************************************************
+
+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.
+
+********************************************************/
+
+#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>
+
+#include <stdio.h>
+#if !defined(WIN32) && !defined(Lynx)
+#include <sys/time.h>
+#endif
+
+/* given an OtherClientPtr obj, get the ClientPtr */
+#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
+
+/* given a MultibufferPtr b, get the ClientPtr */
+#define bClient(b) (clients[CLIENT_ID(b->pPixmap->drawable.id)])
+
+#define ValidEventMasks (ExposureMask|MultibufferClobberNotifyMask|MultibufferUpdateNotifyMask)
+
+static int MultibufferEventBase;
+static int MultibufferErrorBase;
+static DevPrivateKey MultibufferScreenPrivKey = &MultibufferScreenPrivKey;
+static DevPrivateKey MultibufferWindowPrivKey = &MultibufferWindowPrivKey;
+
+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;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+ if (!(pMultibufferScreen = (MultibufferScreenPtr) xalloc (sizeof (MultibufferScreenRec))))
+ {
+ for (j = 0; j < i; j++)
+ xfree (dixLookupPrivate(&screenInfo.screens[j]->devPrivates, MultibufferScreenPrivKey));
+ return;
+ }
+ dixSetPrivate(&pScreen->devPrivates, MultibufferScreenPrivKey, 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_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)))
+ {
+ 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;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+ if ((pMultibufferScreen = (MultibufferScreenPtr)dixLookupPrivate(&pScreen->devPrivates, MultibufferScreenPrivKey)))
+ {
+ 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, 0);
+ 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;
+ dixSetPrivate(&pWin->devPrivates, MultibufferWindowPrivKey, 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, i, err, rc;
+
+ REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq);
+ len = stuff->length - (sizeof(xMbufCreateImageBuffersReq) >> 2);
+ if (len == 0)
+ return BadLength;
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+ if (rc != Success)
+ return rc;
+ 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) (dixLookupPrivate(&pWin->devPrivates, MultibufferWindowPrivKey)))->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 *) xalloc(nbuf * sizeof (MultibuffersPtr));
+ pMultibuffer = (MultibufferPtr *) xalloc(nbuf * sizeof (MultibufferPtr));
+ if (!ppMultibuffers || !pMultibuffer)
+ {
+ if (ppMultibuffers) xfree(ppMultibuffers);
+ if (pMultibuffer) xfree(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])
+ {
+ xfree(ppMultibuffers);
+ xfree(pMultibuffer);
+ client->errorValue = ids[i];
+ return MultibufferErrorBase + MultibufferBadBuffer;
+ }
+ ppMultibuffers[i] = pMultibuffer[i]->pMultibuffers;
+ for (j = 0; j < i; j++)
+ {
+ if (ppMultibuffers[i] == ppMultibuffers[j])
+ {
+ xfree(ppMultibuffers);
+ xfree(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);
+
+ xfree(ppMultibuffers);
+ xfree(pMultibuffer);
+ return Success;
+}
+
+
+static int
+ProcDestroyImageBuffers (client)
+ register ClientPtr client;
+{
+ REQUEST (xMbufDestroyImageBuffersReq);
+ WindowPtr pWin;
+ int rc;
+
+ REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+ if (rc != Success)
+ return rc;
+ DestroyImageBuffers (pWin);
+ return Success;
+}
+
+static int
+ProcSetMBufferAttributes (client)
+ register ClientPtr client;
+{
+ REQUEST (xMbufSetMBufferAttributesReq);
+ WindowPtr pWin;
+ MultibuffersPtr pMultibuffers;
+ int len, rc;
+ Mask vmask;
+ Mask index2;
+ CARD32 updateHint;
+ XID *vlist;
+
+ REQUEST_AT_LEAST_SIZE (xMbufSetMBufferAttributesReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+ if (rc != Success)
+ return rc;
+ 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, rc;
+
+ REQUEST_SIZE_MATCH (xMbufGetMBufferAttributesReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+ if (rc != Success)
+ return rc;
+ pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType);
+ if (!pMultibuffers)
+ return BadAccess;
+ ids = (XID *) xalloc (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);
+ xfree((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, n, rc;
+ xMbufBufferInfo *pInfo;
+ int nInfo;
+ DepthPtr pDepth;
+
+ rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
+ DixUnknownAccess);
+ if (rc != Success)
+ return rc;
+ pScreen = pDrawable->pScreen;
+ 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 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);
+ xfree ((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, &region, &box, 1);
+ MultibufferExpose(pMultibuffer, &region);
+ REGION_UNINIT(pScreen, &region);
+ }
+ 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) dixLookupPrivate(&pWin->devPrivates, MultibufferWindowPrivKey)))
+ 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 *) xalloc (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])
+ {
+ xfree (pMultibuffer);
+ return MultibufferErrorBase + MultibufferBadBuffer;
+ }
+ pMultibuffers[i] = pMultibuffer[i]->pMultibuffers;
+ for (j = 0; j < i; j++)
+ if (pMultibuffers[i] == pMultibuffers[j])
+ {
+ xfree (pMultibuffer);
+ return BadMatch;
+ }
+ }
+ PerformDisplayRequest (pMultibuffers, pMultibuffer, nbuf);
+ xfree (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 *) xalloc(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);
+ xfree(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 */
+ dixSetPrivate(&pWin->devPrivates, MultibufferWindowPrivKey, 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) dixLookupPrivate(&pScreen->devPrivates, MultibufferScreenPrivKey);
+ (*pMultibufferScreen->PositionWindow) (pWin, x, y);
+
+ /* if this window is not multibuffered, we're done */
+ if (!(pMultibuffers = (MultibuffersPtr) dixLookupPrivate(&pWin->devPrivates, MultibufferWindowPrivKey)))
+ 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,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ 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) dixLookupPrivate(&pWin->devPrivates, MultibufferWindowPrivKey);
+ 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/xorg-server/Xext/mbufbf.c b/xorg-server/Xext/mbufbf.c
new file mode 100644
index 000000000..a3b3de79d
--- /dev/null
+++ b/xorg-server/Xext/mbufbf.c
@@ -0,0 +1,1011 @@
+/*
+
+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.
+
+*/
+
+
+#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 - 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, &reg, &box, 1);
+
+ REGION_INTERSECT(pScreen, &reg, &reg, &pBuffer->clipList);
+ if (pBuffer->backgroundState != None)
+ miPaintWindow(pBuffer, &reg, PW_BACKGROUND);
+ if (generateExposures)
+ MultibufferExpose(pMBBuffer, &reg);
+#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, &reg, pBSReg);
+ else if (pBuffer->backgroundState != None)
+ miPaintWindow(pBuffer, &reg, PW_BACKGROUND);
+#endif
+ REGION_UNINIT(pScreen, &reg);
+ 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 *)xalloc(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);
+
+ xfree(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 miPaintWindow 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)
+ miPaintWindow(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/xorg-server/Xext/mbufpx.c b/xorg-server/Xext/mbufpx.c
new file mode 100644
index 000000000..21d525906
--- /dev/null
+++ b/xorg-server/Xext/mbufpx.c
@@ -0,0 +1,650 @@
+/************************************************************
+
+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.
+
+********************************************************/
+
+#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, 0);
+ 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 *)xalloc(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);
+ xfree(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,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ 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, &region, &box, 1);
+
+ if (pMBBuffer->number == pMBBuffer->pMBWindow->displayedMultibuffer)
+ pDrawable = (DrawablePtr) pWin;
+ else
+ pDrawable = pMBBuffer->pDrawable;
+
+ MultibufferPaintBackgroundRegion(pWin, pDrawable, &region);
+
+ if (exposures)
+ MultibufferExpose(pMBBuffer, &region);
+
+ REGION_UNINIT(pScreen, &region);
+}
+
+static void
+pixDeleteBufferDrawable(pDrawable)
+ DrawablePtr pDrawable;
+{
+ (* pDrawable->pScreen->DestroyPixmap)((PixmapPtr) pDrawable);
+}
diff --git a/xorg-server/Xext/mitmisc.c b/xorg-server/Xext/mitmisc.c
new file mode 100644
index 000000000..e793d4dc1
--- /dev/null
+++ b/xorg-server/Xext/mitmisc.c
@@ -0,0 +1,155 @@
+/************************************************************
+
+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 */
+
+
+#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"
+
+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)
+{
+ AddExtension(MITMISCNAME, 0, 0,
+ ProcMITDispatch, SProcMITDispatch,
+ MITResetProc, StandardMinorOpcode);
+}
+
+/*ARGSUSED*/
+static void
+MITResetProc (extEntry)
+ExtensionEntry *extEntry;
+{
+}
+
+static int
+ProcMITSetBugMode(client)
+ register ClientPtr client;
+{
+ REQUEST(xMITSetBugModeReq);
+
+ REQUEST_SIZE_MATCH(xMITSetBugModeReq);
+ if (stuff->onOff != xFalse)
+ return BadRequest;
+ 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 = FALSE;
+ 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/xorg-server/Xext/panoramiX.c b/xorg-server/Xext/panoramiX.c
new file mode 100644
index 000000000..8bc5c42c2
--- /dev/null
+++ b/xorg-server/Xext/panoramiX.c
@@ -0,0 +1,1283 @@
+/*****************************************************************
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+******************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#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
+
+/*
+ * PanoramiX data declarations
+ */
+
+int PanoramiXPixWidth = 0;
+int PanoramiXPixHeight = 0;
+_X_EXPORT int PanoramiXNumScreens = 0;
+
+_X_EXPORT PanoramiXData *panoramiXdataPtr = NULL;
+static RegionRec PanoramiXScreenRegion = {{0, 0, 0, 0}, NULL};
+
+static int PanoramiXNumDepths;
+static DepthPtr PanoramiXDepths;
+static int PanoramiXNumVisuals;
+static VisualPtr PanoramiXVisuals;
+
+_X_EXPORT unsigned long XRC_DRAWABLE;
+_X_EXPORT unsigned long XRT_WINDOW;
+_X_EXPORT unsigned long XRT_PIXMAP;
+_X_EXPORT unsigned long XRT_GC;
+_X_EXPORT unsigned long XRT_COLORMAP;
+
+static Bool VisualsEqual(VisualPtr, ScreenPtr, VisualPtr);
+_X_EXPORT XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr = &VisualsEqual;
+
+/*
+ * 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, };
+
+static DevPrivateKey PanoramiXGCKey = &PanoramiXGCKey;
+static DevPrivateKey PanoramiXScreenKey = &PanoramiXScreenKey;
+
+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);
+
+static GCFuncs XineramaGCFuncs = {
+ XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC,
+ XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip
+};
+
+#define Xinerama_GC_FUNC_PROLOGUE(pGC)\
+ PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr) \
+ dixLookupPrivate(&(pGC)->devPrivates, PanoramiXGCKey); \
+ (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)
+ dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
+
+ 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);
+}
+
+static Bool
+XineramaCreateGC(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
+ dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
+ Bool ret;
+
+ pScreen->CreateGC = pScreenPriv->CreateGC;
+ if((ret = (*pScreen->CreateGC)(pGC))) {
+ PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr)
+ dixLookupPrivate(&pGC->devPrivates, PanoramiXGCKey);
+
+ 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)
+ dixLookupPrivate(&pGCSrc->devPrivates, PanoramiXGCKey);
+ 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);
+}
+
+_X_EXPORT int
+XineramaDeleteResource(pointer data, XID id)
+{
+ xfree(data);
+ return 1;
+}
+
+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);
+}
+
+typedef struct _connect_callback_list {
+ void (*func)(void);
+ struct _connect_callback_list *next;
+} XineramaConnectionCallbackList;
+
+static XineramaConnectionCallbackList *ConnectionCallbackList = NULL;
+
+_X_EXPORT 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;
+
+ 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)
+ break;
+
+ /*
+ * First make sure all the basic allocations succeed. If not,
+ * run in non-PanoramiXeen mode.
+ */
+
+ panoramiXdataPtr = (PanoramiXData *)
+ xcalloc(PanoramiXNumScreens, sizeof(PanoramiXData));
+
+ BREAK_IF(!panoramiXdataPtr);
+
+ if (!dixRequestPrivate(PanoramiXGCKey, sizeof(PanoramiXGCRec))) {
+ noPanoramiXExtension = TRUE;
+ return;
+ }
+
+ for (i = 0; i < PanoramiXNumScreens; i++) {
+ pScreen = screenInfo.screens[i];
+ pScreenPriv = xalloc(sizeof(PanoramiXScreenRec));
+ dixSetPrivate(&pScreen->devPrivates, PanoramiXScreenKey,
+ 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(PANORAMIX_PROTOCOL_NAME " extension failed to initialize\n");
+ 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("Xinerama error: 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("Xinerama error: 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;
+
+ for (i = 0; i < PanoramiXNumDepths; i++)
+ xfree(PanoramiXDepths[i].vids);
+ xfree(PanoramiXDepths);
+ PanoramiXDepths = NULL;
+
+ /*
+ * 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;
+}
+
+/*
+ * This isn't just memcmp(), bitsPerRGBValue is skipped. markv made that
+ * change way back before xf86 4.0, but the comment for _why_ is a bit
+ * opaque, so I'm not going to question it for now.
+ *
+ * This is probably better done as a screen hook so DBE/EVI/GLX can add
+ * their own tests, and adding privates to VisualRec so they don't have to
+ * do their own back-mapping.
+ */
+static Bool
+VisualsEqual(VisualPtr a, ScreenPtr pScreenB, VisualPtr b)
+{
+ return ((a->class == b->class) &&
+ (a->ColormapEntries == b->ColormapEntries) &&
+ (a->nplanes == b->nplanes) &&
+ (a->redMask == b->redMask) &&
+ (a->greenMask == b->greenMask) &&
+ (a->blueMask == b->blueMask) &&
+ (a->offsetRed == b->offsetRed) &&
+ (a->offsetGreen == b->offsetGreen) &&
+ (a->offsetBlue == b->offsetBlue));
+}
+
+static void
+PanoramiXMaybeAddDepth(DepthPtr pDepth)
+{
+ ScreenPtr pScreen;
+ int j, k;
+ Bool found = FALSE;
+
+ for (j = 1; j < PanoramiXNumScreens; j++) {
+ pScreen = screenInfo.screens[j];
+ for (k = 0; k < pScreen->numDepths; k++) {
+ if (pScreen->allowedDepths[k].depth == pDepth->depth) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ return;
+
+ j = PanoramiXNumDepths;
+ PanoramiXNumDepths++;
+ PanoramiXDepths = xrealloc(PanoramiXDepths,
+ PanoramiXNumDepths * sizeof(DepthRec));
+ PanoramiXDepths[j].depth = pDepth->depth;
+ PanoramiXDepths[j].numVids = 0;
+ /* XXX suboptimal, should grow these dynamically */
+ if(pDepth->numVids)
+ PanoramiXDepths[j].vids = xalloc(sizeof(VisualID) * pDepth->numVids);
+ else
+ PanoramiXDepths[j].vids = NULL;
+}
+
+static void
+PanoramiXMaybeAddVisual(VisualPtr pVisual)
+{
+ ScreenPtr pScreen;
+ int j, k;
+ Bool found = FALSE;
+
+ for (j = 1; j < PanoramiXNumScreens; j++) {
+ pScreen = screenInfo.screens[j];
+ found = FALSE;
+
+ for (k = 0; k < pScreen->numVisuals; k++) {
+ VisualPtr candidate = &pScreen->visuals[k];
+
+ if ((*XineramaVisualsEqualPtr)(pVisual, pScreen, candidate)
+#ifdef GLXPROXY
+ && glxMatchVisual(screenInfo.screens[0], pVisual, pScreen)
+#endif
+ ) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ return;
+ }
+
+ /* found a matching visual on all screens, add it to the subset list */
+ j = PanoramiXNumVisuals;
+ PanoramiXNumVisuals++;
+ PanoramiXVisuals = xrealloc(PanoramiXVisuals,
+ PanoramiXNumVisuals * sizeof(VisualRec));
+
+ memcpy(&PanoramiXVisuals[j], pVisual, sizeof(VisualRec));
+
+ for (k = 0; k < PanoramiXNumDepths; k++) {
+ if (PanoramiXDepths[k].depth == pVisual->nplanes) {
+ PanoramiXDepths[k].vids[PanoramiXDepths[k].numVids] = pVisual->vid;
+ PanoramiXDepths[k].numVids++;
+ break;
+ }
+ }
+}
+
+extern void
+PanoramiXConsolidate(void)
+{
+ int i;
+ PanoramiXRes *root, *defmap, *saver;
+ ScreenPtr pScreen = screenInfo.screens[0];
+ DepthPtr pDepth = pScreen->allowedDepths;
+ VisualPtr pVisual = pScreen->visuals;
+
+ PanoramiXNumDepths = 0;
+ PanoramiXNumVisuals = 0;
+
+ for (i = 0; i < pScreen->numDepths; i++)
+ PanoramiXMaybeAddDepth(pDepth++);
+
+ for (i = 0; i < pScreen->numVisuals; i++)
+ PanoramiXMaybeAddVisual(pVisual++);
+
+ root = xalloc(sizeof(PanoramiXRes));
+ root->type = XRT_WINDOW;
+ defmap = xalloc(sizeof(PanoramiXRes));
+ defmap->type = XRT_COLORMAP;
+ saver = 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);
+}
+
+_X_EXPORT VisualID
+PanoramiXTranslateVisualID(int screen, VisualID orig)
+{
+ ScreenPtr pOtherScreen = screenInfo.screens[screen];
+ VisualPtr pVisual = NULL;
+ int i;
+
+ for (i = 0; i < PanoramiXNumVisuals; i++) {
+ if (orig == PanoramiXVisuals[i].vid) {
+ pVisual = &PanoramiXVisuals[i];
+ break;
+ }
+ }
+
+ if (!pVisual)
+ return 0;
+
+ /* if screen is 0, orig is already the correct visual ID */
+ if (screen == 0)
+ return orig;
+
+ /* found the original, now translate it relative to the backend screen */
+ for (i = 0; i < pOtherScreen->numVisuals; i++) {
+ VisualPtr pOtherVisual = &pOtherScreen->visuals[i];
+
+ if ((*XineramaVisualsEqualPtr)(pVisual, pOtherScreen, pOtherVisual))
+ return pOtherVisual->vid;
+ }
+
+ return 0;
+}
+
+
+/*
+ * 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, rc;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.state = !noPanoramiXExtension;
+ rep.window = stuff->window;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.window, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep);
+ return client->noClientException;
+
+}
+
+int
+ProcPanoramiXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenCountReply rep;
+ register int n, rc;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.ScreenCount = PanoramiXNumScreens;
+ rep.window = stuff->window;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.window, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep);
+ return client->noClientException;
+}
+
+int
+ProcPanoramiXGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenSizeReply rep;
+ register int n, rc;
+
+ if (stuff->screen >= PanoramiXNumScreens)
+ return BadMatch;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ /* screen dimensions */
+ rep.width = panoramiXdataPtr[stuff->screen].width;
+ rep.height = panoramiXdataPtr[stuff->screen].height;
+ rep.window = stuff->window;
+ rep.screen = stuff->screen;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.width, n);
+ swapl (&rep.height, n);
+ swapl (&rep.window, n);
+ swapl (&rep.screen, 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. */
+ 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];
+ 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/xorg-server/Xext/panoramiX.h b/xorg-server/Xext/panoramiX.h
new file mode 100644
index 000000000..89c754732
--- /dev/null
+++ b/xorg-server/Xext/panoramiX.h
@@ -0,0 +1,100 @@
+/*****************************************************************
+
+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.
+
+******************************************************************/
+
+
+/* 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 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/xorg-server/Xext/panoramiXSwap.c b/xorg-server/Xext/panoramiXSwap.c
new file mode 100644
index 000000000..b13c286dd
--- /dev/null
+++ b/xorg-server/Xext/panoramiXSwap.c
@@ -0,0 +1,142 @@
+/*****************************************************************
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+******************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <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"
+#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);
+ swapl (&stuff->window, n);
+ return ProcPanoramiXGetState(client);
+}
+
+static int
+SProcPanoramiXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ swapl (&stuff->window, n);
+ return ProcPanoramiXGetScreenCount(client);
+}
+
+static int
+SProcPanoramiXGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ swapl (&stuff->window, n);
+ swapl (&stuff->screen, n);
+ 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/xorg-server/Xext/panoramiXh.h b/xorg-server/Xext/panoramiXh.h
new file mode 100644
index 000000000..1a76a45cd
--- /dev/null
+++ b/xorg-server/Xext/panoramiXh.h
@@ -0,0 +1,74 @@
+
+/*
+ * 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 PanoramiXChangeGC(ClientPtr client);
+extern int PanoramiXCopyGC(ClientPtr client);
+extern int PanoramiXCopyColormapAndFree(ClientPtr client);
+extern int PanoramiXCreateGC(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 int SProcPanoramiXDispatch(ClientPtr client);
+
+extern char *ConnectionInfo;
+extern int connBlockScreenStart;
+extern xConnSetupPrefix connSetupPrefix;
+
+extern int (* SavedProcVector[256]) (ClientPtr client);
diff --git a/xorg-server/Xext/panoramiXprocs.c b/xorg-server/Xext/panoramiXprocs.c
new file mode 100644
index 000000000..30aff7460
--- /dev/null
+++ b/xorg-server/Xext/panoramiXprocs.c
@@ -0,0 +1,2377 @@
+/*****************************************************************
+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> */
+
+
+#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 )
+
+/* 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, DixWriteAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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 = PanoramiXTranslateVisualID(j, orig_visual);
+ 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, DixWriteAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixDestroyAccess)))
+ 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, DixDestroyAccess)))
+ 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, DixReadAccess)))
+ 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, DixWriteAccess)))
+ return BadWindow;
+
+ if(!(parent = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->parent, XRT_WINDOW, DixWriteAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixWriteAccess)))
+ return BadWindow;
+
+ if (!(win = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->window, XRT_WINDOW, DixWriteAccess)))
+ 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, DixReadAccess)))
+ 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, DixWriteAccess)))
+ 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;
+ int rc;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ 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);
+ int rc;
+ WindowPtr pWin, pDst;
+ xTranslateCoordsReply rep;
+
+ REQUEST_SIZE_MATCH(xTranslateCoordsReq);
+ rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+ rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+ 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, DixReadAccess)))
+ 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, DixDestroyAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ return BadGC;
+
+ if(!(dstGC = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->dstGC, XRT_GC, DixWriteAccess)))
+ 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, DixWriteAccess)))
+ 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, DixWriteAccess)))
+ 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, DixDestroyAccess)))
+ 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, DixWriteAccess)))
+ 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, DixReadAccess)))
+ return BadDrawable;
+
+ srcShared = IS_SHARED_PIXMAP(src);
+
+ if(!(dst = (PanoramiXRes *)SecurityLookupIDByClass(
+ client, stuff->dstDrawable, XRC_DRAWABLE, DixWriteAccess)))
+ return BadDrawable;
+
+ dstShared = IS_SHARED_PIXMAP(dst);
+
+ if(dstShared && srcShared)
+ return (* SavedProcVector[X_CopyArea])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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, rc;
+
+ FOR_NSCREENS(j) {
+ rc = dixLookupDrawable(drawables+j, src->info[j].id, client, 0,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+ 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, DixWriteAccess);
+ 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];
+ int rc;
+
+ 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, DixWriteAccess);
+
+ if (stuff->dstDrawable != stuff->srcDrawable) {
+ rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
+ DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ 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, rc;
+ 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, DixReadAccess)))
+ return BadDrawable;
+
+ srcShared = IS_SHARED_PIXMAP(src);
+
+ if(!(dst = (PanoramiXRes *)SecurityLookupIDByClass(
+ client, stuff->dstDrawable, XRC_DRAWABLE, DixWriteAccess)))
+ return BadDrawable;
+
+ dstShared = IS_SHARED_PIXMAP(dst);
+
+ if(dstShared && srcShared)
+ return (* SavedProcVector[X_CopyPlane])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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, DixWriteAccess);
+ if (stuff->dstDrawable != stuff->srcDrawable) {
+ rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
+ DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ 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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyPoint])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ return BadGC;
+
+ isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2;
+ if (npoint > 0) {
+ origPts = (xPoint *) xalloc(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;
+ }
+ xfree(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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyLine])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ return BadGC;
+
+ isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2;
+ if (npoint > 0){
+ origPts = (xPoint *) xalloc(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;
+ }
+ xfree(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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolySegment])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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 *) xalloc(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;
+ }
+ xfree(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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyRectangle])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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 *) xalloc(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;
+ }
+ xfree(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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyArc])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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 *) xalloc(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;
+ }
+ xfree(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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_FillPoly])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ return BadGC;
+
+ isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+
+ count = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2;
+ if (count > 0){
+ locPts = (DDXPointPtr) xalloc(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;
+ }
+ xfree(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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyFillRectangle])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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 *) xalloc(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;
+ }
+ xfree(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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyFillArc])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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 *) xalloc(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;
+ }
+ xfree(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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PutImage])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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, rc;
+ 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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(draw->type == XRT_PIXMAP)
+ return (*SavedProcVector[X_GetImage])(client);
+
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
+ DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ 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++) {
+ rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+ 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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyText8])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyText16])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_ImageText8])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_ImageText16])(client);
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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, DixReadAccess)))
+ return BadWindow;
+
+ 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 = PanoramiXTranslateVisualID(j, orig_visual);
+ 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, DixDestroyAccess)))
+ 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,
+ DixReadAccess | DixWriteAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixWriteAccess)))
+ 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, DixWriteAccess)))
+ 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, DixWriteAccess)))
+ 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, DixWriteAccess)))
+ 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, DixWriteAccess)))
+ 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, DixWriteAccess)))
+ 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, DixWriteAccess)))
+ 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/xorg-server/Xext/panoramiXsrv.h b/xorg-server/Xext/panoramiXsrv.h
new file mode 100644
index 000000000..d5c3d9827
--- /dev/null
+++ b/xorg-server/Xext/panoramiXsrv.h
@@ -0,0 +1,56 @@
+
+#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 VisualID PanoramiXTranslateVisualID(int screen, VisualID orig);
+extern void PanoramiXConsolidate(void);
+extern Bool PanoramiXCreateConnectionBlock(void);
+extern PanoramiXRes * PanoramiXFindIDByScrnum(RESTYPE, XID, int);
+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;
+
+/*
+ * Drivers are allowed to wrap this function. Each wrapper can decide that the
+ * two visuals are unequal, but if they are deemed equal, the wrapper must call
+ * down and return FALSE if the wrapped function does. This ensures that all
+ * layers agree that the visuals are equal. The first visual is always from
+ * screen 0.
+ */
+typedef Bool (*XineramaVisualsEqualProcPtr)(VisualPtr, ScreenPtr, VisualPtr);
+extern XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr;
+
+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/xorg-server/Xext/sampleEVI.c b/xorg-server/Xext/sampleEVI.c
new file mode 100644
index 000000000..b871bfd74
--- /dev/null
+++ b/xorg-server/Xext/sampleEVI.c
@@ -0,0 +1,123 @@
+/************************************************************
+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.
+********************************************************/
+
+#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/xorg-server/Xext/saver.c b/xorg-server/Xext/saver.c
new file mode 100644
index 000000000..feab972e2
--- /dev/null
+++ b/xorg-server/Xext/saver.c
@@ -0,0 +1,1570 @@
+/*
+ *
+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
+ */
+
+
+#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"
+#include "xace.h"
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+#ifdef DPMSExtension
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+#endif
+
+#include <stdio.h>
+
+#include "modinit.h"
+
+static int ScreenSaverEventBase = 0;
+
+static 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(ProcScreenSaverSuspend);
+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 DISPATCH_PROC(SProcScreenSaverSuspend);
+
+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 */
+ );
+
+static RESTYPE SuspendType; /* resource type for suspension records */
+
+typedef struct _ScreenSaverSuspension *ScreenSaverSuspensionPtr;
+
+/* List of clients that are suspending the screensaver. */
+static ScreenSaverSuspensionPtr suspendingClients = NULL;
+
+/*
+ * clientResource is a resource ID that's added when the record is
+ * allocated, so the record is freed and the screensaver resumed when
+ * the client disconnects. count is the number of times the client has
+ * requested the screensaver be suspended.
+ */
+typedef struct _ScreenSaverSuspension
+{
+ ScreenSaverSuspensionPtr next;
+ ClientPtr pClient;
+ XID clientResource;
+ int count;
+} ScreenSaverSuspensionRec;
+
+static int ScreenSaverFreeSuspend(
+ pointer /*value */,
+ XID /* id */
+);
+
+/*
+ * 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 DevPrivateKey ScreenPrivateKey = &ScreenPrivateKey;
+
+#define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr) \
+ dixLookupPrivate(&(s)->devPrivates, ScreenPrivateKey))
+#define SetScreenPrivate(s,v) \
+ dixSetPrivate(&(s)->devPrivates, ScreenPrivateKey, 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);
+ SuspendType = CreateNewResourceType(ScreenSaverFreeSuspend);
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+ SetScreenPrivate (pScreen, NULL);
+ }
+ if (AttrType && EventType && SuspendType &&
+ (extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0,
+ ProcScreenSaverDispatch, SProcScreenSaverDispatch,
+ ScreenSaverResetProc, StandardMinorOpcode)))
+ {
+ 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)
+ {
+ dixSaveScreens (serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
+ dixSaveScreens (serverClient, SCREEN_SAVER_FORCER, ScreenSaverActive);
+ }
+ CheckScreenPrivate (pScreen);
+ return TRUE;
+}
+
+static int
+ScreenSaverFreeSuspend (pointer value, XID id)
+{
+ ScreenSaverSuspensionPtr data = (ScreenSaverSuspensionPtr) value;
+ ScreenSaverSuspensionPtr *prev, this;
+
+ /* Unlink and free the suspension record for the client */
+ for (prev = &suspendingClients; (this = *prev); prev = &this->next)
+ {
+ if (this == data)
+ {
+ *prev = this->next;
+ xfree (this);
+ break;
+ }
+ }
+
+ /* Reenable the screensaver if this was the last client suspending it. */
+ if (screenSaverSuspended && suspendingClients == NULL)
+ {
+ screenSaverSuspended = FALSE;
+
+ /* The screensaver could be active, since suspending it (by design)
+ doesn't prevent it from being forceably activated */
+#ifdef DPMSExtension
+ if (screenIsSaved != SCREEN_SAVER_ON && DPMSPowerLevel == DPMSModeOn)
+#else
+ if (screenIsSaved != SCREEN_SAVER_ON)
+#endif
+ {
+ UpdateCurrentTimeIf();
+ lastDeviceEventTime = currentTime;
+ SetScreenSaverTimer();
+ }
+ }
+
+ return Success;
+}
+
+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 *) xalloc (pScreen->maxInstalledCmaps *
+ sizeof (Colormap));
+ numInstalled = (*pWin->drawable.pScreen->ListInstalledColormaps)
+ (pScreen, installedMaps);
+ for (i = 0; i < numInstalled; i++)
+ if (installedMaps[i] == wantMap)
+ break;
+
+ xfree ((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);
+}
+
+static int
+ProcScreenSaverQueryInfo (client)
+ register ClientPtr client;
+{
+ REQUEST(xScreenSaverQueryInfoReq);
+ xScreenSaverQueryInfoReply rep;
+ register int n, rc;
+ ScreenSaverStuffPtr pSaver;
+ DrawablePtr pDraw;
+ CARD32 lastInput;
+ ScreenSaverScreenPrivatePtr pPriv;
+
+ REQUEST_SIZE_MATCH (xScreenSaverQueryInfoReq);
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ 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;
+ int rc;
+
+ REQUEST_SIZE_MATCH (xScreenSaverSelectInputReq);
+ rc = dixLookupDrawable (&pDraw, stuff->drawable, client, 0,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen,
+ DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ 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, len, 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);
+ ret = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
+ DixGetAttrAccess);
+ if (ret != Success)
+ return ret;
+ pScreen = pDraw->pScreen;
+ pParent = WindowTable[pScreen->myNum];
+
+ ret = XaceHook(XACE_SCREENSAVER_ACCESS, client, pScreen, DixSetAttrAccess);
+ if (ret != Success)
+ return ret;
+
+ 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
+ {
+ ret = dixLookupResource((pointer *)&pPixmap, pixID, RT_PIXMAP,
+ client, DixReadAccess);
+ if (ret == Success)
+ {
+ if ((pPixmap->drawable.depth != depth) ||
+ (pPixmap->drawable.pScreen != pScreen))
+ {
+ ret = BadMatch;
+ goto PatchUp;
+ }
+ pAttr->pBackgroundPixmap = pPixmap;
+ pPixmap->refcnt++;
+ pAttr->mask &= ~CWBackPixmap;
+ }
+ else
+ {
+ ret = (ret == BadValue) ? BadPixmap : ret;
+ 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
+ {
+ ret = dixLookupResource((pointer *)&pPixmap, pixID, RT_PIXMAP,
+ client, DixReadAccess);
+ if (ret == Success)
+ {
+ if ((pPixmap->drawable.depth != depth) ||
+ (pPixmap->drawable.pScreen != pScreen))
+ {
+ ret = BadMatch;
+ goto PatchUp;
+ }
+ pAttr->pBorderPixmap = pPixmap;
+ pPixmap->refcnt++;
+ pAttr->mask &= ~CWBorderPixmap;
+ }
+ else
+ {
+ ret = (ret == BadValue) ? BadPixmap : ret;
+ 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;
+ ret = dixLookupResource((pointer *)&pCmap, cmap, RT_COLORMAP,
+ client, DixUseAccess);
+ if (ret != Success)
+ {
+ ret = (ret == BadValue) ? BadColor : ret;
+ 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
+ {
+ ret = dixLookupResource((pointer *)&pCursor, cursorID,
+ RT_CURSOR, client, DixUseAccess);
+ if (ret != Success)
+ {
+ ret = (ret == BadValue) ? BadCursor : ret;
+ 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;
+ int rc;
+
+ REQUEST_SIZE_MATCH (xScreenSaverUnsetAttributesReq);
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ 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, DixWriteAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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 = PanoramiXTranslateVisualID(i, orig_visual);
+
+ 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, DixWriteAccess)))
+ 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 int
+ProcScreenSaverSuspend (ClientPtr client)
+{
+ ScreenSaverSuspensionPtr *prev, this;
+
+ REQUEST(xScreenSaverSuspendReq);
+ REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
+
+ /* Check if this client is suspending the screensaver */
+ for (prev = &suspendingClients; (this = *prev); prev = &this->next)
+ if (this->pClient == client)
+ break;
+
+ if (this)
+ {
+ if (stuff->suspend == TRUE)
+ this->count++;
+ else if (--this->count == 0)
+ FreeResource (this->clientResource, RT_NONE);
+
+ return Success;
+ }
+
+ /* If we get to this point, this client isn't suspending the screensaver */
+ if (stuff->suspend == FALSE)
+ return Success;
+
+ /*
+ * Allocate a suspension record for the client, and stop the screensaver
+ * if it isn't already suspended by another client. We attach a resource ID
+ * to the record, so the screensaver will be reenabled and the record freed
+ * if the client disconnects without reenabling it first.
+ */
+ this = (ScreenSaverSuspensionPtr) xalloc (sizeof (ScreenSaverSuspensionRec));
+
+ if (!this)
+ return BadAlloc;
+
+ this->next = NULL;
+ this->pClient = client;
+ this->count = 1;
+ this->clientResource = FakeClientID (client->index);
+
+ if (!AddResource (this->clientResource, SuspendType, (pointer) this))
+ {
+ xfree (this);
+ return BadAlloc;
+ }
+
+ *prev = this;
+ if (!screenSaverSuspended)
+ {
+ screenSaverSuspended = TRUE;
+ FreeScreenSaverTimer();
+ }
+
+ return (client->noClientException);
+}
+
+static DISPATCH_PROC((*NormalVector[])) = {
+ ProcScreenSaverQueryVersion,
+ ProcScreenSaverQueryInfo,
+ ProcScreenSaverSelectInput,
+ ProcScreenSaverSetAttributes,
+ ProcScreenSaverUnsetAttributes,
+ ProcScreenSaverSuspend,
+};
+
+#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 int
+SProcScreenSaverSuspend (ClientPtr client)
+{
+ int n;
+ REQUEST(xScreenSaverSuspendReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
+ swapl(&stuff->suspend, n);
+ return ProcScreenSaverSuspend (client);
+}
+
+static DISPATCH_PROC((*SwappedVector[])) = {
+ SProcScreenSaverQueryVersion,
+ SProcScreenSaverQueryInfo,
+ SProcScreenSaverSelectInput,
+ SProcScreenSaverSetAttributes,
+ SProcScreenSaverUnsetAttributes,
+ SProcScreenSaverSuspend,
+};
+
+static int
+SProcScreenSaverDispatch (client)
+ ClientPtr client;
+{
+ REQUEST(xReq);
+
+ if (stuff->data < NUM_REQUESTS)
+ return (*SwappedVector[stuff->data])(client);
+ return BadRequest;
+}
diff --git a/xorg-server/Xext/security.c b/xorg-server/Xext/security.c
new file mode 100644
index 000000000..ad30e06b8
--- /dev/null
+++ b/xorg-server/Xext/security.c
@@ -0,0 +1,1149 @@
+/*
+
+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.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "scrnintstr.h"
+#include "inputstr.h"
+#include "windowstr.h"
+#include "propertyst.h"
+#include "colormapst.h"
+#include "privates.h"
+#include "registry.h"
+#include "xacestr.h"
+#include "securitysrv.h"
+#include <X11/extensions/securstr.h>
+#ifdef XAPPGROUP
+#include "appgroup.h"
+#endif
+#include "modinit.h"
+
+/* Extension stuff */
+static int SecurityErrorBase; /* first Security error number */
+static int SecurityEventBase; /* first Security event number */
+
+RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */
+static RESTYPE RTEventClient;
+
+static CallbackListPtr SecurityValidateGroupCallback = NULL;
+
+/* Private state record */
+static DevPrivateKey stateKey = &stateKey;
+
+/* This is what we store as client security state */
+typedef struct {
+ int haveState;
+ unsigned int trustLevel;
+ XID authId;
+} SecurityStateRec;
+
+/* Extensions that untrusted clients shouldn't have access to */
+static char *SecurityUntrustedExtensions[] = {
+ "RandR",
+ "SECURITY",
+ "XFree86-DGA",
+ NULL
+};
+
+/*
+ * Access modes that untrusted clients are allowed on trusted objects.
+ */
+static const Mask SecurityResourceMask =
+ DixGetAttrAccess | DixReceiveAccess | DixListPropAccess |
+ DixGetPropAccess | DixListAccess;
+static const Mask SecurityRootWindowExtraMask =
+ DixReceiveAccess | DixSendAccess | DixAddAccess | DixRemoveAccess;
+static const Mask SecurityDeviceMask =
+ DixGetAttrAccess | DixReceiveAccess | DixGetFocusAccess |
+ DixGrabAccess | DixSetAttrAccess | DixUseAccess;
+static const Mask SecurityServerMask = DixGetAttrAccess | DixGrabAccess;
+static const Mask SecurityClientMask = DixGetAttrAccess;
+
+
+/* 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.
+ */
+
+static void
+SecurityAudit(char *format, ...)
+{
+ va_list args;
+
+ if (auditTrailLevel < SECURITY_AUDIT_LEVEL)
+ return;
+ va_start(args, format);
+ VAuditF(format, args);
+ va_end(args);
+} /* SecurityAudit */
+
+/*
+ * Performs a Security permission check.
+ */
+static int
+SecurityDoCheck(SecurityStateRec *subj, SecurityStateRec *obj,
+ Mask requested, Mask allowed)
+{
+ if (!subj->haveState || !obj->haveState)
+ return Success;
+ if (subj->trustLevel == XSecurityClientTrusted)
+ return Success;
+ if (obj->trustLevel != XSecurityClientTrusted)
+ return Success;
+ if ((requested | allowed) == allowed)
+ return Success;
+
+ return BadAccess;
+}
+
+/*
+ * Labels initial server objects.
+ */
+static void
+SecurityLabelInitial(void)
+{
+ SecurityStateRec *state;
+
+ /* Do the serverClient */
+ state = dixLookupPrivate(&serverClient->devPrivates, stateKey);
+ state->trustLevel = XSecurityClientTrusted;
+ state->haveState = TRUE;
+}
+
+/*
+ * Looks up a request name
+ */
+static _X_INLINE const char *
+SecurityLookupRequestName(ClientPtr client)
+{
+ int major = ((xReq *)client->requestBuffer)->reqType;
+ int minor = MinorOpcodeOfRequest(client);
+ return LookupRequestName(major, minor);
+}
+
+
+#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]) {
+ SecurityStateRec *state;
+ state = dixLookupPrivate(&clients[i]->devPrivates, stateKey);
+ if (state->haveState && state->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;
+
+ 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 */
+
+ /* 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;
+
+ REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
+
+ pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(client,
+ stuff->authId, SecurityAuthorizationResType, DixDestroyAccess);
+ 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);
+}
+
+/* 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.
+ */
+
+static void
+SecurityDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceDeviceAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
+ Mask requested = rec->access_mode;
+ Mask allowed = SecurityDeviceMask;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&serverClient->devPrivates, stateKey);
+
+ if (rec->dev != inputInfo.keyboard)
+ /* this extension only supports the core keyboard */
+ allowed = requested;
+
+ if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
+ SecurityAudit("Security denied client %d keyboard access on request "
+ "%s\n", rec->client->index,
+ SecurityLookupRequestName(rec->client));
+ rec->status = BadAccess;
+ }
+}
+
+/* SecurityResource
+ *
+ * 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.
+ * res is a pointer to the resource structure for this resource.
+ *
+ * Returns:
+ * If access is granted, the value of rval that was passed in, else FALSE.
+ *
+ * Side Effects:
+ * Disallowed resource accesses are audited.
+ */
+
+static void
+SecurityResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceResourceAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
+ int cid = CLIENT_ID(rec->id);
+ Mask requested = rec->access_mode;
+ Mask allowed = SecurityResourceMask;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&clients[cid]->devPrivates, stateKey);
+
+ /* disable background None for untrusted windows */
+ if ((requested & DixCreateAccess) && (rec->rtype == RT_WINDOW))
+ if (subj->haveState && subj->trustLevel != XSecurityClientTrusted)
+ ((WindowPtr)rec->res)->forcedBG = TRUE;
+
+ /* special checks for server-owned resources */
+ if (cid == 0) {
+ if (rec->rtype & RC_DRAWABLE)
+ /* additional operations allowed on root windows */
+ allowed |= SecurityRootWindowExtraMask;
+
+ else if (rec->rtype == RT_COLORMAP)
+ /* allow access to default colormaps */
+ allowed = requested;
+
+ else
+ /* allow read access to other server-owned resources */
+ allowed |= DixReadAccess;
+ }
+
+ if (SecurityDoCheck(subj, obj, requested, allowed) == Success)
+ return;
+
+#ifdef XAPPGROUP
+ if (rec->id == XagDefaultColormap(rec->client))
+ return;
+#endif
+
+ SecurityAudit("Security: denied client %d access %x to resource 0x%x "
+ "of client %d on request %s\n", rec->client->index,
+ requested, rec->id, cid,
+ SecurityLookupRequestName(rec->client));
+ rec->status = BadAccess; /* deny access */
+}
+
+
+static void
+SecurityExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceExtAccessRec *rec = calldata;
+ SecurityStateRec *subj;
+ int i = 0;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+
+ if (subj->haveState && subj->trustLevel != XSecurityClientTrusted)
+ while (SecurityUntrustedExtensions[i])
+ if (!strcmp(SecurityUntrustedExtensions[i++], rec->ext->name)) {
+ SecurityAudit("Security: denied client %d access to extension "
+ "%s on request %s\n",
+ rec->client->index, rec->ext->name,
+ SecurityLookupRequestName(rec->client));
+ rec->status = BadAccess;
+ return;
+ }
+}
+
+static void
+SecurityServer(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceServerAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
+ Mask requested = rec->access_mode;
+ Mask allowed = SecurityServerMask;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&serverClient->devPrivates, stateKey);
+
+ if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
+ SecurityAudit("Security: denied client %d access to server "
+ "configuration request %s\n", rec->client->index,
+ SecurityLookupRequestName(rec->client));
+ rec->status = BadAccess;
+ }
+}
+
+static void
+SecurityClient(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceClientAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
+ Mask requested = rec->access_mode;
+ Mask allowed = SecurityClientMask;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&rec->target->devPrivates, stateKey);
+
+ if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
+ SecurityAudit("Security: denied client %d access to client %d on "
+ "request %s\n", rec->client->index, rec->target->index,
+ SecurityLookupRequestName(rec->client));
+ rec->status = BadAccess;
+ }
+}
+
+static void
+SecurityProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XacePropertyAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
+ ATOM name = (*rec->ppProp)->propertyName;
+ Mask requested = rec->access_mode;
+ Mask allowed = SecurityResourceMask | DixReadAccess;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
+
+ if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
+ SecurityAudit("Security: denied client %d access to property %s "
+ "(atom 0x%x) window 0x%x of client %d on request %s\n",
+ rec->client->index, NameForAtom(name), name,
+ rec->pWin->drawable.id, wClient(rec->pWin)->index,
+ SecurityLookupRequestName(rec->client));
+ rec->status = BadAccess;
+ }
+}
+
+static void
+SecuritySend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceSendAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
+
+ if (rec->client) {
+ int i;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
+
+ if (SecurityDoCheck(subj, obj, DixSendAccess, 0) == Success)
+ return;
+
+ for (i = 0; i < rec->count; i++)
+ if (rec->events[i].u.u.type != UnmapNotify &&
+ rec->events[i].u.u.type != ConfigureRequest &&
+ rec->events[i].u.u.type != ClientMessage) {
+
+ SecurityAudit("Security: denied client %d from sending event "
+ "of type %s to window 0x%x of client %d\n",
+ rec->client->index, rec->pWin->drawable.id,
+ wClient(rec->pWin)->index,
+ LookupEventName(rec->events[i].u.u.type));
+ rec->status = BadAccess;
+ return;
+ }
+ }
+}
+
+static void
+SecurityReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceReceiveAccessRec *rec = calldata;
+ SecurityStateRec *subj, *obj;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
+
+ if (SecurityDoCheck(subj, obj, DixReceiveAccess, 0) == Success)
+ return;
+
+ SecurityAudit("Security: denied client %d from receiving an event "
+ "sent to window 0x%x of client %d\n",
+ rec->client->index, rec->pWin->drawable.id,
+ wClient(rec->pWin)->index);
+ rec->status = BadAccess;
+}
+
+/* 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 TRUSTLEVEL(client).
+ *
+ * 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
+SecurityClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ NewClientInfoRec *pci = calldata;
+ SecurityStateRec *state;
+ SecurityAuthorizationPtr pAuth;
+ int rc;
+
+ state = dixLookupPrivate(&pci->client->devPrivates, stateKey);
+
+ switch (pci->client->clientState) {
+ case ClientStateInitial:
+ state->trustLevel = XSecurityClientTrusted;
+ state->authId = None;
+ state->haveState = TRUE;
+ break;
+
+ case ClientStateRunning:
+ state->authId = AuthorizationIDOfClient(pci->client);
+ rc = dixLookupResource((pointer *)&pAuth, state->authId,
+ SecurityAuthorizationResType, serverClient,
+ DixGetAttrAccess);
+ if (rc == Success) {
+ /* it is a generated authorization */
+ pAuth->refcnt++;
+ if (pAuth->refcnt == 1 && pAuth->timer)
+ TimerCancel(pAuth->timer);
+
+ state->trustLevel = pAuth->trustLevel;
+ }
+ break;
+
+ case ClientStateGone:
+ case ClientStateRetained:
+ rc = dixLookupResource((pointer *)&pAuth, state->authId,
+ SecurityAuthorizationResType, serverClient,
+ DixGetAttrAccess);
+ if (rc == Success) {
+ /* it is a generated authorization */
+ pAuth->refcnt--;
+ if (pAuth->refcnt == 0)
+ SecurityStartAuthorizationTimer(pAuth);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* 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)
+{
+ /* Unregister callbacks */
+ DeleteCallback(&ClientStateCallback, SecurityClientState, NULL);
+
+ XaceDeleteCallback(XACE_EXT_DISPATCH, SecurityExtension, NULL);
+ XaceDeleteCallback(XACE_RESOURCE_ACCESS, SecurityResource, NULL);
+ XaceDeleteCallback(XACE_DEVICE_ACCESS, SecurityDevice, NULL);
+ XaceDeleteCallback(XACE_PROPERTY_ACCESS, SecurityProperty, NULL);
+ XaceDeleteCallback(XACE_SEND_ACCESS, SecuritySend, NULL);
+ XaceDeleteCallback(XACE_RECEIVE_ACCESS, SecurityReceive, NULL);
+ XaceDeleteCallback(XACE_CLIENT_ACCESS, SecurityClient, NULL);
+ XaceDeleteCallback(XACE_EXT_ACCESS, SecurityExtension, NULL);
+ XaceDeleteCallback(XACE_SERVER_ACCESS, SecurityServer, NULL);
+}
+
+
+/* SecurityExtensionInit
+ *
+ * Arguments: none.
+ *
+ * Returns: nothing.
+ *
+ * Side Effects:
+ * Enables the Security extension if possible.
+ */
+
+void
+SecurityExtensionInit(INITARGS)
+{
+ ExtensionEntry *extEntry;
+ int ret = TRUE;
+
+ SecurityAuthorizationResType =
+ CreateNewResourceType(SecurityDeleteAuthorization);
+
+ RTEventClient = CreateNewResourceType(
+ SecurityDeleteAuthorizationEventClient);
+
+ if (!SecurityAuthorizationResType || !RTEventClient)
+ return;
+
+ RTEventClient |= RC_NEVERRETAIN;
+ RegisterResourceName(SecurityAuthorizationResType, "SecurityAuthorization");
+ RegisterResourceName(RTEventClient, "SecurityEventClient");
+
+ /* Allocate the private storage */
+ if (!dixRequestPrivate(stateKey, sizeof(SecurityStateRec)))
+ FatalError("SecurityExtensionSetup: Can't allocate client private.\n");
+
+ /* Register callbacks */
+ ret &= AddCallback(&ClientStateCallback, SecurityClientState, NULL);
+
+ ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SecurityExtension, NULL);
+ ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SecurityResource, NULL);
+ ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SecurityDevice, NULL);
+ ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SecurityProperty, NULL);
+ ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SecuritySend, NULL);
+ ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SecurityReceive, NULL);
+ ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SecurityClient, NULL);
+ ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SecurityExtension, NULL);
+ ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SecurityServer, NULL);
+
+ if (!ret)
+ FatalError("SecurityExtensionSetup: Failed to register callbacks\n");
+
+ /* Add extension to server */
+ extEntry = AddExtension(SECURITY_EXTENSION_NAME,
+ XSecurityNumberEvents, XSecurityNumberErrors,
+ ProcSecurityDispatch, SProcSecurityDispatch,
+ SecurityResetProc, StandardMinorOpcode);
+
+ SecurityErrorBase = extEntry->errorBase;
+ SecurityEventBase = extEntry->eventBase;
+
+ EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] =
+ (EventSwapPtr)SwapSecurityAuthorizationRevokedEvent;
+
+ /* Label objects that were created before we could register ourself */
+ SecurityLabelInitial();
+}
diff --git a/xorg-server/Xext/securitysrv.h b/xorg-server/Xext/securitysrv.h
new file mode 100644
index 000000000..f4f3e32ae
--- /dev/null
+++ b/xorg-server/Xext/securitysrv.h
@@ -0,0 +1,83 @@
+/*
+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.
+*/
+
+/* Xserver internals for Security extension - moved here from
+ _SECURITY_SERVER section of <X11/extensions/security.h> */
+
+#ifndef _SECURITY_SRV_H
+#define _SECURITY_SRV_H
+
+/* Allow client side portions of <X11/extensions/security.h> to compile */
+#ifndef Status
+# define Status int
+# define NEED_UNDEF_Status
+#endif
+#ifndef Display
+# define Display void
+# define NEED_UNDEF_Display
+#endif
+
+#include <X11/extensions/security.h>
+
+#ifdef NEED_UNDEF_Status
+# undef Status
+# undef NEED_UNDEF_Status
+#endif
+#ifdef NEED_UNDEF_Display
+# undef Display
+# undef NEED_UNDEF_Display
+#endif
+
+
+#include "input.h" /* for DeviceIntPtr */
+#include "property.h" /* for PropertyPtr */
+#include "pixmap.h" /* for DrawablePtr */
+#include "resource.h" /* for RESTYPE */
+
+/* resource type to pass in LookupIDByType for authorizations */
+extern RESTYPE SecurityAuthorizationResType;
+
+/* this is what we store for an authorization */
+typedef struct {
+ XID id; /* resource ID */
+ CARD32 timeout; /* how long to live in seconds after refcnt == 0 */
+ unsigned int trustLevel; /* trusted/untrusted */
+ XID group; /* see embedding extension */
+ unsigned int refcnt; /* how many clients connected with this auth */
+ unsigned int secondsRemaining; /* overflow time amount for >49 days */
+ OsTimerPtr timer; /* timer for this auth */
+ struct _OtherClients *eventClients; /* clients wanting events */
+} SecurityAuthorizationRec, *SecurityAuthorizationPtr;
+
+typedef struct {
+ XID group; /* the group that was sent in GenerateAuthorization */
+ Bool valid; /* did anyone recognize it? if so, set to TRUE */
+} SecurityValidateGroupInfoRec;
+
+/* Give this value or higher to the -audit option to get security messages */
+#define SECURITY_AUDIT_LEVEL 4
+
+#endif /* _SECURITY_SRV_H */
diff --git a/xorg-server/Xext/shape.c b/xorg-server/Xext/shape.c
new file mode 100644
index 000000000..2f1baf917
--- /dev/null
+++ b/xorg-server/Xext/shape.c
@@ -0,0 +1,1329 @@
+/************************************************************
+
+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.
+
+********************************************************/
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdlib.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"
+#define _SHAPE_SERVER_ /* don't want Xlib structures */
+#include <X11/extensions/shapestr.h>
+#include "regionstr.h"
+#include "gcstruct.h"
+#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
+
+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(void)
+{
+ ExtensionEntry *extEntry;
+
+ ClientType = CreateNewResourceType(ShapeFreeClient);
+ EventType = CreateNewResourceType(ShapeFreeEvents);
+ if (ClientType && EventType &&
+ (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0,
+ ProcShapeDispatch, SProcShapeDispatch,
+ ShapeResetProc, StandardMinorOpcode)))
+ {
+ 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, rc;
+ RegionPtr srcRgn;
+ RegionPtr *destRgn;
+ CreateDftPtr createDefault;
+
+ REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq);
+ UpdateCurrentTime();
+ rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ 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, DixWriteAccess)))
+ 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;
+ int rc;
+
+ REQUEST_SIZE_MATCH (xShapeMaskReq);
+ UpdateCurrentTime();
+ rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ 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 {
+ rc = dixLookupResource((pointer *)&pPixmap, stuff->src, RT_PIXMAP,
+ client, DixReadAccess);
+ if (rc != Success)
+ return (rc == BadValue) ? BadPixmap : rc;
+ 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, DixWriteAccess)))
+ return BadWindow;
+
+ if(stuff->src != None) {
+ if(!(pmap = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->src, XRT_PIXMAP, DixReadAccess)))
+ 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;
+ int rc;
+
+ REQUEST_SIZE_MATCH (xShapeCombineReq);
+ UpdateCurrentTime();
+ rc = dixLookupWindow(&pDestWin, stuff->dest, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ 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;
+
+ rc = dixLookupWindow(&pSrcWin, stuff->src, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ 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, DixWriteAccess)))
+ return BadWindow;
+
+ if(!(win2 = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->src, XRT_WINDOW, DixReadAccess)))
+ 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;
+ int rc;
+
+ REQUEST_SIZE_MATCH (xShapeOffsetReq);
+ UpdateCurrentTime();
+ rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ 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, DixWriteAccess)))
+ 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, rc;
+ RegionPtr region;
+
+ REQUEST_SIZE_MATCH (xShapeQueryExtentsReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ 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;
+ int rc;
+
+ REQUEST_SIZE_MATCH (xShapeSelectInputReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess);
+ if (rc != Success)
+ return rc;
+ pHead = (ShapeEventPtr *)SecurityLookupIDByType(client,
+ pWin->drawable.id, EventType, DixWriteAccess);
+ 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, rc;
+ xShapeInputSelectedReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xShapeInputSelectedReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ pHead = (ShapeEventPtr *) SecurityLookupIDByType(client,
+ pWin->drawable.id, EventType, DixReadAccess);
+ 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, rc;
+ RegionPtr region;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ 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 *) xalloc (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 *) xalloc (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);
+ xfree (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/xorg-server/Xext/shm.c b/xorg-server/Xext/shm.c
new file mode 100644
index 000000000..34c875274
--- /dev/null
+++ b/xorg-server/Xext/shm.c
@@ -0,0 +1,1309 @@
+/************************************************************
+
+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 */
+
+
+#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"
+#include "shmint.h"
+#include "xace.h"
+#define _XSHM_SERVER_
+#include <X11/extensions/shmstr.h>
+#include <X11/Xfuncproto.h>
+
+/* Needed for Solaris cross-zone shared memory extension */
+#ifdef HAVE_SHMCTL64
+#include <sys/ipc_impl.h>
+#define SHMSTAT(id, buf) shmctl64(id, IPC_STAT64, buf)
+#define SHMSTAT_TYPE struct shmid_ds64
+#define SHMPERM_TYPE struct ipc_perm64
+#define SHM_PERM(buf) buf.shmx_perm
+#define SHM_SEGSZ(buf) buf.shmx_segsz
+#define SHMPERM_UID(p) p->ipcx_uid
+#define SHMPERM_CUID(p) p->ipcx_cuid
+#define SHMPERM_GID(p) p->ipcx_gid
+#define SHMPERM_CGID(p) p->ipcx_cgid
+#define SHMPERM_MODE(p) p->ipcx_mode
+#define SHMPERM_ZONEID(p) p->ipcx_zoneid
+#else
+#define SHMSTAT(id, buf) shmctl(id, IPC_STAT, buf)
+#define SHMSTAT_TYPE struct shmid_ds
+#define SHMPERM_TYPE struct ipc_perm
+#define SHM_PERM(buf) buf.shm_perm
+#define SHM_SEGSZ(buf) buf.shm_segsz
+#define SHMPERM_UID(p) p->uid
+#define SHMPERM_CUID(p) p->cuid
+#define SHMPERM_GID(p) p->gid
+#define SHMPERM_CGID(p) p->cgid
+#define SHMPERM_MODE(p) p->mode
+#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 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;
+_X_EXPORT int ShmCompletionCode;
+_X_EXPORT int BadShmSegCode;
+_X_EXPORT RESTYPE ShmSegType;
+static ShmDescPtr Shmsegs;
+static Bool sharedPixmaps;
+static int pixmapFormat;
+static int shmPixFormat[MAXSCREENS];
+static ShmFuncsPtr shmFuncs[MAXSCREENS];
+static DestroyPixmapProcPtr destroyPixmap[MAXSCREENS];
+static DevPrivateKey shmPixmapPrivate = &shmPixmapPrivate;
+static ShmFuncs miFuncs = {NULL, NULL};
+static ShmFuncs fbFuncs = {fbShmCreatePixmap, NULL};
+
+#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__) || defined(__DragonFly__)
+#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;
+ }
+ }
+ 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;
+ shmdesc = (ShmDescPtr)dixLookupPrivate(&pPixmap->devPrivates,
+ shmPixmapPrivate);
+ 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, SHMPERM_TYPE *perm, int readonly)
+{
+ int uid, gid;
+ mode_t mask;
+ int uidset = 0, gidset = 0;
+ LocalClientCredRec *lcc;
+
+ if (GetLocalClientCreds(client, &lcc) != -1) {
+
+ if (lcc->fieldsSet & LCC_UID_SET) {
+ uid = lcc->euid;
+ uidset = 1;
+ }
+ if (lcc->fieldsSet & LCC_GID_SET) {
+ gid = lcc->egid;
+ gidset = 1;
+ }
+
+#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID)
+ if ( ((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1)
+ || (lcc->zoneid != SHMPERM_ZONEID(perm))) {
+ uidset = 0;
+ gidset = 0;
+ }
+#endif
+ FreeLocalClientCreds(lcc);
+
+ if (uidset) {
+ /* User id 0 always gets access */
+ if (uid == 0) {
+ return 0;
+ }
+ /* Check the owner */
+ if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) {
+ mask = S_IRUSR;
+ if (!readonly) {
+ mask |= S_IWUSR;
+ }
+ return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
+ }
+ }
+
+ if (gidset) {
+ /* Check the group */
+ if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) {
+ mask = S_IRGRP;
+ if (!readonly) {
+ mask |= S_IWGRP;
+ }
+ return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
+ }
+ }
+ }
+ /* Otherwise, check everyone else */
+ mask = S_IROTH;
+ if (!readonly) {
+ mask |= S_IWOTH;
+ }
+ return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
+}
+
+static int
+ProcShmAttach(client)
+ register ClientPtr client;
+{
+ SHMSTAT_TYPE 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)) ||
+ SHMSTAT(stuff->shmid, &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, &(SHM_PERM(buf)), stuff->readOnly) == -1) {
+ shmdt(shmdesc->addr);
+ xfree(shmdesc);
+ return BadAccess;
+ }
+
+ shmdesc->shmid = stuff->shmid;
+ shmdesc->refcnt = 1;
+ shmdesc->writable = !stuff->readOnly;
+ shmdesc->size = SHM_SEGSZ(buf);
+ 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);
+}
+
+/*
+ * If the given request doesn't exactly match PutImage's constraints,
+ * wrap the image in a scratch pixmap header and let CopyArea sort it out.
+ */
+static void
+doShmPutImage(DrawablePtr dst, GCPtr pGC,
+ int depth, unsigned int format,
+ int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
+ char *data)
+{
+ PixmapPtr pPixmap;
+
+ pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth,
+ BitsPerPixel(depth),
+ PixmapBytePad(w, depth),
+ data);
+ if (!pPixmap)
+ return;
+ pGC->ops->CopyArea((DrawablePtr)pPixmap, dst, pGC, sx, sy, sw, sh, dx, dy);
+ FreeScratchPixmapHeader(pPixmap);
+}
+
+#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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ 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, rc;
+ 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, DixWriteAccess)))
+ return BadDrawable;
+
+ if (draw->type == XRT_PIXMAP)
+ return ProcShmGetImage(client);
+
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
+ DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ 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++) {
+ rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0,
+ DixReadAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+ 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, rc;
+ 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);
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ 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) {
+ dixSetPrivate(&pMap->devPrivates, shmPixmapPrivate, shmdesc);
+ 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;
+{
+ GCPtr pGC;
+ DrawablePtr pDraw;
+ long length;
+ ShmDescPtr shmdesc;
+ REQUEST(xShmPutImageReq);
+
+ REQUEST_SIZE_MATCH(xShmPutImageReq);
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+ 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
+ doShmPutImage(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;
+{
+ DrawablePtr pDraw;
+ long lenPer = 0, length;
+ Mask plane = 0;
+ xShmGetImageReply xgi;
+ ShmDescPtr shmdesc;
+ int n, rc;
+
+ REQUEST(xShmGetImageReq);
+
+ REQUEST_SIZE_MATCH(xShmGetImageReq);
+ if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap))
+ {
+ client->errorValue = stuff->format;
+ return(BadValue);
+ }
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
+ DixReadAccess);
+ if (rc != Success)
+ return rc;
+ 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, 0);
+ 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;
+ DrawablePtr pDraw;
+ DepthPtr pDepth;
+ register int i, rc;
+ 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);
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ 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)
+ {
+ rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
+ pMap, RT_NONE, NULL, DixCreateAccess);
+ if (rc != Success) {
+ pDraw->pScreen->DestroyPixmap(pMap);
+ return rc;
+ }
+ dixSetPrivate(&pMap->devPrivates, shmPixmapPrivate, shmdesc);
+ shmdesc->refcnt++;
+ pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ pMap->drawable.id = stuff->pid;
+ if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap))
+ {
+ return(client->noClientException);
+ }
+ pDraw->pScreen->DestroyPixmap(pMap);
+ }
+ 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/xorg-server/Xext/shmint.h b/xorg-server/Xext/shmint.h
new file mode 100644
index 000000000..fc056bc72
--- /dev/null
+++ b/xorg-server/Xext/shmint.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2003 Keith Packard
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SHMINT_H_
+#define _SHMINT_H_
+
+#define _XSHM_SERVER_
+#include <X11/extensions/shmstr.h>
+
+#include "screenint.h"
+#include "pixmap.h"
+#include "gc.h"
+
+void
+ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
+
+void
+ShmSetPixmapFormat(ScreenPtr pScreen, int format);
+
+void
+ShmRegisterFbFuncs(ScreenPtr pScreen);
+
+#endif /* _SHMINT_H_ */
diff --git a/xorg-server/Xext/sleepuntil.c b/xorg-server/Xext/sleepuntil.c
new file mode 100644
index 000000000..f8cedbe6e
--- /dev/null
+++ b/xorg-server/Xext/sleepuntil.c
@@ -0,0 +1,237 @@
+/*
+ *
+Copyright 1992, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ *
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+/* dixsleep.c - implement millisecond timeouts for X clients */
+
+#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 */
+);
+
+_X_EXPORT 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/xorg-server/Xext/sleepuntil.h b/xorg-server/Xext/sleepuntil.h
new file mode 100644
index 000000000..a3618d99c
--- /dev/null
+++ b/xorg-server/Xext/sleepuntil.h
@@ -0,0 +1,46 @@
+/*
+ * 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/xorg-server/Xext/sync.c b/xorg-server/Xext/sync.c
new file mode 100644
index 000000000..10d448106
--- /dev/null
+++ b/xorg-server/Xext/sync.c
@@ -0,0 +1,2642 @@
+/*
+
+Copyright 1991, 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+
+Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
+and Olivetti Research Limited, Cambridge, England.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Digital or Olivetti
+not be used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission. Digital and Olivetti
+make no representations about the suitability of this software
+for any purpose. It is provided "as is" without express or implied warranty.
+
+DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#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>
+
+#include <stdio.h>
+#if !defined(WIN32) && !defined(Lynx)
+#include <sys/time.h>
+#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
+SyncInitIdleTime(
+ 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;
+ SyncTriggerList *pPrev;
+
+ /* pCounter needs to be stored in pTrigger before calling here. */
+
+ if (!pTrigger->pCounter)
+ return;
+
+ pPrev = NULL;
+ pCur = pTrigger->pCounter->pTriglist;
+
+ while (pCur)
+ {
+ if (pCur->pTrigger == pTrigger)
+ {
+ if (pPrev)
+ pPrev->next = pCur->next;
+ else
+ pTrigger->pCounter->pTriglist = pCur->next;
+
+ xfree(pCur);
+ break;
+ }
+
+ pPrev = pCur;
+ pCur = pCur->next;
+ }
+
+ 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 rc;
+ Bool newcounter = FALSE;
+
+ if (changes & XSyncCACounter)
+ {
+ if (counter == None)
+ pCounter = NULL;
+ else if (Success != (rc = dixLookupResource((pointer *)&pCounter,
+ counter, RTCounter, client, DixReadAccess)))
+ {
+ client->errorValue = counter;
+ return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc;
+ }
+ 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 ((rc = SyncAddTriggerToCounter(pTrigger)) != Success)
+ return rc;
+ }
+ 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 *)
+ xalloc(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);
+ xfree(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 **)xalloc(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);
+ xfree(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;
+ CARD64 *pnewgtval = NULL;
+ CARD64 *pnewltval = NULL;
+ SyncCounterType ct;
+
+ if (!pCounter)
+ return;
+
+ psci = pCounter->pSysCounterInfo;
+ 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 *) xalloc(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);
+ xfree(list);
+ }
+
+ return (client->noClientException);
+}
+
+/*
+ * ** Set client Priority
+ */
+static int
+ProcSyncSetPriority(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncSetPriorityReq);
+ ClientPtr priorityclient;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
+
+ if (stuff->id == None)
+ priorityclient = client;
+ else {
+ rc = dixLookupClient(&priorityclient, stuff->id, client,
+ DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+ 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;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
+
+ if (stuff->id == None)
+ priorityclient = client;
+ else {
+ rc = dixLookupClient(&priorityclient, stuff->id, client,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+ 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, DixWriteAccess);
+ 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, DixWriteAccess);
+ 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, DixDestroyAccess);
+ 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, DixReadAccess);
+ 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, DixWriteAccess)))
+ {
+ 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, DixReadAccess);
+ 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, DixDestroyAccess)))
+ {
+ 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();
+ SyncInitIdleTime();
+
+#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(void)
+{
+ CARD64 resolution;
+
+ XSyncIntsToValue(&Now, GetTimeInMillis(), 0);
+ XSyncIntToValue(&resolution, 4);
+ ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
+ XSyncCounterNeverDecreases,
+ ServertimeQueryValue, ServertimeBracketValues);
+ pnext_time = NULL;
+}
+
+
+
+/*
+ * IDLETIME implementation
+ */
+
+static pointer IdleTimeCounter;
+static XSyncValue *pIdleTimeValueLess;
+static XSyncValue *pIdleTimeValueGreater;
+
+static void
+IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return)
+{
+ CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds;
+ XSyncIntsToValue (pValue_return, idle, 0);
+}
+
+static void
+IdleTimeBlockHandler (pointer env,
+ struct timeval **wt,
+ pointer LastSelectMask)
+{
+ XSyncValue idle;
+
+ if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
+ return;
+
+ IdleTimeQueryValue (NULL, &idle);
+
+ if (pIdleTimeValueLess &&
+ XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))
+ {
+ AdjustWaitForDelay (wt, 0);
+ }
+ else if (pIdleTimeValueGreater)
+ {
+ unsigned long timeout = 0;
+
+ if (XSyncValueLessThan (idle, *pIdleTimeValueGreater))
+ {
+ XSyncValue value;
+ Bool overflow;
+
+ XSyncValueSubtract (&value, *pIdleTimeValueGreater,
+ idle, &overflow);
+ timeout = XSyncValueLow32 (value);
+ }
+
+ AdjustWaitForDelay (wt, timeout);
+ }
+}
+
+static void
+IdleTimeWakeupHandler (pointer env,
+ int rc,
+ pointer LastSelectMask)
+{
+ XSyncValue idle;
+
+ if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
+ return;
+
+ IdleTimeQueryValue (NULL, &idle);
+
+ if ((pIdleTimeValueGreater &&
+ XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) ||
+ (pIdleTimeValueLess &&
+ XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)))
+ {
+ SyncChangeCounter (IdleTimeCounter, idle);
+ }
+}
+
+static void
+IdleTimeBracketValues (pointer pCounter,
+ CARD64 *pbracket_less,
+ CARD64 *pbracket_greater)
+{
+ Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater);
+
+ if (registered && !pbracket_less && !pbracket_greater)
+ {
+ RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler,
+ IdleTimeWakeupHandler,
+ NULL);
+ }
+ else if (!registered && (pbracket_less || pbracket_greater))
+ {
+ RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler,
+ IdleTimeWakeupHandler,
+ NULL);
+ }
+
+ pIdleTimeValueGreater = pbracket_greater;
+ pIdleTimeValueLess = pbracket_less;
+}
+
+static void
+SyncInitIdleTime (void)
+{
+ CARD64 resolution;
+ XSyncValue idle;
+
+ IdleTimeQueryValue (NULL, &idle);
+ XSyncIntToValue (&resolution, 4);
+
+ IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution,
+ XSyncCounterUnrestricted,
+ IdleTimeQueryValue,
+ IdleTimeBracketValues);
+
+ pIdleTimeValueLess = pIdleTimeValueGreater = NULL;
+}
diff --git a/xorg-server/Xext/xace.c b/xorg-server/Xext/xace.c
new file mode 100644
index 000000000..8a8f8c61d
--- /dev/null
+++ b/xorg-server/Xext/xace.c
@@ -0,0 +1,341 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@epoch.ncsc.mil>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+this permission notice appear in supporting documentation. 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
+AUTHOR 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.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdarg.h>
+#include "scrnintstr.h"
+#include "extnsionst.h"
+#include "pixmapstr.h"
+#include "regionstr.h"
+#include "gcstruct.h"
+#include "xacestr.h"
+
+CallbackListPtr XaceHooks[XACE_NUM_HOOKS] = {0};
+
+/* Special-cased hook functions. Called by Xserver.
+ */
+int XaceHookDispatch(ClientPtr client, int major)
+{
+ /* Call the audit begin callback, there is no return value. */
+ XaceAuditRec rec = { client, 0 };
+ CallCallbacks(&XaceHooks[XACE_AUDIT_BEGIN], &rec);
+
+ if (major < 128) {
+ /* Call the core dispatch hook */
+ XaceCoreDispatchRec rec = { client, Success /* default allow */ };
+ CallCallbacks(&XaceHooks[XACE_CORE_DISPATCH], &rec);
+ return rec.status;
+ } else {
+ /* Call the extension dispatch hook */
+ ExtensionEntry *ext = GetExtensionEntry(major);
+ XaceExtAccessRec rec = { client, ext, DixUseAccess, Success };
+ if (ext)
+ CallCallbacks(&XaceHooks[XACE_EXT_DISPATCH], &rec);
+ /* On error, pretend extension doesn't exist */
+ return (rec.status == Success) ? Success : BadRequest;
+ }
+}
+
+int XaceHookPropertyAccess(ClientPtr client, WindowPtr pWin,
+ PropertyPtr *ppProp, Mask access_mode)
+{
+ XacePropertyAccessRec rec = { client, pWin, ppProp, access_mode, Success };
+ CallCallbacks(&XaceHooks[XACE_PROPERTY_ACCESS], &rec);
+ return rec.status;
+}
+
+int XaceHookSelectionAccess(ClientPtr client,
+ Selection **ppSel, Mask access_mode)
+{
+ XaceSelectionAccessRec rec = { client, ppSel, access_mode, Success };
+ CallCallbacks(&XaceHooks[XACE_SELECTION_ACCESS], &rec);
+ return rec.status;
+}
+
+void XaceHookAuditEnd(ClientPtr ptr, int result)
+{
+ XaceAuditRec rec = { ptr, result };
+ /* call callbacks, there is no return value. */
+ CallCallbacks(&XaceHooks[XACE_AUDIT_END], &rec);
+}
+
+/* Entry point for hook functions. Called by Xserver.
+ */
+int XaceHook(int hook, ...)
+{
+ pointer calldata; /* data passed to callback */
+ int *prv = NULL; /* points to return value from callback */
+ va_list ap; /* argument list */
+ va_start(ap, hook);
+
+ /* Marshal arguments for passing to callback.
+ * Each callback has its own case, which sets up a structure to hold
+ * the arguments and integer return parameter, or in some cases just
+ * sets calldata directly to a single argument (with no return result)
+ */
+ switch (hook)
+ {
+ case XACE_RESOURCE_ACCESS: {
+ XaceResourceAccessRec rec = {
+ va_arg(ap, ClientPtr),
+ va_arg(ap, XID),
+ va_arg(ap, RESTYPE),
+ va_arg(ap, pointer),
+ va_arg(ap, RESTYPE),
+ va_arg(ap, pointer),
+ va_arg(ap, Mask),
+ Success /* default allow */
+ };
+ calldata = &rec;
+ prv = &rec.status;
+ break;
+ }
+ case XACE_DEVICE_ACCESS: {
+ XaceDeviceAccessRec rec = {
+ va_arg(ap, ClientPtr),
+ va_arg(ap, DeviceIntPtr),
+ va_arg(ap, Mask),
+ Success /* default allow */
+ };
+ calldata = &rec;
+ prv = &rec.status;
+ break;
+ }
+ case XACE_SEND_ACCESS: {
+ XaceSendAccessRec rec = {
+ va_arg(ap, ClientPtr),
+ va_arg(ap, DeviceIntPtr),
+ va_arg(ap, WindowPtr),
+ va_arg(ap, xEventPtr),
+ va_arg(ap, int),
+ Success /* default allow */
+ };
+ calldata = &rec;
+ prv = &rec.status;
+ break;
+ }
+ case XACE_RECEIVE_ACCESS: {
+ XaceReceiveAccessRec rec = {
+ va_arg(ap, ClientPtr),
+ va_arg(ap, WindowPtr),
+ va_arg(ap, xEventPtr),
+ va_arg(ap, int),
+ Success /* default allow */
+ };
+ calldata = &rec;
+ prv = &rec.status;
+ break;
+ }
+ case XACE_CLIENT_ACCESS: {
+ XaceClientAccessRec rec = {
+ va_arg(ap, ClientPtr),
+ va_arg(ap, ClientPtr),
+ va_arg(ap, Mask),
+ Success /* default allow */
+ };
+ calldata = &rec;
+ prv = &rec.status;
+ break;
+ }
+ case XACE_EXT_ACCESS: {
+ XaceExtAccessRec rec = {
+ va_arg(ap, ClientPtr),
+ va_arg(ap, ExtensionEntry*),
+ DixGetAttrAccess,
+ Success /* default allow */
+ };
+ calldata = &rec;
+ prv = &rec.status;
+ break;
+ }
+ case XACE_SERVER_ACCESS: {
+ XaceServerAccessRec rec = {
+ va_arg(ap, ClientPtr),
+ va_arg(ap, Mask),
+ Success /* default allow */
+ };
+ calldata = &rec;
+ prv = &rec.status;
+ break;
+ }
+ case XACE_SCREEN_ACCESS:
+ case XACE_SCREENSAVER_ACCESS: {
+ XaceScreenAccessRec rec = {
+ va_arg(ap, ClientPtr),
+ va_arg(ap, ScreenPtr),
+ va_arg(ap, Mask),
+ Success /* default allow */
+ };
+ calldata = &rec;
+ prv = &rec.status;
+ break;
+ }
+ case XACE_AUTH_AVAIL: {
+ XaceAuthAvailRec rec = {
+ va_arg(ap, ClientPtr),
+ va_arg(ap, XID)
+ };
+ calldata = &rec;
+ break;
+ }
+ case XACE_KEY_AVAIL: {
+ XaceKeyAvailRec rec = {
+ va_arg(ap, xEventPtr),
+ va_arg(ap, DeviceIntPtr),
+ va_arg(ap, int)
+ };
+ calldata = &rec;
+ break;
+ }
+ default: {
+ va_end(ap);
+ return 0; /* unimplemented hook number */
+ }
+ }
+ va_end(ap);
+
+ /* call callbacks and return result, if any. */
+ CallCallbacks(&XaceHooks[hook], calldata);
+ return prv ? *prv : Success;
+}
+
+/* XaceCensorImage
+ *
+ * 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
+XaceCensorImage(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;
+ RegionRec imageRegion; /* region representing x,y,w,h */
+ RegionRec censorRegion; /* region to obliterate */
+ BoxRec imageBox;
+ int nRects;
+
+ pScreen = pDraw->pScreen;
+
+ 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 *)xalloc(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) xfree(pRects);
+ if (pScratchGC) FreeScratchGC(pScratchGC);
+ if (pPix) FreeScratchPixmapHeader(pPix);
+ }
+ REGION_UNINIT(pScreen, &imageRegion);
+ REGION_UNINIT(pScreen, &censorRegion);
+} /* XaceCensorImage */
diff --git a/xorg-server/Xext/xace.h b/xorg-server/Xext/xace.h
new file mode 100644
index 000000000..bd69bca98
--- /dev/null
+++ b/xorg-server/Xext/xace.h
@@ -0,0 +1,126 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@epoch.ncsc.mil>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+this permission notice appear in supporting documentation. 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
+AUTHOR 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.
+
+********************************************************/
+
+#ifndef _XACE_H
+#define _XACE_H
+
+#ifdef XACE
+
+#define XACE_MAJOR_VERSION 2
+#define XACE_MINOR_VERSION 0
+
+#include "pixmap.h"
+#include "region.h"
+#include "window.h"
+#include "property.h"
+#include "selection.h"
+
+/* Default window background */
+#define XaceBackgroundNoneState(w) ((w)->forcedBG ? BackgroundPixel : None)
+
+/* security hooks */
+/* Constants used to identify the available security hooks
+ */
+#define XACE_CORE_DISPATCH 0
+#define XACE_EXT_DISPATCH 1
+#define XACE_RESOURCE_ACCESS 2
+#define XACE_DEVICE_ACCESS 3
+#define XACE_PROPERTY_ACCESS 4
+#define XACE_SEND_ACCESS 5
+#define XACE_RECEIVE_ACCESS 6
+#define XACE_CLIENT_ACCESS 7
+#define XACE_EXT_ACCESS 8
+#define XACE_SERVER_ACCESS 9
+#define XACE_SELECTION_ACCESS 10
+#define XACE_SCREEN_ACCESS 11
+#define XACE_SCREENSAVER_ACCESS 12
+#define XACE_AUTH_AVAIL 13
+#define XACE_KEY_AVAIL 14
+#define XACE_AUDIT_BEGIN 15
+#define XACE_AUDIT_END 16
+#define XACE_NUM_HOOKS 17
+
+extern CallbackListPtr XaceHooks[XACE_NUM_HOOKS];
+
+/* Entry point for hook functions. Called by Xserver.
+ */
+extern int XaceHook(
+ int /*hook*/,
+ ... /*appropriate args for hook*/
+ );
+
+/* Special-cased hook functions
+ */
+extern int XaceHookDispatch(ClientPtr ptr, int major);
+extern int XaceHookPropertyAccess(ClientPtr ptr, WindowPtr pWin,
+ PropertyPtr *ppProp, Mask access_mode);
+extern int XaceHookSelectionAccess(ClientPtr ptr,
+ Selection **ppSel, Mask access_mode);
+extern void XaceHookAuditEnd(ClientPtr ptr, int result);
+
+/* Register a callback for a given hook.
+ */
+#define XaceRegisterCallback(hook,callback,data) \
+ AddCallback(XaceHooks+(hook), callback, data)
+
+/* Unregister an existing callback for a given hook.
+ */
+#define XaceDeleteCallback(hook,callback,data) \
+ DeleteCallback(XaceHooks+(hook), callback, data)
+
+
+/* From the original Security extension...
+ */
+
+extern void XaceCensorImage(
+ ClientPtr client,
+ RegionPtr pVisibleRegion,
+ long widthBytesLine,
+ DrawablePtr pDraw,
+ int x, int y, int w, int h,
+ unsigned int format,
+ char * pBuf
+ );
+
+#else /* XACE */
+
+/* Default window background */
+#define XaceBackgroundNoneState(w) None
+
+/* Define calls away when XACE is not being built. */
+
+#ifdef __GNUC__
+#define XaceHook(args...) Success
+#define XaceHookDispatch(args...) Success
+#define XaceHookPropertyAccess(args...) Success
+#define XaceHookSelectionAccess(args...) Success
+#define XaceHookAuditEnd(args...) { ; }
+#define XaceCensorImage(args...) { ; }
+#else
+#define XaceHook(...) Success
+#define XaceHookDispatch(...) Success
+#define XaceHookPropertyAccess(...) Success
+#define XaceHookSelectionAccess(...) Success
+#define XaceHookAuditEnd(...) { ; }
+#define XaceCensorImage(...) { ; }
+#endif
+
+#endif /* XACE */
+
+#endif /* _XACE_H */
diff --git a/xorg-server/Xext/xacestr.h b/xorg-server/Xext/xacestr.h
new file mode 100644
index 000000000..ba115a427
--- /dev/null
+++ b/xorg-server/Xext/xacestr.h
@@ -0,0 +1,147 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@epoch.ncsc.mil>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+this permission notice appear in supporting documentation. 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
+AUTHOR 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.
+
+********************************************************/
+
+#ifndef _XACESTR_H
+#define _XACESTR_H
+
+#include "dix.h"
+#include "resource.h"
+#include "extnsionst.h"
+#include "window.h"
+#include "input.h"
+#include "property.h"
+#include "selection.h"
+#include "xace.h"
+
+/* XACE_CORE_DISPATCH */
+typedef struct {
+ ClientPtr client;
+ int status;
+} XaceCoreDispatchRec;
+
+/* XACE_RESOURCE_ACCESS */
+typedef struct {
+ ClientPtr client;
+ XID id;
+ RESTYPE rtype;
+ pointer res;
+ RESTYPE ptype;
+ pointer parent;
+ Mask access_mode;
+ int status;
+} XaceResourceAccessRec;
+
+/* XACE_DEVICE_ACCESS */
+typedef struct {
+ ClientPtr client;
+ DeviceIntPtr dev;
+ Mask access_mode;
+ int status;
+} XaceDeviceAccessRec;
+
+/* XACE_PROPERTY_ACCESS */
+typedef struct {
+ ClientPtr client;
+ WindowPtr pWin;
+ PropertyPtr *ppProp;
+ Mask access_mode;
+ int status;
+} XacePropertyAccessRec;
+
+/* XACE_SEND_ACCESS */
+typedef struct {
+ ClientPtr client;
+ DeviceIntPtr dev;
+ WindowPtr pWin;
+ xEventPtr events;
+ int count;
+ int status;
+} XaceSendAccessRec;
+
+/* XACE_RECEIVE_ACCESS */
+typedef struct {
+ ClientPtr client;
+ WindowPtr pWin;
+ xEventPtr events;
+ int count;
+ int status;
+} XaceReceiveAccessRec;
+
+/* XACE_CLIENT_ACCESS */
+typedef struct {
+ ClientPtr client;
+ ClientPtr target;
+ Mask access_mode;
+ int status;
+} XaceClientAccessRec;
+
+/* XACE_EXT_DISPATCH */
+/* XACE_EXT_ACCESS */
+typedef struct {
+ ClientPtr client;
+ ExtensionEntry *ext;
+ Mask access_mode;
+ int status;
+} XaceExtAccessRec;
+
+/* XACE_SERVER_ACCESS */
+typedef struct {
+ ClientPtr client;
+ Mask access_mode;
+ int status;
+} XaceServerAccessRec;
+
+/* XACE_SELECTION_ACCESS */
+typedef struct {
+ ClientPtr client;
+ Selection **ppSel;
+ Mask access_mode;
+ int status;
+} XaceSelectionAccessRec;
+
+/* XACE_SCREEN_ACCESS */
+/* XACE_SCREENSAVER_ACCESS */
+typedef struct {
+ ClientPtr client;
+ ScreenPtr screen;
+ Mask access_mode;
+ int status;
+} XaceScreenAccessRec;
+
+/* XACE_AUTH_AVAIL */
+typedef struct {
+ ClientPtr client;
+ XID authId;
+} XaceAuthAvailRec;
+
+/* XACE_KEY_AVAIL */
+typedef struct {
+ xEventPtr event;
+ DeviceIntPtr keybd;
+ int count;
+} XaceKeyAvailRec;
+
+/* XACE_AUDIT_BEGIN */
+/* XACE_AUDIT_END */
+typedef struct {
+ ClientPtr client;
+ int requestResult;
+} XaceAuditRec;
+
+#endif /* _XACESTR_H */
diff --git a/xorg-server/Xext/xcalibrate.c b/xorg-server/Xext/xcalibrate.c
new file mode 100644
index 000000000..3fe2bdc5c
--- /dev/null
+++ b/xorg-server/Xext/xcalibrate.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright © 2003 Philip Blundell
+ *
+ * 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 Philip Blundell not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Philip Blundell makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * PHILIP BLUNDELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL PHILIP BLUNDELL 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_KDRIVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+
+#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/xcalibrateproto.h>
+#include <X11/extensions/xcalibratewire.h>
+
+extern void (*tslib_raw_event_hook)(int x, int y, int pressure, void *closure);
+extern void *tslib_raw_event_closure;
+
+static CARD8 XCalibrateReqCode;
+int XCalibrateEventBase;
+int XCalibrateReqBase;
+int XCalibrateErrorBase;
+
+static ClientPtr xcalibrate_client;
+
+static void
+xcalibrate_event_hook (int x, int y, int pressure, void *closure)
+{
+ ClientPtr pClient = (ClientPtr) closure;
+ xXCalibrateRawTouchscreenEvent ev;
+
+ ev.type = XCalibrateEventBase + X_XCalibrateRawTouchscreen;
+ ev.sequenceNumber = pClient->sequence;
+ ev.x = x;
+ ev.y = y;
+ ev.pressure = pressure;
+
+ if (!pClient->clientGone)
+ WriteEventsToClient (pClient, 1, (xEvent *) &ev);
+}
+
+static int
+ProcXCalibrateQueryVersion (ClientPtr client)
+{
+ REQUEST(xXCalibrateQueryVersionReq);
+ xXCalibrateQueryVersionReply rep;
+ CARD16 client_major, client_minor; /* not used */
+
+ REQUEST_SIZE_MATCH (xXCalibrateQueryVersionReq);
+
+ client_major = stuff->majorVersion;
+ client_minor = stuff->minorVersion;
+
+ fprintf(stderr, "%s(): called\n", __func__);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = XCALIBRATE_MAJOR_VERSION;
+ rep.minorVersion = XCALIBRATE_MINOR_VERSION;
+ if (client->swapped) {
+ int n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof (xXCalibrateQueryVersionReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static int
+SProcXCalibrateQueryVersion (ClientPtr client)
+{
+ REQUEST(xXCalibrateQueryVersionReq);
+ int n;
+
+ REQUEST_SIZE_MATCH (xXCalibrateQueryVersionReq);
+ swaps(&stuff->majorVersion,n);
+ swaps(&stuff->minorVersion,n);
+ return ProcXCalibrateQueryVersion(client);
+}
+
+static int
+ProcXCalibrateSetRawMode (ClientPtr client)
+{
+ REQUEST(xXCalibrateRawModeReq);
+ xXCalibrateRawModeReply rep;
+
+ REQUEST_SIZE_MATCH (xXCalibrateRawModeReq);
+
+ memset (&rep, 0, sizeof (rep));
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+
+ if (stuff->on)
+ {
+ if (xcalibrate_client == NULL)
+ {
+ /* Start calibrating. */
+ xcalibrate_client = client;
+ tslib_raw_event_hook = xcalibrate_event_hook;
+ tslib_raw_event_closure = client;
+ rep.status = GrabSuccess;
+ }
+ else
+ {
+ rep.status = AlreadyGrabbed;
+ }
+ }
+ else
+ {
+ if (xcalibrate_client == client)
+ {
+ /* Stop calibrating. */
+ xcalibrate_client = NULL;
+ tslib_raw_event_hook = NULL;
+ tslib_raw_event_closure = NULL;
+ rep.status = GrabSuccess;
+
+ /* Cycle input off and on to reload configuration. */
+ KdDisableInput ();
+ KdEnableInput ();
+ }
+ else
+ {
+ rep.status = AlreadyGrabbed;
+ }
+ }
+
+ if (client->swapped)
+ {
+ int n;
+
+ swaps (&rep.sequenceNumber, n);
+ swaps (&rep.status, n);
+ }
+ WriteToClient(client, sizeof (rep), (char *) &rep);
+ return (client->noClientException);
+}
+
+static int
+SProcXCalibrateSetRawMode (ClientPtr client)
+{
+ REQUEST(xXCalibrateRawModeReq);
+ int n;
+
+ REQUEST_SIZE_MATCH (xXCalibrateRawModeReq);
+
+ swaps(&stuff->on, n);
+
+ return ProcXCalibrateSetRawMode(client);
+}
+
+static int
+ProcXCalibrateScreenToCoord (ClientPtr client)
+{
+ REQUEST(xXCalibrateScreenToCoordReq);
+ xXCalibrateScreenToCoordReply rep;
+
+ REQUEST_SIZE_MATCH (xXCalibrateScreenToCoordReq);
+
+ memset (&rep, 0, sizeof (rep));
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.x = stuff->x;
+ rep.y = stuff->y;
+
+ KdScreenToPointerCoords(&rep.x, &rep.y);
+
+ if (client->swapped)
+ {
+ int n;
+
+ swaps (&rep.x, n);
+ swaps (&rep.y, n);
+ }
+ WriteToClient(client, sizeof (rep), (char *) &rep);
+ return (client->noClientException);
+}
+
+static int
+SProcXCalibrateScreenToCoord (ClientPtr client)
+{
+ REQUEST(xXCalibrateScreenToCoordReq);
+ int n;
+
+ REQUEST_SIZE_MATCH (xXCalibrateScreenToCoordReq);
+
+ swaps(&stuff->x, n);
+ swaps(&stuff->y, n);
+
+ return ProcXCalibrateScreenToCoord(client);
+}
+
+static void
+XCalibrateResetProc (ExtensionEntry *extEntry)
+{
+}
+
+static int
+ProcXCalibrateDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+ switch (stuff->data) {
+ case X_XCalibrateQueryVersion:
+ return ProcXCalibrateQueryVersion(client);
+ case X_XCalibrateRawMode:
+ return ProcXCalibrateSetRawMode(client);
+ case X_XCalibrateScreenToCoord:
+ return ProcXCalibrateScreenToCoord(client);
+
+ default: break;
+ }
+
+ return BadRequest;
+}
+
+static int
+SProcXCalibrateDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+ int n;
+
+ swaps(&stuff->length,n);
+
+ switch (stuff->data) {
+ case X_XCalibrateQueryVersion:
+ return SProcXCalibrateQueryVersion(client);
+ case X_XCalibrateRawMode:
+ return SProcXCalibrateSetRawMode(client);
+ case X_XCalibrateScreenToCoord:
+ return SProcXCalibrateScreenToCoord(client);
+
+ default: break;
+ }
+
+ return BadRequest;
+}
+
+static void
+XCalibrateClientCallback (CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
+ ClientPtr pClient = clientinfo->client;
+
+ if (clientinfo->setup == NULL
+ && xcalibrate_client != NULL
+ && xcalibrate_client == pClient)
+ {
+ /* Stop calibrating. */
+ xcalibrate_client = NULL;
+ tslib_raw_event_hook = NULL;
+ tslib_raw_event_closure = NULL;
+ }
+}
+
+void
+XCalibrateExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+
+ if (!AddCallback (&ClientStateCallback, XCalibrateClientCallback, 0))
+ return;
+
+ extEntry = AddExtension(XCALIBRATE_NAME, XCalibrateNumberEvents, XCalibrateNumberErrors,
+ ProcXCalibrateDispatch, SProcXCalibrateDispatch,
+ XCalibrateResetProc, StandardMinorOpcode);
+
+ if (!extEntry)
+ return;
+
+ XCalibrateReqCode = (unsigned char)extEntry->base;
+ XCalibrateEventBase = extEntry->eventBase;
+ XCalibrateErrorBase = extEntry->errorBase;
+
+ xcalibrate_client = 0;
+}
diff --git a/xorg-server/Xext/xcmisc.c b/xorg-server/Xext/xcmisc.c
new file mode 100644
index 000000000..a42d2e210
--- /dev/null
+++ b/xorg-server/Xext/xcmisc.c
@@ -0,0 +1,236 @@
+/*
+
+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.
+
+*/
+
+#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
+
+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)
+{
+ AddExtension(XCMiscExtensionName, 0, 0,
+ ProcXCMiscDispatch, SProcXCMiscDispatch,
+ XCMiscResetProc, StandardMinorOpcode);
+}
+
+/*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/xorg-server/Xext/xevie.c b/xorg-server/Xext/xevie.c
new file mode 100644
index 000000000..1d51fd825
--- /dev/null
+++ b/xorg-server/Xext/xevie.c
@@ -0,0 +1,744 @@
+/************************************************************
+
+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.
+
+************************************************************/
+
+#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 <xkbsrv.h>
+
+#include "../os/osdep.h"
+
+#define NoSuchEvent 0x80000000
+
+#ifdef XKB
+extern Bool noXkbExtension;
+#endif
+extern int xeviegrabState;
+
+static DISPATCH_PROC(ProcXevieDispatch);
+static DISPATCH_PROC(SProcXevieDispatch);
+
+static void XevieResetProc (ExtensionEntry *extEntry);
+
+static unsigned char XevieReqCode = 0;
+static int XevieErrorBase;
+
+int xevieFlag = 0;
+int xevieClientIndex = 0;
+DeviceIntPtr xeviekb = NULL;
+DeviceIntPtr xeviemouse = NULL;
+Mask xevieMask = 0;
+int xevieEventSent = 0;
+int xevieKBEventSent = 0;
+static DevPrivateKey xevieDevicePrivateKey = &xevieDevicePrivateKey;
+static Bool xevieModifiersOn = FALSE;
+
+#define XEVIEINFO(dev) ((xevieDeviceInfoPtr) \
+ dixLookupPrivate(&(dev)->devPrivates, xevieDevicePrivateKey))
+
+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
+static xevieKeycQueueRec keycq[KEYC_QUEUE_SIZE] = {{0, NULL}};
+static int keycqHead = 0, keycqTail = 0;
+
+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 (void)
+{
+ ExtensionEntry* extEntry;
+
+ if (!AddCallback(&ServerGrabCallback,XevieServerGrabStateCallback,NULL))
+ return;
+
+ if ((extEntry = AddExtension (XEVIENAME,
+ 0,
+ XevieNumberErrors,
+ ProcXevieDispatch,
+ SProcXevieDispatch,
+ XevieResetProc,
+ StandardMinorOpcode))) {
+ XevieReqCode = (unsigned char)extEntry->base;
+ XevieErrorBase = extEntry->errorBase;
+ }
+}
+
+/*ARGSUSED*/
+static
+void XevieResetProc (ExtensionEntry *extEntry)
+{
+}
+
+static
+int ProcXevieQueryVersion (register ClientPtr client)
+{
+ xXevieQueryVersionReply rep;
+ 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;
+ 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 (xXevieQueryVersionReply), (char *)&rep);
+ return client->noClientException;
+}
+
+static
+int ProcXevieStart (register ClientPtr client)
+{
+ xXevieStartReply rep;
+ 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;
+#ifdef XKB
+ if (!noXkbExtension) {
+ if (!XevieStart()) {
+ DeleteCallback(&ClientStateCallback,XevieClientStateCallback,NULL);
+ return BadAlloc;
+ }
+ }
+#endif
+
+ xevieModifiersOn = FALSE;
+
+ rep.length = 0;
+ rep.type = X_Reply;
+ rep.sequence_number = client->sequence;
+ if (client->swapped) {
+ swaps(&rep.sequence_number, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient (client, sizeof (xXevieStartReply), (char *)&rep);
+ return client->noClientException;
+}
+
+static
+int ProcXevieEnd (register ClientPtr client)
+{
+ xXevieEndReply rep;
+ int n;
+
+ REQUEST_SIZE_MATCH (xXevieEndReq);
+
+ if (xevieFlag) {
+ if (client->index != xevieClientIndex)
+ return BadAccess;
+
+ DeleteCallback(&ClientStateCallback,XevieClientStateCallback,NULL);
+ XevieEnd(xevieClientIndex);
+ }
+
+ rep.length = 0;
+ rep.type = X_Reply;
+ rep.sequence_number = client->sequence;
+ if (client->swapped) {
+ swaps(&rep.sequence_number, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient (client, sizeof (xXevieEndReply), (char *)&rep);
+ return client->noClientException;
+}
+
+static
+int ProcXevieSend (register ClientPtr client)
+{
+ REQUEST (xXevieSendReq);
+ xXevieSendReply rep;
+ xEvent *xE;
+ static unsigned char lastDetail = 0, lastType = 0;
+ int n;
+
+ REQUEST_SIZE_MATCH (xXevieSendReq);
+
+ if (client->index != xevieClientIndex)
+ return BadAccess;
+
+ xE = (xEvent *)&stuff->event;
+ rep.length = 0;
+ rep.type = X_Reply;
+ rep.sequence_number = client->sequence;
+ if (client->swapped) {
+ swaps(&rep.sequence_number, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient (client, sizeof (xXevieSendReply), (char *)&rep);
+
+ switch(xE->u.u.type) {
+ case KeyPress:
+ case KeyRelease:
+ xevieKBEventSent = 1;
+#ifdef XKB
+ if(!noXkbExtension)
+ doSendEvent(xE, inputInfo.keyboard);
+ else
+#endif
+ CoreProcessKeyboardEvent (xE, xeviekb, 1);
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ xevieEventSent = 1;
+#ifdef XKB
+ if(!noXkbExtension)
+ doSendEvent(xE, inputInfo.pointer);
+ else
+#endif
+ CoreProcessPointerEvent(xE, xeviemouse, 1);
+ break;
+ default:
+ break;
+ }
+ lastType = xE->u.u.type;
+ lastDetail = xE->u.u.detail;
+ return client->noClientException;
+}
+
+static
+int ProcXevieSelectInput (register ClientPtr client)
+{
+ REQUEST (xXevieSelectInputReq);
+ xXevieSelectInputReply rep;
+ int n;
+
+ REQUEST_SIZE_MATCH (xXevieSelectInputReq);
+
+ if (client->index != xevieClientIndex)
+ return BadAccess;
+
+ xevieMask = stuff->event_mask;
+ rep.length = 0;
+ rep.type = X_Reply;
+ rep.sequence_number = client->sequence;
+ if (client->swapped) {
+ swaps(&rep.sequence_number, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient (client, sizeof (xXevieSelectInputReply), (char *)&rep);
+ return client->noClientException;
+}
+
+static
+int ProcXevieDispatch (register ClientPtr client)
+{
+ REQUEST (xReq);
+ switch (stuff->data)
+ {
+ case X_XevieQueryVersion:
+ return ProcXevieQueryVersion (client);
+ case X_XevieStart:
+ return ProcXevieStart (client);
+ case X_XevieEnd:
+ return ProcXevieEnd (client);
+ case X_XevieSend:
+ return ProcXevieSend (client);
+ case X_XevieSelectInput:
+ return ProcXevieSelectInput(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static
+int SProcXevieQueryVersion (register ClientPtr client)
+{
+ register int n;
+
+ REQUEST(xXevieQueryVersionReq);
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXevieQueryVersionReq);
+ swaps (&stuff->client_major_version, n);
+ swaps (&stuff->client_minor_version, n);
+ return ProcXevieQueryVersion(client);
+}
+
+static
+int SProcXevieStart (ClientPtr client)
+{
+ register int n;
+
+ REQUEST (xXevieStartReq);
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXevieStartReq);
+ swapl (&stuff->screen, n);
+ return ProcXevieStart (client);
+}
+
+static
+int SProcXevieEnd (ClientPtr client)
+{
+ register int n;
+
+ REQUEST (xXevieEndReq);
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXevieEndReq);
+ swapl (&stuff->cmap, n);
+ return ProcXevieEnd (client);
+}
+
+static
+int SProcXevieSend (ClientPtr client)
+{
+ register int n;
+ xEvent eventT;
+ EventSwapPtr proc;
+
+ REQUEST (xXevieSendReq);
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXevieSendReq);
+ swapl (&stuff->dataType, n);
+
+ /* Swap event */
+ proc = EventSwapVector[stuff->event.u.u.type & 0177];
+ if (!proc || proc == NotImplemented) /* no swapping proc; invalid event type? */
+ return (BadValue);
+ (*proc)(&stuff->event, &eventT);
+ stuff->event = eventT;
+
+ return ProcXevieSend (client);
+}
+
+static
+int SProcXevieSelectInput (ClientPtr client)
+{
+ register int n;
+
+ REQUEST (xXevieSelectInputReq);
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXevieSelectInputReq);
+ swapl (&stuff->event_mask, n);
+ return ProcXevieSelectInput (client);
+}
+
+
+static
+int SProcXevieDispatch (register ClientPtr client)
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_XevieQueryVersion:
+ return SProcXevieQueryVersion (client);
+ case X_XevieStart:
+ return SProcXevieStart (client);
+ case X_XevieEnd:
+ return SProcXevieEnd (client);
+ case X_XevieSend:
+ return SProcXevieSend (client);
+ case X_XevieSelectInput:
+ return SProcXevieSelectInput(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;
+#ifdef XKB
+ /* fix for bug5092586 */
+ if(!noXkbExtension) {
+ switch(xE->u.u.type) {
+ case KeyPress: *kptr |= bit; break;
+ case KeyRelease: *kptr &= ~bit; break;
+ }
+ }
+#endif
+ 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) {
+
+#ifdef XKB
+ 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);
+ }
+#endif
+
+ 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;
+
+ xeviep = xalloc (sizeof (xevieDeviceInfoRec));
+ if (!xeviep)
+ return FALSE;
+
+ dixSetPrivate(&device->devPrivates, xevieDevicePrivateKey, 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);
+ dixSetPrivate(&device->devPrivates, xevieDevicePrivateKey, 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/xorg-server/Xext/xf86bigfont.c b/xorg-server/Xext/xf86bigfont.c
new file mode 100644
index 000000000..d5c5704de
--- /dev/null
+++ b/xorg-server/Xext/xf86bigfont.c
@@ -0,0 +1,771 @@
+/*
+ * 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);
+
+#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__) || defined(__DragonFly__)
+
+#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 (AddExtension(XF86BIGFONTNAME,
+ XF86BigfontNumberEvents,
+ XF86BigfontNumberErrors,
+ ProcXF86BigfontDispatch,
+ SProcXF86BigfontDispatch,
+ XF86BigfontResetProc,
+ StandardMinorOpcode)) {
+#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, %s\n",
+ size, strerror(errno));
+ xfree(pDesc);
+ return (ShmDescPtr) NULL;
+ }
+
+ if ((addr = shmat(shmid, 0, 0)) == (char *)-1) {
+ ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n",
+ size, strerror(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,
+ DixGetAttrAccess);
+ if (!pFont) {
+ GC *pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC,
+ DixGetAttrAccess);
+ 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 *)
+ xalloc(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*)
+ xalloc((4*nCharInfos+1) * sizeof(CARD16));
+ if (!tmp) {
+ if (!pDesc) xfree(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 *) xalloc(rlength);
+ char* p;
+ if (!reply) {
+ if (nCharInfos > 0) {
+ if (shmid == -1) xfree(pIndex2UniqIndex);
+ if (!pDesc) xfree(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);
+ xfree(reply);
+ if (nCharInfos > 0) {
+ if (shmid == -1) xfree(pIndex2UniqIndex);
+ if (!pDesc) xfree(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/xorg-server/Xext/xprint.c b/xorg-server/Xext/xprint.c
new file mode 100644
index 000000000..a5d8fcc33
--- /dev/null
+++ b/xorg-server/Xext/xprint.c
@@ -0,0 +1,2617 @@
+/*
+(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.
+** *
+** *********************************************************
+**
+********************************************************************/
+
+#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 "../hw/xprint/DiPrint.h"
+#include "../hw/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 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 DevPrivateKey XpClientPrivateKey = &XpClientPrivateKey;
+
+#define XP_GETPRIV(pClient) ((XpContextPtr) \
+ dixLookupPrivate(&(pClient)->devPrivates, XpClientPrivateKey))
+#define XP_SETPRIV(pClient, p) \
+ dixSetPrivate(&(pClient)->devPrivates, XpClientPrivateKey, p)
+
+/*
+ * 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;
+ }
+
+ 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;
+ }
+ }
+}
+
+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;
+
+ return (*CloseScreen)(index, pScreen);
+}
+
+/*
+ * 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,
+ DixReadAccess))
+ == (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,
+ DixWriteAccess))
+ == (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,
+ DixReadAccess))
+ == (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(sizeof(XpContextRec))) ==
+ (XpContextPtr) NULL)
+ return BadAlloc;
+
+ 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->devPrivates = NULL;
+
+ 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 = XP_GETPRIV(client)) != (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);
+ }
+
+ XP_SETPRIV(client, 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,
+ DixWriteAccess))
+ == (XpContextPtr)NULL)
+ {
+ client->errorValue = stuff->printContext;
+ return XpErrorBase+XPBadContext;
+ }
+
+ if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL)
+ return BadAlloc;
+
+ XP_SETPRIV(client, pContext);
+
+ XpSetFontResFunc(client);
+
+ if (client->noClientException != Success)
+ return client->noClientException;
+ else
+ return result;
+}
+
+XpContextPtr
+XpGetPrintContext(ClientPtr client)
+{
+ return XP_GETPRIV(client);
+}
+
+static int
+ProcXpGetContext(ClientPtr client)
+{
+ /* REQUEST(xPrintGetContextReq); */
+ xPrintGetContextReply rep;
+
+ XpContextPtr pContext;
+ register int n;
+ register long l;
+
+ REQUEST_SIZE_MATCH(xPrintGetContextReq);
+
+ if((pContext = XP_GETPRIV(client)) == (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,
+ DixDestroyAccess))
+ == (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,
+ DixReadAccess))
+ == (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);
+ dixFreePrivates(pContext->devPrivates);
+ 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(XP_GETPRIV(pXpClient->client) == pXpClient->context)
+ {
+ XP_SETPRIV(pXpClient->client, 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;
+}
+
+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 = XP_GETPRIV(client)) == (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 = XP_GETPRIV(client)) == (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 = XP_GETPRIV(client)) == (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 = XP_GETPRIV(client)) == (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 = XP_GETPRIV(client)) == (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;
+
+ result = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+ if (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 = XP_GETPRIV(client)) == (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 = XP_GETPRIV(client)) == (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;
+ result = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
+ DixWriteAccess);
+ if (result != Success)
+ return result;
+ if (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,
+ DixWriteAccess))
+ == (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,
+ DixReadAccess))
+ == (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,
+ DixWriteAccess))
+ == (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,
+ DixReadAccess))
+ == (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,
+ DixWriteAccess))
+ == (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,
+ DixReadAccess))
+ == (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 XP_GETPRIV(client);
+}
+
+
+/*******************************************************************************
+ *
+ * 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/xorg-server/Xext/xres.c b/xorg-server/Xext/xres.c
new file mode 100644
index 000000000..f444c4e69
--- /dev/null
+++ b/xorg-server/Xext/xres.c
@@ -0,0 +1,390 @@
+/*
+ Copyright (c) 2002 XFree86 Inc
+*/
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "swaprep.h"
+#include "registry.h"
+#include <X11/extensions/XResproto.h>
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "gcstruct.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 = xalloc(currentMaxClients * sizeof(int));
+
+ num_clients = 0;
+ for(i = 0; 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);
+ }
+ }
+
+ xfree(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);
+
+ if((clientID >= currentMaxClients) || !clients[clientID]) {
+ client->errorValue = stuff->xid;
+ return BadValue;
+ }
+
+ counts = xalloc((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;
+ char *name;
+
+ for(i = 0; i < lastResourceType; i++) {
+ if(!counts[i]) continue;
+
+ name = (char *)LookupResourceName(i + 1);
+ if (strcmp(name, XREGISTRY_UNKNOWN))
+ scratch.resource_type = MakeAtom(name, strlen(name), TRUE);
+ else {
+ char buf[40];
+ snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1);
+ scratch.resource_type = MakeAtom(buf, strlen(buf), TRUE);
+ }
+
+ 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);
+ }
+ }
+
+ xfree(counts);
+
+ return (client->noClientException);
+}
+
+static unsigned long
+ResGetApproxPixmapBytes (PixmapPtr pix)
+{
+ unsigned long nPixels;
+ int bytesPerPixel;
+
+ bytesPerPixel = pix->drawable.bitsPerPixel>>3;
+ nPixels = pix->drawable.width * pix->drawable.height;
+
+ /* Divide by refcnt as pixmap could be shared between clients,
+ * so total pixmap mem is shared between these.
+ */
+ return ( nPixels * bytesPerPixel ) / pix->refcnt;
+}
+
+static void
+ResFindPixmaps (pointer value, XID id, pointer cdata)
+{
+ unsigned long *bytes = (unsigned long *)cdata;
+ PixmapPtr pix = (PixmapPtr)value;
+
+ *bytes += ResGetApproxPixmapBytes(pix);
+}
+
+static void
+ResFindWindowPixmaps (pointer value, XID id, pointer cdata)
+{
+ unsigned long *bytes = (unsigned long *)cdata;
+ WindowPtr pWin = (WindowPtr)value;
+
+ if (pWin->backgroundState == BackgroundPixmap)
+ *bytes += ResGetApproxPixmapBytes(pWin->background.pixmap);
+
+ if (pWin->border.pixmap != NULL && !pWin->borderIsPixel)
+ *bytes += ResGetApproxPixmapBytes(pWin->border.pixmap);
+}
+
+static void
+ResFindGCPixmaps (pointer value, XID id, pointer cdata)
+{
+ unsigned long *bytes = (unsigned long *)cdata;
+ GCPtr pGC = (GCPtr)value;
+
+ if (pGC->stipple != NULL)
+ *bytes += ResGetApproxPixmapBytes(pGC->stipple);
+
+ if (pGC->tile.pixmap != NULL && !pGC->tileIsPixel)
+ *bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap);
+}
+
+static int
+ProcXResQueryClientPixmapBytes (ClientPtr client)
+{
+ REQUEST(xXResQueryClientPixmapBytesReq);
+ xXResQueryClientPixmapBytesReply rep;
+ int clientID;
+ unsigned long bytes;
+
+ REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq);
+
+ clientID = CLIENT_ID(stuff->xid);
+
+ if((clientID >= currentMaxClients) || !clients[clientID]) {
+ client->errorValue = stuff->xid;
+ return BadValue;
+ }
+
+ bytes = 0;
+
+ FindClientResourcesByType(clients[clientID], RT_PIXMAP, ResFindPixmaps,
+ (pointer)(&bytes));
+
+ /*
+ * Make sure win background pixmaps also held to account.
+ */
+ FindClientResourcesByType(clients[clientID], RT_WINDOW,
+ ResFindWindowPixmaps,
+ (pointer)(&bytes));
+
+ /*
+ * GC Tile & Stipple pixmaps too.
+ */
+ FindClientResourcesByType(clients[clientID], RT_GC,
+ ResFindGCPixmaps,
+ (pointer)(&bytes));
+
+#ifdef COMPOSITE
+ /* FIXME: include composite pixmaps too */
+#endif
+
+ 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);
+}
diff --git a/xorg-server/Xext/xselinux.c b/xorg-server/Xext/xselinux.c
new file mode 100644
index 000000000..1d3449b9a
--- /dev/null
+++ b/xorg-server/Xext/xselinux.c
@@ -0,0 +1,2037 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@epoch.ncsc.mil>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+this permission notice appear in supporting documentation. 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
+AUTHOR 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.
+
+********************************************************/
+
+/*
+ * Portions of this code copyright (c) 2005 by Trusted Computer Solutions, Inc.
+ * All rights reserved.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+#include <selinux/avc.h>
+
+#include <libaudit.h>
+
+#include <X11/Xatom.h>
+#include "globals.h"
+#include "resource.h"
+#include "privates.h"
+#include "registry.h"
+#include "dixstruct.h"
+#include "inputstr.h"
+#include "windowstr.h"
+#include "propertyst.h"
+#include "extnsionst.h"
+#include "scrnintstr.h"
+#include "selection.h"
+#include "xacestr.h"
+#include "xselinux.h"
+#define XSERV_t
+#define TRANS_SERVER
+#include <X11/Xtrans/Xtrans.h>
+#include "../os/osdep.h"
+#include "modinit.h"
+
+
+/*
+ * Globals
+ */
+
+/* private state keys */
+static DevPrivateKey subjectKey = &subjectKey;
+static DevPrivateKey objectKey = &objectKey;
+static DevPrivateKey dataKey = &dataKey;
+
+/* subject state (clients and devices only) */
+typedef struct {
+ security_id_t sid;
+ security_id_t dev_create_sid;
+ security_id_t win_create_sid;
+ security_id_t sel_create_sid;
+ security_id_t prp_create_sid;
+ security_id_t sel_use_sid;
+ security_id_t prp_use_sid;
+ struct avc_entry_ref aeref;
+ char *command;
+ int privileged;
+} SELinuxSubjectRec;
+
+/* object state */
+typedef struct {
+ security_id_t sid;
+ int poly;
+} SELinuxObjectRec;
+
+/* selection and property atom cache */
+typedef struct {
+ SELinuxObjectRec prp;
+ SELinuxObjectRec sel;
+} SELinuxAtomRec;
+
+/* audit file descriptor */
+static int audit_fd;
+
+/* structure passed to auditing callback */
+typedef struct {
+ ClientPtr client; /* client */
+ DeviceIntPtr dev; /* device */
+ char *command; /* client's executable path */
+ unsigned id; /* resource id, if any */
+ int restype; /* resource type, if any */
+ int event; /* event type, if any */
+ Atom property; /* property name, if any */
+ Atom selection; /* selection name, if any */
+ char *extension; /* extension name, if any */
+} SELinuxAuditRec;
+
+/* labeling handle */
+static struct selabel_handle *label_hnd;
+
+/* whether AVC is active */
+static int avc_active;
+
+/* atoms for window label properties */
+static Atom atom_ctx;
+static Atom atom_client_ctx;
+
+/* The unlabeled SID */
+static security_id_t unlabeled_sid;
+
+/* Array of object classes indexed by resource type */
+static security_class_t *knownTypes;
+static unsigned numKnownTypes;
+
+/* Array of event SIDs indexed by event type */
+static security_id_t *knownEvents;
+static unsigned numKnownEvents;
+
+/* Array of property and selection SID structures */
+static SELinuxAtomRec *knownAtoms;
+static unsigned numKnownAtoms;
+
+/* dynamically allocated security classes and permissions */
+static struct security_class_mapping map[] = {
+ { "x_drawable", { "read", "write", "destroy", "create", "getattr", "setattr", "list_property", "get_property", "set_property", "", "", "list_child", "add_child", "remove_child", "hide", "show", "blend", "override", "", "", "", "", "send", "receive", "", "manage", NULL }},
+ { "x_screen", { "", "", "", "", "getattr", "setattr", "saver_getattr", "saver_setattr", "", "", "", "", "", "", "hide_cursor", "show_cursor", "saver_hide", "saver_show", NULL }},
+ { "x_gc", { "", "", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
+ { "x_font", { "", "", "destroy", "create", "getattr", "", "", "", "", "", "", "", "add_glyph", "remove_glyph", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
+ { "x_colormap", { "read", "write", "destroy", "create", "getattr", "", "", "", "", "", "", "", "add_color", "remove_color", "", "", "", "", "", "", "install", "uninstall", "", "", "use", NULL }},
+ { "x_property", { "read", "write", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "write", NULL }},
+ { "x_selection", { "read", "", "", "setattr", "getattr", "setattr", NULL }},
+ { "x_cursor", { "read", "write", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
+ { "x_client", { "", "", "destroy", "", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "manage", NULL }},
+ { "x_device", { "read", "write", "", "", "getattr", "setattr", "", "", "", "getfocus", "setfocus", "", "", "", "", "", "", "grab", "freeze", "force_cursor", "", "", "", "", "use", "manage", "", "bell", NULL }},
+ { "x_server", { "record", "", "", "", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "grab", "", "", "", "", "", "", "", "manage", "debug", NULL }},
+ { "x_extension", { "", "", "", "", "query", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
+ { "x_event", { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "send", "receive", NULL }},
+ { "x_synthetic_event", { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "send", "receive", NULL }},
+ { "x_resource", { "read", "write", "write", "write", "read", "write", "read", "read", "write", "read", "write", "read", "write", "write", "write", "read", "read", "write", "write", "write", "write", "write", "write", "read", "read", "write", "read", "write", NULL }},
+ { NULL }
+};
+
+/* x_resource "read" bits from the list above */
+#define SELinuxReadMask (DixReadAccess|DixGetAttrAccess|DixListPropAccess| \
+ DixGetPropAccess|DixGetFocusAccess|DixListAccess| \
+ DixShowAccess|DixBlendAccess|DixReceiveAccess| \
+ DixUseAccess|DixDebugAccess)
+
+/* forward declarations */
+static void SELinuxScreen(CallbackListPtr *, pointer, pointer);
+
+/* "true" pointer value for use as callback data */
+static pointer truep = (pointer)1;
+
+
+/*
+ * Support Routines
+ */
+
+/*
+ * Looks up a name in the selection or property mappings
+ */
+static int
+SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec *obj, int map, int polymap)
+{
+ const char *name = NameForAtom(atom);
+ security_context_t ctx;
+ int rc = Success;
+
+ obj->poly = 1;
+
+ /* Look in the mappings of names to contexts */
+ if (selabel_lookup(label_hnd, &ctx, name, map) == 0) {
+ obj->poly = 0;
+ } else if (errno != ENOENT) {
+ ErrorF("SELinux: a property label lookup failed!\n");
+ return BadValue;
+ } else if (selabel_lookup(label_hnd, &ctx, name, polymap) < 0) {
+ ErrorF("SELinux: a property label lookup failed!\n");
+ return BadValue;
+ }
+
+ /* Get a SID for context */
+ if (avc_context_to_sid(ctx, &obj->sid) < 0) {
+ ErrorF("SELinux: a context_to_SID call failed!\n");
+ rc = BadAlloc;
+ }
+
+ freecon(ctx);
+ return rc;
+}
+
+/*
+ * Looks up the SID corresponding to the given property or selection atom
+ */
+static int
+SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn)
+{
+ SELinuxObjectRec *obj;
+ int rc, map, polymap;
+
+ if (atom >= numKnownAtoms) {
+ /* Need to increase size of atoms array */
+ unsigned size = sizeof(SELinuxAtomRec);
+ knownAtoms = xrealloc(knownAtoms, (atom + 1) * size);
+ if (!knownAtoms)
+ return BadAlloc;
+ memset(knownAtoms + numKnownAtoms, 0,
+ (atom - numKnownAtoms + 1) * size);
+ numKnownAtoms = atom + 1;
+ }
+
+ if (prop) {
+ obj = &knownAtoms[atom].prp;
+ map = SELABEL_X_PROP;
+ polymap = SELABEL_X_POLYPROP;
+ } else {
+ obj = &knownAtoms[atom].sel;
+ map = SELABEL_X_SELN;
+ polymap = SELABEL_X_POLYSELN;
+ }
+
+ if (!obj->sid) {
+ rc = SELinuxAtomToSIDLookup(atom, obj, map, polymap);
+ if (rc != Success)
+ goto out;
+ }
+
+ *obj_rtn = obj;
+ rc = Success;
+out:
+ return rc;
+}
+
+/*
+ * Looks up a SID for a selection/subject pair
+ */
+static int
+SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec *subj,
+ security_id_t *sid_rtn, int *poly_rtn)
+{
+ int rc;
+ SELinuxObjectRec *obj;
+ security_id_t tsid;
+
+ /* Get the default context and polyinstantiation bit */
+ rc = SELinuxAtomToSID(selection, 0, &obj);
+ if (rc != Success)
+ return rc;
+
+ /* Check for an override context next */
+ if (subj->sel_use_sid) {
+ sidget(tsid = subj->sel_use_sid);
+ goto out;
+ }
+
+ sidget(tsid = obj->sid);
+
+ /* Polyinstantiate if necessary to obtain the final SID */
+ if (obj->poly) {
+ sidput(tsid);
+ if (avc_compute_member(subj->sid, obj->sid,
+ SECCLASS_X_SELECTION, &tsid) < 0) {
+ ErrorF("SELinux: a compute_member call failed!\n");
+ return BadValue;
+ }
+ }
+out:
+ *sid_rtn = tsid;
+ if (poly_rtn)
+ *poly_rtn = obj->poly;
+ return Success;
+}
+
+/*
+ * Looks up a SID for a property/subject pair
+ */
+static int
+SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj,
+ security_id_t *sid_rtn, int *poly_rtn)
+{
+ int rc;
+ SELinuxObjectRec *obj;
+ security_id_t tsid, tsid2;
+
+ /* Get the default context and polyinstantiation bit */
+ rc = SELinuxAtomToSID(property, 1, &obj);
+ if (rc != Success)
+ return rc;
+
+ /* Check for an override context next */
+ if (subj->prp_use_sid) {
+ sidget(tsid = subj->prp_use_sid);
+ goto out;
+ }
+
+ /* Perform a transition */
+ if (avc_compute_create(subj->sid, obj->sid,
+ SECCLASS_X_PROPERTY, &tsid) < 0) {
+ ErrorF("SELinux: a compute_create call failed!\n");
+ return BadValue;
+ }
+
+ /* Polyinstantiate if necessary to obtain the final SID */
+ if (obj->poly) {
+ tsid2 = tsid;
+ if (avc_compute_member(subj->sid, tsid2,
+ SECCLASS_X_PROPERTY, &tsid) < 0) {
+ ErrorF("SELinux: a compute_member call failed!\n");
+ sidput(tsid2);
+ return BadValue;
+ }
+ sidput(tsid2);
+ }
+out:
+ *sid_rtn = tsid;
+ if (poly_rtn)
+ *poly_rtn = obj->poly;
+ return Success;
+}
+
+/*
+ * Looks up the SID corresponding to the given event type
+ */
+static int
+SELinuxEventToSID(unsigned type, security_id_t sid_of_window,
+ SELinuxObjectRec *sid_return)
+{
+ const char *name = LookupEventName(type);
+ security_context_t con;
+ type &= 127;
+
+ if (type >= numKnownEvents) {
+ /* Need to increase size of classes array */
+ unsigned size = sizeof(security_id_t);
+ knownEvents = xrealloc(knownEvents, (type + 1) * size);
+ if (!knownEvents)
+ return BadAlloc;
+ memset(knownEvents + numKnownEvents, 0,
+ (type - numKnownEvents + 1) * size);
+ numKnownEvents = type + 1;
+ }
+
+ if (!knownEvents[type]) {
+ /* Look in the mappings of event names to contexts */
+ if (selabel_lookup(label_hnd, &con, name, SELABEL_X_EVENT) < 0) {
+ ErrorF("SELinux: an event label lookup failed!\n");
+ return BadValue;
+ }
+ /* Get a SID for context */
+ if (avc_context_to_sid(con, knownEvents + type) < 0) {
+ ErrorF("SELinux: a context_to_SID call failed!\n");
+ return BadAlloc;
+ }
+ freecon(con);
+ }
+
+ /* Perform a transition to obtain the final SID */
+ if (avc_compute_create(sid_of_window, knownEvents[type], SECCLASS_X_EVENT,
+ &sid_return->sid) < 0) {
+ ErrorF("SELinux: a compute_create call failed!\n");
+ return BadValue;
+ }
+
+ return Success;
+}
+
+/*
+ * Returns the object class corresponding to the given resource type.
+ */
+static security_class_t
+SELinuxTypeToClass(RESTYPE type)
+{
+ RESTYPE fulltype = type;
+ type &= TypeMask;
+
+ if (type >= numKnownTypes) {
+ /* Need to increase size of classes array */
+ unsigned size = sizeof(security_class_t);
+ knownTypes = xrealloc(knownTypes, (type + 1) * size);
+ if (!knownTypes)
+ return 0;
+ memset(knownTypes + numKnownTypes, 0,
+ (type - numKnownTypes + 1) * size);
+ numKnownTypes = type + 1;
+ }
+
+ if (!knownTypes[type]) {
+ const char *str;
+ knownTypes[type] = SECCLASS_X_RESOURCE;
+
+ if (fulltype & RC_DRAWABLE)
+ knownTypes[type] = SECCLASS_X_DRAWABLE;
+ if (fulltype == RT_GC)
+ knownTypes[type] = SECCLASS_X_GC;
+ if (fulltype == RT_FONT)
+ knownTypes[type] = SECCLASS_X_FONT;
+ if (fulltype == RT_CURSOR)
+ knownTypes[type] = SECCLASS_X_CURSOR;
+ if (fulltype == RT_COLORMAP)
+ knownTypes[type] = SECCLASS_X_COLORMAP;
+
+ /* Need to do a string lookup */
+ str = LookupResourceName(fulltype);
+ if (!strcmp(str, "PICTURE"))
+ knownTypes[type] = SECCLASS_X_DRAWABLE;
+ if (!strcmp(str, "GLYPHSET"))
+ knownTypes[type] = SECCLASS_X_FONT;
+ }
+
+ return knownTypes[type];
+}
+
+/*
+ * Performs an SELinux permission check.
+ */
+static int
+SELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj,
+ security_class_t class, Mask mode, SELinuxAuditRec *auditdata)
+{
+ /* serverClient requests OK */
+ if (subj->privileged)
+ return Success;
+
+ auditdata->command = subj->command;
+ errno = 0;
+
+ if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref,
+ auditdata) < 0) {
+ if (mode == DixUnknownAccess)
+ return Success; /* DixUnknownAccess requests OK ... for now */
+ if (errno == EACCES)
+ return BadAccess;
+ ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno);
+ return BadValue;
+ }
+
+ return Success;
+}
+
+/*
+ * Labels a newly connected client.
+ */
+static void
+SELinuxLabelClient(ClientPtr client)
+{
+ XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn;
+ int fd = _XSERVTransGetConnectionNumber(ci);
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ security_context_t ctx;
+
+ subj = dixLookupPrivate(&client->devPrivates, subjectKey);
+ sidput(subj->sid);
+ obj = dixLookupPrivate(&client->devPrivates, objectKey);
+ sidput(obj->sid);
+
+ /* Try to get a context from the socket */
+ if (fd < 0 || getpeercon(fd, &ctx) < 0) {
+ /* Otherwise, fall back to a default context */
+ if (selabel_lookup(label_hnd, &ctx, NULL, SELABEL_X_CLIENT) < 0)
+ FatalError("SELinux: failed to look up remote-client context\n");
+ }
+
+ /* For local clients, try and determine the executable name */
+ if (_XSERVTransIsLocal(ci)) {
+ struct ucred creds;
+ socklen_t len = sizeof(creds);
+ char path[PATH_MAX + 1];
+ size_t bytes;
+
+ memset(&creds, 0, sizeof(creds));
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0)
+ goto finish;
+
+ snprintf(path, PATH_MAX + 1, "/proc/%d/cmdline", creds.pid);
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ goto finish;
+
+ bytes = read(fd, path, PATH_MAX + 1);
+ close(fd);
+ if (bytes <= 0)
+ goto finish;
+
+ subj->command = xalloc(bytes);
+ if (!subj->command)
+ goto finish;
+
+ memcpy(subj->command, path, bytes);
+ subj->command[bytes - 1] = 0;
+ }
+
+finish:
+ /* Get a SID from the context */
+ if (avc_context_to_sid(ctx, &subj->sid) < 0)
+ FatalError("SELinux: client %d: context_to_sid(%s) failed\n",
+ client->index, ctx);
+
+ sidget(obj->sid = subj->sid);
+ freecon(ctx);
+}
+
+/*
+ * Labels initial server objects.
+ */
+static void
+SELinuxLabelInitial(void)
+{
+ int i;
+ XaceScreenAccessRec srec;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ security_context_t ctx;
+ pointer unused;
+
+ /* Do the serverClient */
+ subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&serverClient->devPrivates, objectKey);
+ subj->privileged = 1;
+ sidput(subj->sid);
+
+ /* Use the context of the X server process for the serverClient */
+ if (getcon(&ctx) < 0)
+ FatalError("SELinux: couldn't get context of X server process\n");
+
+ /* Get a SID from the context */
+ if (avc_context_to_sid(ctx, &subj->sid) < 0)
+ FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx);
+
+ sidget(obj->sid = subj->sid);
+ freecon(ctx);
+
+ srec.client = serverClient;
+ srec.access_mode = DixCreateAccess;
+ srec.status = Success;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ /* Do the screen object */
+ srec.screen = screenInfo.screens[i];
+ SELinuxScreen(NULL, NULL, &srec);
+
+ /* Do the default colormap */
+ dixLookupResource(&unused, screenInfo.screens[i]->defColormap,
+ RT_COLORMAP, serverClient, DixCreateAccess);
+ }
+}
+
+/*
+ * Labels new resource objects.
+ */
+static int
+SELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj,
+ SELinuxObjectRec *obj, security_class_t class)
+{
+ int offset;
+ security_id_t tsid;
+
+ /* Check for a create context */
+ if (rec->rtype == RT_WINDOW && subj->win_create_sid) {
+ sidget(obj->sid = subj->win_create_sid);
+ return Success;
+ }
+
+ if (rec->parent)
+ offset = dixLookupPrivateOffset(rec->ptype);
+
+ if (rec->parent && offset >= 0) {
+ /* Use the SID of the parent object in the labeling operation */
+ PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset);
+ SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey);
+ tsid = pobj->sid;
+ } else {
+ /* Use the SID of the subject */
+ tsid = subj->sid;
+ }
+
+ /* Perform a transition to obtain the final SID */
+ if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) {
+ ErrorF("SELinux: a compute_create call failed!\n");
+ return BadValue;
+ }
+
+ return Success;
+}
+
+
+/*
+ * Libselinux Callbacks
+ */
+
+static int
+SELinuxAudit(void *auditdata,
+ security_class_t class,
+ char *msgbuf,
+ size_t msgbufsize)
+{
+ SELinuxAuditRec *audit = auditdata;
+ ClientPtr client = audit->client;
+ char idNum[16], *propertyName, *selectionName;
+ int major = -1, minor = -1;
+
+ if (client) {
+ REQUEST(xReq);
+ if (stuff) {
+ major = stuff->reqType;
+ minor = MinorOpcodeOfRequest(client);
+ }
+ }
+ if (audit->id)
+ snprintf(idNum, 16, "%x", audit->id);
+
+ propertyName = audit->property ? NameForAtom(audit->property) : NULL;
+ selectionName = audit->selection ? NameForAtom(audit->selection) : NULL;
+
+ return snprintf(msgbuf, msgbufsize,
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ (major >= 0) ? "request=" : "",
+ (major >= 0) ? LookupRequestName(major, minor) : "",
+ audit->command ? " comm=" : "",
+ audit->command ? audit->command : "",
+ audit->dev ? " xdevice=\"" : "",
+ audit->dev ? audit->dev->name : "",
+ audit->dev ? "\"" : "",
+ audit->id ? " resid=" : "",
+ audit->id ? idNum : "",
+ audit->restype ? " restype=" : "",
+ audit->restype ? LookupResourceName(audit->restype) : "",
+ audit->event ? " event=" : "",
+ audit->event ? LookupEventName(audit->event & 127) : "",
+ audit->property ? " property=" : "",
+ audit->property ? propertyName : "",
+ audit->selection ? " selection=" : "",
+ audit->selection ? selectionName : "",
+ audit->extension ? " extension=" : "",
+ audit->extension ? audit->extension : "");
+}
+
+static int
+SELinuxLog(int type, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[MAX_AUDIT_MESSAGE_LENGTH];
+ int rc, aut = AUDIT_USER_AVC;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap);
+ rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0);
+ va_end(ap);
+ LogMessageVerb(X_WARNING, 0, "%s", buf);
+ return 0;
+}
+
+/*
+ * XACE Callbacks
+ */
+
+static void
+SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceDeviceAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev };
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey);
+
+ /* If this is a new object that needs labeling, do it now */
+ if (rec->access_mode & DixCreateAccess) {
+ SELinuxSubjectRec *dsubj;
+ dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey);
+
+ sidput(dsubj->sid);
+ sidput(obj->sid);
+
+ if (subj->dev_create_sid) {
+ /* Label the device with the create context */
+ sidget(obj->sid = subj->dev_create_sid);
+ sidget(dsubj->sid = subj->dev_create_sid);
+ } else {
+ /* Label the device directly with the process SID */
+ sidget(obj->sid = subj->sid);
+ sidget(dsubj->sid = subj->sid);
+ }
+ }
+
+ /* XXX only check read permission on XQueryKeymap */
+ /* This is to allow the numerous apps that call XQueryPointer to work */
+ if (rec->access_mode & DixReadAccess) {
+ ClientPtr client = rec->client;
+ REQUEST(xReq);
+ if (stuff && stuff->reqType != X_QueryKeymap) {
+ rec->access_mode &= ~DixReadAccess;
+ rec->access_mode |= DixGetAttrAccess;
+ }
+ }
+
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DEVICE, rec->access_mode,
+ &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+}
+
+static void
+SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceSendAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj, ev_sid;
+ SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev };
+ security_class_t class;
+ int rc, i, type;
+
+ if (rec->dev)
+ subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey);
+ else
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+
+ obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey);
+
+ /* Check send permission on window */
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess,
+ &auditdata);
+ if (rc != Success)
+ goto err;
+
+ /* Check send permission on specific event types */
+ for (i = 0; i < rec->count; i++) {
+ type = rec->events[i].u.u.type;
+ class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT;
+
+ rc = SELinuxEventToSID(type, obj->sid, &ev_sid);
+ if (rc != Success)
+ goto err;
+
+ auditdata.event = type;
+ rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata);
+ if (rc != Success)
+ goto err;
+ }
+ return;
+err:
+ rec->status = rc;
+}
+
+static void
+SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceReceiveAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj, ev_sid;
+ SELinuxAuditRec auditdata = { .client = NULL };
+ security_class_t class;
+ int rc, i, type;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey);
+
+ /* Check receive permission on window */
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess,
+ &auditdata);
+ if (rc != Success)
+ goto err;
+
+ /* Check receive permission on specific event types */
+ for (i = 0; i < rec->count; i++) {
+ type = rec->events[i].u.u.type;
+ class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT;
+
+ rc = SELinuxEventToSID(type, obj->sid, &ev_sid);
+ if (rc != Success)
+ goto err;
+
+ auditdata.event = type;
+ rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata);
+ if (rc != Success)
+ goto err;
+ }
+ return;
+err:
+ rec->status = rc;
+}
+
+static void
+SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceExtAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj, *serv;
+ SELinuxObjectRec *obj;
+ SELinuxAuditRec auditdata = { .client = rec->client };
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey);
+
+ /* If this is a new object that needs labeling, do it now */
+ /* XXX there should be a separate callback for this */
+ if (obj->sid == unlabeled_sid) {
+ const char *name = rec->ext->name;
+ security_context_t con;
+ security_id_t sid;
+
+ serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
+
+ /* Look in the mappings of extension names to contexts */
+ if (selabel_lookup(label_hnd, &con, name, SELABEL_X_EXT) < 0) {
+ ErrorF("SELinux: a property label lookup failed!\n");
+ rec->status = BadValue;
+ return;
+ }
+ /* Get a SID for context */
+ if (avc_context_to_sid(con, &sid) < 0) {
+ ErrorF("SELinux: a context_to_SID call failed!\n");
+ rec->status = BadAlloc;
+ return;
+ }
+
+ sidput(obj->sid);
+
+ /* Perform a transition to obtain the final SID */
+ if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION,
+ &obj->sid) < 0) {
+ ErrorF("SELinux: a SID transition call failed!\n");
+ freecon(con);
+ rec->status = BadValue;
+ return;
+ }
+ freecon(con);
+ }
+
+ /* Perform the security check */
+ auditdata.extension = rec->ext->name;
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode,
+ &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+}
+
+static void
+SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceSelectionAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj, *data;
+ Selection *pSel = *rec->ppSel;
+ Atom name = pSel->selection;
+ Mask access_mode = rec->access_mode;
+ SELinuxAuditRec auditdata = { .client = rec->client, .selection = name };
+ security_id_t tsid;
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&pSel->devPrivates, objectKey);
+
+ /* If this is a new object that needs labeling, do it now */
+ if (access_mode & DixCreateAccess) {
+ sidput(obj->sid);
+ rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly);
+ if (rc != Success)
+ obj->sid = unlabeled_sid;
+ access_mode = DixSetAttrAccess;
+ }
+ /* If this is a polyinstantiated object, find the right instance */
+ else if (obj->poly) {
+ rc = SELinuxSelectionToSID(name, subj, &tsid, NULL);
+ if (rc != Success) {
+ rec->status = rc;
+ return;
+ }
+ while (pSel->selection != name || obj->sid != tsid) {
+ if ((pSel = pSel->next) == NULL)
+ break;
+ obj = dixLookupPrivate(&pSel->devPrivates, objectKey);
+ }
+ sidput(tsid);
+
+ if (pSel)
+ *rec->ppSel = pSel;
+ else {
+ rec->status = BadMatch;
+ return;
+ }
+ }
+
+ /* Perform the security check */
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode,
+ &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+
+ /* Label the content (advisory only) */
+ if (access_mode & DixSetAttrAccess) {
+ data = dixLookupPrivate(&pSel->devPrivates, dataKey);
+ sidput(data->sid);
+ if (subj->sel_create_sid)
+ sidget(data->sid = subj->sel_create_sid);
+ else
+ sidget(data->sid = obj->sid);
+ }
+}
+
+static void
+SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XacePropertyAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj, *data;
+ PropertyPtr pProp = *rec->ppProp;
+ Atom name = pProp->propertyName;
+ SELinuxAuditRec auditdata = { .client = rec->client, .property = name };
+ security_id_t tsid;
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&pProp->devPrivates, objectKey);
+
+ /* If this is a new object that needs labeling, do it now */
+ if (rec->access_mode & DixCreateAccess) {
+ sidput(obj->sid);
+ rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly);
+ if (rc != Success) {
+ rec->status = rc;
+ return;
+ }
+ }
+ /* If this is a polyinstantiated object, find the right instance */
+ else if (obj->poly) {
+ rc = SELinuxPropertyToSID(name, subj, &tsid, NULL);
+ if (rc != Success) {
+ rec->status = rc;
+ return;
+ }
+ while (pProp->propertyName != name || obj->sid != tsid) {
+ if ((pProp = pProp->next) == NULL)
+ break;
+ obj = dixLookupPrivate(&pProp->devPrivates, objectKey);
+ }
+ sidput(tsid);
+
+ if (pProp)
+ *rec->ppProp = pProp;
+ else {
+ rec->status = BadMatch;
+ return;
+ }
+ }
+
+ /* Perform the security check */
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode,
+ &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+
+ /* Label the content (advisory only) */
+ if (rec->access_mode & DixWriteAccess) {
+ data = dixLookupPrivate(&pProp->devPrivates, dataKey);
+ sidput(data->sid);
+ if (subj->prp_create_sid)
+ sidget(data->sid = subj->prp_create_sid);
+ else
+ sidget(data->sid = obj->sid);
+ }
+}
+
+static void
+SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceResourceAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ SELinuxAuditRec auditdata = { .client = rec->client };
+ Mask access_mode = rec->access_mode;
+ PrivateRec **privatePtr;
+ security_class_t class;
+ int rc, offset;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+
+ /* Determine if the resource object has a devPrivates field */
+ offset = dixLookupPrivateOffset(rec->rtype);
+ if (offset < 0) {
+ /* No: use the SID of the owning client */
+ class = SECCLASS_X_RESOURCE;
+ privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates;
+ obj = dixLookupPrivate(privatePtr, objectKey);
+ } else {
+ /* Yes: use the SID from the resource object itself */
+ class = SELinuxTypeToClass(rec->rtype);
+ privatePtr = DEVPRIV_AT(rec->res, offset);
+ obj = dixLookupPrivate(privatePtr, objectKey);
+ }
+
+ /* If this is a new object that needs labeling, do it now */
+ if (access_mode & DixCreateAccess && offset >= 0) {
+ rc = SELinuxLabelResource(rec, subj, obj, class);
+ if (rc != Success) {
+ rec->status = rc;
+ return;
+ }
+ }
+
+ /* Collapse generic resource permissions down to read/write */
+ if (class == SECCLASS_X_RESOURCE) {
+ access_mode = !!(rec->access_mode & SELinuxReadMask); /* rd */
+ access_mode |= !!(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */
+ }
+
+ /* Perform the security check */
+ auditdata.restype = rec->rtype;
+ auditdata.id = rec->id;
+ rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+
+ /* Perform the background none check on windows */
+ if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) {
+ rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata);
+ if (rc != Success)
+ ((WindowPtr)rec->res)->forcedBG = TRUE;
+ }
+}
+
+static void
+SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata)
+{
+ XaceScreenAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ SELinuxAuditRec auditdata = { .client = rec->client };
+ Mask access_mode = rec->access_mode;
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey);
+
+ /* If this is a new object that needs labeling, do it now */
+ if (access_mode & DixCreateAccess) {
+ sidput(obj->sid);
+
+ /* Perform a transition to obtain the final SID */
+ if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN,
+ &obj->sid) < 0) {
+ ErrorF("SELinux: a compute_create call failed!\n");
+ rec->status = BadValue;
+ return;
+ }
+ }
+
+ if (is_saver)
+ access_mode <<= 2;
+
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+}
+
+static void
+SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceClientAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ SELinuxAuditRec auditdata = { .client = rec->client };
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&rec->target->devPrivates, objectKey);
+
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode,
+ &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+}
+
+static void
+SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceServerAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ SELinuxAuditRec auditdata = { .client = rec->client };
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&serverClient->devPrivates, objectKey);
+
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode,
+ &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+}
+
+
+/*
+ * DIX Callbacks
+ */
+
+static void
+SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ NewClientInfoRec *pci = calldata;
+
+ switch (pci->client->clientState) {
+ case ClientStateInitial:
+ SELinuxLabelClient(pci->client);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ ResourceStateInfoRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ WindowPtr pWin;
+
+ if (rec->type != RT_WINDOW)
+ return;
+
+ pWin = (WindowPtr)rec->value;
+ subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey);
+
+ if (subj->sid) {
+ security_context_t ctx;
+ int rc = avc_sid_to_context(subj->sid, &ctx);
+ if (rc < 0)
+ FatalError("SELinux: Failed to get security context!\n");
+ rc = dixChangeWindowProperty(serverClient,
+ pWin, atom_client_ctx, XA_STRING, 8,
+ PropModeReplace, strlen(ctx), ctx, FALSE);
+ if (rc != Success)
+ FatalError("SELinux: Failed to set label property on window!\n");
+ freecon(ctx);
+ } else
+ FatalError("SELinux: Unexpected unlabeled client found\n");
+
+ obj = dixLookupPrivate(&pWin->devPrivates, objectKey);
+
+ if (obj->sid) {
+ security_context_t ctx;
+ int rc = avc_sid_to_context(obj->sid, &ctx);
+ if (rc < 0)
+ FatalError("SELinux: Failed to get security context!\n");
+ rc = dixChangeWindowProperty(serverClient,
+ pWin, atom_ctx, XA_STRING, 8,
+ PropModeReplace, strlen(ctx), ctx, FALSE);
+ if (rc != Success)
+ FatalError("SELinux: Failed to set label property on window!\n");
+ freecon(ctx);
+ } else
+ FatalError("SELinux: Unexpected unlabeled window found\n");
+}
+
+
+/*
+ * DevPrivates Callbacks
+ */
+
+static void
+SELinuxSubjectInit(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ PrivateCallbackRec *rec = calldata;
+ SELinuxSubjectRec *subj = *rec->value;
+
+ sidget(unlabeled_sid);
+ subj->sid = unlabeled_sid;
+
+ avc_entry_ref_init(&subj->aeref);
+}
+
+static void
+SELinuxSubjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ PrivateCallbackRec *rec = calldata;
+ SELinuxSubjectRec *subj = *rec->value;
+
+ xfree(subj->command);
+
+ if (avc_active) {
+ sidput(subj->sid);
+ sidput(subj->dev_create_sid);
+ sidput(subj->win_create_sid);
+ sidput(subj->sel_create_sid);
+ sidput(subj->prp_create_sid);
+ }
+}
+
+static void
+SELinuxObjectInit(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ PrivateCallbackRec *rec = calldata;
+ SELinuxObjectRec *obj = *rec->value;
+
+ sidget(unlabeled_sid);
+ obj->sid = unlabeled_sid;
+}
+
+static void
+SELinuxObjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ PrivateCallbackRec *rec = calldata;
+ SELinuxObjectRec *obj = *rec->value;
+
+ if (avc_active)
+ sidput(obj->sid);
+}
+
+
+/*
+ * Extension Dispatch
+ */
+
+#define CTX_DEV offsetof(SELinuxSubjectRec, dev_create_sid)
+#define CTX_WIN offsetof(SELinuxSubjectRec, win_create_sid)
+#define CTX_PRP offsetof(SELinuxSubjectRec, prp_create_sid)
+#define CTX_SEL offsetof(SELinuxSubjectRec, sel_create_sid)
+#define USE_PRP offsetof(SELinuxSubjectRec, prp_use_sid)
+#define USE_SEL offsetof(SELinuxSubjectRec, sel_use_sid)
+
+typedef struct {
+ security_context_t octx;
+ security_context_t dctx;
+ CARD32 octx_len;
+ CARD32 dctx_len;
+ CARD32 id;
+} SELinuxListItemRec;
+
+static int
+ProcSELinuxQueryVersion(ClientPtr client)
+{
+ SELinuxQueryVersionReply rep;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.server_major = SELINUX_MAJOR_VERSION;
+ rep.server_minor = SELINUX_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(rep), (char *)&rep);
+ return (client->noClientException);
+}
+
+static int
+SELinuxSendContextReply(ClientPtr client, security_id_t sid)
+{
+ SELinuxGetContextReply rep;
+ security_context_t ctx = NULL;
+ int len = 0;
+
+ if (sid) {
+ if (avc_sid_to_context(sid, &ctx) < 0)
+ return BadValue;
+ len = strlen(ctx) + 1;
+ }
+
+ rep.type = X_Reply;
+ rep.length = (len + 3) >> 2;
+ rep.sequenceNumber = client->sequence;
+ rep.context_len = len;
+
+ if (client->swapped) {
+ int n;
+ swapl(&rep.length, n);
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.context_len, n);
+ }
+
+ WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep);
+ WriteToClient(client, len, ctx);
+ freecon(ctx);
+ return client->noClientException;
+}
+
+static int
+ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
+{
+ PrivateRec **privPtr = &client->devPrivates;
+ security_id_t *pSid;
+ security_context_t ctx;
+ char *ptr;
+
+ REQUEST(SELinuxSetCreateContextReq);
+ REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq, stuff->context_len);
+
+ ctx = (char *)(stuff + 1);
+ if (stuff->context_len > 0 && ctx[stuff->context_len - 1])
+ return BadLength;
+
+ if (offset == CTX_DEV) {
+ /* Device create context currently requires manage permission */
+ int rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
+ if (rc != Success)
+ return rc;
+ privPtr = &serverClient->devPrivates;
+ }
+ else if (offset == USE_SEL) {
+ /* Selection use context currently requires no selections owned */
+ Selection *pSel;
+ for (pSel = CurrentSelections; pSel; pSel = pSel->next)
+ if (pSel->client == client)
+ return BadMatch;
+ }
+
+ ptr = dixLookupPrivate(privPtr, subjectKey);
+ pSid = (security_id_t *)(ptr + offset);
+ sidput(*pSid);
+ *pSid = NULL;
+
+ if (stuff->context_len > 0) {
+ if (security_check_context(ctx) < 0)
+ return BadValue;
+ if (avc_context_to_sid(ctx, pSid) < 0)
+ return BadValue;
+ }
+ return Success;
+}
+
+static int
+ProcSELinuxGetCreateContext(ClientPtr client, unsigned offset)
+{
+ security_id_t *pSid;
+ char *ptr;
+
+ REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq);
+
+ if (offset == CTX_DEV)
+ ptr = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
+ else
+ ptr = dixLookupPrivate(&client->devPrivates, subjectKey);
+
+ pSid = (security_id_t *)(ptr + offset);
+ return SELinuxSendContextReply(client, *pSid);
+}
+
+static int
+ProcSELinuxSetDeviceContext(ClientPtr client)
+{
+ security_context_t ctx;
+ security_id_t sid;
+ DeviceIntPtr dev;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ int rc;
+
+ REQUEST(SELinuxSetContextReq);
+ REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len);
+
+ ctx = (char *)(stuff + 1);
+ if (stuff->context_len < 1 || ctx[stuff->context_len - 1])
+ return BadLength;
+
+ rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess);
+ if (rc != Success)
+ return rc;
+
+ if (security_check_context(ctx) < 0)
+ return BadValue;
+ if (avc_context_to_sid(ctx, &sid) < 0)
+ return BadValue;
+
+ subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
+ sidput(subj->sid);
+ subj->sid = sid;
+ obj = dixLookupPrivate(&dev->devPrivates, objectKey);
+ sidput(obj->sid);
+ sidget(obj->sid = sid);
+
+ return Success;
+}
+
+static int
+ProcSELinuxGetDeviceContext(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ SELinuxSubjectRec *subj;
+ int rc;
+
+ REQUEST(SELinuxGetContextReq);
+ REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+
+ rc = dixLookupDevice(&dev, stuff->id, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
+ return SELinuxSendContextReply(client, subj->sid);
+}
+
+static int
+ProcSELinuxGetWindowContext(ClientPtr client)
+{
+ WindowPtr pWin;
+ SELinuxObjectRec *obj;
+ int rc;
+
+ REQUEST(SELinuxGetContextReq);
+ REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+
+ rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ obj = dixLookupPrivate(&pWin->devPrivates, objectKey);
+ return SELinuxSendContextReply(client, obj->sid);
+}
+
+static int
+ProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey)
+{
+ WindowPtr pWin;
+ PropertyPtr pProp;
+ SELinuxObjectRec *obj;
+ int rc;
+
+ REQUEST(SELinuxGetPropertyContextReq);
+ REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq);
+
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = dixLookupProperty(&pProp, pWin, stuff->property, client,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ obj = dixLookupPrivate(&pProp->devPrivates, privKey);
+ return SELinuxSendContextReply(client, obj->sid);
+}
+
+static int
+ProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey)
+{
+ Selection *pSel;
+ SELinuxObjectRec *obj;
+ int rc;
+
+ REQUEST(SELinuxGetContextReq);
+ REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+
+ rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ obj = dixLookupPrivate(&pSel->devPrivates, privKey);
+ return SELinuxSendContextReply(client, obj->sid);
+}
+
+static int
+ProcSELinuxGetClientContext(ClientPtr client)
+{
+ ClientPtr target;
+ SELinuxSubjectRec *subj;
+ int rc;
+
+ REQUEST(SELinuxGetContextReq);
+ REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+
+ rc = dixLookupClient(&target, stuff->id, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ subj = dixLookupPrivate(&target->devPrivates, subjectKey);
+ return SELinuxSendContextReply(client, subj->sid);
+}
+
+static int
+SELinuxPopulateItem(SELinuxListItemRec *i, PrivateRec **privPtr, CARD32 id,
+ int *size)
+{
+ SELinuxObjectRec *obj = dixLookupPrivate(privPtr, objectKey);
+ SELinuxObjectRec *data = dixLookupPrivate(privPtr, dataKey);
+
+ if (avc_sid_to_context(obj->sid, &i->octx) < 0)
+ return BadValue;
+ if (avc_sid_to_context(data->sid, &i->dctx) < 0)
+ return BadValue;
+
+ i->id = id;
+ i->octx_len = (strlen(i->octx) + 4) >> 2;
+ i->dctx_len = (strlen(i->dctx) + 4) >> 2;
+
+ *size += i->octx_len + i->dctx_len + 3;
+ return Success;
+}
+
+static void
+SELinuxFreeItems(SELinuxListItemRec *items, int count)
+{
+ int k;
+ for (k = 0; k < count; k++) {
+ freecon(items[k].octx);
+ freecon(items[k].dctx);
+ }
+ xfree(items);
+}
+
+static int
+SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec *items,
+ int size, int count)
+{
+ int rc, k, n, pos = 0;
+ SELinuxListItemsReply rep;
+ CARD32 *buf;
+
+ buf = xcalloc(size, sizeof(CARD32));
+ if (!buf) {
+ rc = BadAlloc;
+ goto out;
+ }
+
+ /* Fill in the buffer */
+ for (k = 0; k < count; k++) {
+ buf[pos] = items[k].id;
+ if (client->swapped)
+ swapl(buf + pos, n);
+ pos++;
+
+ buf[pos] = items[k].octx_len * 4;
+ if (client->swapped)
+ swapl(buf + pos, n);
+ pos++;
+
+ buf[pos] = items[k].dctx_len * 4;
+ if (client->swapped)
+ swapl(buf + pos, n);
+ pos++;
+
+ memcpy((char *)(buf + pos), items[k].octx, strlen(items[k].octx) + 1);
+ pos += items[k].octx_len;
+ memcpy((char *)(buf + pos), items[k].dctx, strlen(items[k].dctx) + 1);
+ pos += items[k].dctx_len;
+ }
+
+ /* Send reply to client */
+ rep.type = X_Reply;
+ rep.length = size;
+ rep.sequenceNumber = client->sequence;
+ rep.count = count;
+
+ if (client->swapped) {
+ swapl(&rep.length, n);
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.count, n);
+ }
+
+ WriteToClient(client, sizeof(SELinuxListItemsReply), (char *)&rep);
+ WriteToClient(client, size * 4, (char *)buf);
+
+ /* Free stuff and return */
+ rc = client->noClientException;
+ xfree(buf);
+out:
+ SELinuxFreeItems(items, count);
+ return rc;
+}
+
+static int
+ProcSELinuxListProperties(ClientPtr client)
+{
+ WindowPtr pWin;
+ PropertyPtr pProp;
+ SELinuxListItemRec *items;
+ int rc, count, size, i;
+ CARD32 id;
+
+ REQUEST(SELinuxGetContextReq);
+ REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+
+ rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
+ if (rc != Success)
+ return rc;
+
+ /* Count the number of properties and allocate items */
+ count = 0;
+ for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
+ count++;
+ items = xcalloc(count, sizeof(SELinuxListItemRec));
+ if (!items)
+ return BadAlloc;
+
+ /* Fill in the items and calculate size */
+ i = 0;
+ size = 0;
+ for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
+ id = pProp->propertyName;
+ rc = SELinuxPopulateItem(items + i, &pProp->devPrivates, id, &size);
+ if (rc != Success) {
+ SELinuxFreeItems(items, count);
+ return rc;
+ }
+ i++;
+ }
+
+ return SELinuxSendItemsToClient(client, items, size, count);
+}
+
+static int
+ProcSELinuxListSelections(ClientPtr client)
+{
+ Selection *pSel;
+ SELinuxListItemRec *items;
+ int rc, count, size, i;
+ CARD32 id;
+
+ REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq);
+
+ /* Count the number of selections and allocate items */
+ count = 0;
+ for (pSel = CurrentSelections; pSel; pSel = pSel->next)
+ count++;
+ items = xcalloc(count, sizeof(SELinuxListItemRec));
+ if (!items)
+ return BadAlloc;
+
+ /* Fill in the items and calculate size */
+ i = 0;
+ size = 0;
+ for (pSel = CurrentSelections; pSel; pSel = pSel->next) {
+ id = pSel->selection;
+ rc = SELinuxPopulateItem(items + i, &pSel->devPrivates, id, &size);
+ if (rc != Success) {
+ SELinuxFreeItems(items, count);
+ return rc;
+ }
+ i++;
+ }
+
+ return SELinuxSendItemsToClient(client, items, size, count);
+}
+
+static int
+ProcSELinuxDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ switch (stuff->data) {
+ case X_SELinuxQueryVersion:
+ return ProcSELinuxQueryVersion(client);
+ case X_SELinuxSetDeviceCreateContext:
+ return ProcSELinuxSetCreateContext(client, CTX_DEV);
+ case X_SELinuxGetDeviceCreateContext:
+ return ProcSELinuxGetCreateContext(client, CTX_DEV);
+ case X_SELinuxSetDeviceContext:
+ return ProcSELinuxSetDeviceContext(client);
+ case X_SELinuxGetDeviceContext:
+ return ProcSELinuxGetDeviceContext(client);
+ case X_SELinuxSetWindowCreateContext:
+ return ProcSELinuxSetCreateContext(client, CTX_WIN);
+ case X_SELinuxGetWindowCreateContext:
+ return ProcSELinuxGetCreateContext(client, CTX_WIN);
+ case X_SELinuxGetWindowContext:
+ return ProcSELinuxGetWindowContext(client);
+ case X_SELinuxSetPropertyCreateContext:
+ return ProcSELinuxSetCreateContext(client, CTX_PRP);
+ case X_SELinuxGetPropertyCreateContext:
+ return ProcSELinuxGetCreateContext(client, CTX_PRP);
+ case X_SELinuxSetPropertyUseContext:
+ return ProcSELinuxSetCreateContext(client, USE_PRP);
+ case X_SELinuxGetPropertyUseContext:
+ return ProcSELinuxGetCreateContext(client, USE_PRP);
+ case X_SELinuxGetPropertyContext:
+ return ProcSELinuxGetPropertyContext(client, objectKey);
+ case X_SELinuxGetPropertyDataContext:
+ return ProcSELinuxGetPropertyContext(client, dataKey);
+ case X_SELinuxListProperties:
+ return ProcSELinuxListProperties(client);
+ case X_SELinuxSetSelectionCreateContext:
+ return ProcSELinuxSetCreateContext(client, CTX_SEL);
+ case X_SELinuxGetSelectionCreateContext:
+ return ProcSELinuxGetCreateContext(client, CTX_SEL);
+ case X_SELinuxSetSelectionUseContext:
+ return ProcSELinuxSetCreateContext(client, USE_SEL);
+ case X_SELinuxGetSelectionUseContext:
+ return ProcSELinuxGetCreateContext(client, USE_SEL);
+ case X_SELinuxGetSelectionContext:
+ return ProcSELinuxGetSelectionContext(client, objectKey);
+ case X_SELinuxGetSelectionDataContext:
+ return ProcSELinuxGetSelectionContext(client, dataKey);
+ case X_SELinuxListSelections:
+ return ProcSELinuxListSelections(client);
+ case X_SELinuxGetClientContext:
+ return ProcSELinuxGetClientContext(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+SProcSELinuxQueryVersion(ClientPtr client)
+{
+ REQUEST(SELinuxQueryVersionReq);
+ int n;
+
+ REQUEST_SIZE_MATCH(SELinuxQueryVersionReq);
+ swaps(&stuff->client_major, n);
+ swaps(&stuff->client_minor, n);
+ return ProcSELinuxQueryVersion(client);
+}
+
+static int
+SProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
+{
+ REQUEST(SELinuxSetCreateContextReq);
+ int n;
+
+ REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq);
+ swapl(&stuff->context_len, n);
+ return ProcSELinuxSetCreateContext(client, offset);
+}
+
+static int
+SProcSELinuxSetDeviceContext(ClientPtr client)
+{
+ REQUEST(SELinuxSetContextReq);
+ int n;
+
+ REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq);
+ swapl(&stuff->id, n);
+ swapl(&stuff->context_len, n);
+ return ProcSELinuxSetDeviceContext(client);
+}
+
+static int
+SProcSELinuxGetDeviceContext(ClientPtr client)
+{
+ REQUEST(SELinuxGetContextReq);
+ int n;
+
+ REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+ swapl(&stuff->id, n);
+ return ProcSELinuxGetDeviceContext(client);
+}
+
+static int
+SProcSELinuxGetWindowContext(ClientPtr client)
+{
+ REQUEST(SELinuxGetContextReq);
+ int n;
+
+ REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+ swapl(&stuff->id, n);
+ return ProcSELinuxGetWindowContext(client);
+}
+
+static int
+SProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey)
+{
+ REQUEST(SELinuxGetPropertyContextReq);
+ int n;
+
+ REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq);
+ swapl(&stuff->window, n);
+ swapl(&stuff->property, n);
+ return ProcSELinuxGetPropertyContext(client, privKey);
+}
+
+static int
+SProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey)
+{
+ REQUEST(SELinuxGetContextReq);
+ int n;
+
+ REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+ swapl(&stuff->id, n);
+ return ProcSELinuxGetSelectionContext(client, privKey);
+}
+
+static int
+SProcSELinuxListProperties(ClientPtr client)
+{
+ REQUEST(SELinuxGetContextReq);
+ int n;
+
+ REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+ swapl(&stuff->id, n);
+ return ProcSELinuxListProperties(client);
+}
+
+static int
+SProcSELinuxGetClientContext(ClientPtr client)
+{
+ REQUEST(SELinuxGetContextReq);
+ int n;
+
+ REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+ swapl(&stuff->id, n);
+ return ProcSELinuxGetClientContext(client);
+}
+
+static int
+SProcSELinuxDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ int n;
+
+ swaps(&stuff->length, n);
+
+ switch (stuff->data) {
+ case X_SELinuxQueryVersion:
+ return SProcSELinuxQueryVersion(client);
+ case X_SELinuxSetDeviceCreateContext:
+ return SProcSELinuxSetCreateContext(client, CTX_DEV);
+ case X_SELinuxGetDeviceCreateContext:
+ return ProcSELinuxGetCreateContext(client, CTX_DEV);
+ case X_SELinuxSetDeviceContext:
+ return SProcSELinuxSetDeviceContext(client);
+ case X_SELinuxGetDeviceContext:
+ return SProcSELinuxGetDeviceContext(client);
+ case X_SELinuxSetWindowCreateContext:
+ return SProcSELinuxSetCreateContext(client, CTX_WIN);
+ case X_SELinuxGetWindowCreateContext:
+ return ProcSELinuxGetCreateContext(client, CTX_WIN);
+ case X_SELinuxGetWindowContext:
+ return SProcSELinuxGetWindowContext(client);
+ case X_SELinuxSetPropertyCreateContext:
+ return SProcSELinuxSetCreateContext(client, CTX_PRP);
+ case X_SELinuxGetPropertyCreateContext:
+ return ProcSELinuxGetCreateContext(client, CTX_PRP);
+ case X_SELinuxSetPropertyUseContext:
+ return SProcSELinuxSetCreateContext(client, USE_PRP);
+ case X_SELinuxGetPropertyUseContext:
+ return ProcSELinuxGetCreateContext(client, USE_PRP);
+ case X_SELinuxGetPropertyContext:
+ return SProcSELinuxGetPropertyContext(client, objectKey);
+ case X_SELinuxGetPropertyDataContext:
+ return SProcSELinuxGetPropertyContext(client, dataKey);
+ case X_SELinuxListProperties:
+ return SProcSELinuxListProperties(client);
+ case X_SELinuxSetSelectionCreateContext:
+ return SProcSELinuxSetCreateContext(client, CTX_SEL);
+ case X_SELinuxGetSelectionCreateContext:
+ return ProcSELinuxGetCreateContext(client, CTX_SEL);
+ case X_SELinuxSetSelectionUseContext:
+ return SProcSELinuxSetCreateContext(client, USE_SEL);
+ case X_SELinuxGetSelectionUseContext:
+ return ProcSELinuxGetCreateContext(client, USE_SEL);
+ case X_SELinuxGetSelectionContext:
+ return SProcSELinuxGetSelectionContext(client, objectKey);
+ case X_SELinuxGetSelectionDataContext:
+ return SProcSELinuxGetSelectionContext(client, dataKey);
+ case X_SELinuxListSelections:
+ return ProcSELinuxListSelections(client);
+ case X_SELinuxGetClientContext:
+ return SProcSELinuxGetClientContext(client);
+ default:
+ return BadRequest;
+ }
+}
+
+
+/*
+ * Extension Setup / Teardown
+ */
+
+static void
+SELinuxResetProc(ExtensionEntry *extEntry)
+{
+ /* Unregister callbacks */
+ DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL);
+ DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL);
+
+ XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL);
+ XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL);
+ XaceDeleteCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL);
+ XaceDeleteCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL);
+ XaceDeleteCallback(XACE_SEND_ACCESS, SELinuxSend, NULL);
+ XaceDeleteCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL);
+ XaceDeleteCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL);
+ XaceDeleteCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL);
+ XaceDeleteCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL);
+ XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
+ XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL);
+ XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep);
+
+ /* Tear down SELinux stuff */
+ selabel_close(label_hnd);
+ label_hnd = NULL;
+
+ audit_close(audit_fd);
+
+ avc_destroy();
+ avc_active = 0;
+
+ /* Free local state */
+ xfree(knownAtoms);
+ knownAtoms = NULL;
+ numKnownAtoms = 0;
+
+ xfree(knownEvents);
+ knownEvents = NULL;
+ numKnownEvents = 0;
+
+ xfree(knownTypes);
+ knownTypes = NULL;
+ numKnownTypes = 0;
+}
+
+void
+SELinuxExtensionInit(INITARGS)
+{
+ ExtensionEntry *extEntry;
+ struct selinux_opt selabel_option = { SELABEL_OPT_VALIDATE, (char *)1 };
+ struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 };
+ security_context_t con;
+ int ret = TRUE;
+
+ /* Check SELinux mode on system */
+ if (!is_selinux_enabled()) {
+ ErrorF("SELinux: Disabled on system, not enabling in X server\n");
+ return;
+ }
+
+ /* Check SELinux mode in configuration file */
+ switch(selinuxEnforcingState) {
+ case SELINUX_MODE_DISABLED:
+ LogMessage(X_INFO, "SELinux: Disabled in configuration file\n");
+ return;
+ case SELINUX_MODE_ENFORCING:
+ LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n");
+ avc_option.value = (char *)1;
+ break;
+ case SELINUX_MODE_PERMISSIVE:
+ LogMessage(X_INFO, "SELinux: Configured in permissive mode\n");
+ avc_option.value = (char *)0;
+ break;
+ default:
+ avc_option.type = AVC_OPT_UNUSED;
+ break;
+ }
+
+ /* Set up SELinux stuff */
+ selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog);
+ selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit);
+
+ if (selinux_set_mapping(map) < 0) {
+ if (errno == EINVAL) {
+ ErrorF("SELinux: Invalid object class mapping, disabling SELinux support.\n");
+ return;
+ }
+ FatalError("SELinux: Failed to set up security class mapping\n");
+ }
+
+ if (avc_open(&avc_option, 1) < 0)
+ FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n");
+ avc_active = 1;
+
+ label_hnd = selabel_open(SELABEL_CTX_X, &selabel_option, 1);
+ if (!label_hnd)
+ FatalError("SELinux: Failed to open x_contexts mapping in policy\n");
+
+ if (security_get_initial_context("unlabeled", &con) < 0)
+ FatalError("SELinux: Failed to look up unlabeled context\n");
+ if (avc_context_to_sid(con, &unlabeled_sid) < 0)
+ FatalError("SELinux: a context_to_SID call failed!\n");
+ freecon(con);
+
+ /* Prepare for auditing */
+ audit_fd = audit_open();
+ if (audit_fd < 0)
+ FatalError("SELinux: Failed to open the system audit log\n");
+
+ /* Allocate private storage */
+ if (!dixRequestPrivate(subjectKey, sizeof(SELinuxSubjectRec)) ||
+ !dixRequestPrivate(objectKey, sizeof(SELinuxObjectRec)) ||
+ !dixRequestPrivate(dataKey, sizeof(SELinuxObjectRec)))
+ FatalError("SELinux: Failed to allocate private storage.\n");
+
+ /* Create atoms for doing window labeling */
+ atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE);
+ if (atom_ctx == BAD_RESOURCE)
+ FatalError("SELinux: Failed to create atom\n");
+ atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE);
+ if (atom_client_ctx == BAD_RESOURCE)
+ FatalError("SELinux: Failed to create atom\n");
+
+ /* Register callbacks */
+ ret &= dixRegisterPrivateInitFunc(subjectKey, SELinuxSubjectInit, NULL);
+ ret &= dixRegisterPrivateDeleteFunc(subjectKey, SELinuxSubjectFree, NULL);
+ ret &= dixRegisterPrivateInitFunc(objectKey, SELinuxObjectInit, NULL);
+ ret &= dixRegisterPrivateDeleteFunc(objectKey, SELinuxObjectFree, NULL);
+ ret &= dixRegisterPrivateInitFunc(dataKey, SELinuxObjectInit, NULL);
+ ret &= dixRegisterPrivateDeleteFunc(dataKey, SELinuxObjectFree, NULL);
+
+ ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL);
+ ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL);
+
+ ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL);
+ ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL);
+ ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL);
+ ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL);
+ ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, NULL);
+ ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL);
+ ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL);
+ ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL);
+ ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL);
+ ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
+ ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL);
+ ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep);
+ if (!ret)
+ FatalError("SELinux: Failed to register one or more callbacks\n");
+
+ /* Add extension to server */
+ extEntry = AddExtension(SELINUX_EXTENSION_NAME,
+ SELinuxNumberEvents, SELinuxNumberErrors,
+ ProcSELinuxDispatch, SProcSELinuxDispatch,
+ SELinuxResetProc, StandardMinorOpcode);
+
+ AddExtensionAlias("Flask", extEntry);
+
+ /* Label objects that were created before we could register ourself */
+ SELinuxLabelInitial();
+}
diff --git a/xorg-server/Xext/xselinux.h b/xorg-server/Xext/xselinux.h
new file mode 100644
index 000000000..7c3ffdcb7
--- /dev/null
+++ b/xorg-server/Xext/xselinux.h
@@ -0,0 +1,159 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@epoch.ncsc.mil>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+this permission notice appear in supporting documentation. 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
+AUTHOR 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.
+
+********************************************************/
+
+#ifndef _XSELINUX_H
+#define _XSELINUX_H
+
+#include "dixaccess.h"
+
+/* Extension info */
+#define SELINUX_EXTENSION_NAME "SELinux"
+#define SELINUX_MAJOR_VERSION 1
+#define SELINUX_MINOR_VERSION 0
+#define SELinuxNumberEvents 0
+#define SELinuxNumberErrors 0
+
+/* Extension protocol */
+#define X_SELinuxQueryVersion 0
+#define X_SELinuxSetDeviceCreateContext 1
+#define X_SELinuxGetDeviceCreateContext 2
+#define X_SELinuxSetDeviceContext 3
+#define X_SELinuxGetDeviceContext 4
+#define X_SELinuxSetWindowCreateContext 5
+#define X_SELinuxGetWindowCreateContext 6
+#define X_SELinuxGetWindowContext 7
+#define X_SELinuxSetPropertyCreateContext 8
+#define X_SELinuxGetPropertyCreateContext 9
+#define X_SELinuxSetPropertyUseContext 10
+#define X_SELinuxGetPropertyUseContext 11
+#define X_SELinuxGetPropertyContext 12
+#define X_SELinuxGetPropertyDataContext 13
+#define X_SELinuxListProperties 14
+#define X_SELinuxSetSelectionCreateContext 15
+#define X_SELinuxGetSelectionCreateContext 16
+#define X_SELinuxSetSelectionUseContext 17
+#define X_SELinuxGetSelectionUseContext 18
+#define X_SELinuxGetSelectionContext 19
+#define X_SELinuxGetSelectionDataContext 20
+#define X_SELinuxListSelections 21
+#define X_SELinuxGetClientContext 22
+
+typedef struct {
+ CARD8 reqType;
+ CARD8 SELinuxReqType;
+ CARD16 length;
+ CARD8 client_major;
+ CARD8 client_minor;
+} SELinuxQueryVersionReq;
+
+typedef struct {
+ CARD8 type;
+ CARD8 pad1;
+ CARD16 sequenceNumber;
+ CARD32 length;
+ CARD16 server_major;
+ CARD16 server_minor;
+ CARD32 pad2;
+ CARD32 pad3;
+ CARD32 pad4;
+ CARD32 pad5;
+ CARD32 pad6;
+} SELinuxQueryVersionReply;
+
+typedef struct {
+ CARD8 reqType;
+ CARD8 SELinuxReqType;
+ CARD16 length;
+ CARD32 context_len;
+} SELinuxSetCreateContextReq;
+
+typedef struct {
+ CARD8 reqType;
+ CARD8 SELinuxReqType;
+ CARD16 length;
+} SELinuxGetCreateContextReq;
+
+typedef struct {
+ CARD8 reqType;
+ CARD8 SELinuxReqType;
+ CARD16 length;
+ CARD32 id;
+ CARD32 context_len;
+} SELinuxSetContextReq;
+
+typedef struct {
+ CARD8 reqType;
+ CARD8 SELinuxReqType;
+ CARD16 length;
+ CARD32 id;
+} SELinuxGetContextReq;
+
+typedef struct {
+ CARD8 reqType;
+ CARD8 SELinuxReqType;
+ CARD16 length;
+ CARD32 window;
+ CARD32 property;
+} SELinuxGetPropertyContextReq;
+
+typedef struct {
+ CARD8 type;
+ CARD8 pad1;
+ CARD16 sequenceNumber;
+ CARD32 length;
+ CARD32 context_len;
+ CARD32 pad2;
+ CARD32 pad3;
+ CARD32 pad4;
+ CARD32 pad5;
+ CARD32 pad6;
+} SELinuxGetContextReply;
+
+typedef struct {
+ CARD8 type;
+ CARD8 pad1;
+ CARD16 sequenceNumber;
+ CARD32 length;
+ CARD32 count;
+ CARD32 pad2;
+ CARD32 pad3;
+ CARD32 pad4;
+ CARD32 pad5;
+ CARD32 pad6;
+} SELinuxListItemsReply;
+
+
+/* Private Flask definitions */
+#define SECCLASS_X_DRAWABLE 1
+#define SECCLASS_X_SCREEN 2
+#define SECCLASS_X_GC 3
+#define SECCLASS_X_FONT 4
+#define SECCLASS_X_COLORMAP 5
+#define SECCLASS_X_PROPERTY 6
+#define SECCLASS_X_SELECTION 7
+#define SECCLASS_X_CURSOR 8
+#define SECCLASS_X_CLIENT 9
+#define SECCLASS_X_DEVICE 10
+#define SECCLASS_X_SERVER 11
+#define SECCLASS_X_EXTENSION 12
+#define SECCLASS_X_EVENT 13
+#define SECCLASS_X_FAKEEVENT 14
+#define SECCLASS_X_RESOURCE 15
+
+#endif /* _XSELINUX_H */
diff --git a/xorg-server/Xext/xtest.c b/xorg-server/Xext/xtest.c
new file mode 100644
index 000000000..db6d54543
--- /dev/null
+++ b/xorg-server/Xext/xtest.c
@@ -0,0 +1,591 @@
+/*
+
+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.
+
+*/
+
+#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
+#endif /* XINPUT */
+
+#include "modinit.h"
+
+#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)
+{
+ AddExtension(XTestExtensionName, 0, 0,
+ ProcXTestDispatch, SProcXTestDispatch,
+ XTestResetProc, StandardMinorOpcode);
+}
+
+/*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, rc;
+
+ REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ if (stuff->cursor == None)
+ pCursor = NullCursor;
+ else if (stuff->cursor == XTestCurrentCursor)
+ pCursor = GetSpriteCursor();
+ else {
+ rc = dixLookupResource((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
+ client, DixReadAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->cursor;
+ return (rc == BadValue) ? BadCursor : rc;
+ }
+ }
+ 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, n, type, rc;
+ xEvent *ev;
+ DeviceIntPtr dev = NULL;
+ WindowPtr root;
+#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)
+ {
+ rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client,
+ DixWriteAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->deviceid & 0177;
+ return rc;
+ }
+ 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 = inputInfo.keyboard;
+ 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 = inputInfo.pointer;
+ if (ev->u.keyButtonPointer.root == None)
+ root = GetCurrentRootWindow();
+ else
+ {
+ rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root, client,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ 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);
+ dev->valuator->lastx = ev->u.keyButtonPointer.rootX;
+ dev->valuator->lasty = ev->u.keyButtonPointer.rootY;
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+#ifdef XINPUT
+ if (!extension)
+#endif /* XINPUT */
+ dev = inputInfo.pointer;
+ 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)
+ dixSaveScreens(serverClient, 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/xorg-server/Xext/xvdisp.c b/xorg-server/Xext/xvdisp.c
new file mode 100644
index 000000000..de0128e14
--- /dev/null
+++ b/xorg-server/Xext/xvdisp.c
@@ -0,0 +1,2055 @@
+/***********************************************************
+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.
+******************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#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
+
+#include "xvdisp.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+
+unsigned long XvXRTPort;
+#endif
+
+static int
+SWriteQueryExtensionReply(
+ ClientPtr client,
+ xvQueryExtensionReply *rep
+){
+ 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
+){
+ 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
+){
+ 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
+){
+ 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
+){
+ 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
+){
+ char n;
+
+ swapl(&pFormat->visual, n);
+ (void)WriteToClient(client, sz_xvFormat, (char *)pFormat);
+
+ return Success;
+}
+
+static int
+SWriteAttributeInfo(
+ ClientPtr client,
+ xvAttributeInfo *pAtt
+){
+ 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
+){
+ 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
+){
+ 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
+){
+ 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
+){
+ 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
+){
+ 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
+){
+ 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
+){
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swapl(&rep->num_formats, n);
+
+ (void)WriteToClient(client, sz_xvListImageFormatsReply, (char *)rep);
+
+ return Success;
+}
+
+#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
+
+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, na, nf, rc;
+ int nameSize;
+ XvAdaptorPtr pa;
+ XvFormatPtr pf;
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ XvScreenPtr pxvs;
+
+ REQUEST(xvQueryAdaptorsReq);
+ REQUEST_SIZE_MATCH(xvQueryAdaptorsReq);
+
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ pScreen = pWin->drawable.pScreen;
+ pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ XvGetScreenKey());
+ 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 = nameSize = strlen(pa->name);
+ ainfo.num_formats = pa->nFormats;
+
+ _WriteAdaptorInfo(client, &ainfo);
+
+ WriteToClient(client, nameSize, 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;
+ int nameSize;
+ 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 = nameSize = 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, nameSize, pe->name);
+ pe++;
+ }
+
+ return (client->noClientException);
+}
+
+static int
+ProcXvPutVideo(ClientPtr client)
+{
+ DrawablePtr pDraw;
+ XvPortPtr pPort;
+ GCPtr pGC;
+ int status;
+
+ REQUEST(xvPutVideoReq);
+ REQUEST_SIZE_MATCH(xvPutVideoReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+
+ 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)
+{
+ DrawablePtr pDraw;
+ XvPortPtr pPort;
+ GCPtr pGC;
+ int status;
+
+ REQUEST(xvPutStillReq);
+ REQUEST_SIZE_MATCH(xvPutStillReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+
+ 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)
+{
+ DrawablePtr pDraw;
+ XvPortPtr pPort;
+ GCPtr pGC;
+ int status;
+
+ REQUEST(xvGetVideoReq);
+ REQUEST_SIZE_MATCH(xvGetVideoReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixReadAccess);
+
+ 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)
+{
+ DrawablePtr pDraw;
+ XvPortPtr pPort;
+ GCPtr pGC;
+ int status;
+
+ REQUEST(xvGetStillReq);
+ REQUEST_SIZE_MATCH(xvGetStillReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixReadAccess);
+
+ 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)
+{
+ DrawablePtr pDraw;
+ int rc;
+ REQUEST(xvSelectVideoNotifyReq);
+ REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq);
+
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixReceiveAccess);
+ if (rc != Success)
+ return rc;
+
+ 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, rc;
+ 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);
+ }
+
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ 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 < pPort->pAdaptor->nAttributes; i++, pAtt++)
+ {
+ rep.text_size += (strlen(pAtt->name) + 1 + 3) & ~3L;
+ }
+
+ rep.length = (pPort->pAdaptor->nAttributes * sz_xvAttributeInfo)
+ + rep.text_size;
+ rep.length >>= 2;
+
+ _WriteQueryPortAttributesReply(client, &rep);
+
+ for(i = 0, pAtt = pPort->pAdaptor->pAttributes;
+ i < pPort->pAdaptor->nAttributes; 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, DixWriteAccess);
+
+ 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, DixWriteAccess);
+
+ 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;
+}
+#else /* !MITSHM */
+static int
+ProcXvShmPutImage(ClientPtr client)
+{
+ SendErrorToClient(client, XvReqCode, xv_ShmPutImage, 0, BadImplementation);
+ return(BadImplementation);
+}
+#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;
+ int planeLength;
+ 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 = planeLength = 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, planeLength);
+ WriteToClient(client, planeLength << 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 = pPort->pAdaptor->nImages * sz_xvImageFormatInfo >> 2;
+
+ _WriteListImageFormatsReply(client, &rep);
+
+ pImage = pPort->pAdaptor->pImages;
+
+ for(i = 0; i < pPort->pAdaptor->nImages; 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;
+}
+
+static int (*XvProcVector[xvNumRequests])(ClientPtr) = {
+ ProcXvQueryExtension,
+ ProcXvQueryAdaptors,
+ ProcXvQueryEncodings,
+ ProcXvGrabPort,
+ ProcXvUngrabPort,
+ ProcXvPutVideo,
+ ProcXvPutStill,
+ ProcXvGetVideo,
+ ProcXvGetStill,
+ ProcXvStopVideo,
+ ProcXvSelectVideoNotify,
+ ProcXvSelectPortNotify,
+ ProcXvQueryBestSize,
+ ProcXvSetPortAttribute,
+ ProcXvGetPortAttribute,
+ ProcXvQueryPortAttributes,
+ ProcXvListImageFormats,
+ ProcXvQueryImageAttributes,
+ ProcXvPutImage,
+ ProcXvShmPutImage,
+};
+
+int
+ProcXvDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+
+ UpdateCurrentTime();
+
+ if (stuff->data > xvNumRequests) {
+ SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest);
+ return(BadRequest);
+ }
+
+ return XvProcVector[stuff->data](client);
+}
+
+/* Swapped Procs */
+
+static int
+SProcXvQueryExtension(ClientPtr client)
+{
+ char n;
+ REQUEST(xvQueryExtensionReq);
+ swaps(&stuff->length, n);
+ return XvProcVector[xv_QueryExtension](client);
+}
+
+static int
+SProcXvQueryAdaptors(ClientPtr client)
+{
+ char n;
+ REQUEST(xvQueryAdaptorsReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->window, n);
+ return XvProcVector[xv_QueryAdaptors](client);
+}
+
+static int
+SProcXvQueryEncodings(ClientPtr client)
+{
+ char n;
+ REQUEST(xvQueryEncodingsReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->port, n);
+ return XvProcVector[xv_QueryEncodings](client);
+}
+
+static int
+SProcXvGrabPort(ClientPtr client)
+{
+ char n;
+ REQUEST(xvGrabPortReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->port, n);
+ swapl(&stuff->time, n);
+ return XvProcVector[xv_GrabPort](client);
+}
+
+static int
+SProcXvUngrabPort(ClientPtr client)
+{
+ char n;
+ REQUEST(xvUngrabPortReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->port, n);
+ swapl(&stuff->time, n);
+ return XvProcVector[xv_UngrabPort](client);
+}
+
+static int
+SProcXvPutVideo(ClientPtr client)
+{
+ 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 XvProcVector[xv_PutVideo](client);
+}
+
+static int
+SProcXvPutStill(ClientPtr client)
+{
+ 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 XvProcVector[xv_PutStill](client);
+}
+
+static int
+SProcXvGetVideo(ClientPtr client)
+{
+ 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 XvProcVector[xv_GetVideo](client);
+}
+
+static int
+SProcXvGetStill(ClientPtr client)
+{
+ 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 XvProcVector[xv_GetStill](client);
+}
+
+static int
+SProcXvPutImage(ClientPtr client)
+{
+ 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 XvProcVector[xv_PutImage](client);
+}
+
+#ifdef MITSHM
+static int
+SProcXvShmPutImage(ClientPtr client)
+{
+ 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);
+ swapl(&stuff->offset, 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 XvProcVector[xv_ShmPutImage](client);
+}
+#else /* MITSHM */
+#define SProcXvShmPutImage ProcXvShmPutImage
+#endif
+
+static int
+SProcXvSelectVideoNotify(ClientPtr client)
+{
+ char n;
+ REQUEST(xvSelectVideoNotifyReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->drawable, n);
+ return XvProcVector[xv_SelectVideoNotify](client);
+}
+
+static int
+SProcXvSelectPortNotify(ClientPtr client)
+{
+ char n;
+ REQUEST(xvSelectPortNotifyReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->port, n);
+ return XvProcVector[xv_SelectPortNotify](client);
+}
+
+static int
+SProcXvStopVideo(ClientPtr client)
+{
+ char n;
+ REQUEST(xvStopVideoReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->port, n);
+ swapl(&stuff->drawable, n);
+ return XvProcVector[xv_StopVideo](client);
+}
+
+static int
+SProcXvSetPortAttribute(ClientPtr client)
+{
+ char n;
+ REQUEST(xvSetPortAttributeReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->port, n);
+ swapl(&stuff->attribute, n);
+ swapl(&stuff->value, n);
+ return XvProcVector[xv_SetPortAttribute](client);
+}
+
+static int
+SProcXvGetPortAttribute(ClientPtr client)
+{
+ char n;
+ REQUEST(xvGetPortAttributeReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->port, n);
+ swapl(&stuff->attribute, n);
+ return XvProcVector[xv_GetPortAttribute](client);
+}
+
+static int
+SProcXvQueryBestSize(ClientPtr client)
+{
+ 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 XvProcVector[xv_QueryBestSize](client);
+}
+
+static int
+SProcXvQueryPortAttributes(ClientPtr client)
+{
+ char n;
+ REQUEST(xvQueryPortAttributesReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->port, n);
+ return XvProcVector[xv_QueryPortAttributes](client);
+}
+
+static int
+SProcXvQueryImageAttributes(ClientPtr client)
+{
+ char n;
+ REQUEST(xvQueryImageAttributesReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->port, n);
+ swapl(&stuff->id, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ return XvProcVector[xv_QueryImageAttributes](client);
+}
+
+static int
+SProcXvListImageFormats(ClientPtr client)
+{
+ char n;
+ REQUEST(xvListImageFormatsReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->port, n);
+ return XvProcVector[xv_ListImageFormats](client);
+}
+
+static int (*SXvProcVector[xvNumRequests])(ClientPtr) = {
+ SProcXvQueryExtension,
+ SProcXvQueryAdaptors,
+ SProcXvQueryEncodings,
+ SProcXvGrabPort,
+ SProcXvUngrabPort,
+ SProcXvPutVideo,
+ SProcXvPutStill,
+ SProcXvGetVideo,
+ SProcXvGetStill,
+ SProcXvStopVideo,
+ SProcXvSelectVideoNotify,
+ SProcXvSelectPortNotify,
+ SProcXvQueryBestSize,
+ SProcXvSetPortAttribute,
+ SProcXvGetPortAttribute,
+ SProcXvQueryPortAttributes,
+ SProcXvListImageFormats,
+ SProcXvQueryImageAttributes,
+ SProcXvPutImage,
+ SProcXvShmPutImage,
+};
+
+int
+SProcXvDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+
+ UpdateCurrentTime();
+
+ if (stuff->data > xvNumRequests) {
+ SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest);
+ return(BadRequest);
+ }
+
+ return SXvProcVector[stuff->data](client);
+}
+
+#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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(!(port = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->port, XvXRTPort, DixReadAccess)))
+ 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, DixReadAccess)))
+ 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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ return BadGC;
+
+ if(!(port = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->port, XvXRTPort, DixReadAccess)))
+ 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;
+}
+#else
+#define XineramaXvShmPutImage ProcXvShmPutImage
+#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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ return BadGC;
+
+ if(!(port = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->port, XvXRTPort, DixReadAccess)))
+ 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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ return BadGC;
+
+ if(!(port = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->port, XvXRTPort, DixReadAccess)))
+ 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, DixWriteAccess)))
+ return BadDrawable;
+
+ if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->gc, XRT_GC, DixReadAccess)))
+ return BadGC;
+
+ if(!(port = (PanoramiXRes *)SecurityLookupIDByType(
+ client, stuff->port, XvXRTPort, DixReadAccess)))
+ 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)dixLookupPrivate(&screen0->devPrivates,
+ XvGetScreenKey());
+ 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)dixLookupPrivate(&pScreen->devPrivates,
+ XvGetScreenKey());
+ /* 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;
+ }
+ }
+ }
+
+ /* munge the dispatch vector */
+ XvProcVector[xv_PutVideo] = XineramaXvPutVideo;
+ XvProcVector[xv_PutStill] = XineramaXvPutStill;
+ XvProcVector[xv_StopVideo] = XineramaXvStopVideo;
+ XvProcVector[xv_SetPortAttribute] = XineramaXvSetPortAttribute;
+ XvProcVector[xv_PutImage] = XineramaXvPutImage;
+ XvProcVector[xv_ShmPutImage] = XineramaXvShmPutImage;
+}
+#endif /* PANORAMIX */
+
+void
+XvResetProcVector(void)
+{
+#ifdef PANORAMIX
+ XvProcVector[xv_PutVideo] = ProcXvPutVideo;
+ XvProcVector[xv_PutStill] = ProcXvPutStill;
+ XvProcVector[xv_StopVideo] = ProcXvStopVideo;
+ XvProcVector[xv_SetPortAttribute] = ProcXvSetPortAttribute;
+ XvProcVector[xv_PutImage] = ProcXvPutImage;
+ XvProcVector[xv_ShmPutImage] = ProcXvShmPutImage;
+#endif
+}
diff --git a/xorg-server/Xext/xvdisp.h b/xorg-server/Xext/xvdisp.h
new file mode 100644
index 000000000..298d39560
--- /dev/null
+++ b/xorg-server/Xext/xvdisp.h
@@ -0,0 +1,2 @@
+extern void XineramifyXv(void);
+extern void XvResetProcVector(void);
diff --git a/xorg-server/Xext/xvdix.h b/xorg-server/Xext/xvdix.h
new file mode 100644
index 000000000..a516cf113
--- /dev/null
+++ b/xorg-server/Xext/xvdix.h
@@ -0,0 +1,287 @@
+/***********************************************************
+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.
+
+******************************************************************/
+
+#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 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) \
+ dixLookupPrivate(&(pScreen)->devPrivates, XvScreenKey))->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 DevPrivateKey XvGetScreenKey(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/xorg-server/Xext/xvmain.c b/xorg-server/Xext/xvmain.c
new file mode 100644
index 000000000..9834fcfa0
--- /dev/null
+++ b/xorg-server/Xext/xvmain.c
@@ -0,0 +1,1187 @@
+/***********************************************************
+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.
+
+******************************************************************/
+
+/*
+** 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 <string.h>
+
+#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 PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+#include "xvdisp.h"
+
+static DevPrivateKey XvScreenKey = &XvScreenKey;
+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(void)
+{
+ 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;
+ }
+#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(void)
+
+{
+
+ 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;
+
+}
+
+_X_EXPORT int
+XvScreenInit(ScreenPtr pScreen)
+{
+ XvScreenPtr pxvs;
+
+ if (XvScreenGeneration != serverGeneration)
+ {
+ if (!CreateResourceTypes())
+ {
+ ErrorF("XvScreenInit: Unable to allocate resource types\n");
+ return BadAlloc;
+ }
+#ifdef PANORAMIX
+ XineramaRegisterConnectionBlockCallback(XineramifyXv);
+#endif
+ XvScreenGeneration = serverGeneration;
+ }
+
+ if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey))
+ {
+ 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;
+ }
+
+ dixSetPrivate(&pScreen->devPrivates, XvScreenKey, 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)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
+
+ pScreen->DestroyPixmap = pxvs->DestroyPixmap;
+ pScreen->DestroyWindow = pxvs->DestroyWindow;
+ pScreen->CloseScreen = pxvs->CloseScreen;
+
+ (* pxvs->ddCloseScreen)(ii, pScreen);
+
+ xfree(pxvs);
+
+ dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL);
+
+ return (*pScreen->CloseScreen)(ii, pScreen);
+}
+
+static void
+XvResetProc(ExtensionEntry* extEntry)
+{
+ XvResetProcVector();
+}
+
+_X_EXPORT DevPrivateKey
+XvGetScreenKey(void)
+{
+ return XvScreenKey;
+}
+
+_X_EXPORT unsigned long
+XvGetRTPort(void)
+{
+ 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)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
+
+ /* 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)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
+
+ /* 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/xorg-server/Xext/xvmc.c b/xorg-server/Xext/xvmc.c
new file mode 100644
index 000000000..7ae8cc0da
--- /dev/null
+++ b/xorg-server/Xext/xvmc.c
@@ -0,0 +1,792 @@
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#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
+
+static DevPrivateKey XvMCScreenKey = NULL;
+
+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)(dixLookupPrivate(&(pScreen)->devPrivates, XvMCScreenKey))
+
+
+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(XvMCScreenKey) { /* 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(XvMCScreenKey == NULL) /* 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(XvMCScreenKey == NULL) /* 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(void)
+{
+ ExtensionEntry *extEntry;
+
+ if(XvMCScreenKey == NULL) /* 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;
+
+ XvMCScreenKey = &XvMCScreenKey;
+
+ if(!(pScreenPriv = (XvMCScreenPtr)xalloc(sizeof(XvMCScreenRec))))
+ return BadAlloc;
+
+ dixSetPrivate(&pScreen->devPrivates, XvMCScreenKey, 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(XvMCScreenKey == NULL) 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/xorg-server/Xext/xvmcext.h b/xorg-server/Xext/xvmcext.h
new file mode 100644
index 000000000..9c019fee6
--- /dev/null
+++ b/xorg-server/Xext/xvmcext.h
@@ -0,0 +1,115 @@
+
+#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 */