summaryrefslogtreecommitdiff
path: root/Xext
diff options
context:
space:
mode:
Diffstat (limited to 'Xext')
-rw-r--r--Xext/Makefile.am140
-rw-r--r--Xext/Makefile.in930
-rw-r--r--Xext/bigreq.c78
-rw-r--r--Xext/dpms.c379
-rw-r--r--Xext/dpmsproc.h15
-rw-r--r--Xext/dpmsstubs.c45
-rw-r--r--Xext/geext.c262
-rw-r--r--Xext/geext.h83
-rw-r--r--Xext/geint.h53
-rw-r--r--Xext/panoramiX.c1299
-rw-r--r--Xext/panoramiX.h78
-rw-r--r--Xext/panoramiXSwap.c142
-rw-r--r--Xext/panoramiXh.h73
-rw-r--r--Xext/panoramiXprocs.c2428
-rw-r--r--Xext/panoramiXsrv.h54
-rw-r--r--Xext/saver.c1511
-rw-r--r--Xext/security.c1146
-rw-r--r--Xext/securitysrv.h83
-rw-r--r--Xext/shape.c1260
-rw-r--r--Xext/shm.c1327
-rw-r--r--Xext/shmint.h69
-rw-r--r--Xext/sleepuntil.c225
-rw-r--r--Xext/sleepuntil.h46
-rw-r--r--Xext/sync.c2925
-rw-r--r--Xext/syncsdk.h47
-rw-r--r--Xext/syncsrv.h146
-rw-r--r--Xext/xace.c327
-rw-r--r--Xext/xace.h131
-rw-r--r--Xext/xacestr.h147
-rw-r--r--Xext/xcalibrate.c297
-rw-r--r--Xext/xcmisc.c207
-rw-r--r--Xext/xf86bigfont.c750
-rw-r--r--Xext/xf86bigfontsrv.h34
-rw-r--r--Xext/xres.c383
-rw-r--r--Xext/xselinux.h139
-rw-r--r--Xext/xselinux_ext.c732
-rw-r--r--Xext/xselinux_hooks.c935
-rw-r--r--Xext/xselinux_label.c374
-rw-r--r--Xext/xselinuxint.h561
-rw-r--r--Xext/xtest.c689
-rw-r--r--Xext/xvdisp.c1961
-rw-r--r--Xext/xvdisp.h2
-rw-r--r--Xext/xvdix.h275
-rw-r--r--Xext/xvmain.c1185
-rw-r--r--Xext/xvmc.c789
-rw-r--r--Xext/xvmcext.h118
46 files changed, 24880 insertions, 0 deletions
diff --git a/Xext/Makefile.am b/Xext/Makefile.am
new file mode 100644
index 0000000..b6c95cb
--- /dev/null
+++ b/Xext/Makefile.am
@@ -0,0 +1,140 @@
+# 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 geext.h geint.h shmint.h syncsdk.h
+endif
+
+# Sources always included in libXextbuiltin.la & libXext.la
+BUILTIN_SRCS = \
+ bigreq.c \
+ geext.c \
+ shape.c \
+ sleepuntil.c \
+ sleepuntil.h \
+ sync.c \
+ syncsdk.h \
+ syncsrv.h \
+ xcmisc.c \
+ xtest.c
+
+# Sources always included in libXextmodule.la & libXext.la. That's right, zero.
+MODULE_SRCS =
+MODULE_LIBS =
+
+# 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)
+if XORG
+sdk_HEADERS += panoramiXsrv.h panoramiX.h
+endif
+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)
+if XORG
+sdk_HEADERS += xace.h xacestr.h
+endif
+endif
+
+# SELinux extension: provides SELinux policy support for X objects
+# requires X-ACE extension
+XSELINUX_SRCS = xselinux_ext.c xselinux_hooks.c xselinux_label.c xselinux.h xselinuxint.h
+if XSELINUX
+MODULE_SRCS += $(XSELINUX_SRCS)
+MODULE_LIBS += $(SELINUX_LIBS)
+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
+
+# XF86 Big Font extension
+BIGFONT_SRCS = xf86bigfont.c xf86bigfontsrv.h
+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)
+libXext_la_LIBADD = $(MODULE_LIBS)
+
+if XORG
+libXextbuiltin_la_SOURCES = $(BUILTIN_SRCS)
+
+libXextmodule_la_SOURCES = $(MODULE_SRCS)
+libXextmodule_la_LIBADD = $(MODULE_LIBS)
+endif
+
+EXTRA_DIST = \
+ $(MITSHM_SRCS) \
+ $(XV_SRCS) \
+ $(RES_SRCS) \
+ $(SCREENSAVER_SRCS) \
+ $(XACE_SRCS) \
+ $(XCSECURITY_SRCS) \
+ $(XSELINUX_SRCS) \
+ $(XCALIBRATE_SRCS) \
+ $(XINERAMA_SRCS) \
+ $(BIGFONT_SRCS) \
+ $(DPMS_SRCS) \
+ $(GE_SRCS)
+
diff --git a/Xext/Makefile.in b/Xext/Makefile.in
new file mode 100644
index 0000000..b9e63d2
--- /dev/null
+++ b/Xext/Makefile.in
@@ -0,0 +1,930 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@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)
+@XINERAMA_TRUE@@XORG_TRUE@am__append_6 = panoramiXsrv.h panoramiX.h
+@XACE_TRUE@am__append_7 = $(XACE_SRCS)
+@XACE_TRUE@@XORG_TRUE@am__append_8 = xace.h xacestr.h
+@XSELINUX_TRUE@am__append_9 = $(XSELINUX_SRCS)
+@XSELINUX_TRUE@am__append_10 = $(SELINUX_LIBS)
+@XCSECURITY_TRUE@am__append_11 = $(XCSECURITY_SRCS)
+@XCALIBRATE_TRUE@am__append_12 = $(XCALIBRATE_SRCS)
+@XF86BIGFONT_TRUE@am__append_13 = $(BIGFONT_SRCS)
+@DPMSExtension_TRUE@am__append_14 = $(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)/m4/ac_define_dir.m4 \
+ $(top_srcdir)/m4/ax_tls.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/xorg-config.h \
+ $(top_builddir)/include/xkb-config.h \
+ $(top_builddir)/include/xwin-config.h \
+ $(top_builddir)/include/kdrive-config.h \
+ $(top_builddir)/include/version-config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+@XSELINUX_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2)
+libXext_la_DEPENDENCIES = $(am__DEPENDENCIES_3)
+am__libXext_la_SOURCES_DIST = bigreq.c geext.c shape.c sleepuntil.c \
+ sleepuntil.h sync.c syncsdk.h syncsrv.h xcmisc.c 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 xf86bigfont.c \
+ xf86bigfontsrv.h xvmain.c xvdisp.c xvmc.c xvdix.h xvmcext.h \
+ xvdisp.h xres.c saver.c xselinux_ext.c xselinux_hooks.c \
+ xselinux_label.c xselinux.h xselinuxint.h 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 = xf86bigfont.lo
+@XF86BIGFONT_TRUE@am__objects_12 = $(am__objects_11)
+am__objects_13 = bigreq.lo geext.lo shape.lo sleepuntil.lo sync.lo \
+ xcmisc.lo xtest.lo $(am__objects_2) $(am__objects_4) \
+ $(am__objects_6) $(am__objects_8) $(am__objects_10) \
+ $(am__objects_12)
+am__objects_14 = xvmain.lo xvdisp.lo xvmc.lo
+@XV_TRUE@am__objects_15 = $(am__objects_14)
+am__objects_16 = xres.lo
+@RES_TRUE@am__objects_17 = $(am__objects_16)
+am__objects_18 = saver.lo
+@SCREENSAVER_TRUE@am__objects_19 = $(am__objects_18)
+am__objects_20 = xselinux_ext.lo xselinux_hooks.lo xselinux_label.lo
+@XSELINUX_TRUE@am__objects_21 = $(am__objects_20)
+am__objects_22 = dpms.lo
+@DPMSExtension_TRUE@am__objects_23 = $(am__objects_22)
+am__objects_24 = $(am__objects_15) $(am__objects_17) $(am__objects_19) \
+ $(am__objects_21) $(am__objects_23)
+am_libXext_la_OBJECTS = $(am__objects_13) $(am__objects_24)
+libXext_la_OBJECTS = $(am_libXext_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+@XORG_FALSE@am_libXext_la_rpath =
+@XORG_TRUE@am_libXext_la_rpath =
+libXextbuiltin_la_LIBADD =
+am__libXextbuiltin_la_SOURCES_DIST = bigreq.c geext.c shape.c \
+ sleepuntil.c sleepuntil.h sync.c syncsdk.h syncsrv.h xcmisc.c \
+ 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 xf86bigfont.c \
+ xf86bigfontsrv.h
+@XORG_TRUE@am_libXextbuiltin_la_OBJECTS = $(am__objects_13)
+libXextbuiltin_la_OBJECTS = $(am_libXextbuiltin_la_OBJECTS)
+@XORG_TRUE@am_libXextbuiltin_la_rpath =
+@XORG_TRUE@libXextmodule_la_DEPENDENCIES = $(am__DEPENDENCIES_3)
+am__libXextmodule_la_SOURCES_DIST = xvmain.c xvdisp.c xvmc.c xvdix.h \
+ xvmcext.h xvdisp.h xres.c saver.c xselinux_ext.c \
+ xselinux_hooks.c xselinux_label.c xselinux.h xselinuxint.h \
+ dpms.c dpmsproc.h
+@XORG_TRUE@am_libXextmodule_la_OBJECTS = $(am__objects_24)
+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
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+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 geext.h geint.h shmint.h \
+ syncsdk.h panoramiXsrv.h panoramiX.h xace.h xacestr.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 = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(sdkdir)"
+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@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@
+APPLE_APPLICATION_NAME = @APPLE_APPLICATION_NAME@
+APP_MAN_DIR = @APP_MAN_DIR@
+APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
+AR = @AR@
+ARM_BACKTRACE_CFLAGS = @ARM_BACKTRACE_CFLAGS@
+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@
+CHANGELOG_CMD = @CHANGELOG_CMD@
+COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CWARNFLAGS = @CWARNFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DARWIN_LIBS = @DARWIN_LIBS@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DEFAULT_LIBRARY_PATH = @DEFAULT_LIBRARY_PATH@
+DEFAULT_LOGDIR = @DEFAULT_LOGDIR@
+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@
+DIX_LIB = @DIX_LIB@
+DLLTOOL = @DLLTOOL@
+DLOPEN_LIBS = @DLOPEN_LIBS@
+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@
+DOXYGEN = @DOXYGEN@
+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_CFLAGS = @DRI_CFLAGS@
+DRI_DRIVER_PATH = @DRI_DRIVER_PATH@
+DRI_LIBS = @DRI_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DTRACE = @DTRACE@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILE_MAN_DIR = @FILE_MAN_DIR@
+FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+FONT100DPIDIR = @FONT100DPIDIR@
+FONT75DPIDIR = @FONT75DPIDIR@
+FONTMISCDIR = @FONTMISCDIR@
+FONTOTFDIR = @FONTOTFDIR@
+FONTROOTDIR = @FONTROOTDIR@
+FONTTTFDIR = @FONTTTFDIR@
+FONTTYPE1DIR = @FONTTYPE1DIR@
+FOP = @FOP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@
+GLX_DEFINES = @GLX_DEFINES@
+GLX_TLS = @GLX_TLS@
+GL_CFLAGS = @GL_CFLAGS@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+INSTALL = @INSTALL@
+INSTALL_CMD = @INSTALL_CMD@
+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_ID_PREFIX = @LAUNCHD_ID_PREFIX@
+LD = @LD@
+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@
+LIBSHA1_CFLAGS = @LIBSHA1_CFLAGS@
+LIBSHA1_LIBS = @LIBSHA1_LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MAN_DIR = @LIB_MAN_DIR@
+LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAIN_LIB = @MAIN_LIB@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAN_SUBSTS = @MAN_SUBSTS@
+MISC_MAN_DIR = @MISC_MAN_DIR@
+MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCCLD = @OBJCCLD@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJCFLAGS = @OBJCFLAGS@
+OBJCLINK = @OBJCLINK@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OS_LIB = @OS_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+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@
+PIXMAN_CFLAGS = @PIXMAN_CFLAGS@
+PIXMAN_LIBS = @PIXMAN_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROJECTROOT = @PROJECTROOT@
+RANLIB = @RANLIB@
+RAWCPP = @RAWCPP@
+RAWCPPFLAGS = @RAWCPPFLAGS@
+RELEASE_DATE = @RELEASE_DATE@
+SDK_REQUIRED_MODULES = @SDK_REQUIRED_MODULES@
+SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
+SERVER_MISC_CONFIG_PATH = @SERVER_MISC_CONFIG_PATH@
+SET_MAKE = @SET_MAKE@
+SHA1_CFLAGS = @SHA1_CFLAGS@
+SHA1_LIBS = @SHA1_LIBS@
+SHELL = @SHELL@
+SOLARIS_ASM_CFLAGS = @SOLARIS_ASM_CFLAGS@
+SOLARIS_INOUT_ARCH = @SOLARIS_INOUT_ARCH@
+STRIP = @STRIP@
+STYLESHEET_SRCDIR = @STYLESHEET_SRCDIR@
+SYSCONFDIR = @SYSCONFDIR@
+TSLIB_CFLAGS = @TSLIB_CFLAGS@
+TSLIB_LIBS = @TSLIB_LIBS@
+UDEV_CFLAGS = @UDEV_CFLAGS@
+UDEV_LIBS = @UDEV_LIBS@
+UTILS_SYS_LIBS = @UTILS_SYS_LIBS@
+VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@
+VERSION = @VERSION@
+WINDOWSWM_CFLAGS = @WINDOWSWM_CFLAGS@
+WINDOWSWM_LIBS = @WINDOWSWM_LIBS@
+WINDRES = @WINDRES@
+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@
+XEPHYR_CFLAGS = @XEPHYR_CFLAGS@
+XEPHYR_INCS = @XEPHYR_INCS@
+XEPHYR_LIBS = @XEPHYR_LIBS@
+XF86CONFIGDIR = @XF86CONFIGDIR@
+XF86CONFIGFILE = @XF86CONFIGFILE@
+XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@
+XF86VIDMODE_LIBS = @XF86VIDMODE_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@
+XMLTO = @XMLTO@
+XNESTMODULES_CFLAGS = @XNESTMODULES_CFLAGS@
+XNESTMODULES_LIBS = @XNESTMODULES_LIBS@
+XNEST_LIBS = @XNEST_LIBS@
+XNEST_SYS_LIBS = @XNEST_SYS_LIBS@
+XORG_CFLAGS = @XORG_CFLAGS@
+XORG_INCS = @XORG_INCS@
+XORG_LIBS = @XORG_LIBS@
+XORG_MAN_PAGE = @XORG_MAN_PAGE@
+XORG_MODULES_CFLAGS = @XORG_MODULES_CFLAGS@
+XORG_MODULES_LIBS = @XORG_MODULES_LIBS@
+XORG_OS = @XORG_OS@
+XORG_OS_SUBDIR = @XORG_OS_SUBDIR@
+XORG_SGML_PATH = @XORG_SGML_PATH@
+XORG_SYS_LIBS = @XORG_SYS_LIBS@
+XPBPROXY_CFLAGS = @XPBPROXY_CFLAGS@
+XPBPROXY_LIBS = @XPBPROXY_LIBS@
+XQUARTZ_SPARKLE = @XQUARTZ_SPARKLE@
+XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@
+XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_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@
+XSL_STYLESHEET = @XSL_STYLESHEET@
+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@
+__XCONFIGDIR__ = @__XCONFIGDIR__@
+__XCONFIGFILE__ = @__XCONFIGFILE__@
+abi_ansic = @abi_ansic@
+abi_extension = @abi_extension@
+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_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+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@
+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@
+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@
+symbol_visibility = @symbol_visibility@
+sysconfdir = @sysconfdir@
+sysconfigdir = @sysconfigdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+@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 geext.h geint.h shmint.h \
+@XORG_TRUE@ syncsdk.h $(am__append_6) $(am__append_8)
+
+# Sources always included in libXextbuiltin.la & libXext.la
+BUILTIN_SRCS = bigreq.c geext.c shape.c sleepuntil.c sleepuntil.h \
+ sync.c syncsdk.h syncsrv.h xcmisc.c xtest.c $(am__append_1) \
+ $(am__append_5) $(am__append_7) $(am__append_11) \
+ $(am__append_12) $(am__append_13)
+
+# Sources always included in libXextmodule.la & libXext.la. That's right, zero.
+MODULE_SRCS = $(am__append_2) $(am__append_3) $(am__append_4) \
+ $(am__append_9) $(am__append_14)
+MODULE_LIBS = $(am__append_10)
+
+# 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_ext.c xselinux_hooks.c xselinux_label.c xselinux.h xselinuxint.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
+
+# XF86 Big Font extension
+BIGFONT_SRCS = xf86bigfont.c xf86bigfontsrv.h
+
+# 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)
+libXext_la_LIBADD = $(MODULE_LIBS)
+@XORG_TRUE@libXextbuiltin_la_SOURCES = $(BUILTIN_SRCS)
+@XORG_TRUE@libXextmodule_la_SOURCES = $(MODULE_SRCS)
+@XORG_TRUE@libXextmodule_la_LIBADD = $(MODULE_LIBS)
+EXTRA_DIST = \
+ $(MITSHM_SRCS) \
+ $(XV_SRCS) \
+ $(RES_SRCS) \
+ $(SCREENSAVER_SRCS) \
+ $(XACE_SRCS) \
+ $(XCSECURITY_SRCS) \
+ $(XSELINUX_SRCS) \
+ $(XCALIBRATE_SRCS) \
+ $(XINERAMA_SRCS) \
+ $(BIGFONT_SRCS) \
+ $(DPMS_SRCS) \
+ $(GE_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 ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Xext/Makefile'; \
+ $(am__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
+$(am__aclocal_m4_deps):
+
+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)
+ $(AM_V_CCLD)$(LINK) $(am_libXext_la_rpath) $(libXext_la_OBJECTS) $(libXext_la_LIBADD) $(LIBS)
+libXextbuiltin.la: $(libXextbuiltin_la_OBJECTS) $(libXextbuiltin_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(am_libXextbuiltin_la_rpath) $(libXextbuiltin_la_OBJECTS) $(libXextbuiltin_la_LIBADD) $(LIBS)
+libXextmodule.la: $(libXextmodule_la_OBJECTS) $(libXextmodule_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(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)/bigreq.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dpms.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/geext.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)/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)/xf86bigfont.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xres.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xselinux_ext.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xselinux_hooks.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xselinux_label.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@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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)'; test -n "$(sdkdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(sdkdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(sdkdir)" || exit $$?; \
+ done
+
+uninstall-sdkHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sdk_HEADERS)'; test -n "$(sdkdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(sdkdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(sdkdir)" && rm -f $$files
+
+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; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ 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; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ 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)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__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 "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$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)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_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
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-sdkHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+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/Xext/bigreq.c b/Xext/bigreq.c
new file mode 100644
index 0000000..a540bcb
--- /dev/null
+++ b/Xext/bigreq.c
@@ -0,0 +1,78 @@
+/*
+
+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>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include <X11/extensions/bigreqsproto.h>
+#include "opaque.h"
+#include "modinit.h"
+
+void BigReqExtensionInit(INITARGS);
+
+static int
+ProcBigReqDispatch (ClientPtr client)
+{
+ REQUEST(xBigReqEnableReq);
+ xBigReqEnableReply rep;
+ int n;
+
+ if (client->swapped) {
+ swaps(&stuff->length, n);
+ }
+ if (stuff->brReqType != X_BigReqEnable)
+ return BadRequest;
+ REQUEST_SIZE_MATCH(xBigReqEnableReq);
+ client->big_requests = TRUE;
+ memset(&rep, 0, sizeof(xBigReqEnableReply));
+ 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 Success;
+}
+
+void
+BigReqExtensionInit(INITARGS)
+{
+ AddExtension(XBigReqExtensionName, 0, 0,
+ ProcBigReqDispatch, ProcBigReqDispatch,
+ NULL, StandardMinorOpcode);
+}
diff --git a/Xext/dpms.c b/Xext/dpms.c
new file mode 100644
index 0000000..33a6e26
--- /dev/null
+++ b/Xext/dpms.c
@@ -0,0 +1,379 @@
+/*****************************************************************
+
+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 <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "opaque.h"
+#include <X11/extensions/dpmsproto.h>
+#include "dpmsproc.h"
+#include "modinit.h"
+
+static int
+ProcDPMSGetVersion(ClientPtr client)
+{
+ /* REQUEST(xDPMSGetVersionReq); */
+ xDPMSGetVersionReply rep;
+ 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 Success;
+}
+
+static int
+ProcDPMSCapable(ClientPtr client)
+{
+ /* REQUEST(xDPMSCapableReq); */
+ xDPMSCapableReply rep;
+ 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 Success;
+}
+
+static int
+ProcDPMSGetTimeouts(ClientPtr client)
+{
+ /* REQUEST(xDPMSGetTimeoutsReq); */
+ xDPMSGetTimeoutsReply rep;
+ 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 Success;
+}
+
+static int
+ProcDPMSSetTimeouts(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 Success;
+}
+
+static int
+ProcDPMSEnable(ClientPtr client)
+{
+ Bool was_enabled = DPMSEnabled;
+
+ REQUEST_SIZE_MATCH(xDPMSEnableReq);
+
+ if (DPMSCapableFlag) {
+ DPMSEnabled = TRUE;
+ if (!was_enabled)
+ SetScreenSaverTimer();
+ }
+
+ return Success;
+}
+
+static int
+ProcDPMSDisable(ClientPtr client)
+{
+ /* REQUEST(xDPMSDisableReq); */
+
+ REQUEST_SIZE_MATCH(xDPMSDisableReq);
+
+ DPMSSet(client, DPMSModeOn);
+
+ DPMSEnabled = FALSE;
+
+ return Success;
+}
+
+static int
+ProcDPMSForceLevel(ClientPtr client)
+{
+ REQUEST(xDPMSForceLevelReq);
+
+ REQUEST_SIZE_MATCH(xDPMSForceLevelReq);
+
+ if (!DPMSEnabled)
+ return BadMatch;
+
+ if (stuff->level != DPMSModeOn &&
+ stuff->level != DPMSModeStandby &&
+ stuff->level != DPMSModeSuspend &&
+ stuff->level != DPMSModeOff) {
+ client->errorValue = stuff->level;
+ return BadValue;
+ }
+
+ DPMSSet(client, stuff->level);
+
+ return Success;
+}
+
+static int
+ProcDPMSInfo(ClientPtr client)
+{
+ /* REQUEST(xDPMSInfoReq); */
+ xDPMSInfoReply rep;
+ 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 Success;
+}
+
+static int
+ProcDPMSDispatch (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(ClientPtr client)
+{
+ 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(ClientPtr client)
+{
+ REQUEST(xDPMSCapableReq);
+ int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSCapableReq);
+
+ return ProcDPMSCapable(client);
+}
+
+static int
+SProcDPMSGetTimeouts(ClientPtr client)
+{
+ REQUEST(xDPMSGetTimeoutsReq);
+ int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq);
+
+ return ProcDPMSGetTimeouts(client);
+}
+
+static int
+SProcDPMSSetTimeouts(ClientPtr client)
+{
+ REQUEST(xDPMSSetTimeoutsReq);
+ 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(ClientPtr client)
+{
+ REQUEST(xDPMSEnableReq);
+ int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSEnableReq);
+
+ return ProcDPMSEnable(client);
+}
+
+static int
+SProcDPMSDisable(ClientPtr client)
+{
+ REQUEST(xDPMSDisableReq);
+ int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSDisableReq);
+
+ return ProcDPMSDisable(client);
+}
+
+static int
+SProcDPMSForceLevel(ClientPtr client)
+{
+ REQUEST(xDPMSForceLevelReq);
+ int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSForceLevelReq);
+
+ swaps(&stuff->level, n);
+
+ return ProcDPMSForceLevel(client);
+}
+
+static int
+SProcDPMSInfo(ClientPtr client)
+{
+ REQUEST(xDPMSInfoReq);
+ int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSInfoReq);
+
+ return ProcDPMSInfo(client);
+}
+
+static int
+SProcDPMSDispatch (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;
+ }
+}
+
+void
+DPMSExtensionInit(INITARGS)
+{
+ AddExtension(DPMSExtensionName, 0, 0,
+ ProcDPMSDispatch, SProcDPMSDispatch,
+ NULL, StandardMinorOpcode);
+}
diff --git a/Xext/dpmsproc.h b/Xext/dpmsproc.h
new file mode 100644
index 0000000..c1df56f
--- /dev/null
+++ b/Xext/dpmsproc.h
@@ -0,0 +1,15 @@
+/* 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);
+Bool DPMSSupported(void);
+
+#endif
diff --git a/Xext/dpmsstubs.c b/Xext/dpmsstubs.c
new file mode 100644
index 0000000..f0f54d2
--- /dev/null
+++ b/Xext/dpmsstubs.c
@@ -0,0 +1,45 @@
+/*****************************************************************
+
+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 DPMSSet(ClientPtr client, int level)
+{
+ return Success;
+}
diff --git a/Xext/geext.c b/Xext/geext.c
new file mode 100644
index 0000000..a6fbb09
--- /dev/null
+++ b/Xext/geext.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * 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 (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR 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.
+ *
+ * Author: Peter Hutterer, University of South Australia, NICTA
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+#include "windowstr.h"
+#include <X11/extensions/ge.h>
+
+#include "geint.h"
+#include "geext.h"
+#include "protocol-versions.h"
+
+DevPrivateKeyRec GEClientPrivateKeyRec;
+
+int RT_GECLIENT = 0;
+
+GEExtension GEExtensions[MAXEXTENSIONS];
+
+/* Major available requests */
+static const int version_requests[] = {
+ X_GEQueryVersion, /* before client sends QueryVersion */
+ X_GEQueryVersion, /* must be set to last request in version 1 */
+};
+
+/* Forward declarations */
+static void SGEGenericEvent(xEvent* from, xEvent* to);
+
+#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
+
+/************************************************************/
+/* request handlers */
+/************************************************************/
+
+static int
+ProcGEQueryVersion(ClientPtr client)
+{
+ int n;
+ GEClientInfoPtr pGEClient = GEGetClient(client);
+ xGEQueryVersionReply rep;
+ REQUEST(xGEQueryVersionReq);
+
+ REQUEST_SIZE_MATCH(xGEQueryVersionReq);
+
+ rep.repType = X_Reply;
+ rep.RepType = X_GEQueryVersion;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ /* return the supported version by the server */
+ rep.majorVersion = SERVER_GE_MAJOR_VERSION;
+ rep.minorVersion = SERVER_GE_MINOR_VERSION;
+
+ /* Remember version the client requested */
+ pGEClient->major_version = stuff->majorVersion;
+ pGEClient->minor_version = stuff->minorVersion;
+
+ if (client->swapped)
+ {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+
+ WriteToClient(client, sizeof(xGEQueryVersionReply), (char*)&rep);
+ return Success;
+}
+
+int (*ProcGEVector[GENumberRequests])(ClientPtr) = {
+ /* Version 1.0 */
+ ProcGEQueryVersion
+};
+
+/************************************************************/
+/* swapped request handlers */
+/************************************************************/
+static int
+SProcGEQueryVersion(ClientPtr client)
+{
+ int n;
+ REQUEST(xGEQueryVersionReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xGEQueryVersionReq);
+ swaps(&stuff->majorVersion, n);
+ swaps(&stuff->minorVersion, n);
+ return(*ProcGEVector[stuff->ReqType])(client);
+}
+
+int (*SProcGEVector[GENumberRequests])(ClientPtr) = {
+ /* Version 1.0 */
+ SProcGEQueryVersion
+};
+
+
+/************************************************************/
+/* callbacks */
+/************************************************************/
+
+/* dispatch requests */
+static int
+ProcGEDispatch(ClientPtr client)
+{
+ GEClientInfoPtr pGEClient = GEGetClient(client);
+ REQUEST(xGEReq);
+
+ if (pGEClient->major_version >= NUM_VERSION_REQUESTS)
+ return BadRequest;
+ if (stuff->ReqType > version_requests[pGEClient->major_version])
+ return BadRequest;
+
+ return (ProcGEVector[stuff->ReqType])(client);
+}
+
+/* dispatch swapped requests */
+static int
+SProcGEDispatch(ClientPtr client)
+{
+ REQUEST(xGEReq);
+ if (stuff->ReqType >= GENumberRequests)
+ return BadRequest;
+ return (*SProcGEVector[stuff->ReqType])(client);
+}
+
+/**
+ * Called when a new client inits a connection to the X server.
+ *
+ * We alloc a simple struct to store the client's major/minor version. Can be
+ * used in the furture for versioning support.
+ */
+static void
+GEClientCallback(CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
+ ClientPtr pClient = clientinfo->client;
+ GEClientInfoPtr pGEClient = GEGetClient(pClient);
+
+ pGEClient->major_version = 0;
+ pGEClient->minor_version = 0;
+}
+
+/* Reset extension. Called on server shutdown. */
+static void
+GEResetProc(ExtensionEntry *extEntry)
+{
+ DeleteCallback(&ClientStateCallback, GEClientCallback, 0);
+ EventSwapVector[GenericEvent] = NotImplemented;
+}
+
+/* Calls the registered event swap function for the extension.
+ *
+ * Each extension can register a swap function to handle GenericEvents being
+ * swapped properly. The server calls SGEGenericEvent() before the event is
+ * written on the wire, this one calls the registered swap function to do the
+ * work.
+ */
+static void
+SGEGenericEvent(xEvent* from, xEvent* to)
+{
+ xGenericEvent* gefrom = (xGenericEvent*)from;
+ xGenericEvent* geto = (xGenericEvent*)to;
+
+ if ((gefrom->extension & 0x7f) > MAXEXTENSIONS)
+ {
+ ErrorF("GE: Invalid extension offset for event.\n");
+ return;
+ }
+
+ if (GEExtensions[gefrom->extension & 0x7F].evswap)
+ GEExtensions[gefrom->extension & 0x7F].evswap(gefrom, geto);
+}
+
+/* Init extension, register at server.
+ * Since other extensions may rely on XGE (XInput does already), it is a good
+ * idea to init XGE first, before any other extension.
+ */
+void
+GEExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+
+ if (!dixRegisterPrivateKey(&GEClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(GEClientInfoRec)))
+ FatalError("GEExtensionInit: GE private request failed.\n");
+
+ if(!AddCallback(&ClientStateCallback, GEClientCallback, 0))
+ {
+ FatalError("GEExtensionInit: register client callback failed.\n");
+ }
+
+ if((extEntry = AddExtension(GE_NAME,
+ 0, GENumberErrors,
+ ProcGEDispatch, SProcGEDispatch,
+ GEResetProc, StandardMinorOpcode)) != 0)
+ {
+ memset(GEExtensions, 0, sizeof(GEExtensions));
+
+ EventSwapVector[GenericEvent] = (EventSwapPtr) SGEGenericEvent;
+ } else {
+ FatalError("GEInit: AddExtensions failed.\n");
+ }
+
+}
+
+/************************************************************/
+/* interface for extensions */
+/************************************************************/
+
+/* Register an extension with GE. The given swap function will be called each
+ * time an event is sent to a client with different byte order.
+ * @param extension The extensions major opcode
+ * @param ev_swap The event swap function.
+ * @param ev_fill Called for an event before delivery. The extension now has
+ * the chance to fill in necessary fields for the event.
+ */
+void
+GERegisterExtension(int extension,
+ void (*ev_swap)(xGenericEvent* from, xGenericEvent* to))
+{
+ if ((extension & 0x7F) >= MAXEXTENSIONS)
+ FatalError("GE: extension > MAXEXTENSIONS. This should not happen.\n");
+
+ /* extension opcodes are > 128, might as well save some space here */
+ GEExtensions[extension & 0x7f].evswap = ev_swap;
+}
+
+
+/* Sets type and extension field for a generic event. This is just an
+ * auxiliary function, extensions could do it manually too.
+ */
+void
+GEInitEvent(xGenericEvent* ev, int extension)
+{
+ ev->type = GenericEvent;
+ ev->extension = extension;
+ ev->length = 0;
+}
+
diff --git a/Xext/geext.h b/Xext/geext.h
new file mode 100644
index 0000000..8e6dbeb
--- /dev/null
+++ b/Xext/geext.h
@@ -0,0 +1,83 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter@cs.unisa.edu.au>
+
+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 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.
+
+Except as contained in this notice, the name of the author 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 author.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef _GEEXT_H_
+#define _GEEXT_H_
+#include <X11/extensions/geproto.h>
+
+/** Struct to keep information about registered extensions */
+typedef struct _GEExtension {
+ /** Event swapping routine */
+ void (*evswap)(xGenericEvent* from, xGenericEvent* to);
+} GEExtension, *GEExtensionPtr;
+
+
+/* All registered extensions and their handling functions. */
+extern _X_EXPORT GEExtension GEExtensions[MAXEXTENSIONS];
+
+/* Typecast to generic event */
+#define GEV(ev) ((xGenericEvent*)(ev))
+/* Returns the extension offset from the event */
+#define GEEXT(ev) (GEV(ev)->extension)
+
+/* Return zero-based extension offset (offset - 128). Only for use in arrays */
+#define GEEXTIDX(ev) (GEEXT(ev) & 0x7F)
+/* True if mask is set for extension on window */
+#define GEMaskIsSet(pWin, extension, mask) \
+ ((pWin)->optional && \
+ (pWin)->optional->geMasks && \
+ ((pWin)->optional->geMasks->eventMasks[(extension) & 0x7F] & (mask)))
+
+/* Returns first client */
+#define GECLIENT(pWin) \
+ (((pWin)->optional) ? (pWin)->optional->geMasks->geClients : NULL)
+
+/* Returns the event_fill for the given event */
+#define GEEventFill(ev) \
+ GEExtensions[GEEXTIDX(ev)].evfill
+
+#define GEIsType(ev, ext, ev_type) \
+ ((GEV(ev)->type == GenericEvent) && \
+ GEEXT(ev) == (ext) && \
+ GEV(ev)->evtype == (ev_type))
+
+
+/* Interface for other extensions */
+extern _X_EXPORT void GERegisterExtension(
+ int extension,
+ void (*ev_dispatch)(xGenericEvent* from, xGenericEvent* to));
+
+extern _X_EXPORT void GEInitEvent(xGenericEvent* ev, int extension);
+
+extern _X_EXPORT void GEExtensionInit(void);
+
+#endif /* _GEEXT_H_ */
diff --git a/Xext/geint.h b/Xext/geint.h
new file mode 100644
index 0000000..3e2b8e1
--- /dev/null
+++ b/Xext/geint.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * 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 (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR 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.
+ *
+ * Author: Peter Hutterer, University of South Australia, NICTA
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef _GEINT_H_
+#define _GEINT_H_
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include <X11/extensions/geproto.h>
+
+extern _X_EXPORT DevPrivateKeyRec GEClientPrivateKeyRec;
+#define GEClientPrivateKey (&GEClientPrivateKeyRec)
+
+typedef struct _GEClientInfo {
+ CARD32 major_version;
+ CARD32 minor_version;
+} GEClientInfoRec, *GEClientInfoPtr;
+
+#define GEGetClient(pClient) ((GEClientInfoPtr)(dixLookupPrivate(&((pClient)->devPrivates), GEClientPrivateKey)))
+
+extern _X_EXPORT int (*ProcGEVector[/*GENumRequests*/])(ClientPtr);
+extern _X_EXPORT int (*SProcGEVector[/*GENumRequests*/])(ClientPtr);
+
+#endif /* _GEINT_H_ */
diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c
new file mode 100644
index 0000000..e6334bd
--- /dev/null
+++ b/Xext/panoramiX.c
@@ -0,0 +1,1299 @@
+/*****************************************************************
+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
+
+#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"
+#include "picturestr.h"
+#ifdef XFIXES
+#include "xfixesint.h"
+#endif
+#ifdef COMPOSITE
+#include "compint.h"
+#endif
+#include "modinit.h"
+#include "protocol-versions.h"
+
+#ifdef GLXPROXY
+extern VisualPtr glxMatchVisual(ScreenPtr pScreen,
+ VisualPtr pVisual,
+ ScreenPtr pMatchScreen);
+#endif
+
+/*
+ * PanoramiX data declarations
+ */
+
+int PanoramiXPixWidth = 0;
+int PanoramiXPixHeight = 0;
+int PanoramiXNumScreens = 0;
+
+static RegionRec PanoramiXScreenRegion = {{0, 0, 0, 0}, NULL};
+
+static int PanoramiXNumDepths;
+static DepthPtr PanoramiXDepths;
+static int PanoramiXNumVisuals;
+static VisualPtr PanoramiXVisuals;
+
+unsigned long XRC_DRAWABLE;
+unsigned long XRT_WINDOW;
+unsigned long XRT_PIXMAP;
+unsigned long XRT_GC;
+unsigned long XRT_COLORMAP;
+
+static Bool VisualsEqual(VisualPtr, ScreenPtr, VisualPtr);
+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 DevPrivateKeyRec PanoramiXGCKeyRec;
+#define PanoramiXGCKey (&PanoramiXGCKeyRec)
+static DevPrivateKeyRec PanoramiXScreenKeyRec;
+#define PanoramiXScreenKey (&PanoramiXScreenKeyRec)
+
+typedef struct {
+ DDXPointRec clipOrg;
+ DDXPointRec patOrg;
+ GCFuncs *wrapFuncs;
+} PanoramiXGCRec, *PanoramiXGCPtr;
+
+typedef struct {
+ CreateGCProcPtr CreateGC;
+ CloseScreenProcPtr CloseScreen;
+} PanoramiXScreenRec, *PanoramiXScreenPtr;
+
+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;
+
+ if (pScreen->myNum == 0)
+ RegionUninit(&PanoramiXScreenRegion);
+
+ free((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 = pGC->pScreen->x;
+ int y_off = pGC->pScreen->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);
+}
+
+int
+XineramaDeleteResource(pointer data, XID id)
+{
+ free(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;
+ pointer val;
+
+ if(!screen) {
+ dixLookupResourceByType(&val, id, type, serverClient, DixReadAccess);
+ return val;
+ }
+
+ 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;
+
+Bool
+XineramaRegisterConnectionBlockCallback(void (*func)(void))
+{
+ XineramaConnectionCallbackList *newlist;
+
+ if(!(newlist = malloc(sizeof(XineramaConnectionCallbackList))))
+ return FALSE;
+
+ newlist->next = ConnectionCallbackList;
+ newlist->func = func;
+ ConnectionCallbackList = newlist;
+
+ return TRUE;
+}
+
+static void XineramaInitData(ScreenPtr pScreen)
+{
+ int i, w, h;
+
+ RegionNull(&PanoramiXScreenRegion);
+ for (i = 0; i < PanoramiXNumScreens; i++) {
+ BoxRec TheBox;
+ RegionRec ScreenRegion;
+
+ pScreen = screenInfo.screens[i];
+
+ TheBox.x1 = pScreen->x;
+ TheBox.x2 = TheBox.x1 + pScreen->width;
+ TheBox.y1 = pScreen->y;
+ TheBox.y2 = TheBox.y1 + pScreen->height;
+
+ RegionInit(&ScreenRegion, &TheBox, 1);
+ RegionUnion(&PanoramiXScreenRegion, &PanoramiXScreenRegion,
+ &ScreenRegion);
+ RegionUninit(&ScreenRegion);
+ }
+
+ PanoramiXPixWidth = screenInfo.screens[0]->x + screenInfo.screens[0]->width;
+ PanoramiXPixHeight = screenInfo.screens[0]->y + screenInfo.screens[0]->height;
+
+ for (i = 1; i < PanoramiXNumScreens; i++) {
+ pScreen = screenInfo.screens[i];
+ w = pScreen->x + pScreen->width;
+ h = pScreen->y + pScreen->height;
+
+ if (PanoramiXPixWidth < w)
+ PanoramiXPixWidth = w;
+ if (PanoramiXPixHeight < h)
+ PanoramiXPixHeight = h;
+ }
+}
+
+void XineramaReinitData(ScreenPtr pScreen)
+{
+ RegionUninit(&PanoramiXScreenRegion);
+ 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;
+
+ if (!dixRegisterPrivateKey(&PanoramiXScreenKeyRec, PRIVATE_SCREEN, 0)) {
+ noPanoramiXExtension = TRUE;
+ return;
+ }
+
+ if (!dixRegisterPrivateKey(&PanoramiXGCKeyRec, PRIVATE_GC, sizeof(PanoramiXGCRec))) {
+ noPanoramiXExtension = TRUE;
+ 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.
+ */
+
+ for (i = 0; i < PanoramiXNumScreens; i++) {
+ pScreen = screenInfo.screens[i];
+ pScreenPriv = malloc(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,
+ "XineramaWindow");
+ if (XRT_WINDOW)
+ XRT_WINDOW |= XRC_DRAWABLE;
+ XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource,
+ "XineramaPixmap");
+ if (XRT_PIXMAP)
+ XRT_PIXMAP |= XRC_DRAWABLE;
+ XRT_GC = CreateNewResourceType(XineramaDeleteResource,
+ "XineramaGC");
+ XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource,
+ "XineramaColormap");
+
+ if (XRT_WINDOW && XRT_PIXMAP && XRT_GC && XRT_COLORMAP) {
+ panoramiXGeneration = serverGeneration;
+ success = TRUE;
+ }
+ SetResourceTypeErrorValue(XRT_WINDOW, BadWindow);
+ SetResourceTypeErrorValue(XRT_PIXMAP, BadPixmap);
+ SetResourceTypeErrorValue(XRT_GC, BadGC);
+ SetResourceTypeErrorValue(XRT_COLORMAP, BadColor);
+ }
+
+ 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;
+
+ PanoramiXRenderInit ();
+#ifdef XFIXES
+ PanoramiXFixesInit ();
+#endif
+#ifdef COMPOSITE
+ PanoramiXCompositeInit ();
+#endif
+
+}
+
+extern Bool CreateConnectionBlock(void);
+
+Bool PanoramiXCreateConnectionBlock(void)
+{
+ int i, j, length;
+ Bool disableBackingStore = 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 (disableBackingStore) {
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ pScreen = screenInfo.screens[i];
+ pScreen->backingStoreSupport = 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 = bytes_to_int32(length);
+
+ for (i = 0; i < PanoramiXNumDepths; i++)
+ free(PanoramiXDepths[i].vids);
+ free(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;
+ free(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 = realloc(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 = malloc(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 = realloc(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 = malloc(sizeof(PanoramiXRes));
+ root->type = XRT_WINDOW;
+ defmap = malloc(sizeof(PanoramiXRes));
+ defmap->type = XRT_COLORMAP;
+ saver = malloc(sizeof(PanoramiXRes));
+ saver->type = XRT_WINDOW;
+
+ for (i = 0; i < PanoramiXNumScreens; i++) {
+ ScreenPtr pScreen = screenInfo.screens[i];
+ root->info[i].id = pScreen->root->drawable.id;
+ root->u.win.class = InputOutput;
+ root->u.win.root = TRUE;
+ saver->info[i].id = pScreen->screensaver.wid;
+ saver->u.win.class = InputOutput;
+ saver->u.win.root = TRUE;
+ defmap->info[i].id = pScreen->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);
+}
+
+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;
+
+ PanoramiXRenderReset ();
+#ifdef XFIXES
+ PanoramiXFixesReset ();
+#endif
+ screenInfo.numScreens = PanoramiXNumScreens;
+ for (i = 256; i--; )
+ ProcVector[i] = SavedProcVector[i];
+}
+
+
+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 = SERVER_PANORAMIX_MAJOR_VERSION;
+ rep.minorVersion = SERVER_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 Success;
+}
+
+int
+ProcPanoramiXGetState(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetStateReq);
+ WindowPtr pWin;
+ xPanoramiXGetStateReply rep;
+ 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 Success;
+
+}
+
+int
+ProcPanoramiXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenCountReply rep;
+ 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 Success;
+}
+
+int
+ProcPanoramiXGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenSizeReply rep;
+ 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 = screenInfo.screens[stuff->screen]->width;
+ rep.height = screenInfo.screens[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 Success;
+}
+
+
+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) {
+ int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.state, n);
+ }
+ WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep);
+ return Success;
+}
+
+
+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 = bytes_to_int32(rep.number * sz_XineramaScreenInfo);
+ if (client->swapped) {
+ 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 = screenInfo.screens[i]->x;
+ scratch.y_org = screenInfo.screens[i]->y;
+ scratch.width = screenInfo.screens[i]->width;
+ scratch.height = screenInfo.screens[i]->height;
+
+ if(client->swapped) {
+ 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 Success;
+}
+
+
+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, ScreenRegion, 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 + screenInfo.screens[0]->x;
+ SrcBox.y1 += pDraw->y + screenInfo.screens[0]->y;
+ }
+ SrcBox.x2 = SrcBox.x1 + width;
+ SrcBox.y2 = SrcBox.y1 + height;
+
+ RegionInit(&SrcRegion, &SrcBox, 1);
+ RegionNull(&GrabRegion);
+
+ depth = (format == XYPixmap) ? 1 : pDraw->depth;
+
+ for(i = 0; i < PanoramiXNumScreens; i++) {
+ BoxRec TheBox;
+ ScreenPtr pScreen;
+ pDraw = pDrawables[i];
+ pScreen = pDraw->pScreen;
+
+ TheBox.x1 = pScreen->x;
+ TheBox.x2 = TheBox.x1 + pScreen->width;
+ TheBox.y1 = pScreen->y;
+ TheBox.y2 = TheBox.y1 + pScreen->height;
+
+ RegionInit(&ScreenRegion, &TheBox, 1);
+ inOut = RegionContainsRect(&ScreenRegion, &SrcBox);
+ if(inOut == rgnPART)
+ RegionIntersect(&GrabRegion, &SrcRegion, &ScreenRegion);
+ RegionUninit(&ScreenRegion);
+
+ if(inOut == rgnIN) {
+ (*pScreen->GetImage)(pDraw,
+ SrcBox.x1 - pDraw->x - screenInfo.screens[i]->x,
+ SrcBox.y1 - pDraw->y - screenInfo.screens[i]->y,
+ width, height, format, planemask, data);
+ break;
+ } else if (inOut == rgnOUT)
+ continue;
+
+ nbox = RegionNumRects(&GrabRegion);
+
+ if(nbox) {
+ pbox = RegionRects(&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 = realloc(ScratchMem, sizeNeeded);
+ if(ScratchMem)
+ size = sizeNeeded;
+ else {
+ ScratchMem = tmpdata;
+ break;
+ }
+ }
+
+ x = pbox->x1 - pDraw->x - screenInfo.screens[i]->x;
+ y = pbox->y1 - pDraw->y - screenInfo.screens[i]->y;
+
+ (*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++;
+ }
+
+ RegionSubtract(&SrcRegion, &SrcRegion, &GrabRegion);
+ if(!RegionNotEmpty(&SrcRegion))
+ break;
+ }
+
+ }
+
+ free(ScratchMem);
+
+ RegionUninit(&SrcRegion);
+ RegionUninit(&GrabRegion);
+}
diff --git a/Xext/panoramiX.h b/Xext/panoramiX.h
new file mode 100644
index 0000000..a8684f0
--- /dev/null
+++ b/Xext/panoramiX.h
@@ -0,0 +1,78 @@
+/*****************************************************************
+
+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_
+
+#define _PANORAMIX_SERVER
+#include <X11/extensions/panoramiXproto.h>
+#undef _PANORAMIX_SERVER
+#include "gcstruct.h"
+
+
+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;
+ struct {
+ Bool root;
+ } pict;
+ 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 IS_SHARED_PIXMAP(r) (((r)->type == XRT_PIXMAP) && (r)->u.pix.shared)
+
+#endif /* _PANORAMIX_H_ */
diff --git a/Xext/panoramiXSwap.c b/Xext/panoramiXSwap.c
new file mode 100644
index 0000000..e1720c9
--- /dev/null
+++ b/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);
+ int n;
+
+ swaps(&stuff->length,n);
+ REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
+ return ProcPanoramiXQueryVersion(client);
+}
+
+static int
+SProcPanoramiXGetState(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetStateReq);
+ int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+ swapl (&stuff->window, n);
+ return ProcPanoramiXGetState(client);
+}
+
+static int
+SProcPanoramiXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ swapl (&stuff->window, n);
+ return ProcPanoramiXGetScreenCount(client);
+}
+
+static int
+SProcPanoramiXGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ 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);
+ int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
+ return ProcXineramaIsActive(client);
+}
+
+
+static int
+SProcXineramaQueryScreens(ClientPtr client)
+{
+ REQUEST(xXineramaQueryScreensReq);
+ 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/Xext/panoramiXh.h b/Xext/panoramiXh.h
new file mode 100644
index 0000000..31b8f90
--- /dev/null
+++ b/Xext/panoramiXh.h
@@ -0,0 +1,73 @@
+
+/*
+ * 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 int connBlockScreenStart;
+extern xConnSetupPrefix connSetupPrefix;
+
+extern int (* SavedProcVector[256]) (ClientPtr client);
diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c
new file mode 100644
index 0000000..d843168
--- /dev/null
+++ b/Xext/panoramiXprocs.c
@@ -0,0 +1,2428 @@
+/*****************************************************************
+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>
+#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 )
+
+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, len, j;
+ int orig_x, orig_y;
+ XID orig_visual, tmp;
+ Bool parentIsRoot;
+
+ REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
+
+ len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq));
+ if (Ones(stuff->mask) != len)
+ return BadLength;
+
+ result = dixLookupResourceByType((pointer *)&parent, stuff->parent,
+ XRT_WINDOW, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ 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)) {
+ result = dixLookupResourceByType((pointer *)&backPix, tmp,
+ XRT_PIXMAP, client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+ if ((Mask)stuff->mask & CWBorderPixmap) {
+ pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1));
+ tmp = *((CARD32 *) &stuff[1] + pbord_offset);
+ if (tmp != CopyFromParent) {
+ result = dixLookupResourceByType((pointer *)&bordPix, tmp,
+ XRT_PIXMAP, client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+ if ((Mask)stuff->mask & CWColormap) {
+ cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1));
+ tmp = *((CARD32 *) &stuff[1] + cmap_offset);
+ if ((tmp != CopyFromParent) && (tmp != None)) {
+ result = dixLookupResourceByType((pointer *)&cmap, tmp,
+ XRT_COLORMAP, client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+
+ if(!(newWin = malloc(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 == screenInfo.screens[0]->root->drawable.id) ||
+ (stuff->parent == screenInfo.screens[0]->screensaver.wid);
+ FOR_NSCREENS_BACKWARD(j) {
+ stuff->wid = newWin->info[j].id;
+ stuff->parent = parent->info[j].id;
+ if (parentIsRoot) {
+ stuff->x = orig_x - screenInfo.screens[j]->x;
+ stuff->y = orig_y - screenInfo.screens[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
+ free(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, len, j;
+ XID tmp;
+
+ REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
+
+ len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq));
+ if (Ones(stuff->valueMask) != len)
+ return BadLength;
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->window,
+ XRT_WINDOW, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ 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)) {
+ result = dixLookupResourceByType((pointer *)&backPix, tmp,
+ XRT_PIXMAP, client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+ if ((Mask)stuff->valueMask & CWBorderPixmap) {
+ pbord_offset = Ones((Mask)stuff->valueMask & (CWBorderPixmap - 1));
+ tmp = *((CARD32 *) &stuff[1] + pbord_offset);
+ if (tmp != CopyFromParent) {
+ result = dixLookupResourceByType((pointer *)&bordPix, tmp,
+ XRT_PIXMAP, client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+ if ((Mask)stuff->valueMask & CWColormap) {
+ cmap_offset = Ones((Mask)stuff->valueMask & (CWColormap - 1));
+ tmp = *((CARD32 *) &stuff[1] + cmap_offset);
+ if ((tmp != CopyFromParent) && (tmp != None)) {
+ result = dixLookupResourceByType((pointer *)&cmap, tmp,
+ XRT_COLORMAP, client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+
+ 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, j;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW,
+ client, DixDestroyAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW,
+ client, DixDestroyAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ REQUEST(xChangeSaveSetReq);
+
+ REQUEST_SIZE_MATCH(xChangeSaveSetReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->window,
+ XRT_WINDOW, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ int x, y;
+ Bool parentIsRoot;
+ REQUEST(xReparentWindowReq);
+
+ REQUEST_SIZE_MATCH(xReparentWindowReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->window,
+ XRT_WINDOW, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ result = dixLookupResourceByType((pointer *)&parent, stuff->parent,
+ XRT_WINDOW, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ x = stuff->x;
+ y = stuff->y;
+ parentIsRoot = (stuff->parent == screenInfo.screens[0]->root->drawable.id) ||
+ (stuff->parent == screenInfo.screens[0]->screensaver.wid);
+ FOR_NSCREENS_BACKWARD(j) {
+ stuff->window = win->info[j].id;
+ stuff->parent = parent->info[j].id;
+ if(parentIsRoot) {
+ stuff->x = x - screenInfo.screens[j]->x;
+ stuff->y = y - screenInfo.screens[j]->y;
+ }
+ result = (*SavedProcVector[X_ReparentWindow])(client);
+ if(result != Success) break;
+ }
+
+ return result;
+}
+
+
+int PanoramiXMapWindow(ClientPtr client)
+{
+ PanoramiXRes *win;
+ int result, j;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->id,
+ XRT_WINDOW, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->id,
+ XRT_WINDOW, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->id,
+ XRT_WINDOW, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->id,
+ XRT_WINDOW, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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, 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 - bytes_to_int32(sizeof(xConfigureWindowReq));
+ if (Ones(stuff->mask) != len)
+ return BadLength;
+
+ /* because we need the parent */
+ result = dixLookupResourceByType((pointer *)&pWin, stuff->window,
+ RT_WINDOW, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->window,
+ XRT_WINDOW, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ if ((Mask)stuff->mask & CWSibling) {
+ XID tmp;
+ sib_offset = Ones((Mask)stuff->mask & (CWSibling - 1));
+ if ((tmp = *((CARD32 *) &stuff[1] + sib_offset))) {
+ result = dixLookupResourceByType((pointer *)&sib, tmp, XRT_WINDOW,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+
+ if(pWin->parent && ((pWin->parent == screenInfo.screens[0]->root) ||
+ (pWin->parent->drawable.id == screenInfo.screens[0]->screensaver.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 - screenInfo.screens[j]->x;
+ if(y_offset >= 0)
+ *((CARD32 *) &stuff[1] + y_offset) = y - screenInfo.screens[j]->y;
+ result = (*SavedProcVector[X_ConfigureWindow])(client);
+ if(result != Success) break;
+ }
+
+ return result;
+}
+
+
+int PanoramiXCirculateWindow(ClientPtr client)
+{
+ PanoramiXRes *win;
+ int result, j;
+ REQUEST(xCirculateWindowReq);
+
+ REQUEST_SIZE_MATCH(xCirculateWindowReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->window,
+ XRT_WINDOW, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ 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 = screenInfo.screens[0]->root->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 (WindowDrawable(pDraw->type))
+ {
+ WindowPtr pWin = (WindowPtr)pDraw;
+ rep.x = pWin->origin.x - wBorderWidth (pWin);
+ rep.y = pWin->origin.y - wBorderWidth (pWin);
+ if((pWin->parent == screenInfo.screens[0]->root) ||
+ (pWin->parent->drawable.id == screenInfo.screens[0]->screensaver.wid))
+ {
+ rep.x += screenInfo.screens[0]->x;
+ rep.y += screenInfo.screens[0]->y;
+ }
+ rep.borderWidth = pWin->borderWidth;
+ }
+
+ WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
+ return Success;
+}
+
+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 == screenInfo.screens[0]->root) ||
+ (pWin->drawable.id == screenInfo.screens[0]->screensaver.wid))
+ {
+ x = stuff->srcX - screenInfo.screens[0]->x;
+ y = stuff->srcY - screenInfo.screens[0]->y;
+ } else {
+ x = pWin->drawable.x + stuff->srcX;
+ y = pWin->drawable.y + stuff->srcY;
+ }
+ pWin = pDst->firstChild;
+ while (pWin) {
+ BoxRec box;
+ 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))
+ /* When a window is shaped, a further check
+ * is made to see if the point is inside
+ * borderSize
+ */
+ && (!wBoundingShape(pWin) ||
+ RegionContainsPoint(wBoundingShape(pWin),
+ x - pWin->drawable.x,
+ y - pWin->drawable.y, &box))
+ )
+ {
+ 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 == screenInfo.screens[0]->root) ||
+ (pDst->drawable.id == screenInfo.screens[0]->screensaver.wid))
+ {
+ rep.dstX += screenInfo.screens[0]->x;
+ rep.dstY += screenInfo.screens[0]->y;
+ }
+
+ WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
+ return Success;
+}
+
+int PanoramiXCreatePixmap(ClientPtr client)
+{
+ PanoramiXRes *refDraw, *newPix;
+ int result, j;
+ REQUEST(xCreatePixmapReq);
+
+ REQUEST_SIZE_MATCH(xCreatePixmapReq);
+ client->errorValue = stuff->pid;
+
+ result = dixLookupResourceByClass((pointer *)&refDraw, stuff->drawable,
+ XRC_DRAWABLE, client, DixReadAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(!(newPix = malloc(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
+ free(newPix);
+
+ return result;
+}
+
+
+int PanoramiXFreePixmap(ClientPtr client)
+{
+ PanoramiXRes *pix;
+ int result, j;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ client->errorValue = stuff->id;
+
+ result = dixLookupResourceByType((pointer *)&pix, stuff->id, XRT_PIXMAP,
+ client, DixDestroyAccess);
+ if (result != Success)
+ return result;
+
+ 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, len, j;
+ XID tmp;
+
+ REQUEST_AT_LEAST_SIZE(xCreateGCReq);
+
+ client->errorValue = stuff->gc;
+ len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq));
+ if (Ones(stuff->mask) != len)
+ return BadLength;
+
+ result = dixLookupResourceByClass((pointer *)&refDraw, stuff->drawable,
+ XRC_DRAWABLE, client, DixReadAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if ((Mask)stuff->mask & GCTile) {
+ tile_offset = Ones((Mask)stuff->mask & (GCTile - 1));
+ if ((tmp = *((CARD32 *) &stuff[1] + tile_offset))) {
+ result = dixLookupResourceByType((pointer *)&tile, tmp, XRT_PIXMAP,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+ if ((Mask)stuff->mask & GCStipple) {
+ stip_offset = Ones((Mask)stuff->mask & (GCStipple - 1));
+ if ((tmp = *((CARD32 *) &stuff[1] + stip_offset))) {
+ result = dixLookupResourceByType((pointer *)&stip, tmp, XRT_PIXMAP,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+ if ((Mask)stuff->mask & GCClipMask) {
+ clip_offset = Ones((Mask)stuff->mask & (GCClipMask - 1));
+ if ((tmp = *((CARD32 *) &stuff[1] + clip_offset))) {
+ result = dixLookupResourceByType((pointer *)&clip, tmp, XRT_PIXMAP,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+
+ if(!(newGC = malloc(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
+ free(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, len, j;
+ XID tmp;
+
+ REQUEST_AT_LEAST_SIZE(xChangeGCReq);
+
+ len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq));
+ if (Ones(stuff->mask) != len)
+ return BadLength;
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ if ((Mask)stuff->mask & GCTile) {
+ tile_offset = Ones((Mask)stuff->mask & (GCTile - 1));
+ if ((tmp = *((CARD32 *) &stuff[1] + tile_offset))) {
+ result = dixLookupResourceByType((pointer *)&tile, tmp, XRT_PIXMAP,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+ if ((Mask)stuff->mask & GCStipple) {
+ stip_offset = Ones((Mask)stuff->mask & (GCStipple - 1));
+ if ((tmp = *((CARD32 *) &stuff[1] + stip_offset))) {
+ result = dixLookupResourceByType((pointer *)&stip, tmp, XRT_PIXMAP,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+ if ((Mask)stuff->mask & GCClipMask) {
+ clip_offset = Ones((Mask)stuff->mask & (GCClipMask - 1));
+ if ((tmp = *((CARD32 *) &stuff[1] + clip_offset))) {
+ result = dixLookupResourceByType((pointer *)&clip, tmp, XRT_PIXMAP,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+ }
+ }
+
+
+ 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, j;
+ REQUEST(xCopyGCReq);
+
+ REQUEST_SIZE_MATCH(xCopyGCReq);
+
+ result = dixLookupResourceByType((pointer *)&srcGC, stuff->srcGC, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ result = dixLookupResourceByType((pointer *)&dstGC, stuff->dstGC, XRT_GC,
+ client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ REQUEST(xSetDashesReq);
+
+ REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ REQUEST(xSetClipRectanglesReq);
+
+ REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->id, XRT_GC,
+ client, DixDestroyAccess);
+ if (result != Success)
+ return result;
+
+ 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, j, x, y;
+ Bool isRoot;
+ REQUEST(xClearAreaReq);
+
+ REQUEST_SIZE_MATCH(xClearAreaReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->window,
+ XRT_WINDOW, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ 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 - screenInfo.screens[j]->x;
+ stuff->y = y - screenInfo.screens[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, srcx, srcy, dstx, dsty;
+ PanoramiXRes *gc, *src, *dst;
+ Bool srcIsRoot = FALSE;
+ Bool dstIsRoot = FALSE;
+ Bool srcShared, dstShared;
+ REQUEST(xCopyAreaReq);
+
+ REQUEST_SIZE_MATCH(xCopyAreaReq);
+
+ result = dixLookupResourceByClass((pointer *)&src, stuff->srcDrawable,
+ XRC_DRAWABLE, client, DixReadAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ srcShared = IS_SHARED_PIXMAP(src);
+
+ result = dixLookupResourceByClass((pointer *)&dst, stuff->dstDrawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ dstShared = IS_SHARED_PIXMAP(dst);
+
+ if(dstShared && srcShared)
+ return (* SavedProcVector[X_CopyArea])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 = calloc(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;
+ free(data);
+ return BadMatch;
+ }
+
+ (*pGC->ops->PutImage) (pDst, pGC, pDst->depth, dstx, dsty,
+ stuff->width, stuff->height,
+ 0, ZPixmap, data);
+
+ if(dstShared) break;
+ }
+
+ free(data);
+ } else {
+ DrawablePtr pDst = NULL, pSrc = NULL;
+ GCPtr pGC = NULL;
+ RegionRec totalReg;
+ int rc;
+
+ RegionNull(&totalReg);
+ FOR_NSCREENS_BACKWARD(j) {
+ RegionPtr pRgn;
+ stuff->dstDrawable = dst->info[j].id;
+ stuff->srcDrawable = src->info[j].id;
+ stuff->gc = gc->info[j].id;
+ if (srcIsRoot) {
+ stuff->srcX = srcx - screenInfo.screens[j]->x;
+ stuff->srcY = srcy - screenInfo.screens[j]->y;
+ }
+ if (dstIsRoot) {
+ stuff->dstX = dstx - screenInfo.screens[j]->x;
+ stuff->dstY = dsty - screenInfo.screens[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 = (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
+ stuff->srcX, stuff->srcY,
+ stuff->width, stuff->height,
+ stuff->dstX, stuff->dstY);
+ if(pGC->graphicsExposures && pRgn) {
+ if(srcIsRoot) {
+ RegionTranslate(pRgn,
+ screenInfo.screens[j]->x, screenInfo.screens[j]->y);
+ }
+ RegionAppend(&totalReg, pRgn);
+ RegionDestroy(pRgn);
+ }
+
+ if(dstShared)
+ break;
+ }
+
+ if(pGC->graphicsExposures) {
+ Bool overlap;
+ RegionValidate(&totalReg, &overlap);
+ (*pDst->pScreen->SendGraphicsExpose)(
+ client, &totalReg, stuff->dstDrawable, X_CopyArea, 0);
+ RegionUninit(&totalReg);
+ }
+ }
+
+ return Success;
+}
+
+
+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;
+ RegionRec totalReg;
+ REQUEST(xCopyPlaneReq);
+
+ REQUEST_SIZE_MATCH(xCopyPlaneReq);
+
+ rc = dixLookupResourceByClass((pointer *)&src, stuff->srcDrawable,
+ XRC_DRAWABLE, client, DixReadAccess);
+ if (rc != Success)
+ return (rc == BadValue) ? BadDrawable : rc;
+
+ srcShared = IS_SHARED_PIXMAP(src);
+
+ rc = dixLookupResourceByClass((pointer *)&dst, stuff->dstDrawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (rc != Success)
+ return (rc == BadValue) ? BadDrawable : rc;
+
+ dstShared = IS_SHARED_PIXMAP(dst);
+
+ if(dstShared && srcShared)
+ return (* SavedProcVector[X_CopyPlane])(client);
+
+ rc = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ 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;
+
+ RegionNull(&totalReg);
+ FOR_NSCREENS_BACKWARD(j) {
+ RegionPtr pRgn;
+ stuff->dstDrawable = dst->info[j].id;
+ stuff->srcDrawable = src->info[j].id;
+ stuff->gc = gc->info[j].id;
+ if (srcIsRoot) {
+ stuff->srcX = srcx - screenInfo.screens[j]->x;
+ stuff->srcY = srcy - screenInfo.screens[j]->y;
+ }
+ if (dstIsRoot) {
+ stuff->dstX = dstx - screenInfo.screens[j]->x;
+ stuff->dstY = dsty - screenInfo.screens[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 = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC,
+ stuff->srcX, stuff->srcY,
+ stuff->width, stuff->height,
+ stuff->dstX, stuff->dstY, stuff->bitPlane);
+ if(pGC->graphicsExposures && pRgn) {
+ RegionAppend(&totalReg, pRgn);
+ RegionDestroy(pRgn);
+ }
+
+ if(dstShared)
+ break;
+ }
+
+ if(pGC->graphicsExposures) {
+ Bool overlap;
+ RegionValidate(&totalReg, &overlap);
+ (*pdstDraw->pScreen->SendGraphicsExpose)(
+ client, &totalReg, stuff->dstDrawable, X_CopyPlane, 0);
+ RegionUninit(&totalReg);
+ }
+
+ return Success;
+}
+
+
+int PanoramiXPolyPoint(ClientPtr client)
+{
+ PanoramiXRes *gc, *draw;
+ int result, npoint, j;
+ xPoint *origPts;
+ Bool isRoot;
+ REQUEST(xPolyPointReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyPointReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyPoint])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq));
+ if (npoint > 0) {
+ origPts = malloc(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 = screenInfo.screens[j]->x;
+ int y_off = screenInfo.screens[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;
+ }
+ free(origPts);
+ return result;
+ } else
+ return Success;
+}
+
+
+int PanoramiXPolyLine(ClientPtr client)
+{
+ PanoramiXRes *gc, *draw;
+ int result, npoint, j;
+ xPoint *origPts;
+ Bool isRoot;
+ REQUEST(xPolyLineReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyLineReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyLine])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+ npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
+ if (npoint > 0){
+ origPts = malloc(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 = screenInfo.screens[j]->x;
+ int y_off = screenInfo.screens[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;
+ }
+ free(origPts);
+ return result;
+ } else
+ return Success;
+}
+
+
+int PanoramiXPolySegment(ClientPtr client)
+{
+ int result, nsegs, i, j;
+ PanoramiXRes *gc, *draw;
+ xSegment *origSegs;
+ Bool isRoot;
+ REQUEST(xPolySegmentReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolySegment])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 = malloc(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 = screenInfo.screens[j]->x;
+ int y_off = screenInfo.screens[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;
+ }
+ free(origSegs);
+ return result;
+ } else
+ return Success;
+}
+
+
+int PanoramiXPolyRectangle(ClientPtr client)
+{
+ int result, nrects, i, j;
+ PanoramiXRes *gc, *draw;
+ Bool isRoot;
+ xRectangle *origRecs;
+ REQUEST(xPolyRectangleReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyRectangle])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 = malloc(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 = screenInfo.screens[j]->x;
+ int y_off = screenInfo.screens[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;
+ }
+ free(origRecs);
+ return result;
+ } else
+ return Success;
+}
+
+
+int PanoramiXPolyArc(ClientPtr client)
+{
+ int result, narcs, i, j;
+ PanoramiXRes *gc, *draw;
+ Bool isRoot;
+ xArc *origArcs;
+ REQUEST(xPolyArcReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyArcReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyArc])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 = malloc(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 = screenInfo.screens[j]->x;
+ int y_off = screenInfo.screens[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;
+ }
+ free(origArcs);
+ return result;
+ } else
+ return Success;
+}
+
+
+int PanoramiXFillPoly(ClientPtr client)
+{
+ int result, count, j;
+ PanoramiXRes *gc, *draw;
+ Bool isRoot;
+ DDXPointPtr locPts;
+ REQUEST(xFillPolyReq);
+
+ REQUEST_AT_LEAST_SIZE(xFillPolyReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_FillPoly])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+
+ count = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq));
+ if (count > 0){
+ locPts = malloc(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 = screenInfo.screens[j]->x;
+ int y_off = screenInfo.screens[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;
+ }
+ free(locPts);
+ return result;
+ } else
+ return Success;
+}
+
+
+int PanoramiXPolyFillRectangle(ClientPtr client)
+{
+ int result, things, i, j;
+ PanoramiXRes *gc, *draw;
+ Bool isRoot;
+ xRectangle *origRects;
+ REQUEST(xPolyFillRectangleReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyFillRectangle])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 = malloc(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 = screenInfo.screens[j]->x;
+ int y_off = screenInfo.screens[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;
+ }
+ free(origRects);
+ return result;
+ } else
+ return Success;
+}
+
+
+int PanoramiXPolyFillArc(ClientPtr client)
+{
+ PanoramiXRes *gc, *draw;
+ Bool isRoot;
+ int result, narcs, i, j;
+ xArc *origArcs;
+ REQUEST(xPolyFillArcReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyFillArc])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
+
+ narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
+ if (narcs % sizeof(xArc)) return BadLength;
+ narcs /= sizeof(xArc);
+ if (narcs > 0) {
+ origArcs = malloc(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 = screenInfo.screens[j]->x;
+ int y_off = screenInfo.screens[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;
+ }
+ free(origArcs);
+ return result;
+ } else
+ return Success;
+}
+
+
+int PanoramiXPutImage(ClientPtr client)
+{
+ PanoramiXRes *gc, *draw;
+ Bool isRoot;
+ int j, result, orig_x, orig_y;
+ REQUEST(xPutImageReq);
+
+ REQUEST_AT_LEAST_SIZE(xPutImageReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PutImage])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 - screenInfo.screens[j]->x;
+ stuff->dstY = orig_y - screenInfo.screens[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;
+ }
+
+ rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (rc != Success)
+ return (rc == BadValue) ? BadDrawable : rc;
+
+ 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 */
+ screenInfo.screens[0]->x + pDraw->x + x < 0 ||
+ screenInfo.screens[0]->x + pDraw->x + x + w > PanoramiXPixWidth ||
+ screenInfo.screens[0]->y + pDraw->y + y < 0 ||
+ screenInfo.screens[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 = bytes_to_int32(length);
+
+ 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 = malloc(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)
+ memset(pBuf, 0, 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);
+
+ memset(pBuf, 0, nlines * widthBytesLine);
+
+ XineramaGetImageData(drawables, x, y + linesDone, w,
+ nlines, format, plane, pBuf,
+ widthBytesLine, isRoot);
+
+ (void)WriteToClient(client,
+ (int)(nlines * widthBytesLine),
+ pBuf);
+
+ linesDone += nlines;
+ }
+ }
+ }
+ }
+ free(pBuf);
+ return Success;
+}
+
+
+/* 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, j;
+ int orig_x, orig_y;
+ REQUEST(xPolyTextReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyTextReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyText8])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 - screenInfo.screens[j]->x;
+ stuff->y = orig_y - screenInfo.screens[j]->y;
+ }
+ result = (*SavedProcVector[X_PolyText8])(client);
+ if(result != Success) break;
+ }
+ return result;
+}
+
+int
+PanoramiXPolyText16(ClientPtr client)
+{
+ PanoramiXRes *gc, *draw;
+ Bool isRoot;
+ int result, j;
+ int orig_x, orig_y;
+ REQUEST(xPolyTextReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyTextReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_PolyText16])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 - screenInfo.screens[j]->x;
+ stuff->y = orig_y - screenInfo.screens[j]->y;
+ }
+ result = (*SavedProcVector[X_PolyText16])(client);
+ if(result != Success) break;
+ }
+ return result;
+}
+
+
+int PanoramiXImageText8(ClientPtr client)
+{
+ int result, j;
+ PanoramiXRes *gc, *draw;
+ Bool isRoot;
+ int orig_x, orig_y;
+ REQUEST(xImageTextReq);
+
+ REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_ImageText8])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 - screenInfo.screens[j]->x;
+ stuff->y = orig_y - screenInfo.screens[j]->y;
+ }
+ result = (*SavedProcVector[X_ImageText8])(client);
+ if(result != Success) break;
+ }
+ return result;
+}
+
+
+int PanoramiXImageText16(ClientPtr client)
+{
+ int result, j;
+ PanoramiXRes *gc, *draw;
+ Bool isRoot;
+ int orig_x, orig_y;
+ REQUEST(xImageTextReq);
+
+ REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ if(IS_SHARED_PIXMAP(draw))
+ return (*SavedProcVector[X_ImageText16])(client);
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 - screenInfo.screens[j]->x;
+ stuff->y = orig_y - screenInfo.screens[j]->y;
+ }
+ result = (*SavedProcVector[X_ImageText16])(client);
+ if(result != Success) break;
+ }
+ return result;
+}
+
+
+
+int PanoramiXCreateColormap(ClientPtr client)
+{
+ PanoramiXRes *win, *newCmap;
+ int result, j, orig_visual;
+ REQUEST(xCreateColormapReq);
+
+ REQUEST_SIZE_MATCH(xCreateColormapReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->window,
+ XRT_WINDOW, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ if(!(newCmap = malloc(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
+ free(newCmap);
+
+ return result;
+}
+
+
+int PanoramiXFreeColormap(ClientPtr client)
+{
+ PanoramiXRes *cmap;
+ int result, j;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ client->errorValue = stuff->id;
+
+ result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP,
+ client, DixDestroyAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ REQUEST(xCopyColormapAndFreeReq);
+
+ REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
+
+ client->errorValue = stuff->srcCmap;
+
+ result = dixLookupResourceByType((pointer *)&cmap, stuff->srcCmap,
+ XRT_COLORMAP, client,
+ DixReadAccess | DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ if(!(newCmap = malloc(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
+ free(newCmap);
+
+ return result;
+}
+
+
+int PanoramiXInstallColormap(ClientPtr client)
+{
+ REQUEST(xResourceReq);
+ int result, j;
+ PanoramiXRes *cmap;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ client->errorValue = stuff->id;
+
+ result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ PanoramiXRes *cmap;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ client->errorValue = stuff->id;
+
+ result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ PanoramiXRes *cmap;
+ REQUEST(xAllocColorReq);
+
+ REQUEST_SIZE_MATCH(xAllocColorReq);
+
+ client->errorValue = stuff->cmap;
+
+ result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
+ XRT_COLORMAP, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ PanoramiXRes *cmap;
+ REQUEST(xAllocNamedColorReq);
+
+ REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
+
+ client->errorValue = stuff->cmap;
+
+ result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
+ XRT_COLORMAP, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ PanoramiXRes *cmap;
+ REQUEST(xAllocColorCellsReq);
+
+ REQUEST_SIZE_MATCH(xAllocColorCellsReq);
+
+ client->errorValue = stuff->cmap;
+
+ result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
+ XRT_COLORMAP, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ PanoramiXRes *cmap;
+ REQUEST(xAllocColorPlanesReq);
+
+ REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
+
+ client->errorValue = stuff->cmap;
+
+ result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
+ XRT_COLORMAP, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ PanoramiXRes *cmap;
+ REQUEST(xFreeColorsReq);
+
+ REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
+
+ client->errorValue = stuff->cmap;
+
+ result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
+ XRT_COLORMAP, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ FOR_NSCREENS_BACKWARD(j) {
+ stuff->cmap = cmap->info[j].id;
+ result = (* SavedProcVector[X_FreeColors])(client);
+ }
+ return result;
+}
+
+
+int PanoramiXStoreColors(ClientPtr client)
+{
+ int result, j;
+ PanoramiXRes *cmap;
+ REQUEST(xStoreColorsReq);
+
+ REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
+
+ client->errorValue = stuff->cmap;
+
+ result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
+ XRT_COLORMAP, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ 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, j;
+ PanoramiXRes *cmap;
+ REQUEST(xStoreNamedColorReq);
+
+ REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
+
+ client->errorValue = stuff->cmap;
+
+ result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap,
+ XRT_COLORMAP, client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ FOR_NSCREENS_BACKWARD(j){
+ stuff->cmap = cmap->info[j].id;
+ result = (* SavedProcVector[X_StoreNamedColor])(client);
+ if(result != Success) break;
+ }
+ return result;
+}
diff --git a/Xext/panoramiXsrv.h b/Xext/panoramiXsrv.h
new file mode 100644
index 0000000..b0a5a6e
--- /dev/null
+++ b/Xext/panoramiXsrv.h
@@ -0,0 +1,54 @@
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef _PANORAMIXSRV_H_
+#define _PANORAMIXSRV_H_
+
+#include "panoramiX.h"
+
+extern _X_EXPORT int PanoramiXNumScreens;
+extern _X_EXPORT int PanoramiXPixWidth;
+extern _X_EXPORT int PanoramiXPixHeight;
+
+extern _X_EXPORT VisualID PanoramiXTranslateVisualID(int screen, VisualID orig);
+extern _X_EXPORT void PanoramiXConsolidate(void);
+extern _X_EXPORT Bool PanoramiXCreateConnectionBlock(void);
+extern _X_EXPORT PanoramiXRes * PanoramiXFindIDByScrnum(RESTYPE, XID, int);
+extern _X_EXPORT Bool XineramaRegisterConnectionBlockCallback(void (*func)(void));
+extern _X_EXPORT int XineramaDeleteResource(pointer, XID);
+
+extern _X_EXPORT void XineramaReinitData(ScreenPtr);
+
+extern _X_EXPORT unsigned long XRC_DRAWABLE;
+extern _X_EXPORT unsigned long XRT_WINDOW;
+extern _X_EXPORT unsigned long XRT_PIXMAP;
+extern _X_EXPORT unsigned long XRT_GC;
+extern _X_EXPORT unsigned long XRT_COLORMAP;
+extern _X_EXPORT unsigned long XRT_PICTURE;
+
+/*
+ * 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 _X_EXPORT XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr;
+
+extern _X_EXPORT 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/Xext/saver.c b/Xext/saver.c
new file mode 100644
index 0000000..1888603
--- /dev/null
+++ b/Xext/saver.c
@@ -0,0 +1,1511 @@
+/*
+ *
+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
+ */
+
+
+#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
+#include <X11/extensions/dpmsconst.h>
+#endif
+#include "protocol-versions.h"
+
+#include <stdio.h>
+
+#include "modinit.h"
+
+static int ScreenSaverEventBase = 0;
+
+
+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 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 SaverEventType; /* 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 DevPrivateKeyRec ScreenPrivateKeyRec;
+#define ScreenPrivateKey (&ScreenPrivateKeyRec)
+
+#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) (malloc(sizeof (t)))
+
+static void
+CheckScreenPrivate (ScreenPtr pScreen)
+{
+ SetupScreen (pScreen);
+
+ if (!pPriv)
+ return;
+ if (!pPriv->attr && !pPriv->events &&
+ !pPriv->hasWindow && pPriv->installedMap == None)
+ {
+ free(pPriv);
+ SetScreenPrivate (pScreen, NULL);
+ pScreen->screensaver.ExternalScreenSaver = NULL;
+ }
+}
+
+static ScreenSaverScreenPrivatePtr
+MakeScreenPrivate (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);
+ pScreen->screensaver.ExternalScreenSaver = ScreenSaverHandle;
+ return pPriv;
+}
+
+static unsigned long
+getEventMask (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 (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, SaverEventType);
+ *pPrev = pEv->next;
+ free(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, SaverEventType, (pointer) pEv))
+ return FALSE;
+ }
+ pEv->mask = mask;
+ }
+ return TRUE;
+}
+
+static void
+FreeAttrs (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 (ScreenSaverAttrPtr pAttr)
+{
+ FreeAttrs (pAttr);
+ free(pAttr->values);
+ free(pAttr);
+}
+
+static int
+ScreenSaverFreeEvents (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;
+ free(pEv);
+ CheckScreenPrivate (pScreen);
+ return TRUE;
+}
+
+static int
+ScreenSaverFreeAttr (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;
+ free(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 (ScreenPtr pScreen, int state, Bool forced)
+{
+ ScreenSaverScreenPrivatePtr pPriv;
+ ScreenSaverEventPtr pEv;
+ unsigned long mask;
+ xScreenSaverNotifyEvent ev;
+ 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)
+ {
+ if (!(pEv->mask & mask))
+ continue;
+ ev.type = ScreenSaverNotify + ScreenSaverEventBase;
+ ev.state = state;
+ ev.timestamp = currentTime.milliseconds;
+ ev.root = pScreen->root->drawable.id;
+ ev.window = pScreen->screensaver.wid;
+ ev.kind = kind;
+ ev.forced = forced;
+ WriteEventsToClient (pEv->client, 1, (xEvent *) &ev);
+ }
+}
+
+static void
+SScreenSaverNotifyEvent (xScreenSaverNotifyEvent *from,
+ xScreenSaverNotifyEvent *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 (ScreenPtr pScreen)
+{
+ SetupScreen(pScreen);
+ ColormapPtr pCmap;
+ int rc;
+
+ if (pPriv && pPriv->installedMap != None)
+ {
+ rc = dixLookupResourceByType((pointer *)&pCmap, pPriv->installedMap,
+ RT_COLORMAP, serverClient,
+ DixUninstallAccess);
+ if (rc == Success)
+ (*pCmap->pScreen->UninstallColormap) (pCmap);
+ pPriv->installedMap = None;
+ CheckScreenPrivate (pScreen);
+ }
+}
+
+static Bool
+CreateSaverWindow (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 = &pScreen->screensaver;
+ 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, pScreen->root,
+ 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;
+ }
+ pAttr->pCursor->refcnt++;
+ if (pWin->optional->cursor)
+ FreeCursor (pWin->optional->cursor, (Cursor)0);
+ pWin->optional->cursor = pAttr->pCursor;
+ 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 = malloc(pScreen->maxInstalledCmaps * sizeof (Colormap));
+ numInstalled = (*pWin->drawable.pScreen->ListInstalledColormaps)
+ (pScreen, installedMaps);
+ for (i = 0; i < numInstalled; i++)
+ if (installedMaps[i] == wantMap)
+ break;
+
+ free((char *) installedMaps);
+
+ if (i < numInstalled)
+ return TRUE;
+
+ result = dixLookupResourceByType((pointer *)&pCmap, wantMap, RT_COLORMAP,
+ serverClient, DixInstallAccess);
+ if (result != Success)
+ return TRUE;
+
+ pPriv->installedMap = wantMap;
+
+ (*pCmap->pScreen->InstallColormap) (pCmap);
+
+ return TRUE;
+}
+
+static Bool
+DestroySaverWindow (ScreenPtr pScreen)
+{
+ SetupScreen(pScreen);
+ ScreenSaverStuffPtr pSaver;
+
+ if (!pPriv || !pPriv->hasWindow)
+ return FALSE;
+
+ pSaver = &pScreen->screensaver;
+ if (pSaver->pWindow)
+ {
+ pSaver->pWindow = NullWindow;
+ FreeResource (pSaver->wid, RT_NONE);
+ }
+ pPriv->hasWindow = FALSE;
+ CheckScreenPrivate (pScreen);
+ UninstallSaverColormap (pScreen);
+ return TRUE;
+}
+
+static Bool
+ScreenSaverHandle (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 (ClientPtr client)
+{
+ xScreenSaverQueryVersionReply rep;
+ int n;
+
+ REQUEST_SIZE_MATCH (xScreenSaverQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = SERVER_SAVER_MAJOR_VERSION;
+ rep.minorVersion = SERVER_SAVER_MINOR_VERSION;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient(client, sizeof (xScreenSaverQueryVersionReply), (char *)&rep);
+ return Success;
+}
+
+static int
+ProcScreenSaverQueryInfo (ClientPtr client)
+{
+ REQUEST(xScreenSaverQueryInfoReq);
+ xScreenSaverQueryInfoReply rep;
+ 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 = &pDraw->pScreen->screensaver;
+ 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 Success;
+}
+
+static int
+ProcScreenSaverSelectInput (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 = pScreen->root;
+
+ ret = XaceHook(XACE_SCREENSAVER_ACCESS, client, pScreen, DixSetAttrAccess);
+ if (ret != Success)
+ return ret;
+
+ len = stuff->length - bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
+ 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 = malloc((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 = dixLookupResourceByType((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
+ {
+ 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 = dixLookupResourceByType((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
+ {
+ 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 = dixLookupResourceByType((pointer *)&pCmap, cmap, RT_COLORMAP,
+ client, DixUseAccess);
+ if (ret != Success)
+ {
+ 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 = dixLookupResourceByType((pointer *)&pCursor, cursorID,
+ RT_CURSOR, client, DixUseAccess);
+ if (ret != Success)
+ {
+ 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) free(pAttr->values);
+ free(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, len;
+ int pback_offset = 0, pbord_offset = 0, cmap_offset = 0;
+ XID orig_visual, tmp;
+
+ REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq);
+
+ status = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (status != Success)
+ return (status == BadValue) ? BadDrawable : status;
+
+ len = stuff->length - bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
+ 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)) {
+ status = dixLookupResourceByType((pointer *)&backPix, tmp,
+ XRT_PIXMAP, client,
+ DixReadAccess);
+ if (status != Success)
+ return status;
+ }
+ }
+
+ if ((Mask)stuff->mask & CWBorderPixmap) {
+ pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1));
+ tmp = *((CARD32 *) &stuff[1] + pbord_offset);
+ if (tmp != CopyFromParent) {
+ status = dixLookupResourceByType((pointer *)&bordPix, tmp,
+ XRT_PIXMAP, client,
+ DixReadAccess);
+ if (status != Success)
+ return status;
+ }
+ }
+
+ if ((Mask)stuff->mask & CWColormap) {
+ cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1));
+ tmp = *((CARD32 *) &stuff[1] + cmap_offset);
+ if ((tmp != CopyFromParent) && (tmp != None)) {
+ status = dixLookupResourceByType((pointer *)&cmap, tmp,
+ XRT_COLORMAP, client,
+ DixReadAccess);
+ if (status != Success)
+ return status;
+ }
+ }
+
+ 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 rc, i;
+
+ rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (rc != Success)
+ return (rc == BadValue) ? BadDrawable : rc;
+
+ 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 = malloc(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))
+ {
+ free(this);
+ return BadAlloc;
+ }
+
+ *prev = this;
+ if (!screenSaverSuspended)
+ {
+ screenSaverSuspended = TRUE;
+ FreeScreenSaverTimer();
+ }
+
+ return Success;
+}
+
+static int (*NormalVector[]) (ClientPtr /* client */) = {
+ ProcScreenSaverQueryVersion,
+ ProcScreenSaverQueryInfo,
+ ProcScreenSaverSelectInput,
+ ProcScreenSaverSetAttributes,
+ ProcScreenSaverUnsetAttributes,
+ ProcScreenSaverSuspend,
+};
+
+#define NUM_REQUESTS ((sizeof NormalVector) / (sizeof NormalVector[0]))
+
+static int
+ProcScreenSaverDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ if (stuff->data < NUM_REQUESTS)
+ return (*NormalVector[stuff->data])(client);
+ return BadRequest;
+}
+
+static int
+SProcScreenSaverQueryVersion (ClientPtr client)
+{
+ REQUEST(xScreenSaverQueryVersionReq);
+ int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq);
+ return ProcScreenSaverQueryVersion (client);
+}
+
+static int
+SProcScreenSaverQueryInfo (ClientPtr client)
+{
+ REQUEST(xScreenSaverQueryInfoReq);
+ int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq);
+ swapl (&stuff->drawable, n);
+ return ProcScreenSaverQueryInfo (client);
+}
+
+static int
+SProcScreenSaverSelectInput (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 (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 (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 int (*SwappedVector[]) (ClientPtr /* client */) = {
+ SProcScreenSaverQueryVersion,
+ SProcScreenSaverQueryInfo,
+ SProcScreenSaverSelectInput,
+ SProcScreenSaverSetAttributes,
+ SProcScreenSaverUnsetAttributes,
+ SProcScreenSaverSuspend,
+};
+
+static int
+SProcScreenSaverDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ if (stuff->data < NUM_REQUESTS)
+ return (*SwappedVector[stuff->data])(client);
+ return BadRequest;
+}
+
+void
+ScreenSaverExtensionInit(INITARGS)
+{
+ ExtensionEntry *extEntry;
+ int i;
+ ScreenPtr pScreen;
+
+ if (!dixRegisterPrivateKey(&ScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
+ return;
+
+ AttrType = CreateNewResourceType(ScreenSaverFreeAttr, "SaverAttr");
+ SaverEventType = CreateNewResourceType(ScreenSaverFreeEvents,
+ "SaverEvent");
+ SuspendType = CreateNewResourceType(ScreenSaverFreeSuspend,
+ "SaverSuspend");
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+ SetScreenPrivate (pScreen, NULL);
+ }
+ if (AttrType && SaverEventType && SuspendType &&
+ (extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0,
+ ProcScreenSaverDispatch, SProcScreenSaverDispatch,
+ NULL, StandardMinorOpcode)))
+ {
+ ScreenSaverEventBase = extEntry->eventBase;
+ EventSwapVector[ScreenSaverEventBase] = (EventSwapPtr) SScreenSaverNotifyEvent;
+ }
+}
diff --git a/Xext/security.c b/Xext/security.c
new file mode 100644
index 0000000..8673880
--- /dev/null
+++ b/Xext/security.c
@@ -0,0 +1,1146 @@
+/*
+
+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/securproto.h>
+#include "modinit.h"
+#include "protocol-versions.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 DevPrivateKeyRec stateKeyRec;
+#define stateKey (&stateKeyRec)
+
+/* 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 *SecurityTrustedExtensions[] = {
+ "XC-MISC",
+ "BIG-REQUESTS",
+ "XpExtension",
+ NULL
+};
+
+/*
+ * Access modes that untrusted clients are allowed on trusted objects.
+ */
+static const Mask SecurityResourceMask =
+ DixGetAttrAccess | DixReceiveAccess | DixListPropAccess |
+ DixGetPropAccess | DixListAccess;
+static const Mask SecurityWindowExtraMask = DixRemoveAccess;
+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);
+}
+
+
+/* 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 */
+ xSecurityAuthorizationRevokedEvent are;
+ are.type = SecurityEventBase + XSecurityAuthorizationRevoked;
+ are.authId = pAuth->id;
+ WriteEventsToClient(rClient(pEventClient), 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);
+ free(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;
+ free(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 = SERVER_SECURITY_MAJOR_VERSION;
+ rep.minorVersion = SERVER_SECURITY_MINOR_VERSION;
+ if(client->swapped)
+ {
+ char n;
+ swaps(&rep.sequenceNumber, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ (void)WriteToClient(client, SIZEOF(xSecurityQueryVersionReply),
+ (char *)&rep);
+ return Success;
+} /* 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 = malloc(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))
+ {
+ free(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 = bytes_to_int32(SIZEOF(xSecurityGenerateAuthorizationReq));
+ len += bytes_to_int32(stuff->nbytesAuthProto);
+ len += bytes_to_int32(stuff->nbytesAuthData);
+ 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 + bytes_to_int32(stuff->nbytesAuthProto);
+
+ /* 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 = malloc(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 = bytes_to_int32(authdata_len);
+ rep.sequenceNumber = client->sequence;
+ rep.authId = authId;
+ rep.dataLength = authdata_len;
+
+ if (client->swapped)
+ {
+ 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 */
+ return Success;
+
+bailout:
+ if (removeAuth)
+ RemoveAuthorization(stuff->nbytesAuthProto, protoname,
+ authdata_len, pAuthdata);
+ free(pAuth);
+ return err;
+
+} /* ProcSecurityGenerateAuthorization */
+
+static int
+ProcSecurityRevokeAuthorization(
+ ClientPtr client)
+{
+ REQUEST(xSecurityRevokeAuthorizationReq);
+ SecurityAuthorizationPtr pAuth;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
+
+ rc = dixLookupResourceByType((pointer *)&pAuth, stuff->authId,
+ SecurityAuthorizationResType, client,
+ DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ 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);
+ 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);
+ 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 = bytes_to_int32(stuff->nbytesAuthProto) +
+ bytes_to_int32(stuff->nbytesAuthData);
+ if (values_offset >
+ stuff->length - bytes_to_int32(sz_xSecurityGenerateAuthorizationReq))
+ 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);
+ 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);
+
+ /* disable background None for untrusted windows */
+ if ((requested & DixCreateAccess) && (rec->rtype == RT_WINDOW))
+ if (subj->haveState && subj->trustLevel != XSecurityClientTrusted)
+ ((WindowPtr)rec->res)->forcedBG = TRUE;
+
+ /* additional permissions for specific resource types */
+ if (rec->rtype == RT_WINDOW)
+ allowed |= SecurityWindowExtraMask;
+
+ /* 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 (clients[cid] != NULL) {
+ obj = dixLookupPrivate(&clients[cid]->devPrivates, stateKey);
+ if (SecurityDoCheck(subj, obj, requested, allowed) == Success)
+ return;
+ }
+
+ 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)
+ return;
+
+ while (SecurityTrustedExtensions[i])
+ if (!strcmp(SecurityTrustedExtensions[i++], rec->ext->name))
+ return;
+
+ 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;
+}
+
+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,
+ LookupEventName(rec->events[i].u.u.type),
+ rec->pWin->drawable.id,
+ wClient(rec->pWin)->index);
+ 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 = dixLookupResourceByType((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 = dixLookupResourceByType((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,
+ "SecurityAuthorization");
+
+ RTEventClient =
+ CreateNewResourceType(SecurityDeleteAuthorizationEventClient,
+ "SecurityEventClient");
+
+ if (!SecurityAuthorizationResType || !RTEventClient)
+ return;
+
+ RTEventClient |= RC_NEVERRETAIN;
+
+ /* Allocate the private storage */
+ if (!dixRegisterPrivateKey(stateKey, PRIVATE_CLIENT, 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;
+
+ SetResourceTypeErrorValue(SecurityAuthorizationResType, SecurityErrorBase + XSecurityBadAuthorization);
+
+ /* Label objects that were created before we could register ourself */
+ SecurityLabelInitial();
+}
diff --git a/Xext/securitysrv.h b/Xext/securitysrv.h
new file mode 100644
index 0000000..3d3894a
--- /dev/null
+++ b/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/secur.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/Xext/shape.c b/Xext/shape.c
new file mode 100644
index 0000000..115fc07
--- /dev/null
+++ b/Xext/shape.c
@@ -0,0 +1,1260 @@
+/************************************************************
+
+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.
+
+********************************************************/
+
+#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"
+#include <X11/extensions/shapeproto.h>
+#include "regionstr.h"
+#include "gcstruct.h"
+#include "modinit.h"
+#include "protocol-versions.h"
+
+typedef RegionPtr (*CreateDftPtr)(
+ WindowPtr /* pWin */
+ );
+
+static int ShapeFreeClient(
+ pointer /* data */,
+ XID /* id */
+ );
+static int ShapeFreeEvents(
+ pointer /* data */,
+ XID /* id */
+ );
+static void SShapeNotifyEvent(
+ xShapeNotifyEvent * /* from */,
+ xShapeNotifyEvent * /* to */
+ );
+
+/* SendShapeNotify, CreateBoundingShape and CreateClipShape are used
+ * externally by the Xfixes extension and are now defined in window.h
+ */
+
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+static int ShapeEventBase = 0;
+static RESTYPE ClientType, ShapeEventType; /* 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.
+ *
+ ****************/
+
+static int
+RegionOperate (
+ ClientPtr client,
+ WindowPtr pWin,
+ int kind,
+ RegionPtr *destRgnp,
+ RegionPtr srcRgn,
+ int op,
+ int xoff, int yoff,
+ CreateDftPtr create)
+{
+ if (srcRgn && (xoff || yoff))
+ RegionTranslate(srcRgn, xoff, yoff);
+ if (!pWin->parent)
+ {
+ if (srcRgn)
+ RegionDestroy(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) {
+ RegionDestroy(*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)
+ RegionDestroy(*destRgnp);
+ *destRgnp = srcRgn;
+ srcRgn = 0;
+ break;
+ case ShapeUnion:
+ if (*destRgnp)
+ RegionUnion(*destRgnp, *destRgnp, srcRgn);
+ break;
+ case ShapeIntersect:
+ if (*destRgnp)
+ RegionIntersect(*destRgnp, *destRgnp, srcRgn);
+ else {
+ *destRgnp = srcRgn;
+ srcRgn = 0;
+ }
+ break;
+ case ShapeSubtract:
+ if (!*destRgnp)
+ *destRgnp = (*create)(pWin);
+ RegionSubtract(*destRgnp, *destRgnp, srcRgn);
+ break;
+ case ShapeInvert:
+ if (!*destRgnp)
+ *destRgnp = RegionCreate((BoxPtr) 0, 0);
+ else
+ RegionSubtract(*destRgnp, srcRgn, *destRgnp);
+ break;
+ default:
+ client->errorValue = op;
+ return BadValue;
+ }
+ if (srcRgn)
+ RegionDestroy(srcRgn);
+ (*pWin->drawable.pScreen->SetShape) (pWin, kind);
+ SendShapeNotify (pWin, kind);
+ return Success;
+}
+
+RegionPtr
+CreateBoundingShape (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 RegionCreate(&extents, 1);
+}
+
+RegionPtr
+CreateClipShape (WindowPtr pWin)
+{
+ BoxRec extents;
+
+ extents.x1 = 0;
+ extents.y1 = 0;
+ extents.x2 = pWin->drawable.width;
+ extents.y2 = pWin->drawable.height;
+ return RegionCreate(&extents, 1);
+}
+
+static int
+ProcShapeQueryVersion (ClientPtr client)
+{
+ xShapeQueryVersionReply rep;
+ int n;
+
+ REQUEST_SIZE_MATCH (xShapeQueryVersionReq);
+ memset(&rep, 0, sizeof(xShapeQueryVersionReply));
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = SERVER_SHAPE_MAJOR_VERSION;
+ rep.minorVersion = SERVER_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 Success;
+}
+
+/*****************
+ * ProcShapeRectangles
+ *
+ *****************/
+
+static int
+ProcShapeRectangles (ClientPtr client)
+{
+ WindowPtr pWin;
+ 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;
+ }
+ 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 = RegionFromRects(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(
+ ClientPtr client)
+{
+ REQUEST(xShapeRectanglesReq);
+ PanoramiXRes *win;
+ int j, result;
+
+ REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW,
+ client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ FOR_NSCREENS(j) {
+ stuff->dest = win->info[j].id;
+ result = ProcShapeRectangles (client);
+ if (result != Success) break;
+ }
+ return result;
+}
+#endif
+
+
+/**************
+ * ProcShapeMask
+ **************/
+
+
+static int
+ProcShapeMask (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 = dixLookupResourceByType((pointer *)&pPixmap, stuff->src, RT_PIXMAP,
+ client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+ if (pPixmap->drawable.pScreen != pScreen ||
+ pPixmap->drawable.depth != 1)
+ return BadMatch;
+ srcRgn = BitmapToRegion(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(
+ ClientPtr client)
+{
+ REQUEST(xShapeMaskReq);
+ PanoramiXRes *win, *pmap;
+ int j, result;
+
+ REQUEST_SIZE_MATCH (xShapeMaskReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW,
+ client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ if(stuff->src != None) {
+ result = dixLookupResourceByType((pointer *)&pmap, stuff->src,
+ XRT_PIXMAP, client, DixReadAccess);
+ if (result != Success)
+ return result;
+ } else
+ pmap = NULL;
+
+ FOR_NSCREENS(j) {
+ stuff->dest = win->info[j].id;
+ if(pmap)
+ stuff->src = pmap->info[j].id;
+ result = ProcShapeMask (client);
+ if (result != Success) break;
+ }
+ return result;
+}
+#endif
+
+
+/************
+ * ProcShapeCombine
+ ************/
+
+static int
+ProcShapeCombine (ClientPtr client)
+{
+ WindowPtr pSrcWin, pDestWin;
+ 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;
+ }
+
+ 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 != pDestWin->drawable.pScreen)
+ {
+ return BadMatch;
+ }
+
+ if (srcRgn) {
+ tmp = RegionCreate((BoxPtr) 0, 0);
+ RegionCopy(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(
+ ClientPtr client)
+{
+ REQUEST(xShapeCombineReq);
+ PanoramiXRes *win, *win2;
+ int j, result;
+
+ REQUEST_AT_LEAST_SIZE (xShapeCombineReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW,
+ client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ result = dixLookupResourceByType((pointer *)&win2, stuff->src, XRT_WINDOW,
+ client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ FOR_NSCREENS(j) {
+ stuff->dest = win->info[j].id;
+ stuff->src = win2->info[j].id;
+ result = ProcShapeCombine (client);
+ if (result != Success) break;
+ }
+ return result;
+}
+#endif
+
+/*************
+ * ProcShapeOffset
+ *************/
+
+static int
+ProcShapeOffset (ClientPtr client)
+{
+ WindowPtr pWin;
+ 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;
+ }
+ if (srcRgn)
+ {
+ RegionTranslate(srcRgn, stuff->xOff, stuff->yOff);
+ (*pWin->drawable.pScreen->SetShape) (pWin, stuff->destKind);
+ }
+ SendShapeNotify (pWin, (int)stuff->destKind);
+ return Success;
+}
+
+
+#ifdef PANORAMIX
+static int
+ProcPanoramiXShapeOffset(
+ ClientPtr client)
+{
+ REQUEST(xShapeOffsetReq);
+ PanoramiXRes *win;
+ int j, result;
+
+ REQUEST_AT_LEAST_SIZE (xShapeOffsetReq);
+
+ result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW,
+ client, DixWriteAccess);
+ if (result != Success)
+ return result;
+
+ FOR_NSCREENS(j) {
+ stuff->dest = win->info[j].id;
+ result = ProcShapeOffset (client);
+ if(result != Success) break;
+ }
+ return result;
+}
+#endif
+
+
+static int
+ProcShapeQueryExtents (ClientPtr client)
+{
+ REQUEST(xShapeQueryExtentsReq);
+ WindowPtr pWin;
+ xShapeQueryExtentsReply rep;
+ BoxRec extents, *pExtents;
+ int n, rc;
+ RegionPtr region;
+
+ REQUEST_SIZE_MATCH (xShapeQueryExtentsReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ memset(&rep, 0, sizeof(xShapeQueryExtentsReply));
+ 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 = RegionExtents(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 = RegionExtents(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 Success;
+}
+
+/*ARGSUSED*/
+static int
+ShapeFreeClient (pointer data, XID id)
+{
+ ShapeEventPtr pShapeEvent;
+ WindowPtr pWin;
+ ShapeEventPtr *pHead, pCur, pPrev;
+ int rc;
+
+ pShapeEvent = (ShapeEventPtr) data;
+ pWin = pShapeEvent->window;
+ rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
+ ShapeEventType, serverClient, DixReadAccess);
+ if (rc == Success) {
+ 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;
+ }
+ }
+ free((pointer) pShapeEvent);
+ return 1;
+}
+
+/*ARGSUSED*/
+static int
+ShapeFreeEvents (pointer data, XID id)
+{
+ ShapeEventPtr *pHead, pCur, pNext;
+
+ pHead = (ShapeEventPtr *) data;
+ for (pCur = *pHead; pCur; pCur = pNext) {
+ pNext = pCur->next;
+ FreeResource (pCur->clientResource, ClientType);
+ free((pointer) pCur);
+ }
+ free((pointer) pHead);
+ return 1;
+}
+
+static int
+ProcShapeSelectInput (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;
+ rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
+ ShapeEventType, client, DixWriteAccess);
+ if (rc != Success && rc != BadValue)
+ return rc;
+
+ 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 = malloc(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 = malloc(sizeof (ShapeEventPtr));
+ if (!pHead ||
+ !AddResource (pWin->drawable.id, ShapeEventType, (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;
+ free(pShapeEvent);
+ }
+ }
+ break;
+ default:
+ client->errorValue = stuff->enable;
+ return BadValue;
+ }
+ return Success;
+}
+
+/*
+ * deliver the event
+ */
+
+void
+SendShapeNotify (WindowPtr pWin, int which)
+{
+ ShapeEventPtr *pHead, pShapeEvent;
+ xShapeNotifyEvent se;
+ BoxRec extents;
+ RegionPtr region;
+ BYTE shaped;
+ int rc;
+
+ rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
+ ShapeEventType, serverClient, DixReadAccess);
+ if (rc != Success)
+ return;
+ switch (which) {
+ case ShapeBounding:
+ region = wBoundingShape(pWin);
+ if (region) {
+ extents = *RegionExtents(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 = *RegionExtents(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 = *RegionExtents(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) {
+ se.type = ShapeNotify + ShapeEventBase;
+ se.kind = which;
+ se.window = pWin->drawable.id;
+ 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 (pShapeEvent->client, 1, (xEvent *) &se);
+ }
+}
+
+static int
+ProcShapeInputSelected (ClientPtr client)
+{
+ REQUEST(xShapeInputSelectedReq);
+ WindowPtr pWin;
+ ShapeEventPtr pShapeEvent, *pHead;
+ int enabled, rc;
+ xShapeInputSelectedReply rep;
+ int n;
+
+ REQUEST_SIZE_MATCH (xShapeInputSelectedReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id,
+ ShapeEventType, client, DixReadAccess);
+ if (rc != Success && rc != BadValue)
+ return rc;
+ 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 Success;
+}
+
+static int
+ProcShapeGetRectangles (ClientPtr client)
+{
+ REQUEST(xShapeGetRectanglesReq);
+ WindowPtr pWin;
+ xShapeGetRectanglesReply rep;
+ xRectangle *rects;
+ int nrects, i, rc;
+ RegionPtr region;
+ 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 = malloc(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 = RegionNumRects(region);
+ box = RegionRects(region);
+ rects = malloc(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 = bytes_to_int32(nrects * sizeof (xRectangle));
+ 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);
+ free(rects);
+ return Success;
+}
+
+static int
+ProcShapeDispatch (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(xShapeNotifyEvent *from, xShapeNotifyEvent *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 (ClientPtr client)
+{
+ int n;
+ REQUEST (xShapeQueryVersionReq);
+
+ swaps (&stuff->length, n);
+ return ProcShapeQueryVersion (client);
+}
+
+static int
+SProcShapeRectangles (ClientPtr client)
+{
+ 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 (ClientPtr client)
+{
+ 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 (ClientPtr client)
+{
+ 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 (ClientPtr client)
+{
+ 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 (ClientPtr client)
+{
+ char n;
+ REQUEST (xShapeQueryExtentsReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xShapeQueryExtentsReq);
+ swapl (&stuff->window, n);
+ return ProcShapeQueryExtents (client);
+}
+
+static int
+SProcShapeSelectInput (ClientPtr client)
+{
+ char n;
+ REQUEST (xShapeSelectInputReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xShapeSelectInputReq);
+ swapl (&stuff->window, n);
+ return ProcShapeSelectInput (client);
+}
+
+static int
+SProcShapeInputSelected (ClientPtr client)
+{
+ int n;
+ REQUEST (xShapeInputSelectedReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xShapeInputSelectedReq);
+ swapl (&stuff->window, n);
+ return ProcShapeInputSelected (client);
+}
+
+static int
+SProcShapeGetRectangles (ClientPtr client)
+{
+ REQUEST(xShapeGetRectanglesReq);
+ char n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
+ swapl (&stuff->window, n);
+ return ProcShapeGetRectangles (client);
+}
+
+static int
+SProcShapeDispatch (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;
+ }
+}
+
+void
+ShapeExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+
+ ClientType = CreateNewResourceType(ShapeFreeClient, "ShapeClient");
+ ShapeEventType = CreateNewResourceType(ShapeFreeEvents, "ShapeEvent");
+ if (ClientType && ShapeEventType &&
+ (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0,
+ ProcShapeDispatch, SProcShapeDispatch,
+ NULL, StandardMinorOpcode)))
+ {
+ ShapeEventBase = extEntry->eventBase;
+ EventSwapVector[ShapeEventBase] = (EventSwapPtr) SShapeNotifyEvent;
+ }
+}
diff --git a/Xext/shm.c b/Xext/shm.c
new file mode 100644
index 0000000..23afe6b
--- /dev/null
+++ b/Xext/shm.c
@@ -0,0 +1,1327 @@
+/************************************************************
+
+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>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <unistd.h>
+#include <sys/stat.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 "windowstr.h"
+#include "pixmapstr.h"
+#include "gcstruct.h"
+#include "extnsionst.h"
+#include "servermd.h"
+#include "shmint.h"
+#include "xace.h"
+#include <X11/extensions/shmproto.h>
+#include <X11/Xfuncproto.h>
+#include "protocol-versions.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;
+
+typedef struct _ShmScrPrivateRec {
+ CloseScreenProcPtr CloseScreen;
+ ShmFuncsPtr shmFuncs;
+ DestroyPixmapProcPtr destroyPixmap;
+} ShmScrPrivateRec;
+
+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 unsigned char ShmReqCode;
+int ShmCompletionCode;
+int BadShmSegCode;
+RESTYPE ShmSegType;
+static ShmDescPtr Shmsegs;
+static Bool sharedPixmaps;
+static DevPrivateKeyRec shmScrPrivateKeyRec;
+#define shmScrPrivateKey (&shmScrPrivateKeyRec)
+static DevPrivateKeyRec shmPixmapPrivateKeyRec;
+#define shmPixmapPrivateKey (&shmPixmapPrivateKeyRec)
+static ShmFuncs miFuncs = {NULL, NULL};
+static ShmFuncs fbFuncs = {fbShmCreatePixmap, NULL};
+
+#define ShmGetScreenPriv(s) ((ShmScrPrivateRec *)dixLookupPrivate(&(s)->devPrivates, shmScrPrivateKey))
+
+#define VERIFY_SHMSEG(shmseg,shmdesc,client) \
+{ \
+ int rc; \
+ rc = dixLookupResourceByType((pointer *)&(shmdesc), shmseg, ShmSegType, \
+ client, DixReadAccess); \
+ if (rc != Success) \
+ return rc; \
+}
+
+#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(int signo)
+{
+ badSysCall = TRUE;
+}
+
+static Bool CheckForShmSyscall(void)
+{
+ 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, NULL);
+ }
+ else
+ {
+ /* Allocation failed */
+ badSysCall = TRUE;
+ }
+ signal(SIGSYS, oldHandler);
+ return !badSysCall;
+}
+
+#define MUST_CHECK_FOR_SHM_SYSCALL
+
+#endif
+
+static Bool
+ShmCloseScreen(int i, ScreenPtr pScreen)
+{
+ ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen);
+ pScreen->CloseScreen = screen_priv->CloseScreen;
+ dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, NULL);
+ free(screen_priv);
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+static ShmScrPrivateRec *
+ShmInitScreenPriv(ScreenPtr pScreen)
+{
+ ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen);
+ if (!screen_priv)
+ {
+ screen_priv = calloc(1, sizeof (ShmScrPrivateRec));
+ screen_priv->CloseScreen = pScreen->CloseScreen;
+ dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, screen_priv);
+ pScreen->CloseScreen = ShmCloseScreen;
+ }
+ return screen_priv;
+}
+
+static Bool
+ShmRegisterPrivates(void)
+{
+ if (!dixRegisterPrivateKey(&shmScrPrivateKeyRec, PRIVATE_SCREEN, 0))
+ return FALSE;
+ if (!dixRegisterPrivateKey(&shmPixmapPrivateKeyRec, PRIVATE_PIXMAP, 0))
+ return FALSE;
+ return TRUE;
+}
+
+/*ARGSUSED*/
+static void
+ShmResetProc(ExtensionEntry *extEntry)
+{
+ int i;
+ for (i = 0; i < screenInfo.numScreens; i++)
+ ShmRegisterFuncs(screenInfo.screens[i], NULL);
+}
+
+void
+ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs)
+{
+ if (!ShmRegisterPrivates())
+ return;
+ ShmInitScreenPriv(pScreen)->shmFuncs = funcs;
+}
+
+static Bool
+ShmDestroyPixmap (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen);
+ Bool ret;
+ if (pPixmap->refcnt == 1)
+ {
+ ShmDescPtr shmdesc;
+ shmdesc = (ShmDescPtr)dixLookupPrivate(&pPixmap->devPrivates,
+ shmPixmapPrivateKey);
+ if (shmdesc)
+ ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id);
+ }
+
+ pScreen->DestroyPixmap = screen_priv->destroyPixmap;
+ ret = (*pScreen->DestroyPixmap) (pPixmap);
+ screen_priv->destroyPixmap = pScreen->DestroyPixmap;
+ pScreen->DestroyPixmap = ShmDestroyPixmap;
+ return ret;
+}
+
+void
+ShmRegisterFbFuncs(ScreenPtr pScreen)
+{
+ ShmRegisterFuncs(pScreen, &fbFuncs);
+}
+
+static int
+ProcShmQueryVersion(ClientPtr client)
+{
+ xShmQueryVersionReply rep;
+ int n;
+
+ REQUEST_SIZE_MATCH(xShmQueryVersionReq);
+ memset(&rep, 0, sizeof(xShmQueryVersionReply));
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.sharedPixmaps = sharedPixmaps;
+ rep.pixmapFormat = sharedPixmaps ? ZPixmap : 0;
+ rep.majorVersion = SERVER_SHM_MAJOR_VERSION;
+ rep.minorVersion = SERVER_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 Success;
+}
+
+/*
+ * 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(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 = malloc(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))
+ {
+ free(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);
+ free(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 Success;
+}
+
+/*ARGSUSED*/
+static int
+ShmDetachSegment(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;
+ free(shmdesc);
+ return Success;
+}
+
+static int
+ProcShmDetach(ClientPtr client)
+{
+ ShmDescPtr shmdesc;
+ REQUEST(xShmDetachReq);
+
+ REQUEST_SIZE_MATCH(xShmDetachReq);
+ VERIFY_SHMSEG(stuff->shmseg, shmdesc, client);
+ FreeResource(stuff->shmseg, RT_NONE);
+ return Success;
+}
+
+/*
+ * 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;
+
+ if (format == ZPixmap || depth == 1) {
+ 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);
+ } else {
+ GCPtr putGC = GetScratchGC(depth, dst->pScreen);
+
+ if (!putGC)
+ return;
+
+ pPixmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pPixmap) {
+ FreeScratchGC(putGC);
+ return;
+ }
+ ValidateGC(&pPixmap->drawable, putGC);
+ (*putGC->ops->PutImage)(&pPixmap->drawable, putGC, depth, -sx, -sy, w, h, 0,
+ (format == XYPixmap) ? XYPixmap : ZPixmap, data);
+ FreeScratchGC(putGC);
+ if (format == XYBitmap)
+ (void)(*pGC->ops->CopyPlane)(&pPixmap->drawable, dst, pGC, 0, 0, sw, sh,
+ dx, dy, 1L);
+ else
+ (void)(*pGC->ops->CopyArea)(&pPixmap->drawable, dst, pGC, 0, 0, sw, sh,
+ dx, dy);
+ (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
+ }
+}
+
+static int
+ProcShmPutImage(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.minorEvent = X_ShmPutImage;
+ ev.majorEvent = ShmReqCode;
+ ev.shmseg = stuff->shmseg;
+ ev.offset = stuff->offset;
+ WriteEventsToClient(client, 1, (xEvent *) &ev);
+ }
+
+ return Success;
+}
+
+static int
+ProcShmGetImage(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 Success;
+}
+
+#ifdef PANORAMIX
+static int
+ProcPanoramiXShmPutImage(ClientPtr client)
+{
+ int j, result, orig_x, orig_y;
+ PanoramiXRes *draw, *gc;
+ Bool sendEvent, isRoot;
+
+ REQUEST(xShmPutImageReq);
+ REQUEST_SIZE_MATCH(xShmPutImageReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
+ XRT_GC, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 - screenInfo.screens[j]->x;
+ stuff->dstY = orig_y - screenInfo.screens[j]->y;
+ }
+ result = ProcShmPutImage(client);
+ if(result != Success) break;
+ }
+ return result;
+}
+
+static int
+ProcPanoramiXShmGetImage(ClientPtr client)
+{
+ PanoramiXRes *draw;
+ DrawablePtr *drawables;
+ 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;
+ }
+
+ rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (rc != Success)
+ return (rc == BadValue) ? BadDrawable : rc;
+
+ 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 */
+ screenInfo.screens[0]->x + pDraw->x + x < 0 ||
+ screenInfo.screens[0]->x + pDraw->x + x + w > PanoramiXPixWidth ||
+ screenInfo.screens[0]->y + pDraw->y + y < 0 ||
+ screenInfo.screens[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 = calloc(PanoramiXNumScreens, sizeof(DrawablePtr));
+ if(!drawables)
+ return BadAlloc;
+
+ drawables[0] = pDraw;
+ for(i = 1; i < PanoramiXNumScreens; i++) {
+ rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0,
+ DixReadAccess);
+ if (rc != Success)
+ {
+ free(drawables);
+ 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;
+ }
+ }
+ }
+ free(drawables);
+
+ if (client->swapped) {
+ 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 Success;
+}
+
+static int
+ProcPanoramiXShmCreatePixmap(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 = malloc(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 = Success;
+
+ FOR_NSCREENS(j) {
+ ShmScrPrivateRec *screen_priv;
+ pScreen = screenInfo.screens[j];
+
+ screen_priv = ShmGetScreenPriv(pScreen);
+ pMap = (*screen_priv->shmFuncs->CreatePixmap)(pScreen,
+ stuff->width, stuff->height, stuff->depth,
+ shmdesc->addr + stuff->offset);
+
+ if (pMap) {
+ dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, 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);
+ }
+ free(newPix);
+ } else
+ AddResource(stuff->pid, XRT_PIXMAP, newPix);
+
+ return result;
+}
+#endif
+
+static PixmapPtr
+fbShmCreatePixmap (ScreenPtr pScreen,
+ int width, int height, int depth, char *addr)
+{
+ 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(ClientPtr client)
+{
+ PixmapPtr pMap;
+ DrawablePtr pDraw;
+ DepthPtr pDepth;
+ int i, rc;
+ ShmDescPtr shmdesc;
+ ShmScrPrivateRec *screen_priv;
+ 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);
+ screen_priv = ShmGetScreenPriv(pDraw->pScreen);
+ pMap = (*screen_priv->shmFuncs->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, shmPixmapPrivateKey, shmdesc);
+ shmdesc->refcnt++;
+ pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ pMap->drawable.id = stuff->pid;
+ if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap))
+ {
+ return Success;
+ }
+ pDraw->pScreen->DestroyPixmap(pMap);
+ }
+ return BadAlloc;
+}
+
+static int
+ProcShmDispatch (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(xShmCompletionEvent *from, xShmCompletionEvent *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(ClientPtr client)
+{
+ int n;
+ REQUEST(xShmQueryVersionReq);
+
+ swaps(&stuff->length, n);
+ return ProcShmQueryVersion(client);
+}
+
+static int
+SProcShmAttach(ClientPtr client)
+{
+ 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(ClientPtr client)
+{
+ int n;
+ REQUEST(xShmDetachReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xShmDetachReq);
+ swapl(&stuff->shmseg, n);
+ return ProcShmDetach(client);
+}
+
+static int
+SProcShmPutImage(ClientPtr client)
+{
+ 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(ClientPtr client)
+{
+ 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(ClientPtr client)
+{
+ 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 (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;
+ }
+}
+
+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
+
+ if (!ShmRegisterPrivates())
+ return;
+
+ sharedPixmaps = xFalse;
+ {
+ sharedPixmaps = xTrue;
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ ShmScrPrivateRec *screen_priv = ShmInitScreenPriv(screenInfo.screens[i]);
+ if (!screen_priv->shmFuncs)
+ screen_priv->shmFuncs = &miFuncs;
+ if (!screen_priv->shmFuncs->CreatePixmap)
+ sharedPixmaps = xFalse;
+ }
+ if (sharedPixmaps)
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(screenInfo.screens[i]);
+ screen_priv->destroyPixmap = screenInfo.screens[i]->DestroyPixmap;
+ screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap;
+ }
+ }
+ ShmSegType = CreateNewResourceType(ShmDetachSegment, "ShmSeg");
+ if (ShmSegType &&
+ (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors,
+ ProcShmDispatch, SProcShmDispatch,
+ ShmResetProc, StandardMinorOpcode)))
+ {
+ ShmReqCode = (unsigned char)extEntry->base;
+ ShmCompletionCode = extEntry->eventBase;
+ BadShmSegCode = extEntry->errorBase;
+ SetResourceTypeErrorValue(ShmSegType, BadShmSegCode);
+ EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent;
+ }
+}
diff --git a/Xext/shmint.h b/Xext/shmint.h
new file mode 100644
index 0000000..8f8a00d
--- /dev/null
+++ b/Xext/shmint.h
@@ -0,0 +1,69 @@
+/*
+ * 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_
+
+#include <X11/extensions/shmproto.h>
+
+#include "screenint.h"
+#include "pixmap.h"
+#include "gc.h"
+
+#define XSHM_PUT_IMAGE_ARGS \
+ 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 */
+
+#define XSHM_CREATE_PIXMAP_ARGS \
+ ScreenPtr /* pScreen */, \
+ int /* width */, \
+ int /* height */, \
+ int /* depth */, \
+ char * /* addr */
+
+typedef struct _ShmFuncs {
+ PixmapPtr (* CreatePixmap)(XSHM_CREATE_PIXMAP_ARGS);
+ void (* PutImage)(XSHM_PUT_IMAGE_ARGS);
+} ShmFuncs, *ShmFuncsPtr;
+
+extern _X_EXPORT void
+ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
+
+extern _X_EXPORT void
+ShmRegisterFbFuncs(ScreenPtr pScreen);
+
+extern _X_EXPORT RESTYPE ShmSegType;
+extern _X_EXPORT int ShmCompletionCode;
+extern _X_EXPORT int BadShmSegCode;
+
+#endif /* _SHMINT_H_ */
diff --git a/Xext/sleepuntil.c b/Xext/sleepuntil.c
new file mode 100644
index 0000000..3fd06ac
--- /dev/null
+++ b/Xext/sleepuntil.c
@@ -0,0 +1,225 @@
+/*
+ *
+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 */
+);
+
+int
+ClientSleepUntil (ClientPtr client,
+ TimeStamp *revive,
+ void (*notifyFunc)(ClientPtr, pointer),
+ pointer closure)
+{
+ SertafiedPtr pRequest, pReq, pPrev;
+
+ if (SertafiedGeneration != serverGeneration)
+ {
+ SertafiedResType = CreateNewResourceType (SertafiedDelete,
+ "ClientSleep");
+ if (!SertafiedResType)
+ return FALSE;
+ SertafiedGeneration = serverGeneration;
+ BlockHandlerRegistered = FALSE;
+ }
+ pRequest = malloc(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))
+ {
+ free(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 (ClientPtr client, pointer closure)
+{
+ if (!client->clientGone)
+ AttendClient (client);
+}
+
+
+static int
+SertafiedDelete (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);
+ free(pRequest);
+ return TRUE;
+}
+
+static void
+SertafiedBlockHandler (pointer data, OSTimePtr wt, 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 (pointer data, int i, pointer LastSelectMask)
+{
+ SertafiedPtr pReq, pNext;
+ TimeStamp now;
+
+ now.milliseconds = GetTimeInMillis ();
+ now.months = currentTime.months;
+ if ((int) (now.milliseconds - currentTime.milliseconds) < 0)
+ now.months++;
+ for (pReq = pPending; pReq; pReq = pNext)
+ {
+ pNext = pReq->next;
+ if (CompareTimeStamps (pReq->revive, now) == LATER)
+ break;
+ FreeResource (pReq->id, RT_NONE);
+ }
+ if (!pPending)
+ {
+ RemoveBlockAndWakeupHandlers (SertafiedBlockHandler,
+ SertafiedWakeupHandler,
+ (pointer) 0);
+ BlockHandlerRegistered = FALSE;
+ }
+}
diff --git a/Xext/sleepuntil.h b/Xext/sleepuntil.h
new file mode 100644
index 0000000..a3618d9
--- /dev/null
+++ b/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/Xext/sync.c b/Xext/sync.c
new file mode 100644
index 0000000..36dd278
--- /dev/null
+++ b/Xext/sync.c
@@ -0,0 +1,2925 @@
+/*
+
+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.
+
+*/
+
+#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 "scrnintstr.h"
+#include "os.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "pixmapstr.h"
+#include "resource.h"
+#include "opaque.h"
+#include <X11/extensions/syncproto.h>
+#include "syncsrv.h"
+#include "syncsdk.h"
+#include "protocol-versions.h"
+
+#include <stdio.h>
+#if !defined(WIN32)
+#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 RESTYPE RTFence;
+static int SyncNumSystemCounters = 0;
+static SyncCounter **SysCounterList = NULL;
+static int SyncNumInvalidCounterWarnings = 0;
+#define MAX_INVALID_COUNTER_WARNINGS 5
+
+static const char *WARN_INVALID_COUNTER_COMPARE =
+"Warning: Non-counter XSync object using Counter-only\n"
+" comparison. Result will never be true.\n";
+
+static const char *WARN_INVALID_COUNTER_ALARM =
+"Warning: Non-counter XSync object used in alarm. This is\n"
+" the result of a programming error in the X server.\n";
+
+#define IsSystemCounter(pCounter) \
+ (pCounter && (pCounter->sync.client == NULL))
+
+/* these are all the alarm attributes that pertain to the alarm's trigger */
+#define XSyncCAAllTrigger \
+ (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
+
+static void SyncComputeBracketValues(SyncCounter *);
+
+static void SyncInitServerTime(void);
+
+static void SyncInitIdleTime(void);
+
+static Bool
+SyncCheckWarnIsCounter(const SyncObject* pSync, const char *warning)
+{
+ if (pSync && (SYNC_COUNTER != pSync->type))
+ {
+ if (SyncNumInvalidCounterWarnings++ < MAX_INVALID_COUNTER_WARNINGS)
+ {
+ ErrorF("%s", warning);
+ ErrorF(" Counter type: %d\n", pSync->type);
+ }
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* 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
+SyncDeleteTriggerFromSyncObject(SyncTrigger *pTrigger)
+{
+ SyncTriggerList *pCur;
+ SyncTriggerList *pPrev;
+ SyncCounter *pCounter;
+
+ /* pSync needs to be stored in pTrigger before calling here. */
+
+ if (!pTrigger->pSync)
+ return;
+
+ pPrev = NULL;
+ pCur = pTrigger->pSync->pTriglist;
+
+ while (pCur)
+ {
+ if (pCur->pTrigger == pTrigger)
+ {
+ if (pPrev)
+ pPrev->next = pCur->next;
+ else
+ pTrigger->pSync->pTriglist = pCur->next;
+
+ free(pCur);
+ break;
+ }
+
+ pPrev = pCur;
+ pCur = pCur->next;
+ }
+
+ if (SYNC_COUNTER == pTrigger->pSync->type)
+ {
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ if (IsSystemCounter(pCounter))
+ SyncComputeBracketValues(pCounter);
+ } else if (SYNC_FENCE == pTrigger->pSync->type) {
+ SyncFence* pFence = (SyncFence*) pTrigger->pSync;
+ pFence->funcs.DeleteTrigger(pTrigger);
+ }
+}
+
+
+static int
+SyncAddTriggerToSyncObject(SyncTrigger *pTrigger)
+{
+ SyncTriggerList *pCur;
+ SyncCounter *pCounter;
+
+ if (!pTrigger->pSync)
+ return Success;
+
+ /* don't do anything if it's already there */
+ for (pCur = pTrigger->pSync->pTriglist; pCur; pCur = pCur->next)
+ {
+ if (pCur->pTrigger == pTrigger)
+ return Success;
+ }
+
+ if (!(pCur = malloc(sizeof(SyncTriggerList))))
+ return BadAlloc;
+
+ pCur->pTrigger = pTrigger;
+ pCur->next = pTrigger->pSync->pTriglist;
+ pTrigger->pSync->pTriglist = pCur;
+
+ if (SYNC_COUNTER == pTrigger->pSync->type)
+ {
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ if (IsSystemCounter(pCounter))
+ SyncComputeBracketValues(pCounter);
+ } else if (SYNC_FENCE == pTrigger->pSync->type) {
+ SyncFence* pFence = (SyncFence*) pTrigger->pSync;
+ pFence->funcs.AddTrigger(pTrigger);
+ }
+
+ return Success;
+}
+
+
+/* Below are five possible functions that can be plugged into
+ * pTrigger->CheckTrigger for counter sync objects, corresponding to
+ * the four possible test-types, and the one possible function that
+ * can be plugged into pTrigger->CheckTrigger for fence sync objects.
+ * These functions are called after the sync object's state changes
+ * but are also passed the old state 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->pSync == NULL.
+ * This is because the spec says that a trigger with a sync value
+ * of None is always TRUE.
+ */
+
+static Bool
+SyncCheckTriggerPositiveComparison(SyncTrigger *pTrigger, CARD64 oldval)
+{
+ SyncCounter *pCounter;
+
+ /* Non-counter sync objects should never get here because they
+ * never trigger this comparison. */
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
+ return FALSE;
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ return (pCounter == NULL ||
+ XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value));
+}
+
+static Bool
+SyncCheckTriggerNegativeComparison(SyncTrigger *pTrigger, CARD64 oldval)
+{
+ SyncCounter *pCounter;
+
+ /* Non-counter sync objects should never get here because they
+ * never trigger this comparison. */
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
+ return FALSE;
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ return (pCounter == NULL ||
+ XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value));
+}
+
+static Bool
+SyncCheckTriggerPositiveTransition(SyncTrigger *pTrigger, CARD64 oldval)
+{
+ SyncCounter *pCounter;
+
+ /* Non-counter sync objects should never get here because they
+ * never trigger this comparison. */
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
+ return FALSE;
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ return (pCounter == NULL ||
+ (XSyncValueLessThan(oldval, pTrigger->test_value) &&
+ XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value)));
+}
+
+static Bool
+SyncCheckTriggerNegativeTransition(SyncTrigger *pTrigger, CARD64 oldval)
+{
+ SyncCounter *pCounter;
+
+ /* Non-counter sync objects should never get here because they
+ * never trigger this comparison. */
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
+ return FALSE;
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ return (pCounter == NULL ||
+ (XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
+ XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value)));
+}
+
+static Bool
+SyncCheckTriggerFence(SyncTrigger *pTrigger, CARD64 unused)
+{
+ SyncFence* pFence = (SyncFence*) pTrigger->pSync;
+ (void)unused;
+
+ return (pFence == NULL ||
+ pFence->funcs.CheckTriggered(pFence));
+}
+
+static int
+SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XID syncObject,
+ RESTYPE resType, Mask changes)
+{
+ SyncObject *pSync = pTrigger->pSync;
+ SyncCounter *pCounter = NULL;
+ int rc;
+ Bool newSyncObject = FALSE;
+
+ if (changes & XSyncCACounter)
+ {
+ if (syncObject == None)
+ pSync = NULL;
+ else if (Success != (rc = dixLookupResourceByType ((pointer *)&pSync,
+ syncObject, resType, client, DixReadAccess)))
+ {
+ client->errorValue = syncObject;
+ return rc;
+ }
+ if (pSync != pTrigger->pSync)
+ { /* new counter for trigger */
+ SyncDeleteTriggerFromSyncObject(pTrigger);
+ pTrigger->pSync = pSync;
+ newSyncObject = TRUE;
+ }
+ }
+
+ /* if system counter, ask it what the current value is */
+
+ if (pSync && SYNC_COUNTER == pSync->type)
+ {
+ pCounter = (SyncCounter *)pSync;
+
+ 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 (pSync && SYNC_FENCE == pSync->type)
+ {
+ pTrigger->CheckTrigger = SyncCheckTriggerFence;
+ }
+ else
+ {
+ /* 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;
+ default:
+ client->errorValue = pTrigger->test_type;
+ return BadValue;
+ }
+ }
+ }
+
+ 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 (newSyncObject)
+ {
+ if ((rc = SyncAddTriggerToSyncObject(pTrigger)) != Success)
+ return rc;
+ }
+ else if (pCounter && IsSystemCounter(pCounter))
+ {
+ SyncComputeBracketValues(pCounter);
+ }
+
+ 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(SyncAlarm *pAlarm)
+{
+ SyncAlarmClientList *pcl;
+ xSyncAlarmNotifyEvent ane;
+ SyncTrigger *pTrigger = &pAlarm->trigger;
+ SyncCounter *pCounter;
+
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_ALARM))
+ return;
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ UpdateCurrentTime();
+
+ ane.type = SyncEventBase + XSyncAlarmNotify;
+ ane.kind = XSyncAlarmNotify;
+ ane.alarm = pAlarm->alarm_id;
+ if (pTrigger->pSync && SYNC_COUNTER == pTrigger->pSync->type)
+ {
+ ane.counter_value_hi = XSyncValueHigh32(pCounter->value);
+ ane.counter_value_lo = XSyncValueLow32(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)
+ WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
+
+ /* send to other interested clients */
+ for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
+ 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(ClientPtr client, SyncAwait **ppAwait,
+ int num_events)
+{
+ xSyncCounterNotifyEvent *pEvents, *pev;
+ int i;
+
+ if (client->clientGone)
+ return;
+ pev = pEvents = malloc(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->counter = pTrigger->pSync->id;
+ pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
+ pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
+ if (SYNC_COUNTER == pTrigger->pSync->type)
+ {
+ SyncCounter *pCounter = (SyncCounter *)pTrigger->pSync;
+
+ pev->counter_value_lo = XSyncValueLow32(pCounter->value);
+ pev->counter_value_hi = XSyncValueHigh32(pCounter->value);
+ }
+ else
+ {
+ pev->counter_value_lo = 0;
+ pev->counter_value_hi = 0;
+ }
+
+ pev->time = currentTime.milliseconds;
+ pev->count = num_events - i - 1; /* events remaining */
+ pev->destroyed = pTrigger->pSync->beingDestroyed;
+ }
+ /* swapping will be taken care of by this */
+ WriteEventsToClient(client, num_events, (xEvent *)pEvents);
+ free(pEvents);
+}
+
+
+/* This function is called when an alarm's counter is destroyed.
+ * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
+ */
+static void
+SyncAlarmCounterDestroyed(SyncTrigger *pTrigger)
+{
+ SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
+
+ pAlarm->state = XSyncAlarmInactive;
+ SyncSendAlarmNotifyEvents(pAlarm);
+ pTrigger->pSync = NULL;
+}
+
+
+/* This function is called when an alarm "goes off."
+ * It is plugged into pTrigger->TriggerFired (for alarm triggers).
+ */
+static void
+SyncAlarmTriggerFired(SyncTrigger *pTrigger)
+{
+ SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
+ SyncCounter *pCounter;
+ CARD64 new_test_value;
+
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_ALARM))
+ return;
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ /* 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 (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;
+ SyncCounter *paCounter;
+
+ if (!SyncCheckWarnIsCounter(paTrigger->pSync,
+ WARN_INVALID_COUNTER_ALARM))
+ return;
+
+ paCounter = (SyncCounter *)pTrigger->pSync;
+
+ /* "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,
+ paCounter->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(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 = malloc(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.pSync->beingDestroyed)
+ {
+ ppAwait[num_events++] = pAwait;
+ continue;
+ }
+
+ if (SYNC_COUNTER == pAwait->trigger.pSync->type)
+ {
+ SyncCounter *pCounter = (SyncCounter *) pAwait->trigger.pSync;
+
+ /* "The difference between the counter and the test value is
+ * calculated by subtracting the test value from the value of
+ * the counter."
+ */
+ XSyncValueSubtract(&diff, 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);
+ free(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(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->sync.pTriglist; ptl; ptl = pnext)
+ {
+ pnext = ptl->next;
+ if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
+ (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
+ }
+
+ if (IsSystemCounter(pCounter))
+ {
+ SyncComputeBracketValues(pCounter);
+ }
+}
+
+
+/* loosely based on dix/events.c/EventSelectForWindow */
+static Bool
+SyncEventSelectForAlarm(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 = malloc(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);
+
+ /* link it into list after we know all the allocations succeed */
+ pClients->next = pAlarm->pEventClients;
+ pAlarm->pEventClients = pClients;
+ pClients->client = client;
+
+ if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
+ return BadAlloc;
+
+ return Success;
+}
+
+/*
+ * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
+ */
+static int
+SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm *pAlarm, Mask mask,
+ CARD32 *values)
+{
+ int status;
+ XSyncCounter counter;
+ Mask origmask = mask;
+
+ counter =
+ pAlarm->trigger.pSync ? pAlarm->trigger.pSync->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, RTCounter,
+ origmask & XSyncCAAllTrigger)) != Success)
+ return status;
+
+ /* XXX spec does not really say to do this - needs clarification */
+ pAlarm->state = XSyncAlarmActive;
+ return Success;
+}
+
+static SyncObject *
+SyncCreate(ClientPtr client, XID id, unsigned char type)
+{
+ SyncObject *pSync;
+
+ switch (type) {
+ case SYNC_COUNTER:
+ pSync = malloc(sizeof(SyncCounter));
+ break;
+ case SYNC_FENCE:
+ pSync = (SyncObject*)dixAllocateObjectWithPrivates(SyncFence,
+ PRIVATE_SYNC_FENCE);
+ break;
+ default:
+ return NULL;
+ }
+
+ if (!pSync)
+ return NULL;
+
+ pSync->client = client;
+ pSync->id = id;
+ pSync->pTriglist = NULL;
+ pSync->beingDestroyed = FALSE;
+ pSync->type = type;
+
+ return pSync;
+}
+
+
+static SyncCounter *
+SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue)
+{
+ SyncCounter *pCounter;
+
+ if (!(pCounter = (SyncCounter *)SyncCreate(client,
+ id,
+ SYNC_COUNTER)))
+ return NULL;
+
+ pCounter->value = initialvalue;
+ pCounter->pSysCounterInfo = NULL;
+
+ if (!AddResource(id, RTCounter, (pointer) pCounter))
+ return NULL;
+
+ return pCounter;
+}
+
+static int FreeCounter(void *, XID);
+
+/*
+ * ***** System Counter utilities
+ */
+
+pointer
+SyncCreateSystemCounter(
+ 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 = realloc(SysCounterList,
+ (SyncNumSystemCounters+1)*sizeof(SyncCounter *));
+ if (!SysCounterList)
+ return 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, "SyncCounter");
+ if (RTCounter == 0)
+ {
+ return NULL;
+ }
+ }
+
+ pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial);
+
+ if (pCounter)
+ {
+ SysCounterInfo *psci;
+
+ psci = malloc(sizeof(SysCounterInfo));
+ if (!psci)
+ {
+ FreeResource(pCounter->sync.id, RT_NONE);
+ return 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 pCounter;
+}
+
+void
+SyncDestroySystemCounter(pointer pSysCounter)
+{
+ SyncCounter *pCounter = (SyncCounter *)pSysCounter;
+ FreeResource(pCounter->sync.id, RT_NONE);
+}
+
+static void
+SyncComputeBracketValues(SyncCounter *pCounter)
+{
+ 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;
+
+ XSyncMaxValue(&psci->bracket_greater);
+ XSyncMinValue(&psci->bracket_less);
+
+ for (pCur = pCounter->sync.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 == XSyncNegativeTransition &&
+ ct != XSyncCounterNeverIncreases)
+ {
+ 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 (XSyncValueEqual(pCounter->value, pTrigger->test_value) &&
+ XSyncValueLessThan(pTrigger->test_value,
+ psci->bracket_greater))
+ {
+ /*
+ * The value is exactly equal to our threshold. We want one
+ * more event in the positive direction to ensure we pick up
+ * when the value *exceeds* this threshold.
+ */
+ psci->bracket_greater = pTrigger->test_value;
+ pnewgtval = &psci->bracket_greater;
+ }
+ }
+ else if (pTrigger->test_type == XSyncPositiveTransition &&
+ ct != XSyncCounterNeverDecreases)
+ {
+ 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 (XSyncValueEqual(pCounter->value, pTrigger->test_value) &&
+ XSyncValueGreaterThan(pTrigger->test_value,
+ psci->bracket_less))
+ {
+ /*
+ * The value is exactly equal to our threshold. We want one
+ * more event in the negative direction to ensure we pick up
+ * when the value is less than this threshold.
+ */
+ 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(void *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);
+
+ SyncDeleteTriggerFromSyncObject(&pAlarm->trigger);
+
+ free(pAlarm);
+ return Success;
+}
+
+
+/*
+ * ** Cleanup after the destruction of a Counter
+ */
+/* ARGSUSED */
+static int
+FreeCounter(void *env, XID id)
+{
+ SyncCounter *pCounter = (SyncCounter *) env;
+ SyncTriggerList *ptl, *pnext;
+
+ pCounter->sync.beingDestroyed = TRUE;
+ /* tell all the counter's triggers that the counter has been destroyed */
+ for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext)
+ {
+ (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
+ pnext = ptl->next;
+ free(ptl); /* destroy the trigger list as we go */
+ }
+ if (IsSystemCounter(pCounter))
+ {
+ int i, found = 0;
+
+ free(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--;
+ }
+ free(pCounter);
+ return Success;
+}
+
+/*
+ * ** Cleanup after Await
+ */
+/* ARGSUSED */
+static int
+FreeAwait(void *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.
+ */
+ SyncObject *pSync = pAwait->trigger.pSync;
+ if (pSync && !pSync->beingDestroyed)
+ SyncDeleteTriggerFromSyncObject(&pAwait->trigger);
+ }
+ free(pAwaitUnion);
+ return Success;
+}
+
+/* loosely based on dix/events.c/OtherClientGone */
+static int
+FreeAlarmClient(void *value, 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;
+ free(pCur);
+ return Success;
+ }
+ }
+ FatalError("alarm client not on event list");
+ /*NOTREACHED*/
+}
+
+
+/*
+ * ***** Proc functions
+ */
+
+
+/*
+ * ** Initialize the extension
+ */
+static int
+ProcSyncInitialize(ClientPtr client)
+{
+ xSyncInitializeReply rep;
+ int n;
+
+ REQUEST_SIZE_MATCH(xSyncInitializeReq);
+
+ memset(&rep, 0, sizeof(xSyncInitializeReply));
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = SERVER_SYNC_MAJOR_VERSION;
+ rep.minorVersion = SERVER_SYNC_MINOR_VERSION;
+ rep.length = 0;
+
+ if (client->swapped)
+ {
+ swaps(&rep.sequenceNumber, n);
+ }
+ WriteToClient(client, sizeof(rep), (char *) &rep);
+ return Success;
+}
+
+/*
+ * ** Get list of system counters available through the extension
+ */
+static int
+ProcSyncListSystemCounters(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 += pad_to_int32(sz_xSyncSystemCounter + strlen(name));
+ }
+
+ if (len)
+ {
+ walklist = list = malloc(len);
+ if (!list)
+ return BadAlloc;
+ }
+
+ rep.length = bytes_to_int32(len);
+
+ if (client->swapped)
+ {
+ 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]->sync.id;
+ walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
+ walklist->resolution_lo = XSyncValueLow32(psci->resolution);
+ namelen = strlen(psci->name);
+ walklist->name_length = namelen;
+
+ if (client->swapped)
+ {
+ 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) +
+ pad_to_int32(sz_xSyncSystemCounter + namelen));
+ }
+
+ WriteToClient(client, sizeof(rep), (char *) &rep);
+ if (len)
+ {
+ WriteToClient(client, len, (char *) list);
+ free(list);
+ }
+
+ return Success;
+}
+
+/*
+ * ** Set client Priority
+ */
+static int
+ProcSyncSetPriority(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(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)
+ {
+ char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.priority, n);
+ }
+
+ WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
+
+ return Success;
+}
+
+/*
+ * ** Create a new counter
+ */
+static int
+ProcSyncCreateCounter(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 Success;
+}
+
+/*
+ * ** Set Counter value
+ */
+static int
+ProcSyncSetCounter(ClientPtr client)
+{
+ REQUEST(xSyncSetCounterReq);
+ SyncCounter *pCounter;
+ CARD64 newvalue;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncSetCounterReq);
+
+ rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter,
+ client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ 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(ClientPtr client)
+{
+ REQUEST(xSyncChangeCounterReq);
+ SyncCounter *pCounter;
+ CARD64 newvalue;
+ Bool overflow;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
+
+ rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter,
+ client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ 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(ClientPtr client)
+{
+ REQUEST(xSyncDestroyCounterReq);
+ SyncCounter *pCounter;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
+
+ rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ if (IsSystemCounter(pCounter))
+ {
+ client->errorValue = stuff->counter;
+ return BadAccess;
+ }
+ FreeResource(pCounter->sync.id, RT_NONE);
+ return Success;
+}
+
+static SyncAwaitUnion*
+SyncAwaitPrologue(ClientPtr client, int items)
+{
+ SyncAwaitUnion *pAwaitUnion;
+
+ /* all the memory for the entire await list is allocated
+ * here in one chunk
+ */
+ pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion));
+ if (!pAwaitUnion)
+ return NULL;
+
+ /* first item is the header, remainder are real wait conditions */
+
+ pAwaitUnion->header.delete_id = FakeClientID(client->index);
+ pAwaitUnion->header.client = client;
+ pAwaitUnion->header.num_waitconditions = 0;
+
+ if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
+ return NULL;
+
+ return pAwaitUnion;
+}
+
+static void
+SyncAwaitEpilogue(ClientPtr client, int items, SyncAwaitUnion *pAwaitUnion)
+{
+ SyncAwait *pAwait;
+ int i;
+
+ 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++)
+ {
+ CARD64 value;
+
+ /* don't have to worry about NULL counters because the request
+ * errors before we get here out if they occur
+ */
+ switch (pAwait->trigger.pSync->type) {
+ case SYNC_COUNTER:
+ value = ((SyncCounter *)pAwait->trigger.pSync)->value;
+ break;
+ default:
+ XSyncIntToValue(&value, 0);
+ }
+
+ if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, value))
+ {
+ (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
+ break; /* once is enough */
+ }
+ }
+}
+
+/*
+ * ** Await
+ */
+static int
+ProcSyncAwait(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;
+ }
+
+ if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
+ return BadAlloc;
+
+ /* don't need to do any more memory allocation for this request! */
+
+ pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
+
+ 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 sync objects
+ */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+ client->errorValue = pProtocolWaitConds->counter;
+ return SyncErrorBase + XSyncBadCounter;
+ }
+
+ /* sanity checks are in SyncInitTrigger */
+ pAwait->trigger.pSync = 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, RTCounter,
+ XSyncCAAllTrigger);
+ if (status != Success)
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on sync objects
+ */
+ 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++;
+ }
+
+ SyncAwaitEpilogue(client, items, pAwaitUnion);
+
+ return Success;
+}
+
+
+/*
+ * ** Query a counter
+ */
+static int
+ProcSyncQueryCounter(ClientPtr client)
+{
+ REQUEST(xSyncQueryCounterReq);
+ xSyncQueryCounterReply rep;
+ SyncCounter *pCounter;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
+
+ rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter,
+ RTCounter, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ 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)
+ {
+ 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 Success;
+}
+
+
+/*
+ * ** Create Alarm
+ */
+static int
+ProcSyncCreateAlarm(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 - bytes_to_int32(sizeof(xSyncCreateAlarmReq));
+ /* 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 = malloc(sizeof(SyncAlarm))))
+ {
+ return BadAlloc;
+ }
+
+ /* set up defaults */
+
+ pTrigger = &pAlarm->trigger;
+ pTrigger->pSync = 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, RTCounter,
+ XSyncCAAllTrigger);
+ if (status != Success)
+ {
+ free(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)
+ {
+ free(pAlarm);
+ return status;
+ }
+
+ if (!AddResource(stuff->id, RTAlarm, pAlarm))
+ return BadAlloc;
+
+ /* see if alarm already triggered. NULL counter will not trigger
+ * in CreateAlarm and sets alarm state to Inactive.
+ */
+
+ if (!pTrigger->pSync)
+ {
+ pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
+ }
+ else
+ {
+ SyncCounter *pCounter;
+
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync,
+ WARN_INVALID_COUNTER_ALARM))
+ {
+ FreeResource(stuff->id, RT_NONE);
+ return BadAlloc;
+ }
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ if ((*pTrigger->CheckTrigger)(pTrigger, pCounter->value))
+ (*pTrigger->TriggerFired)(pTrigger);
+ }
+
+ return Success;
+}
+
+/*
+ * ** Change Alarm
+ */
+static int
+ProcSyncChangeAlarm(ClientPtr client)
+{
+ REQUEST(xSyncChangeAlarmReq);
+ SyncAlarm *pAlarm;
+ SyncCounter *pCounter = NULL;
+ long vmask;
+ int len, status;
+
+ REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
+
+ status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
+ client, DixWriteAccess);
+ if (status != Success)
+ return status;
+
+ vmask = stuff->valueMask;
+ len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq));
+ /* 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;
+
+ if (SyncCheckWarnIsCounter(pAlarm->trigger.pSync,
+ WARN_INVALID_COUNTER_ALARM))
+ pCounter = (SyncCounter *)pAlarm->trigger.pSync;
+
+ /* see if alarm already triggered. NULL counter WILL trigger
+ * in ChangeAlarm.
+ */
+
+ if (!pCounter ||
+ (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, pCounter->value))
+ {
+ (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
+ }
+ return Success;
+}
+
+static int
+ProcSyncQueryAlarm(ClientPtr client)
+{
+ REQUEST(xSyncQueryAlarmReq);
+ SyncAlarm *pAlarm;
+ xSyncQueryAlarmReply rep;
+ SyncTrigger *pTrigger;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
+
+ rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
+ client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply));
+ rep.sequenceNumber = client->sequence;
+
+ pTrigger = &pAlarm->trigger;
+ rep.counter = (pTrigger->pSync) ? pTrigger->pSync->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)
+ {
+ 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 Success;
+}
+
+static int
+ProcSyncDestroyAlarm(ClientPtr client)
+{
+ SyncAlarm *pAlarm;
+ int rc;
+ REQUEST(xSyncDestroyAlarmReq);
+
+ REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
+
+ rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ FreeResource(stuff->alarm, RT_NONE);
+ return Success;
+}
+
+static int
+ProcSyncCreateFence(ClientPtr client)
+{
+ REQUEST(xSyncCreateFenceReq);
+ DrawablePtr pDraw;
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncCreateFenceReq);
+
+ rc = dixLookupDrawable(&pDraw, stuff->d, client, M_ANY, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ LEGAL_NEW_RESOURCE(stuff->fid, client);
+
+ if (!(pFence = (SyncFence *)SyncCreate(client,
+ stuff->fid,
+ SYNC_FENCE)))
+ return BadAlloc;
+
+ miSyncInitFence(pDraw->pScreen, pFence, stuff->initially_triggered);
+
+ if (!AddResource(stuff->fid, RTFence, (pointer) pFence))
+ return BadAlloc;
+
+ return client->noClientException;
+}
+
+static int
+FreeFence(void *obj, XID id)
+{
+ SyncFence *pFence = (SyncFence *) obj;
+
+ miSyncDestroyFence(pFence);
+
+ return Success;
+}
+
+int SyncVerifyFence(SyncFence **ppSyncFence, XID fid,
+ ClientPtr client, Mask mode)
+{
+ int rc = dixLookupResourceByType((pointer *)ppSyncFence, fid, RTFence,
+ client, mode);
+
+ if (rc != Success)
+ client->errorValue = fid;
+
+ return rc;
+}
+
+static int
+ProcSyncTriggerFence(ClientPtr client)
+{
+ REQUEST(xSyncTriggerFenceReq);
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncTriggerFenceReq);
+
+ rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
+ client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ miSyncTriggerFence(pFence);
+
+ return client->noClientException;
+}
+
+static int
+ProcSyncResetFence(ClientPtr client)
+{
+ REQUEST(xSyncResetFenceReq);
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncResetFenceReq);
+
+ rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
+ client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ if (pFence->funcs.CheckTriggered(pFence) != TRUE)
+ return BadMatch;
+
+ pFence->funcs.Reset(pFence);
+
+ return client->noClientException;
+}
+
+static int
+ProcSyncDestroyFence(ClientPtr client)
+{
+ REQUEST(xSyncDestroyFenceReq);
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncDestroyFenceReq);
+
+ rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ FreeResource(stuff->fid, RT_NONE);
+ return client->noClientException;
+}
+
+static int
+ProcSyncQueryFence(ClientPtr client)
+{
+ REQUEST(xSyncQueryFenceReq);
+ xSyncQueryFenceReply rep;
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncQueryFenceReq);
+
+ rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid,
+ RTFence, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ rep.triggered = pFence->funcs.CheckTriggered(pFence);
+
+ if (client->swapped)
+ {
+ char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ }
+
+ WriteToClient(client, sizeof(xSyncQueryFenceReply), (char *) &rep);
+ return client->noClientException;
+}
+
+static int
+ProcSyncAwaitFence(ClientPtr client)
+{
+ REQUEST(xSyncAwaitFenceReq);
+ SyncAwaitUnion *pAwaitUnion;
+ SyncAwait *pAwait;
+ /* Use CARD32 rather than XSyncFence because XIDs are hard-coded to
+ * CARD32 in protocol definitions */
+ CARD32 *pProtocolFences;
+ int status;
+ int len;
+ int items;
+ int i;
+
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
+
+ len = client->req_len << 2;
+ len -= sz_xSyncAwaitFenceReq;
+ items = len / sizeof(CARD32);
+
+ if (items * sizeof(CARD32) != len)
+ {
+ return BadLength;
+ }
+ if (items == 0)
+ {
+ client->errorValue = items;
+ return BadValue;
+ }
+
+ if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
+ return BadAlloc;
+
+ /* don't need to do any more memory allocation for this request! */
+
+ pProtocolFences = (CARD32 *) & stuff[1];
+
+ pAwait = &(pAwaitUnion+1)->await; /* skip over header */
+ for (i = 0; i < items; i++, pProtocolFences++, pAwait++)
+ {
+ if (*pProtocolFences == None)
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on sync objects
+ */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+ client->errorValue = *pProtocolFences;
+ return SyncErrorBase + XSyncBadFence;
+ }
+
+ pAwait->trigger.pSync = NULL;
+ /* Provide acceptable values for these unused fields to
+ * satisfy SyncInitTrigger's validation logic
+ */
+ pAwait->trigger.value_type = XSyncAbsolute;
+ XSyncIntToValue(&pAwait->trigger.wait_value, 0);
+ pAwait->trigger.test_type = 0;
+
+ status = SyncInitTrigger(client, &pAwait->trigger,
+ *pProtocolFences, RTFence,
+ XSyncCAAllTrigger);
+ if (status != Success)
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on sync objects
+ */
+ 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;
+ /* event_threshold is unused for fence syncs */
+ XSyncIntToValue(&pAwait->event_threshold, 0);
+ pAwait->pHeader = &pAwaitUnion->header;
+ pAwaitUnion->header.num_waitconditions++;
+ }
+
+ SyncAwaitEpilogue(client, items, pAwaitUnion);
+
+ return client->noClientException;
+}
+
+/*
+ * ** Given an extension request, call the appropriate request procedure
+ */
+static int
+ProcSyncDispatch(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);
+ case X_SyncCreateFence:
+ return ProcSyncCreateFence(client);
+ case X_SyncTriggerFence:
+ return ProcSyncTriggerFence(client);
+ case X_SyncResetFence:
+ return ProcSyncResetFence(client);
+ case X_SyncDestroyFence:
+ return ProcSyncDestroyFence(client);
+ case X_SyncQueryFence:
+ return ProcSyncQueryFence(client);
+ case X_SyncAwaitFence:
+ return ProcSyncAwaitFence(client);
+ default:
+ return BadRequest;
+ }
+}
+
+/*
+ * Boring Swapping stuff ...
+ */
+
+static int
+SProcSyncInitialize(ClientPtr client)
+{
+ REQUEST(xSyncInitializeReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncInitializeReq);
+
+ return ProcSyncInitialize(client);
+}
+
+static int
+SProcSyncListSystemCounters(ClientPtr client)
+{
+ REQUEST(xSyncListSystemCountersReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncListSystemCountersReq);
+
+ return ProcSyncListSystemCounters(client);
+}
+
+static int
+SProcSyncCreateCounter(ClientPtr client)
+{
+ REQUEST(xSyncCreateCounterReq);
+ 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(ClientPtr client)
+{
+ REQUEST(xSyncSetCounterReq);
+ 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(ClientPtr client)
+{
+ REQUEST(xSyncChangeCounterReq);
+ 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(ClientPtr client)
+{
+ REQUEST(xSyncQueryCounterReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncQueryCounterReq);
+ swapl(&stuff->counter, n);
+
+ return ProcSyncQueryCounter(client);
+}
+
+static int
+SProcSyncDestroyCounter(ClientPtr client)
+{
+ REQUEST(xSyncDestroyCounterReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncDestroyCounterReq);
+ swapl(&stuff->counter, n);
+
+ return ProcSyncDestroyCounter(client);
+}
+
+static int
+SProcSyncAwait(ClientPtr client)
+{
+ REQUEST(xSyncAwaitReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
+ SwapRestL(stuff);
+
+ return ProcSyncAwait(client);
+}
+
+static int
+SProcSyncCreateAlarm(ClientPtr client)
+{
+ REQUEST(xSyncCreateAlarmReq);
+ 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(ClientPtr client)
+{
+ REQUEST(xSyncChangeAlarmReq);
+ 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(ClientPtr client)
+{
+ REQUEST(xSyncQueryAlarmReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncQueryAlarmReq);
+ swapl(&stuff->alarm, n);
+
+ return ProcSyncQueryAlarm(client);
+}
+
+static int
+SProcSyncDestroyAlarm(ClientPtr client)
+{
+ REQUEST(xSyncDestroyAlarmReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq);
+ swapl(&stuff->alarm, n);
+
+ return ProcSyncDestroyAlarm(client);
+}
+
+static int
+SProcSyncSetPriority(ClientPtr client)
+{
+ REQUEST(xSyncSetPriorityReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncSetPriorityReq);
+ swapl(&stuff->id, n);
+ swapl(&stuff->priority, n);
+
+ return ProcSyncSetPriority(client);
+}
+
+static int
+SProcSyncGetPriority(ClientPtr client)
+{
+ REQUEST(xSyncGetPriorityReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncGetPriorityReq);
+ swapl(&stuff->id, n);
+
+ return ProcSyncGetPriority(client);
+}
+
+static int
+SProcSyncCreateFence(ClientPtr client)
+{
+ REQUEST(xSyncCreateFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncCreateFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncCreateFence(client);
+}
+
+static int
+SProcSyncTriggerFence(ClientPtr client)
+{
+ REQUEST(xSyncTriggerFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncTriggerFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncTriggerFence(client);
+}
+
+static int
+SProcSyncResetFence(ClientPtr client)
+{
+ REQUEST(xSyncResetFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncResetFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncResetFence(client);
+}
+
+static int
+SProcSyncDestroyFence(ClientPtr client)
+{
+ REQUEST(xSyncDestroyFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncDestroyFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncDestroyFence(client);
+}
+
+static int
+SProcSyncQueryFence(ClientPtr client)
+{
+ REQUEST(xSyncQueryFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncQueryFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncQueryFence(client);
+}
+
+static int
+SProcSyncAwaitFence(ClientPtr client)
+{
+ REQUEST(xSyncAwaitFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
+ SwapRestL(stuff);
+
+ return ProcSyncAwaitFence(client);
+}
+
+static int
+SProcSyncDispatch(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);
+ case X_SyncCreateFence:
+ return SProcSyncCreateFence(client);
+ case X_SyncTriggerFence:
+ return SProcSyncTriggerFence(client);
+ case X_SyncResetFence:
+ return SProcSyncResetFence(client);
+ case X_SyncDestroyFence:
+ return SProcSyncDestroyFence(client);
+ case X_SyncQueryFence:
+ return SProcSyncQueryFence(client);
+ case X_SyncAwaitFence:
+ return SProcSyncAwaitFence(client);
+ default:
+ return BadRequest;
+ }
+}
+
+/*
+ * Event Swapping
+ */
+
+static void
+SCounterNotifyEvent(xSyncCounterNotifyEvent *from, xSyncCounterNotifyEvent *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(xSyncAlarmNotifyEvent *from, xSyncAlarmNotifyEvent *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(ExtensionEntry *extEntry)
+{
+ free(SysCounterList);
+ SysCounterList = NULL;
+ RTCounter = 0;
+}
+
+/*
+ * ** Initialise the extension.
+ */
+void
+SyncExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+ int s;
+
+ for (s = 0; s < screenInfo.numScreens; s++)
+ miSyncSetup(screenInfo.screens[s]);
+
+ if (RTCounter == 0)
+ {
+ RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter");
+ }
+ RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm");
+ RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait");
+ RTFence = CreateNewResourceType(FreeFence, "SyncFence");
+ if (RTAwait)
+ RTAwait |= RC_NEVERRETAIN;
+ RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient");
+ if (RTAlarmClient)
+ RTAlarmClient |= 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;
+
+ SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter);
+ SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm);
+ SetResourceTypeErrorValue(RTFence, SyncErrorBase + XSyncBadFence);
+
+ /*
+ * 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 (now deprecated)
+ */
+/*ARGSUSED*/
+static void
+ServertimeBlockHandler(void *env, struct timeval **wt, void *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(void *env, int rc, void *LastSelectMask)
+{
+ if (pnext_time)
+ {
+ GetTime();
+
+ if (XSyncValueGreaterOrEqual(Now, *pnext_time))
+ {
+ SyncChangeCounter(ServertimeCounter, Now);
+ }
+ }
+}
+
+static void
+ServertimeQueryValue(void *pCounter, CARD64 *pValue_return)
+{
+ GetTime();
+ *pValue_return = Now;
+}
+
+static void
+ServertimeBracketValues(void *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 SyncCounter *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, old_idle;
+ SyncTriggerList *list = IdleTimeCounter->sync.pTriglist;
+ SyncTrigger *trig;
+
+ if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
+ return;
+
+ old_idle = IdleTimeCounter->value;
+ IdleTimeQueryValue (NULL, &idle);
+ IdleTimeCounter->value = idle; /* push, so CheckTrigger works */
+
+ if (pIdleTimeValueLess &&
+ XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))
+ {
+ /*
+ * We've been idle for less than the threshold value, and someone
+ * wants to know about that, but now we need to know whether they
+ * want level or edge trigger. Check the trigger list against the
+ * current idle time, and if any succeed, bomb out of select()
+ * immediately so we can reschedule.
+ */
+
+ for (list = IdleTimeCounter->sync.pTriglist; list; list = list->next) {
+ trig = list->pTrigger;
+ if (trig->CheckTrigger(trig, old_idle)) {
+ AdjustWaitForDelay(wt, 0);
+ break;
+ }
+ }
+ /*
+ * We've been called exactly on the idle time, but we have a
+ * NegativeTransition trigger which requires a transition from an
+ * idle time greater than this. Schedule a wakeup for the next
+ * millisecond so we won't miss a transition.
+ */
+ if (XSyncValueEqual (idle, *pIdleTimeValueLess))
+ AdjustWaitForDelay(wt, 1);
+ }
+ else if (pIdleTimeValueGreater)
+ {
+ /*
+ * There's a threshold in the positive direction. If we've been
+ * idle less than it, schedule a wakeup for sometime in the future.
+ * If we've been idle more than it, and someone wants to know about
+ * that level-triggered, schedule an immediate wakeup.
+ */
+ unsigned long timeout = -1;
+
+ if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) {
+ XSyncValue value;
+ Bool overflow;
+
+ XSyncValueSubtract (&value, *pIdleTimeValueGreater,
+ idle, &overflow);
+ timeout = min(timeout, XSyncValueLow32 (value));
+ } else {
+ for (list = IdleTimeCounter->sync.pTriglist; list; list = list->next) {
+ trig = list->pTrigger;
+ if (trig->CheckTrigger(trig, old_idle)) {
+ timeout = min(timeout, 0);
+ break;
+ }
+ }
+ }
+
+ AdjustWaitForDelay (wt, timeout);
+ }
+
+ IdleTimeCounter->value = old_idle; /* pop */
+}
+
+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/Xext/syncsdk.h b/Xext/syncsdk.h
new file mode 100644
index 0000000..a72c585
--- /dev/null
+++ b/Xext/syncsdk.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2010 NVIDIA Corporation
+ *
+ * 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 (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR 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.
+ */
+
+#ifndef _SYNCSDK_H_
+#define _SYNCSDK_H_
+
+#include "misync.h"
+
+extern _X_EXPORT int
+SyncVerifyFence(SyncFence **ppFence, XID fid, ClientPtr client, Mask mode);
+
+#define VERIFY_SYNC_FENCE(pFence, fid, client, mode) \
+ do { \
+ int rc; \
+ rc = SyncVerifyFence(&(pFence), (fid), (client), (mode)); \
+ if (Success != rc) return rc; \
+ } while (0)
+
+#define VERIFY_SYNC_FENCE_OR_NONE(pFence, fid, client, mode) \
+ do { \
+ pFence = 0; \
+ if (None != fid) \
+ VERIFY_SYNC_FENCE((pFence), (fid), (client), (mode)); \
+ } while (0)
+
+#endif /* _SYNCSDK_H_ */
+
diff --git a/Xext/syncsrv.h b/Xext/syncsrv.h
new file mode 100644
index 0000000..7ca1fba
--- /dev/null
+++ b/Xext/syncsrv.h
@@ -0,0 +1,146 @@
+/*
+
+Copyright 1991, 1993, 1994, 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 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.
+
+******************************************************************/
+
+#ifndef _SYNCSRV_H_
+#define _SYNCSRV_H_
+
+#include "misync.h"
+#include "misyncstr.h"
+
+/*
+ * The System Counter interface
+ */
+
+typedef enum {
+ XSyncCounterNeverChanges,
+ XSyncCounterNeverIncreases,
+ XSyncCounterNeverDecreases,
+ XSyncCounterUnrestricted
+} SyncCounterType;
+
+typedef struct _SysCounterInfo {
+ char *name;
+ CARD64 resolution;
+ CARD64 bracket_greater;
+ CARD64 bracket_less;
+ SyncCounterType counterType; /* how can this counter change */
+ void (*QueryValue)(
+ pointer /*pCounter*/,
+ CARD64 * /*freshvalue*/
+);
+ void (*BracketValues)(
+ pointer /*pCounter*/,
+ CARD64 * /*lessthan*/,
+ CARD64 * /*greaterthan*/
+);
+} SysCounterInfo;
+
+
+
+typedef struct _SyncAlarmClientList {
+ ClientPtr client;
+ XID delete_id;
+ struct _SyncAlarmClientList *next;
+} SyncAlarmClientList;
+
+typedef struct _SyncAlarm {
+ SyncTrigger trigger;
+ ClientPtr client;
+ XSyncAlarm alarm_id;
+ CARD64 delta;
+ int events;
+ int state;
+ SyncAlarmClientList *pEventClients;
+} SyncAlarm;
+
+typedef struct {
+ ClientPtr client;
+ CARD32 delete_id;
+ int num_waitconditions;
+} SyncAwaitHeader;
+
+typedef struct {
+ SyncTrigger trigger;
+ CARD64 event_threshold;
+ SyncAwaitHeader *pHeader;
+} SyncAwait;
+
+typedef union {
+ SyncAwaitHeader header;
+ SyncAwait await;
+} SyncAwaitUnion;
+
+extern pointer SyncCreateSystemCounter(
+ char * /* name */,
+ CARD64 /* inital_value */,
+ CARD64 /* resolution */,
+ SyncCounterType /* change characterization */,
+ void (* /*QueryValue*/ ) (
+ pointer /* pCounter */,
+ CARD64 * /* pValue_return */), /* XXX prototype */
+ void (* /*BracketValues*/) (
+ pointer /* pCounter */,
+ CARD64 * /* pbracket_less */,
+ CARD64 * /* pbracket_greater */)
+);
+
+extern void SyncChangeCounter(
+ SyncCounter * /* pCounter*/,
+ CARD64 /* new_value */
+);
+
+extern void SyncDestroySystemCounter(
+ pointer pCounter
+);
+
+extern void InitServertime(void);
+
+extern void SyncExtensionInit(void);
+#endif /* _SYNCSRV_H_ */
diff --git a/Xext/xace.c b/Xext/xace.c
new file mode 100644
index 0000000..c757cad
--- /dev/null
+++ b/Xext/xace.c
@@ -0,0 +1,327 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
+
+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"
+
+#define XSERV_t
+#define TRANS_SERVER
+#include <X11/Xtrans/Xtrans.h>
+#include "../os/osdep.h"
+
+_X_EXPORT 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, ...)
+{
+ union {
+ XaceResourceAccessRec res;
+ XaceDeviceAccessRec dev;
+ XaceSendAccessRec send;
+ XaceReceiveAccessRec recv;
+ XaceClientAccessRec client;
+ XaceExtAccessRec ext;
+ XaceServerAccessRec server;
+ XaceScreenAccessRec screen;
+ XaceAuthAvailRec auth;
+ XaceKeyAvailRec key;
+ } u;
+ 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:
+ u.res.client = va_arg(ap, ClientPtr);
+ u.res.id = va_arg(ap, XID);
+ u.res.rtype = va_arg(ap, RESTYPE);
+ u.res.res = va_arg(ap, pointer);
+ u.res.ptype = va_arg(ap, RESTYPE);
+ u.res.parent = va_arg(ap, pointer);
+ u.res.access_mode = va_arg(ap, Mask);
+ u.res.status = Success; /* default allow */
+ prv = &u.res.status;
+ break;
+ case XACE_DEVICE_ACCESS:
+ u.dev.client = va_arg(ap, ClientPtr);
+ u.dev.dev = va_arg(ap, DeviceIntPtr);
+ u.dev.access_mode = va_arg(ap, Mask);
+ u.dev.status = Success; /* default allow */
+ prv = &u.dev.status;
+ break;
+ case XACE_SEND_ACCESS:
+ u.send.client = va_arg(ap, ClientPtr);
+ u.send.dev = va_arg(ap, DeviceIntPtr);
+ u.send.pWin = va_arg(ap, WindowPtr);
+ u.send.events = va_arg(ap, xEventPtr);
+ u.send.count = va_arg(ap, int);
+ u.send.status = Success; /* default allow */
+ prv = &u.send.status;
+ break;
+ case XACE_RECEIVE_ACCESS:
+ u.recv.client = va_arg(ap, ClientPtr);
+ u.recv.pWin = va_arg(ap, WindowPtr);
+ u.recv.events = va_arg(ap, xEventPtr);
+ u.recv.count = va_arg(ap, int);
+ u.recv.status = Success; /* default allow */
+ prv = &u.recv.status;
+ break;
+ case XACE_CLIENT_ACCESS:
+ u.client.client = va_arg(ap, ClientPtr);
+ u.client.target = va_arg(ap, ClientPtr);
+ u.client.access_mode = va_arg(ap, Mask);
+ u.client.status = Success; /* default allow */
+ prv = &u.client.status;
+ break;
+ case XACE_EXT_ACCESS:
+ u.ext.client = va_arg(ap, ClientPtr);
+ u.ext.ext = va_arg(ap, ExtensionEntry*);
+ u.ext.access_mode = DixGetAttrAccess;
+ u.ext.status = Success; /* default allow */
+ prv = &u.ext.status;
+ break;
+ case XACE_SERVER_ACCESS:
+ u.server.client = va_arg(ap, ClientPtr);
+ u.server.access_mode = va_arg(ap, Mask);
+ u.server.status = Success; /* default allow */
+ prv = &u.server.status;
+ break;
+ case XACE_SCREEN_ACCESS:
+ case XACE_SCREENSAVER_ACCESS:
+ u.screen.client = va_arg(ap, ClientPtr);
+ u.screen.screen = va_arg(ap, ScreenPtr);
+ u.screen.access_mode = va_arg(ap, Mask);
+ u.screen.status = Success; /* default allow */
+ prv = &u.screen.status;
+ break;
+ case XACE_AUTH_AVAIL:
+ u.auth.client = va_arg(ap, ClientPtr);
+ u.auth.authId = va_arg(ap, XID);
+ break;
+ case XACE_KEY_AVAIL:
+ u.key.event = va_arg(ap, xEventPtr);
+ u.key.keybd = va_arg(ap, DeviceIntPtr);
+ u.key.count = va_arg(ap, int);
+ break;
+ default:
+ va_end(ap);
+ return 0; /* unimplemented hook number */
+ }
+ va_end(ap);
+
+ /* call callbacks and return result, if any. */
+ CallCallbacks(&XaceHooks[hook], &u);
+ 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(
+ ClientPtr client,
+ RegionPtr pVisibleRegion,
+ long widthBytesLine,
+ DrawablePtr pDraw,
+ int x, int y, int w, int h,
+ unsigned int format,
+ char *pBuf)
+{
+ RegionRec imageRegion; /* region representing x,y,w,h */
+ RegionRec censorRegion; /* region to obliterate */
+ BoxRec imageBox;
+ int nRects;
+
+ imageBox.x1 = x;
+ imageBox.y1 = y;
+ imageBox.x2 = x + w;
+ imageBox.y2 = y + h;
+ RegionInit(&imageRegion, &imageBox, 1);
+ RegionNull(&censorRegion);
+
+ /* censorRegion = imageRegion - visibleRegion */
+ RegionSubtract(&censorRegion, &imageRegion, pVisibleRegion);
+ nRects = RegionNumRects(&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 = malloc(nRects * sizeof(xRectangle));
+ if (!pRects)
+ {
+ failed = TRUE;
+ goto failSafe;
+ }
+ for (pBox = RegionRects(&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.
+ */
+ memset(pBuf, 0, (int)(widthBytesLine * h));
+ }
+ free(pRects);
+ if (pScratchGC) FreeScratchGC(pScratchGC);
+ if (pPix) FreeScratchPixmapHeader(pPix);
+ }
+ RegionUninit(&imageRegion);
+ RegionUninit(&censorRegion);
+} /* XaceCensorImage */
+
+/*
+ * Xtrans wrappers for use by modules
+ */
+int XaceGetConnectionNumber(ClientPtr client)
+{
+ XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn;
+ return _XSERVTransGetConnectionNumber(ci);
+}
+
+int XaceIsLocal(ClientPtr client)
+{
+ XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn;
+ return _XSERVTransIsLocal(ci);
+}
diff --git a/Xext/xace.h b/Xext/xace.h
new file mode 100644
index 0000000..6029d87
--- /dev/null
+++ b/Xext/xace.h
@@ -0,0 +1,131 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
+
+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 _X_EXPORT CallbackListPtr XaceHooks[XACE_NUM_HOOKS];
+
+/* Entry point for hook functions. Called by Xserver.
+ * Required by libdbe and libextmod
+ */
+extern _X_EXPORT int XaceHook(
+ int /*hook*/,
+ ... /*appropriate args for hook*/
+ );
+
+/* Special-cased hook functions
+ */
+extern _X_EXPORT int XaceHookDispatch(ClientPtr ptr, int major);
+extern _X_EXPORT int XaceHookPropertyAccess(ClientPtr ptr, WindowPtr pWin,
+ PropertyPtr *ppProp, Mask access_mode);
+extern _X_EXPORT int XaceHookSelectionAccess(ClientPtr ptr,
+ Selection **ppSel, Mask access_mode);
+extern _X_EXPORT 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)
+
+/* XTrans wrappers for use by security modules
+ */
+extern _X_EXPORT int XaceGetConnectionNumber(ClientPtr ptr);
+extern _X_EXPORT int XaceIsLocal(ClientPtr ptr);
+
+/* From the original Security extension...
+ */
+
+extern _X_EXPORT 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/Xext/xacestr.h b/Xext/xacestr.h
new file mode 100644
index 0000000..84216c8
--- /dev/null
+++ b/Xext/xacestr.h
@@ -0,0 +1,147 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
+
+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/Xext/xcalibrate.c b/Xext/xcalibrate.c
new file mode 100644
index 0000000..bff1c31
--- /dev/null
+++ b/Xext/xcalibrate.c
@@ -0,0 +1,297 @@
+/*
+ * 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
+
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "swaprep.h"
+#include "protocol-versions.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.x = x;
+ ev.y = y;
+ ev.pressure = pressure;
+
+ 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 = SERVER_XCALIBRATE_MAJOR_VERSION;
+ rep.minorVersion = SERVER_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 Success;
+}
+
+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 Success;
+}
+
+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 Success;
+}
+
+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 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,
+ NULL, StandardMinorOpcode);
+
+ if (!extEntry)
+ return;
+
+ XCalibrateReqCode = (unsigned char)extEntry->base;
+ XCalibrateEventBase = extEntry->eventBase;
+ XCalibrateErrorBase = extEntry->errorBase;
+
+ xcalibrate_client = 0;
+}
diff --git a/Xext/xcmisc.c b/Xext/xcmisc.c
new file mode 100644
index 0000000..378afcc
--- /dev/null
+++ b/Xext/xcmisc.c
@@ -0,0 +1,207 @@
+/*
+
+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.
+
+*/
+
+#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/xcmiscproto.h>
+#include "modinit.h"
+
+#if HAVE_STDINT_H
+#include <stdint.h>
+#elif !defined(UINT32_MAX)
+#define UINT32_MAX 0xffffffffU
+#endif
+
+
+static int
+ProcXCMiscGetVersion(ClientPtr client)
+{
+ xXCMiscGetVersionReply rep;
+ 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 Success;
+}
+
+static int
+ProcXCMiscGetXIDRange(ClientPtr client)
+{
+ xXCMiscGetXIDRangeReply rep;
+ 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 Success;
+}
+
+static int
+ProcXCMiscGetXIDList(ClientPtr client)
+{
+ REQUEST(xXCMiscGetXIDListReq);
+ xXCMiscGetXIDListReply rep;
+ int n;
+ XID *pids;
+ unsigned int count;
+
+ REQUEST_SIZE_MATCH(xXCMiscGetXIDListReq);
+
+ if (stuff->count > UINT32_MAX / sizeof(XID))
+ return BadAlloc;
+
+ pids = (XID *)malloc(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);
+ }
+ free(pids);
+ return Success;
+}
+
+static int
+ProcXCMiscDispatch (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(ClientPtr client)
+{
+ 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(ClientPtr client)
+{
+ int n;
+ REQUEST(xReq);
+
+ swaps(&stuff->length, n);
+ return ProcXCMiscGetXIDRange(client);
+}
+
+static int
+SProcXCMiscGetXIDList(ClientPtr client)
+{
+ int n;
+ REQUEST(xXCMiscGetXIDListReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->count, n);
+ return ProcXCMiscGetXIDList(client);
+}
+
+static int
+SProcXCMiscDispatch (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;
+ }
+}
+
+void
+XCMiscExtensionInit(INITARGS)
+{
+ AddExtension(XCMiscExtensionName, 0, 0,
+ ProcXCMiscDispatch, SProcXCMiscDispatch,
+ NULL, StandardMinorOpcode);
+}
diff --git a/Xext/xf86bigfont.c b/Xext/xf86bigfont.c
new file mode 100644
index 0000000..de82744
--- /dev/null
+++ b/Xext/xf86bigfont.c
@@ -0,0 +1,750 @@
+/*
+ * 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(__CYGWIN__)
+#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"
+#include "protocol-versions.h"
+
+#include <X11/extensions/xf86bigfproto.h>
+#include "xf86bigfontsrv.h"
+
+static void XF86BigfontResetProc(
+ ExtensionEntry * /* extEntry */
+ );
+
+
+#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, NULL);
+ }
+ else
+ {
+ /* Allocation failed */
+ badSysCall = TRUE;
+ }
+ signal(SIGSYS, oldHandler);
+ return !badSysCall;
+}
+
+#define MUST_CHECK_FOR_SHM_SYSCALL
+
+#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 = malloc(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));
+ free(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);
+ free(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;
+ free(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(void)
+{
+#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 = SERVER_XF86BIGFONT_MAJOR_VERSION;
+ reply.minorVersion = SERVER_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 Success;
+}
+
+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 = NULL;
+#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
+ if (dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess) != Success)
+ return BadFont; /* procotol spec says only error is BadFont */
+
+ 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);
+ 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 = malloc(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 = malloc((4*nCharInfos+1) * sizeof(CARD16));
+ if (!tmp) {
+ if (!pDesc) free(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 = malloc(rlength);
+ char* p;
+ if (!reply) {
+ if (nCharInfos > 0) {
+ if (shmid == -1) free(pIndex2UniqIndex);
+ if (!pDesc) free(pCI);
+ }
+ return BadAlloc;
+ }
+ reply->type = X_Reply;
+ reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
+ 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);
+ free(reply);
+ if (nCharInfos > 0) {
+ if (shmid == -1) free(pIndex2UniqIndex);
+ if (!pDesc) free(pCI);
+ }
+ return Success;
+ }
+}
+
+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;
+ }
+}
+
+void
+XFree86BigfontExtensionInit(void)
+{
+ 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
+ }
+}
diff --git a/Xext/xf86bigfontsrv.h b/Xext/xf86bigfontsrv.h
new file mode 100644
index 0000000..2c78dc4
--- /dev/null
+++ b/Xext/xf86bigfontsrv.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2010 Yaakov Selkowitz
+ *
+ * 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 (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR 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.
+ */
+
+#ifndef _XF86BIGFONTSRV_H_
+#define _XF86BIGFONTSRV_H_
+
+#include <X11/fonts/font.h>
+
+extern void XFree86BigfontExtensionInit(void);
+extern void XF86BigfontFreeFontShm(FontPtr);
+extern void XF86BigfontCleanup(void);
+
+#endif
diff --git a/Xext/xres.c b/Xext/xres.c
new file mode 100644
index 0000000..06639a2
--- /dev/null
+++ b/Xext/xres.c
@@ -0,0 +1,383 @@
+/*
+ Copyright (c) 2002 XFree86 Inc
+*/
+
+#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"
+#include "protocol-versions.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 = SERVER_XRES_MAJOR_VERSION;
+ rep.server_minor = SERVER_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 Success;
+}
+
+static int
+ProcXResQueryClients (ClientPtr client)
+{
+ /* REQUEST(xXResQueryClientsReq); */
+ xXResQueryClientsReply rep;
+ int *current_clients;
+ int i, num_clients;
+
+ REQUEST_SIZE_MATCH(xXResQueryClientsReq);
+
+ current_clients = malloc(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 = bytes_to_int32(rep.num_clients * sz_xXResClient);
+ 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) {
+ int n;
+ swapl (&scratch.resource_base, n);
+ swapl (&scratch.resource_mask, n);
+ }
+ WriteToClient (client, sz_xXResClient, (char *) &scratch);
+ }
+ }
+
+ free(current_clients);
+
+ return Success;
+}
+
+
+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 = calloc(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 = bytes_to_int32(rep.num_types * sz_xXResType);
+ 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) {
+ int n;
+ swapl (&scratch.resource_type, n);
+ swapl (&scratch.count, n);
+ }
+ WriteToClient (client, sz_xXResType, (char *) &scratch);
+ }
+ }
+
+ free(counts);
+
+ return Success;
+}
+
+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 Success;
+}
+
+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,
+ NULL, StandardMinorOpcode);
+}
diff --git a/Xext/xselinux.h b/Xext/xselinux.h
new file mode 100644
index 0000000..5723982
--- /dev/null
+++ b/Xext/xselinux.h
@@ -0,0 +1,139 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
+
+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
+
+/* Extension info */
+#define SELINUX_EXTENSION_NAME "SELinux"
+#define SELINUX_MAJOR_VERSION 1
+#define SELINUX_MINOR_VERSION 1
+#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_SELinuxSetDrawableCreateContext 5
+#define X_SELinuxGetDrawableCreateContext 6
+#define X_SELinuxGetDrawableContext 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;
+
+#endif /* _XSELINUX_H */
diff --git a/Xext/xselinux_ext.c b/Xext/xselinux_ext.c
new file mode 100644
index 0000000..374571c
--- /dev/null
+++ b/Xext/xselinux_ext.c
@@ -0,0 +1,732 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
+
+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 "selection.h"
+#include "inputstr.h"
+#include "windowstr.h"
+#include "propertyst.h"
+#include "extnsionst.h"
+#include "modinit.h"
+#include "xselinuxint.h"
+
+#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;
+
+
+/*
+ * Extension Dispatch
+ */
+
+static security_context_t
+SELinuxCopyContext(char *ptr, unsigned len)
+{
+ security_context_t copy = malloc(len + 1);
+ if (!copy)
+ return NULL;
+ strncpy(copy, ptr, len);
+ copy[len] = '\0';
+ return copy;
+}
+
+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 Success;
+}
+
+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_raw(sid, &ctx) < 0)
+ return BadValue;
+ len = strlen(ctx) + 1;
+ }
+
+ rep.type = X_Reply;
+ rep.length = bytes_to_int32(len);
+ 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 Success;
+}
+
+static int
+ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
+{
+ PrivateRec **privPtr = &client->devPrivates;
+ security_id_t *pSid;
+ security_context_t ctx = NULL;
+ char *ptr;
+ int rc;
+
+ REQUEST(SELinuxSetCreateContextReq);
+ REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq, stuff->context_len);
+
+ if (stuff->context_len > 0) {
+ ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len);
+ if (!ctx)
+ return BadAlloc;
+ }
+
+ ptr = dixLookupPrivate(privPtr, subjectKey);
+ pSid = (security_id_t *)(ptr + offset);
+ *pSid = NULL;
+
+ rc = Success;
+ if (stuff->context_len > 0) {
+ if (security_check_context_raw(ctx) < 0 ||
+ avc_context_to_sid_raw(ctx, pSid) < 0)
+ rc = BadValue;
+ }
+
+ free(ctx);
+ return rc;
+}
+
+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);
+
+ if (stuff->context_len < 1)
+ return BadLength;
+ ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len);
+ if (!ctx)
+ return BadAlloc;
+
+ rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess);
+ if (rc != Success)
+ goto out;
+
+ if (security_check_context_raw(ctx) < 0 ||
+ avc_context_to_sid_raw(ctx, &sid) < 0) {
+ rc = BadValue;
+ goto out;
+ }
+
+ subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
+ subj->sid = sid;
+ obj = dixLookupPrivate(&dev->devPrivates, objectKey);
+ obj->sid = sid;
+
+ rc = Success;
+out:
+ free(ctx);
+ return rc;
+}
+
+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
+ProcSELinuxGetDrawableContext(ClientPtr client)
+{
+ DrawablePtr pDraw;
+ PrivateRec **privatePtr;
+ SELinuxObjectRec *obj;
+ int rc;
+
+ REQUEST(SELinuxGetContextReq);
+ REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+
+ rc = dixLookupDrawable(&pDraw, stuff->id, client, 0, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ if (pDraw->type == DRAWABLE_PIXMAP)
+ privatePtr = &((PixmapPtr)pDraw)->devPrivates;
+ else
+ privatePtr = &((WindowPtr)pDraw)->devPrivates;
+
+ obj = dixLookupPrivate(privatePtr, 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_raw(obj->sid, &i->octx) < 0)
+ return BadValue;
+ if (avc_sid_to_context_raw(data->sid, &i->dctx) < 0)
+ return BadValue;
+
+ i->id = id;
+ i->octx_len = bytes_to_int32(strlen(i->octx) + 1);
+ i->dctx_len = bytes_to_int32(strlen(i->dctx) + 1);
+
+ *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);
+ }
+ free(items);
+}
+
+static int
+SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec *items,
+ int size, int count)
+{
+ int rc, k, n, pos = 0;
+ SELinuxListItemsReply rep;
+ CARD32 *buf;
+
+ buf = calloc(size, sizeof(CARD32));
+ if (size && !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 = Success;
+ free(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 = calloc(count, sizeof(SELinuxListItemRec));
+ if (count && !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 = calloc(count, sizeof(SELinuxListItemRec));
+ if (count && !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_SELinuxSetDrawableCreateContext:
+ return ProcSELinuxSetCreateContext(client, CTX_WIN);
+ case X_SELinuxGetDrawableCreateContext:
+ return ProcSELinuxGetCreateContext(client, CTX_WIN);
+ case X_SELinuxGetDrawableContext:
+ return ProcSELinuxGetDrawableContext(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
+SProcSELinuxGetDrawableContext(ClientPtr client)
+{
+ REQUEST(SELinuxGetContextReq);
+ int n;
+
+ REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+ swapl(&stuff->id, n);
+ return ProcSELinuxGetDrawableContext(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_SELinuxSetDrawableCreateContext:
+ return SProcSELinuxSetCreateContext(client, CTX_WIN);
+ case X_SELinuxGetDrawableCreateContext:
+ return ProcSELinuxGetCreateContext(client, CTX_WIN);
+ case X_SELinuxGetDrawableContext:
+ return SProcSELinuxGetDrawableContext(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)
+{
+ SELinuxFlaskReset();
+ SELinuxLabelReset();
+}
+
+void
+SELinuxExtensionInit(INITARGS)
+{
+ ExtensionEntry *extEntry;
+
+ /* Check SELinux mode on system, configuration file, and boolean */
+ if (!is_selinux_enabled()) {
+ LogMessage(X_INFO, "SELinux: Disabled on system\n");
+ return;
+ }
+ if (selinuxEnforcingState == SELINUX_MODE_DISABLED) {
+ LogMessage(X_INFO, "SELinux: Disabled in configuration file\n");
+ return;
+ }
+ if (!security_get_boolean_active("xserver_object_manager")) {
+ LogMessage(X_INFO, "SELinux: Disabled by boolean\n");
+ return;
+ }
+
+ /* Set up XACE hooks */
+ SELinuxLabelInit();
+ SELinuxFlaskInit();
+
+ /* Add extension to server */
+ extEntry = AddExtension(SELINUX_EXTENSION_NAME,
+ SELinuxNumberEvents, SELinuxNumberErrors,
+ ProcSELinuxDispatch, SProcSELinuxDispatch,
+ SELinuxResetProc, StandardMinorOpcode);
+
+ AddExtensionAlias("Flask", extEntry);
+}
diff --git a/Xext/xselinux_hooks.c b/Xext/xselinux_hooks.c
new file mode 100644
index 0000000..560e1e9
--- /dev/null
+++ b/Xext/xselinux_hooks.c
@@ -0,0 +1,935 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
+
+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 <libaudit.h>
+
+#include <X11/Xatom.h>
+#include "selection.h"
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "propertyst.h"
+#include "extnsionst.h"
+#include "xacestr.h"
+#include "../os/osdep.h"
+#define _XSELINUX_NEED_FLASK_MAP
+#include "xselinuxint.h"
+
+
+/* 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;
+
+/* private state keys */
+DevPrivateKeyRec subjectKeyRec;
+DevPrivateKeyRec objectKeyRec;
+DevPrivateKeyRec dataKeyRec;
+
+/* audit file descriptor */
+static int audit_fd;
+
+/* atoms for window label properties */
+static Atom atom_ctx;
+static Atom atom_client_ctx;
+
+/* The unlabeled SID */
+static security_id_t unlabeled_sid;
+
+/* forward declarations */
+static void SELinuxScreen(CallbackListPtr *, pointer, pointer);
+
+/* "true" pointer value for use as callback data */
+static pointer truep = (pointer)1;
+
+
+/*
+ * 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)
+{
+ int fd = XaceGetConnectionNumber(client);
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ security_context_t ctx;
+
+ subj = dixLookupPrivate(&client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&client->devPrivates, objectKey);
+
+ /* Try to get a context from the socket */
+ if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) {
+ /* Otherwise, fall back to a default context */
+ ctx = SELinuxDefaultClientLabel();
+ }
+
+ /* For local clients, try and determine the executable name */
+ if (XaceIsLocal(client)) {
+ 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;
+
+ strncpy(subj->command, path, COMMAND_LEN - 1);
+ }
+
+finish:
+ /* Get a SID from the context */
+ if (avc_context_to_sid_raw(ctx, &subj->sid) < 0)
+ FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n",
+ client->index, ctx);
+
+ 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;
+
+ /* Use the context of the X server process for the serverClient */
+ if (getcon_raw(&ctx) < 0)
+ FatalError("SELinux: couldn't get context of X server process\n");
+
+ /* Get a SID from the context */
+ if (avc_context_to_sid_raw(ctx, &subj->sid) < 0)
+ FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx);
+
+ 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 */
+ dixLookupResourceByType(&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 & RC_DRAWABLE && subj->win_create_sid) {
+ 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];
+ const char *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;
+
+ switch (type) {
+ case SELINUX_INFO:
+ aut = AUDIT_USER_MAC_POLICY_LOAD;
+ break;
+ case SELINUX_AVC:
+ aut = AUDIT_USER_AVC;
+ break;
+ default:
+ aut = AUDIT_USER_SELINUX_ERR;
+ break;
+ }
+
+ 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 };
+ security_class_t cls;
+ 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);
+
+ if (subj->dev_create_sid) {
+ /* Label the device with the create context */
+ obj->sid = subj->dev_create_sid;
+ dsubj->sid = subj->dev_create_sid;
+ } else {
+ /* Label the device directly with the process SID */
+ obj->sid = subj->sid;
+ dsubj->sid = subj->sid;
+ }
+ }
+
+ cls = IsPointerDevice(rec->dev) ? SECCLASS_X_POINTER : SECCLASS_X_KEYBOARD;
+ rc = SELinuxDoCheck(subj, obj, cls, 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 == NULL) {
+ security_id_t sid;
+
+ serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
+ rc = SELinuxExtensionToSID(rec->ext->name, &sid);
+ if (rc != Success) {
+ rec->status = rc;
+ return;
+ }
+
+ /* 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");
+ rec->status = BadValue;
+ return;
+ }
+ }
+
+ /* 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) {
+ 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);
+ }
+
+ 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);
+ if (subj->sel_create_sid)
+ data->sid = subj->sel_create_sid;
+ else
+ 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;
+
+ /* Don't care about the new content check */
+ if (rec->access_mode & DixPostAccess)
+ return;
+
+ 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) {
+ 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);
+ }
+
+ 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);
+ if (subj->prp_create_sid)
+ data->sid = subj->prp_create_sid;
+ else
+ 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) {
+ /* 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;
+ if (rec->state != ResourceStateAdding)
+ return;
+
+ pWin = (WindowPtr)rec->value;
+ subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey);
+
+ if (subj->sid) {
+ security_context_t ctx;
+ int rc = avc_sid_to_context_raw(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_raw(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");
+}
+
+
+static int netlink_fd;
+
+static void
+SELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask)
+{
+}
+
+static void
+SELinuxWakeupHandler(void *data, int err, void *read_mask)
+{
+ if (FD_ISSET(netlink_fd, (fd_set *)read_mask))
+ avc_netlink_check_nb();
+}
+
+void
+SELinuxFlaskReset(void)
+{
+ /* 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 */
+ audit_close(audit_fd);
+ avc_netlink_release_fd();
+ RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler,
+ NULL);
+ RemoveGeneralSocket(netlink_fd);
+
+ avc_destroy();
+}
+
+void
+SELinuxFlaskInit(void)
+{
+ struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 };
+ security_context_t ctx;
+ int ret = TRUE;
+
+ switch(selinuxEnforcingState) {
+ 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");
+
+ if (security_get_initial_context_raw("unlabeled", &ctx) < 0)
+ FatalError("SELinux: Failed to look up unlabeled context\n");
+ if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0)
+ FatalError("SELinux: a context_to_SID call failed!\n");
+ freecon(ctx);
+
+ /* 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 (!dixRegisterPrivateKey(subjectKey, PRIVATE_XSELINUX, sizeof(SELinuxSubjectRec)) ||
+ !dixRegisterPrivateKey(objectKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec)) ||
+ !dixRegisterPrivateKey(dataKey, PRIVATE_XSELINUX, 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");
+
+ netlink_fd = avc_netlink_acquire_fd();
+ AddGeneralSocket(netlink_fd);
+ RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler,
+ NULL);
+
+ /* Register callbacks */
+ 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");
+
+ /* Label objects that were created before we could register ourself */
+ SELinuxLabelInitial();
+}
diff --git a/Xext/xselinux_label.c b/Xext/xselinux_label.c
new file mode 100644
index 0000000..e5929fa
--- /dev/null
+++ b/Xext/xselinux_label.c
@@ -0,0 +1,374 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
+
+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 <selinux/label.h>
+
+#include "registry.h"
+#include "xselinuxint.h"
+
+/* selection and property atom cache */
+typedef struct {
+ SELinuxObjectRec prp;
+ SELinuxObjectRec sel;
+} SELinuxAtomRec;
+
+/* dynamic array */
+typedef struct {
+ unsigned size;
+ void **array;
+} SELinuxArrayRec;
+
+/* labeling handle */
+static struct selabel_handle *label_hnd;
+
+/* Array of object classes indexed by resource type */
+SELinuxArrayRec arr_types;
+/* Array of event SIDs indexed by event type */
+SELinuxArrayRec arr_events;
+/* Array of property and selection SID structures */
+SELinuxArrayRec arr_atoms;
+
+/*
+ * Dynamic array helpers
+ */
+static void *
+SELinuxArrayGet(SELinuxArrayRec *rec, unsigned key)
+{
+ return (rec->size > key) ? rec->array[key] : 0;
+}
+
+static int
+SELinuxArraySet(SELinuxArrayRec *rec, unsigned key, void *val)
+{
+ if (key >= rec->size) {
+ /* Need to increase size of array */
+ rec->array = realloc(rec->array, (key + 1) * sizeof(val));
+ if (!rec->array)
+ return FALSE;
+ memset(rec->array + rec->size, 0, (key - rec->size + 1) * sizeof(val));
+ rec->size = key + 1;
+ }
+
+ rec->array[key] = val;
+ return TRUE;
+}
+
+static void
+SELinuxArrayFree(SELinuxArrayRec *rec, int free_elements)
+{
+ if (free_elements) {
+ unsigned i = rec->size;
+ while (i)
+ free(rec->array[--i]);
+ }
+
+ free(rec->array);
+ rec->size = 0;
+ rec->array = NULL;
+}
+
+/*
+ * 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_raw(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_raw(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_raw(ctx, &obj->sid) < 0) {
+ ErrorF("SELinux: a context_to_SID_raw call failed!\n");
+ rc = BadAlloc;
+ }
+
+ freecon(ctx);
+ return rc;
+}
+
+/*
+ * Looks up the SID corresponding to the given property or selection atom
+ */
+int
+SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn)
+{
+ SELinuxAtomRec *rec;
+ SELinuxObjectRec *obj;
+ int rc, map, polymap;
+
+ rec = SELinuxArrayGet(&arr_atoms, atom);
+ if (!rec) {
+ rec = calloc(1, sizeof(SELinuxAtomRec));
+ if (!rec || !SELinuxArraySet(&arr_atoms, atom, rec))
+ return BadAlloc;
+ }
+
+ if (prop) {
+ obj = &rec->prp;
+ map = SELABEL_X_PROP;
+ polymap = SELABEL_X_POLYPROP;
+ } else {
+ obj = &rec->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
+ */
+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) {
+ tsid = subj->sel_use_sid;
+ goto out;
+ }
+
+ tsid = obj->sid;
+
+ /* Polyinstantiate if necessary to obtain the final SID */
+ if (obj->poly && 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
+ */
+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) {
+ 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");
+ return BadValue;
+ }
+ }
+out:
+ *sid_rtn = tsid;
+ if (poly_rtn)
+ *poly_rtn = obj->poly;
+ return Success;
+}
+
+/*
+ * Looks up the SID corresponding to the given event type
+ */
+int
+SELinuxEventToSID(unsigned type, security_id_t sid_of_window,
+ SELinuxObjectRec *sid_return)
+{
+ const char *name = LookupEventName(type);
+ security_id_t sid;
+ security_context_t ctx;
+ type &= 127;
+
+ sid = SELinuxArrayGet(&arr_events, type);
+ if (!sid) {
+ /* Look in the mappings of event names to contexts */
+ if (selabel_lookup_raw(label_hnd, &ctx, 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_raw(ctx, &sid) < 0) {
+ ErrorF("SELinux: a context_to_SID_raw call failed!\n");
+ freecon(ctx);
+ return BadAlloc;
+ }
+ freecon(ctx);
+ /* Cache the SID value */
+ if (!SELinuxArraySet(&arr_events, type, sid))
+ return BadAlloc;
+ }
+
+ /* Perform a transition to obtain the final SID */
+ if (avc_compute_create(sid_of_window, sid, SECCLASS_X_EVENT,
+ &sid_return->sid) < 0) {
+ ErrorF("SELinux: a compute_create call failed!\n");
+ return BadValue;
+ }
+
+ return Success;
+}
+
+int
+SELinuxExtensionToSID(const char *name, security_id_t *sid_rtn)
+{
+ security_context_t ctx;
+
+ /* Look in the mappings of extension names to contexts */
+ if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EXT) < 0) {
+ ErrorF("SELinux: a property label lookup failed!\n");
+ return BadValue;
+ }
+ /* Get a SID for context */
+ if (avc_context_to_sid_raw(ctx, sid_rtn) < 0) {
+ ErrorF("SELinux: a context_to_SID_raw call failed!\n");
+ freecon(ctx);
+ return BadAlloc;
+ }
+ freecon(ctx);
+ return Success;
+}
+
+/*
+ * Returns the object class corresponding to the given resource type.
+ */
+security_class_t
+SELinuxTypeToClass(RESTYPE type)
+{
+ void *tmp;
+
+ tmp = SELinuxArrayGet(&arr_types, type & TypeMask);
+ if (!tmp) {
+ unsigned long class = SECCLASS_X_RESOURCE;
+
+ if (type & RC_DRAWABLE)
+ class = SECCLASS_X_DRAWABLE;
+ else if (type == RT_GC)
+ class = SECCLASS_X_GC;
+ else if (type == RT_FONT)
+ class = SECCLASS_X_FONT;
+ else if (type == RT_CURSOR)
+ class = SECCLASS_X_CURSOR;
+ else if (type == RT_COLORMAP)
+ class = SECCLASS_X_COLORMAP;
+ else {
+ /* Need to do a string lookup */
+ const char *str = LookupResourceName(type);
+ if (!strcmp(str, "PICTURE"))
+ class = SECCLASS_X_DRAWABLE;
+ else if (!strcmp(str, "GLYPHSET"))
+ class = SECCLASS_X_FONT;
+ }
+
+ tmp = (void *)class;
+ SELinuxArraySet(&arr_types, type & TypeMask, tmp);
+ }
+
+ return (security_class_t)(unsigned long)tmp;
+}
+
+security_context_t
+SELinuxDefaultClientLabel(void)
+{
+ security_context_t ctx;
+
+ if (selabel_lookup_raw(label_hnd, &ctx, "remote", SELABEL_X_CLIENT) < 0)
+ FatalError("SELinux: failed to look up remote-client context\n");
+
+ return ctx;
+}
+
+void
+SELinuxLabelInit(void)
+{
+ struct selinux_opt selabel_option = { SELABEL_OPT_VALIDATE, (char *)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");
+}
+
+void
+SELinuxLabelReset(void)
+{
+ selabel_close(label_hnd);
+ label_hnd = NULL;
+
+ /* Free local state */
+ SELinuxArrayFree(&arr_types, 0);
+ SELinuxArrayFree(&arr_events, 0);
+ SELinuxArrayFree(&arr_atoms, 1);
+}
diff --git a/Xext/xselinuxint.h b/Xext/xselinuxint.h
new file mode 100644
index 0000000..011a103
--- /dev/null
+++ b/Xext/xselinuxint.h
@@ -0,0 +1,561 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
+
+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 _XSELINUXINT_H
+#define _XSELINUXINT_H
+
+#include <selinux/selinux.h>
+#include <selinux/avc.h>
+
+#include "globals.h"
+#include "dixaccess.h"
+#include "dixstruct.h"
+#include "privates.h"
+#include "resource.h"
+#include "registry.h"
+#include "inputstr.h"
+#include "xselinux.h"
+
+/*
+ * Types
+ */
+
+#define COMMAND_LEN 64
+
+/* 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[COMMAND_LEN];
+ int privileged;
+} SELinuxSubjectRec;
+
+/* object state */
+typedef struct {
+ security_id_t sid;
+ int poly;
+} SELinuxObjectRec;
+
+/*
+ * Globals
+ */
+
+extern DevPrivateKeyRec subjectKeyRec;
+#define subjectKey (&subjectKeyRec)
+extern DevPrivateKeyRec objectKeyRec;
+#define objectKey (&objectKeyRec)
+extern DevPrivateKeyRec dataKeyRec;
+#define dataKey (&dataKeyRec)
+
+/*
+ * Label functions
+ */
+
+int
+SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn);
+
+int
+SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec *subj,
+ security_id_t *sid_rtn, int *poly_rtn);
+
+int
+SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj,
+ security_id_t *sid_rtn, int *poly_rtn);
+
+int
+SELinuxEventToSID(unsigned type, security_id_t sid_of_window,
+ SELinuxObjectRec *sid_return);
+
+int
+SELinuxExtensionToSID(const char *name, security_id_t *sid_rtn);
+
+security_class_t
+SELinuxTypeToClass(RESTYPE type);
+
+security_context_t
+SELinuxDefaultClientLabel(void);
+
+void
+SELinuxLabelInit(void);
+
+void
+SELinuxLabelReset(void);
+
+/*
+ * Security module functions
+ */
+
+void
+SELinuxFlaskInit(void);
+
+void
+SELinuxFlaskReset(void);
+
+
+/*
+ * Private Flask definitions
+ */
+
+/* Security class constants */
+#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_POINTER 10
+#define SECCLASS_X_KEYBOARD 11
+#define SECCLASS_X_SERVER 12
+#define SECCLASS_X_EXTENSION 13
+#define SECCLASS_X_EVENT 14
+#define SECCLASS_X_FAKEEVENT 15
+#define SECCLASS_X_RESOURCE 16
+
+#ifdef _XSELINUX_NEED_FLASK_MAP
+/* Mapping from DixAccess bits to Flask permissions */
+static struct security_class_mapping map[] = {
+ { "x_drawable",
+ { "read", /* DixReadAccess */
+ "write", /* DixWriteAccess */
+ "destroy", /* DixDestroyAccess */
+ "create", /* DixCreateAccess */
+ "getattr", /* DixGetAttrAccess */
+ "setattr", /* DixSetAttrAccess */
+ "list_property", /* DixListPropAccess */
+ "get_property", /* DixGetPropAccess */
+ "set_property", /* DixSetPropAccess */
+ "", /* DixGetFocusAccess */
+ "", /* DixSetFocusAccess */
+ "list_child", /* DixListAccess */
+ "add_child", /* DixAddAccess */
+ "remove_child", /* DixRemoveAccess */
+ "hide", /* DixHideAccess */
+ "show", /* DixShowAccess */
+ "blend", /* DixBlendAccess */
+ "override", /* DixGrabAccess */
+ "", /* DixFreezeAccess */
+ "", /* DixForceAccess */
+ "", /* DixInstallAccess */
+ "", /* DixUninstallAccess */
+ "send", /* DixSendAccess */
+ "receive", /* DixReceiveAccess */
+ "", /* DixUseAccess */
+ "manage", /* DixManageAccess */
+ NULL }},
+ { "x_screen",
+ { "", /* DixReadAccess */
+ "", /* DixWriteAccess */
+ "", /* DixDestroyAccess */
+ "", /* DixCreateAccess */
+ "getattr", /* DixGetAttrAccess */
+ "setattr", /* DixSetAttrAccess */
+ "saver_getattr", /* DixListPropAccess */
+ "saver_setattr", /* DixGetPropAccess */
+ "", /* DixSetPropAccess */
+ "", /* DixGetFocusAccess */
+ "", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "", /* DixAddAccess */
+ "", /* DixRemoveAccess */
+ "hide_cursor", /* DixHideAccess */
+ "show_cursor", /* DixShowAccess */
+ "saver_hide", /* DixBlendAccess */
+ "saver_show", /* DixGrabAccess */
+ NULL }},
+ { "x_gc",
+ { "", /* DixReadAccess */
+ "", /* DixWriteAccess */
+ "destroy", /* DixDestroyAccess */
+ "create", /* DixCreateAccess */
+ "getattr", /* DixGetAttrAccess */
+ "setattr", /* DixSetAttrAccess */
+ "", /* DixListPropAccess */
+ "", /* DixGetPropAccess */
+ "", /* DixSetPropAccess */
+ "", /* DixGetFocusAccess */
+ "", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "", /* DixAddAccess */
+ "", /* DixRemoveAccess */
+ "", /* DixHideAccess */
+ "", /* DixShowAccess */
+ "", /* DixBlendAccess */
+ "", /* DixGrabAccess */
+ "", /* DixFreezeAccess */
+ "", /* DixForceAccess */
+ "", /* DixInstallAccess */
+ "", /* DixUninstallAccess */
+ "", /* DixSendAccess */
+ "", /* DixReceiveAccess */
+ "use", /* DixUseAccess */
+ NULL }},
+ { "x_font",
+ { "", /* DixReadAccess */
+ "", /* DixWriteAccess */
+ "destroy", /* DixDestroyAccess */
+ "create", /* DixCreateAccess */
+ "getattr", /* DixGetAttrAccess */
+ "", /* DixSetAttrAccess */
+ "", /* DixListPropAccess */
+ "", /* DixGetPropAccess */
+ "", /* DixSetPropAccess */
+ "", /* DixGetFocusAccess */
+ "", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "add_glyph", /* DixAddAccess */
+ "remove_glyph", /* DixRemoveAccess */
+ "", /* DixHideAccess */
+ "", /* DixShowAccess */
+ "", /* DixBlendAccess */
+ "", /* DixGrabAccess */
+ "", /* DixFreezeAccess */
+ "", /* DixForceAccess */
+ "", /* DixInstallAccess */
+ "", /* DixUninstallAccess */
+ "", /* DixSendAccess */
+ "", /* DixReceiveAccess */
+ "use", /* DixUseAccess */
+ NULL }},
+ { "x_colormap",
+ { "read", /* DixReadAccess */
+ "write", /* DixWriteAccess */
+ "destroy", /* DixDestroyAccess */
+ "create", /* DixCreateAccess */
+ "getattr", /* DixGetAttrAccess */
+ "", /* DixSetAttrAccess */
+ "", /* DixListPropAccess */
+ "", /* DixGetPropAccess */
+ "", /* DixSetPropAccess */
+ "", /* DixGetFocusAccess */
+ "", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "add_color", /* DixAddAccess */
+ "remove_color", /* DixRemoveAccess */
+ "", /* DixHideAccess */
+ "", /* DixShowAccess */
+ "", /* DixBlendAccess */
+ "", /* DixGrabAccess */
+ "", /* DixFreezeAccess */
+ "", /* DixForceAccess */
+ "install", /* DixInstallAccess */
+ "uninstall", /* DixUninstallAccess */
+ "", /* DixSendAccess */
+ "", /* DixReceiveAccess */
+ "use", /* DixUseAccess */
+ NULL }},
+ { "x_property",
+ { "read", /* DixReadAccess */
+ "write", /* DixWriteAccess */
+ "destroy", /* DixDestroyAccess */
+ "create", /* DixCreateAccess */
+ "getattr", /* DixGetAttrAccess */
+ "setattr", /* DixSetAttrAccess */
+ "", /* DixListPropAccess */
+ "", /* DixGetPropAccess */
+ "", /* DixSetPropAccess */
+ "", /* DixGetFocusAccess */
+ "", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "", /* DixAddAccess */
+ "", /* DixRemoveAccess */
+ "", /* DixHideAccess */
+ "", /* DixShowAccess */
+ "write", /* DixBlendAccess */
+ NULL }},
+ { "x_selection",
+ { "read", /* DixReadAccess */
+ "", /* DixWriteAccess */
+ "", /* DixDestroyAccess */
+ "setattr", /* DixCreateAccess */
+ "getattr", /* DixGetAttrAccess */
+ "setattr", /* DixSetAttrAccess */
+ NULL }},
+ { "x_cursor",
+ { "read", /* DixReadAccess */
+ "write", /* DixWriteAccess */
+ "destroy", /* DixDestroyAccess */
+ "create", /* DixCreateAccess */
+ "getattr", /* DixGetAttrAccess */
+ "setattr", /* DixSetAttrAccess */
+ "", /* DixListPropAccess */
+ "", /* DixGetPropAccess */
+ "", /* DixSetPropAccess */
+ "", /* DixGetFocusAccess */
+ "", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "", /* DixAddAccess */
+ "", /* DixRemoveAccess */
+ "", /* DixHideAccess */
+ "", /* DixShowAccess */
+ "", /* DixBlendAccess */
+ "", /* DixGrabAccess */
+ "", /* DixFreezeAccess */
+ "", /* DixForceAccess */
+ "", /* DixInstallAccess */
+ "", /* DixUninstallAccess */
+ "", /* DixSendAccess */
+ "", /* DixReceiveAccess */
+ "use", /* DixUseAccess */
+ NULL }},
+ { "x_client",
+ { "", /* DixReadAccess */
+ "", /* DixWriteAccess */
+ "destroy", /* DixDestroyAccess */
+ "", /* DixCreateAccess */
+ "getattr", /* DixGetAttrAccess */
+ "setattr", /* DixSetAttrAccess */
+ "", /* DixListPropAccess */
+ "", /* DixGetPropAccess */
+ "", /* DixSetPropAccess */
+ "", /* DixGetFocusAccess */
+ "", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "", /* DixAddAccess */
+ "", /* DixRemoveAccess */
+ "", /* DixHideAccess */
+ "", /* DixShowAccess */
+ "", /* DixBlendAccess */
+ "", /* DixGrabAccess */
+ "", /* DixFreezeAccess */
+ "", /* DixForceAccess */
+ "", /* DixInstallAccess */
+ "", /* DixUninstallAccess */
+ "", /* DixSendAccess */
+ "", /* DixReceiveAccess */
+ "", /* DixUseAccess */
+ "manage", /* DixManageAccess */
+ NULL }},
+ { "x_pointer",
+ { "read", /* DixReadAccess */
+ "write", /* DixWriteAccess */
+ "destroy", /* DixDestroyAccess */
+ "create", /* DixCreateAccess */
+ "getattr", /* DixGetAttrAccess */
+ "setattr", /* DixSetAttrAccess */
+ "list_property", /* DixListPropAccess */
+ "get_property", /* DixGetPropAccess */
+ "set_property", /* DixSetPropAccess */
+ "getfocus", /* DixGetFocusAccess */
+ "setfocus", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "add", /* DixAddAccess */
+ "remove", /* DixRemoveAccess */
+ "", /* DixHideAccess */
+ "", /* DixShowAccess */
+ "", /* DixBlendAccess */
+ "grab", /* DixGrabAccess */
+ "freeze", /* DixFreezeAccess */
+ "force_cursor", /* DixForceAccess */
+ "", /* DixInstallAccess */
+ "", /* DixUninstallAccess */
+ "", /* DixSendAccess */
+ "", /* DixReceiveAccess */
+ "use", /* DixUseAccess */
+ "manage", /* DixManageAccess */
+ "", /* DixDebugAccess */
+ "bell", /* DixBellAccess */
+ NULL }},
+ { "x_keyboard",
+ { "read", /* DixReadAccess */
+ "write", /* DixWriteAccess */
+ "destroy", /* DixDestroyAccess */
+ "create", /* DixCreateAccess */
+ "getattr", /* DixGetAttrAccess */
+ "setattr", /* DixSetAttrAccess */
+ "list_property", /* DixListPropAccess */
+ "get_property", /* DixGetPropAccess */
+ "set_property", /* DixSetPropAccess */
+ "getfocus", /* DixGetFocusAccess */
+ "setfocus", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "add", /* DixAddAccess */
+ "remove", /* DixRemoveAccess */
+ "", /* DixHideAccess */
+ "", /* DixShowAccess */
+ "", /* DixBlendAccess */
+ "grab", /* DixGrabAccess */
+ "freeze", /* DixFreezeAccess */
+ "force_cursor", /* DixForceAccess */
+ "", /* DixInstallAccess */
+ "", /* DixUninstallAccess */
+ "", /* DixSendAccess */
+ "", /* DixReceiveAccess */
+ "use", /* DixUseAccess */
+ "manage", /* DixManageAccess */
+ "", /* DixDebugAccess */
+ "bell", /* DixBellAccess */
+ NULL }},
+ { "x_server",
+ { "record", /* DixReadAccess */
+ "", /* DixWriteAccess */
+ "", /* DixDestroyAccess */
+ "", /* DixCreateAccess */
+ "getattr", /* DixGetAttrAccess */
+ "setattr", /* DixSetAttrAccess */
+ "", /* DixListPropAccess */
+ "", /* DixGetPropAccess */
+ "", /* DixSetPropAccess */
+ "", /* DixGetFocusAccess */
+ "", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "", /* DixAddAccess */
+ "", /* DixRemoveAccess */
+ "", /* DixHideAccess */
+ "", /* DixShowAccess */
+ "", /* DixBlendAccess */
+ "grab", /* DixGrabAccess */
+ "", /* DixFreezeAccess */
+ "", /* DixForceAccess */
+ "", /* DixInstallAccess */
+ "", /* DixUninstallAccess */
+ "", /* DixSendAccess */
+ "", /* DixReceiveAccess */
+ "", /* DixUseAccess */
+ "manage", /* DixManageAccess */
+ "debug", /* DixDebugAccess */
+ NULL }},
+ { "x_extension",
+ { "", /* DixReadAccess */
+ "", /* DixWriteAccess */
+ "", /* DixDestroyAccess */
+ "", /* DixCreateAccess */
+ "query", /* DixGetAttrAccess */
+ "", /* DixSetAttrAccess */
+ "", /* DixListPropAccess */
+ "", /* DixGetPropAccess */
+ "", /* DixSetPropAccess */
+ "", /* DixGetFocusAccess */
+ "", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "", /* DixAddAccess */
+ "", /* DixRemoveAccess */
+ "", /* DixHideAccess */
+ "", /* DixShowAccess */
+ "", /* DixBlendAccess */
+ "", /* DixGrabAccess */
+ "", /* DixFreezeAccess */
+ "", /* DixForceAccess */
+ "", /* DixInstallAccess */
+ "", /* DixUninstallAccess */
+ "", /* DixSendAccess */
+ "", /* DixReceiveAccess */
+ "use", /* DixUseAccess */
+ NULL }},
+ { "x_event",
+ { "", /* DixReadAccess */
+ "", /* DixWriteAccess */
+ "", /* DixDestroyAccess */
+ "", /* DixCreateAccess */
+ "", /* DixGetAttrAccess */
+ "", /* DixSetAttrAccess */
+ "", /* DixListPropAccess */
+ "", /* DixGetPropAccess */
+ "", /* DixSetPropAccess */
+ "", /* DixGetFocusAccess */
+ "", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "", /* DixAddAccess */
+ "", /* DixRemoveAccess */
+ "", /* DixHideAccess */
+ "", /* DixShowAccess */
+ "", /* DixBlendAccess */
+ "", /* DixGrabAccess */
+ "", /* DixFreezeAccess */
+ "", /* DixForceAccess */
+ "", /* DixInstallAccess */
+ "", /* DixUninstallAccess */
+ "send", /* DixSendAccess */
+ "receive", /* DixReceiveAccess */
+ NULL }},
+ { "x_synthetic_event",
+ { "", /* DixReadAccess */
+ "", /* DixWriteAccess */
+ "", /* DixDestroyAccess */
+ "", /* DixCreateAccess */
+ "", /* DixGetAttrAccess */
+ "", /* DixSetAttrAccess */
+ "", /* DixListPropAccess */
+ "", /* DixGetPropAccess */
+ "", /* DixSetPropAccess */
+ "", /* DixGetFocusAccess */
+ "", /* DixSetFocusAccess */
+ "", /* DixListAccess */
+ "", /* DixAddAccess */
+ "", /* DixRemoveAccess */
+ "", /* DixHideAccess */
+ "", /* DixShowAccess */
+ "", /* DixBlendAccess */
+ "", /* DixGrabAccess */
+ "", /* DixFreezeAccess */
+ "", /* DixForceAccess */
+ "", /* DixInstallAccess */
+ "", /* DixUninstallAccess */
+ "send", /* DixSendAccess */
+ "receive", /* DixReceiveAccess */
+ NULL }},
+ { "x_resource",
+ { "read", /* DixReadAccess */
+ "write", /* DixWriteAccess */
+ "write", /* DixDestroyAccess */
+ "write", /* DixCreateAccess */
+ "read", /* DixGetAttrAccess */
+ "write", /* DixSetAttrAccess */
+ "read", /* DixListPropAccess */
+ "read", /* DixGetPropAccess */
+ "write", /* DixSetPropAccess */
+ "read", /* DixGetFocusAccess */
+ "write", /* DixSetFocusAccess */
+ "read", /* DixListAccess */
+ "write", /* DixAddAccess */
+ "write", /* DixRemoveAccess */
+ "write", /* DixHideAccess */
+ "read", /* DixShowAccess */
+ "read", /* DixBlendAccess */
+ "write", /* DixGrabAccess */
+ "write", /* DixFreezeAccess */
+ "write", /* DixForceAccess */
+ "write", /* DixInstallAccess */
+ "write", /* DixUninstallAccess */
+ "write", /* DixSendAccess */
+ "read", /* DixReceiveAccess */
+ "read", /* DixUseAccess */
+ "write", /* DixManageAccess */
+ "read", /* DixDebugAccess */
+ "write", /* DixBellAccess */
+ NULL }},
+ { NULL }
+};
+
+/* x_resource "read" bits from the list above */
+#define SELinuxReadMask (DixReadAccess|DixGetAttrAccess|DixListPropAccess| \
+ DixGetPropAccess|DixGetFocusAccess|DixListAccess| \
+ DixShowAccess|DixBlendAccess|DixReceiveAccess| \
+ DixUseAccess|DixDebugAccess)
+
+#endif /* _XSELINUX_NEED_FLASK_MAP */
+#endif /* _XSELINUXINT_H */
diff --git a/Xext/xtest.c b/Xext/xtest.c
new file mode 100644
index 0000000..6780aa6
--- /dev/null
+++ b/Xext/xtest.c
@@ -0,0 +1,689 @@
+/*
+
+ 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>
+#include <X11/Xproto.h>
+#include <X11/Xatom.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"
+#include "mi.h"
+#include "xkbsrv.h"
+#include "xkbstr.h"
+#include <X11/extensions/xtestproto.h>
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "exglobals.h"
+#include "mipointer.h"
+#include "xserver-properties.h"
+#include "exevents.h"
+#include "inpututils.h"
+
+#include "modinit.h"
+
+extern int DeviceValuator;
+
+/* XTest events are sent during request processing and may be interruped by
+ * a SIGIO. We need a separate event list to avoid events overwriting each
+ * other's memory */
+static EventListPtr xtest_evlist;
+
+/**
+ * xtestpointer
+ * is the virtual pointer for XTest. It is the first slave
+ * device of the VCP.
+ * xtestkeyboard
+ * is the virtual keyboard for XTest. It is the first slave
+ * device of the VCK
+ *
+ * Neither of these devices can be deleted.
+ */
+DeviceIntPtr xtestpointer, xtestkeyboard;
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+static int XTestSwapFakeInput(
+ ClientPtr /* client */,
+ xReq * /* req */
+ );
+
+
+static int
+ProcXTestGetVersion(ClientPtr client)
+{
+ xXTestGetVersionReply rep;
+ 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 Success;
+}
+
+static int
+ProcXTestCompareCursor(ClientPtr client)
+{
+ REQUEST(xXTestCompareCursorReq);
+ xXTestCompareCursorReply rep;
+ WindowPtr pWin;
+ CursorPtr pCursor;
+ int n, rc;
+ DeviceIntPtr ptr = PickPointer(client);
+
+ 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(ptr);
+ else {
+ rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
+ client, DixReadAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->cursor;
+ return 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 Success;
+}
+
+static int
+ProcXTestFakeInput(ClientPtr client)
+{
+ REQUEST(xXTestFakeInputReq);
+ int nev, n, type, rc;
+ xEvent *ev;
+ DeviceIntPtr dev = NULL;
+ WindowPtr root;
+ Bool extension = FALSE;
+ deviceValuator *dv = NULL;
+ ValuatorMask mask;
+ int valuators[MAX_VALUATORS] = {0};
+ int numValuators = 0;
+ int firstValuator = 0;
+ int nevents = 0;
+ int i;
+ int base = 0;
+ int flags = 0;
+ int need_ptr_update = 1;
+
+ 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;
+
+ if (type >= EXTENSION_EVENT_BASE)
+ {
+ extension = TRUE;
+
+ /* check device */
+ rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client,
+ DixWriteAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->deviceid & 0177;
+ return rc;
+ }
+
+ /* check type */
+ type -= DeviceValuator;
+ switch (type) {
+ case XI_DeviceKeyPress:
+ case XI_DeviceKeyRelease:
+ if (!dev->key)
+ {
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+ break;
+ case XI_DeviceButtonPress:
+ case XI_DeviceButtonRelease:
+ if (!dev->button)
+ {
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+ break;
+ case XI_DeviceMotionNotify:
+ if (!dev->valuator)
+ {
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+ break;
+ case XI_ProximityIn:
+ case XI_ProximityOut:
+ if (!dev->proximity)
+ {
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+ break;
+ default:
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+
+ /* check validity */
+ if (nev == 1 && type == XI_DeviceMotionNotify)
+ return BadLength; /* DevMotion must be followed by DevValuator */
+
+ if (type == XI_DeviceMotionNotify)
+ {
+ firstValuator = ((deviceValuator *)(ev+1))->first_valuator;
+ if (firstValuator > dev->valuator->numAxes)
+ {
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+
+ if (ev->u.u.detail == xFalse)
+ flags |= POINTER_ABSOLUTE;
+ } else
+ {
+ firstValuator = 0;
+ flags |= POINTER_ABSOLUTE;
+ }
+
+ if (nev > 1 && !dev->valuator)
+ {
+ client->errorValue = dv->first_valuator;
+ return BadValue;
+ }
+
+
+ /* check validity of valuator events */
+ base = firstValuator;
+ 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;
+ }
+ switch(dv->num_valuators)
+ {
+ case 6: valuators[base + 5] = dv->valuator5;
+ case 5: valuators[base + 4] = dv->valuator4;
+ case 4: valuators[base + 3] = dv->valuator3;
+ case 3: valuators[base + 2] = dv->valuator2;
+ case 2: valuators[base + 1] = dv->valuator1;
+ case 1: valuators[base] = dv->valuator0;
+ break;
+ default:
+ client->errorValue = dv->num_valuators;
+ return BadValue;
+ }
+
+ base += dv->num_valuators;
+ numValuators += dv->num_valuators;
+
+ if (firstValuator + numValuators > dev->valuator->numAxes)
+ {
+ client->errorValue = dv->num_valuators;
+ return BadValue;
+ }
+ }
+ type = type - XI_DeviceKeyPress + KeyPress;
+
+ } else
+ {
+ if (nev != 1)
+ return BadLength;
+ switch (type)
+ {
+ case KeyPress:
+ case KeyRelease:
+ dev = PickKeyboard(client);
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ dev = PickPointer(client);
+ break;
+ case MotionNotify:
+ dev = PickPointer(client);
+ valuators[0] = ev->u.keyButtonPointer.rootX;
+ valuators[1] = ev->u.keyButtonPointer.rootY;
+ numValuators = 2;
+ firstValuator = 0;
+ if (ev->u.u.detail == xFalse)
+ flags = POINTER_ABSOLUTE | POINTER_SCREEN;
+ break;
+ default:
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+
+ dev = GetXTestDevice(dev);
+ }
+
+ /* If the event has a time set, wait for it to pass */
+ 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 (from the deprecated Multibuffer
+ * extension) 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;
+ }
+
+ switch (type)
+ {
+ case KeyPress:
+ case KeyRelease:
+ if (!dev->key)
+ return BadDevice;
+
+ if (ev->u.u.detail < dev->key->xkbInfo->desc->min_key_code ||
+ ev->u.u.detail > dev->key->xkbInfo->desc->max_key_code)
+ {
+ client->errorValue = ev->u.u.detail;
+ return BadValue;
+ }
+
+ need_ptr_update = 0;
+ break;
+ case MotionNotify:
+ if (!dev->valuator)
+ return BadDevice;
+
+ if (!(extension || ev->u.keyButtonPointer.root == None))
+ {
+ 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 && ev->u.u.detail != xFalse)
+ {
+ client->errorValue = ev->u.u.detail;
+ return BadValue;
+ }
+
+ /* FIXME: Xinerama! */
+
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ if (!dev->button)
+ return BadDevice;
+
+ 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);
+
+ switch(type) {
+ case MotionNotify:
+ valuator_mask_set_range(&mask, firstValuator, numValuators, valuators);
+ nevents = GetPointerEvents(xtest_evlist, dev, type, 0, flags, &mask);
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ valuator_mask_set_range(&mask, firstValuator, numValuators, valuators);
+ nevents = GetPointerEvents(xtest_evlist, dev, type, ev->u.u.detail,
+ flags, &mask);
+ break;
+ case KeyPress:
+ case KeyRelease:
+ nevents = GetKeyboardEvents(xtest_evlist, dev, type, ev->u.u.detail);
+ break;
+ }
+
+ for (i = 0; i < nevents; i++)
+ mieqProcessDeviceEvent(dev, (InternalEvent*)(xtest_evlist+i)->event, NULL);
+
+ if (need_ptr_update)
+ miPointerUpdateSprite(dev);
+ return Success;
+}
+
+static int
+ProcXTestGrabControl(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 Success;
+}
+
+static int
+ProcXTestDispatch (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(ClientPtr client)
+{
+ int n;
+ REQUEST(xXTestGetVersionReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXTestGetVersionReq);
+ swaps(&stuff->minorVersion, n);
+ return ProcXTestGetVersion(client);
+}
+
+static int
+SProcXTestCompareCursor(ClientPtr client)
+{
+ 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(ClientPtr client, xReq *req)
+{
+ int nev;
+ 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(ClientPtr client)
+{
+ int n;
+ REQUEST(xReq);
+
+ swaps(&stuff->length, n);
+ n = XTestSwapFakeInput(client, stuff);
+ if (n != Success)
+ return n;
+ return ProcXTestFakeInput(client);
+}
+
+static int
+SProcXTestGrabControl(ClientPtr client)
+{
+ int n;
+ REQUEST(xXTestGrabControlReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXTestGrabControlReq);
+ return ProcXTestGrabControl(client);
+}
+
+static int
+SProcXTestDispatch (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;
+ }
+}
+
+/**
+ * Allocate an virtual slave device for xtest events, this
+ * is a slave device to inputInfo master devices
+ */
+void InitXTestDevices(void)
+{
+ if(AllocXTestDevice(serverClient, "Virtual core",
+ &xtestpointer, &xtestkeyboard,
+ inputInfo.pointer, inputInfo.keyboard) != Success)
+ FatalError("Failed to allocate XTest devices");
+
+ if (ActivateDevice(xtestpointer, TRUE) != Success ||
+ ActivateDevice(xtestkeyboard, TRUE) != Success)
+ FatalError("Failed to activate XTest core devices.");
+ if (!EnableDevice(xtestpointer, TRUE) ||
+ !EnableDevice(xtestkeyboard, TRUE))
+ FatalError("Failed to enable XTest core devices.");
+
+ AttachDevice(NULL, xtestpointer, inputInfo.pointer);
+ AttachDevice(NULL, xtestkeyboard, inputInfo.keyboard);
+}
+
+/**
+ * Don't allow changing the XTest property.
+ */
+static int
+DeviceSetXTestProperty(DeviceIntPtr dev, Atom property,
+ XIPropertyValuePtr prop, BOOL checkonly)
+{
+ if (property == XIGetKnownProperty(XI_PROP_XTEST_DEVICE))
+ return BadAccess;
+
+ return Success;
+}
+
+/**
+ * Allocate a device pair that is initialised as a slave
+ * device with properties that identify the devices as belonging
+ * to XTest subsystem.
+ * This only creates the pair, Activate/Enable Device
+ * still need to be called.
+ */
+int AllocXTestDevice (ClientPtr client, char* name,
+ DeviceIntPtr* ptr, DeviceIntPtr* keybd,
+ DeviceIntPtr master_ptr, DeviceIntPtr master_keybd)
+{
+ int retval;
+ int len = strlen(name);
+ char *xtestname = calloc(len + 7, 1 );
+ char dummy = 1;
+
+ strncpy( xtestname, name, len);
+ strncat( xtestname, " XTEST", 6 );
+
+ retval = AllocDevicePair( client, xtestname, ptr, keybd, CorePointerProc, CoreKeyboardProc, FALSE);
+ if ( retval == Success ){
+ (*ptr)->xtest_master_id = master_ptr->id;
+ (*keybd)->xtest_master_id = master_keybd->id;
+
+ XIChangeDeviceProperty(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
+ XA_INTEGER, 8, PropModeReplace, 1, &dummy,
+ FALSE);
+ XISetDevicePropertyDeletable(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE);
+ XIRegisterPropertyHandler(*ptr, DeviceSetXTestProperty, NULL, NULL);
+ XIChangeDeviceProperty(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
+ XA_INTEGER, 8, PropModeReplace, 1, &dummy,
+ FALSE);
+ XISetDevicePropertyDeletable(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE);
+ XIRegisterPropertyHandler(*keybd, DeviceSetXTestProperty, NULL, NULL);
+ }
+
+ free( xtestname );
+
+ return retval;
+}
+
+/**
+ * If master is NULL, return TRUE if the given device is an xtest device or
+ * FALSE otherwise.
+ * If master is not NULL, return TRUE if the given device is this master's
+ * xtest device.
+ */
+BOOL
+IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master)
+{
+ if (IsMaster(dev))
+ return FALSE;
+
+ /* deviceid 0 is reserved for XIAllDevices, non-zero mid means XTest
+ * device */
+ if (master)
+ return dev->xtest_master_id == master->id;
+
+ return dev->xtest_master_id != 0;
+}
+
+/**
+ * @return The X Test virtual device for the given master.
+ */
+DeviceIntPtr
+GetXTestDevice(DeviceIntPtr master)
+{
+ DeviceIntPtr it;
+
+ for (it = inputInfo.devices; it; it = it->next)
+ {
+ if (IsXTestDevice(it, master))
+ return it;
+ }
+
+ /* This only happens if master is a slave device. don't do that */
+ return NULL;
+}
+
+void
+XTestExtensionInit(INITARGS)
+{
+ AddExtension(XTestExtensionName, 0, 0,
+ ProcXTestDispatch, SProcXTestDispatch,
+ NULL, StandardMinorOpcode);
+
+ xtest_evlist = InitEventList(GetMaximumEventsNum());
+}
diff --git a/Xext/xvdisp.c b/Xext/xvdisp.c
new file mode 100644
index 0000000..deddebd
--- /dev/null
+++ b/Xext/xvdisp.c
@@ -0,0 +1,1961 @@
+/***********************************************************
+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
+#include <X11/extensions/shmproto.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 += pad_to_int32(strlen(pa->name));
+ totalSize += pa->nFormats * sz_xvFormat;
+ pa++;
+ }
+
+ rep.length = bytes_to_int32(totalSize);
+
+ _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 Success;
+}
+
+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);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ 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 += pad_to_int32(strlen(pe->name));
+ pe++;
+ }
+
+ rep.length = bytes_to_int32(totalSize);
+
+ _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 Success;
+}
+
+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);
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ 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 = XvdiMatchPort(pPort, pDraw);
+ if (status != Success)
+ {
+ return status;
+ }
+
+ return XvdiPutVideo(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);
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ 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 = XvdiMatchPort(pPort, pDraw);
+ if (status != Success)
+ {
+ return status;
+ }
+
+ return XvdiPutStill(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);
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ 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 = XvdiMatchPort(pPort, pDraw);
+ if (status != Success)
+ {
+ return status;
+ }
+
+ return XvdiGetVideo(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);
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ 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 = XvdiMatchPort(pPort, pDraw);
+ if (status != Success)
+ {
+ return status;
+ }
+
+ return XvdiGetStill(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 XvdiSelectVideoNotify(client, pDraw, stuff->onoff);
+}
+
+static int
+ProcXvSelectPortNotify(ClientPtr client)
+{
+ int status;
+ XvPortPtr pPort;
+ REQUEST(xvSelectPortNotifyReq);
+ REQUEST_SIZE_MATCH(xvSelectPortNotifyReq);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ if ((status = _AllocatePort(stuff->port, pPort)) != Success)
+ {
+ client->errorValue = stuff->port;
+ return status;
+ }
+
+ return XvdiSelectPortNotify(client, pPort, stuff->onoff);
+}
+
+static int
+ProcXvGrabPort(ClientPtr client)
+{
+ int result, status;
+ XvPortPtr pPort;
+ xvGrabPortReply rep;
+ REQUEST(xvGrabPortReq);
+ REQUEST_SIZE_MATCH(xvGrabPortReq);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ if ((status = _AllocatePort(stuff->port, pPort)) != Success)
+ {
+ client->errorValue = stuff->port;
+ return status;
+ }
+
+ status = XvdiGrabPort(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);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ if ((status = _AllocatePort(stuff->port, pPort)) != Success)
+ {
+ client->errorValue = stuff->port;
+ return status;
+ }
+
+ return XvdiUngrabPort(client, pPort, stuff->time);
+}
+
+static int
+ProcXvStopVideo(ClientPtr client)
+{
+ int status, rc;
+ DrawablePtr pDraw;
+ XvPortPtr pPort;
+ REQUEST(xvStopVideoReq);
+ REQUEST_SIZE_MATCH(xvStopVideoReq);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ 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 XvdiStopVideo(client, pPort, pDraw);
+}
+
+static int
+ProcXvSetPortAttribute(ClientPtr client)
+{
+ int status;
+ XvPortPtr pPort;
+ REQUEST(xvSetPortAttributeReq);
+ REQUEST_SIZE_MATCH(xvSetPortAttributeReq);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixSetAttrAccess);
+
+ if ((status = _AllocatePort(stuff->port, pPort)) != Success)
+ {
+ client->errorValue = stuff->port;
+ return status;
+ }
+
+ if (!ValidAtom(stuff->attribute))
+ {
+ client->errorValue = stuff->attribute;
+ return BadAtom;
+ }
+
+ status = XvdiSetPortAttribute(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);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixGetAttrAccess);
+
+ if ((status = _AllocatePort(stuff->port, pPort)) != Success)
+ {
+ client->errorValue = stuff->port;
+ return status;
+ }
+
+ if (!ValidAtom(stuff->attribute))
+ {
+ client->errorValue = stuff->attribute;
+ return BadAtom;
+ }
+
+ status = XvdiGetPortAttribute(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);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ 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);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixGetAttrAccess);
+
+ 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 += pad_to_int32(strlen(pAtt->name) + 1);
+ }
+
+ 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 = pad_to_int32(size);
+
+ _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);
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ 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 = XvdiMatchPort(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 = bytes_to_int32(size);
+
+ if((width < stuff->width) || (height < stuff->height))
+ return BadValue;
+
+ if(client->req_len < size)
+ return BadLength;
+
+ return XvdiPutImage(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 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);
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ 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 = XvdiMatchPort(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;
+
+ status = dixLookupResourceByType((pointer *)&shmdesc, stuff->shmseg,
+ ShmSegType, serverClient, DixReadAccess);
+ if (status != Success)
+ return status;
+
+ 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 = XvdiPutImage(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.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);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ 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 = malloc(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);
+
+ free(offsets);
+
+ return Success;
+}
+
+static int
+ProcXvListImageFormats(ClientPtr client)
+{
+ XvPortPtr pPort;
+ XvImagePtr pImage;
+ int i;
+ xvListImageFormatsReply rep;
+ xvImageFormatInfo info;
+ REQUEST(xvListImageFormatsReq);
+
+ REQUEST_SIZE_MATCH(xvListImageFormatsReq);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.num_formats = pPort->pAdaptor->nImages;
+ rep.length = bytes_to_int32(pPort->pAdaptor->nImages * sz_xvImageFormatInfo);
+
+ _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, i;
+ PanoramiXRes *draw, *port;
+ REQUEST(xvStopVideoReq);
+ REQUEST_SIZE_MATCH(xvStopVideoReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ result = dixLookupResourceByType((pointer *)&port, stuff->port,
+ XvXRTPort, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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, i;
+
+ REQUEST_SIZE_MATCH(xvSetPortAttributeReq);
+
+ result = dixLookupResourceByType((pointer *)&port, stuff->port,
+ XvXRTPort, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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, i, x, y;
+
+ REQUEST_SIZE_MATCH(xvShmPutImageReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
+ XRT_GC, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ result = dixLookupResourceByType((pointer *)&port, stuff->port,
+ XvXRTPort, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 -= screenInfo.screens[i]->x;
+ stuff->drw_y -= screenInfo.screens[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, i, x, y;
+
+ REQUEST_AT_LEAST_SIZE(xvPutImageReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
+ XRT_GC, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ result = dixLookupResourceByType((pointer *)&port, stuff->port,
+ XvXRTPort, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 -= screenInfo.screens[i]->x;
+ stuff->drw_y -= screenInfo.screens[i]->y;
+ }
+
+ result = ProcXvPutImage(client);
+ }
+ }
+ return result;
+}
+
+static int
+XineramaXvPutVideo(ClientPtr client)
+{
+ REQUEST(xvPutImageReq);
+ PanoramiXRes *draw, *gc, *port;
+ Bool isRoot;
+ int result, i, x, y;
+
+ REQUEST_AT_LEAST_SIZE(xvPutVideoReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
+ XRT_GC, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ result = dixLookupResourceByType((pointer *)&port, stuff->port,
+ XvXRTPort, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 -= screenInfo.screens[i]->x;
+ stuff->drw_y -= screenInfo.screens[i]->y;
+ }
+
+ result = ProcXvPutVideo(client);
+ }
+ }
+ return result;
+}
+
+static int
+XineramaXvPutStill(ClientPtr client)
+{
+ REQUEST(xvPutImageReq);
+ PanoramiXRes *draw, *gc, *port;
+ Bool isRoot;
+ int result, i, x, y;
+
+ REQUEST_AT_LEAST_SIZE(xvPutImageReq);
+
+ result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
+ XRC_DRAWABLE, client, DixWriteAccess);
+ if (result != Success)
+ return (result == BadValue) ? BadDrawable : result;
+
+ result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
+ XRT_GC, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ result = dixLookupResourceByType((pointer *)&port, stuff->port,
+ XvXRTPort, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ 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 -= screenInfo.screens[i]->x;
+ stuff->drw_y -= screenInfo.screens[i]->y;
+ }
+
+ result = ProcXvPutStill(client);
+ }
+ }
+ return result;
+}
+
+static Bool
+isImageAdaptor(XvAdaptorPtr pAdapt)
+{
+ return (pAdapt->type & XvImageMask) && (pAdapt->nImages > 0);
+}
+
+static Bool
+hasOverlay(XvAdaptorPtr pAdapt)
+{
+ int i;
+ for(i = 0; i < pAdapt->nAttributes; i++)
+ if(!strcmp(pAdapt->pAttributes[i].name, "XV_COLORKEY"))
+ return TRUE;
+ return FALSE;
+}
+
+static XvAdaptorPtr
+matchAdaptor(ScreenPtr pScreen, XvAdaptorPtr refAdapt, Bool isOverlay)
+{
+ int i;
+ XvScreenPtr xvsp = dixLookupPrivate(&pScreen->devPrivates, XvGetScreenKey());
+ /* Do not try to go on if xv is not supported on this screen */
+ if(xvsp == NULL)
+ return NULL;
+
+ /* if the adaptor has the same name it's a perfect match */
+ for(i = 0; i < xvsp->nAdaptors; i++) {
+ XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
+ if(!strcmp(refAdapt->name, pAdapt->name))
+ return pAdapt;
+ }
+
+ /* otherwise we only look for XvImage adaptors */
+ if(!isImageAdaptor(refAdapt))
+ return NULL;
+
+ /* prefer overlay/overlay non-overlay/non-overlay pairing */
+ for(i = 0; i < xvsp->nAdaptors; i++) {
+ XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
+ if(isImageAdaptor(pAdapt) && isOverlay == hasOverlay(pAdapt))
+ return pAdapt;
+ }
+
+ /* but we'll take any XvImage pairing if we can get it */
+ for(i = 0; i < xvsp->nAdaptors; i++) {
+ XvAdaptorPtr pAdapt = xvsp->pAdaptors + i;
+ if(isImageAdaptor(pAdapt))
+ return pAdapt;
+ }
+ return NULL;
+}
+
+void XineramifyXv(void)
+{
+ XvScreenPtr xvsp0 = dixLookupPrivate(&screenInfo.screens[0]->devPrivates, XvGetScreenKey());
+ XvAdaptorPtr MatchingAdaptors[MAXSCREENS];
+ int i, j, k;
+
+ XvXRTPort = CreateNewResourceType(XineramaDeleteResource, "XvXRTPort");
+
+ if (!xvsp0 || !XvXRTPort) return;
+ SetResourceTypeErrorValue(XvXRTPort, _XvBadPort);
+
+ for(i = 0; i < xvsp0->nAdaptors; i++) {
+ Bool isOverlay;
+ XvAdaptorPtr refAdapt = xvsp0->pAdaptors + i;
+ if(!(refAdapt->type & XvInputMask)) continue;
+
+ MatchingAdaptors[0] = refAdapt;
+ isOverlay = hasOverlay(refAdapt);
+ for(j = 1; j < PanoramiXNumScreens; j++)
+ MatchingAdaptors[j] = matchAdaptor(screenInfo.screens[j], refAdapt, isOverlay);
+
+ /* now create a resource for each port */
+ for(j = 0; j < refAdapt->nPorts; j++) {
+ PanoramiXRes *port = malloc(sizeof(PanoramiXRes));
+ if(!port)
+ break;
+
+ for(k = 0; 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;
+ }
+ AddResource(port->info[0].id, XvXRTPort, port);
+ }
+ }
+
+ /* 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/Xext/xvdisp.h b/Xext/xvdisp.h
new file mode 100644
index 0000000..298d395
--- /dev/null
+++ b/Xext/xvdisp.h
@@ -0,0 +1,2 @@
+extern void XineramifyXv(void);
+extern void XvResetProcVector(void);
diff --git a/Xext/xvdix.h b/Xext/xvdix.h
new file mode 100644
index 0000000..a210615
--- /dev/null
+++ b/Xext/xvdix.h
@@ -0,0 +1,275 @@
+/***********************************************************
+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>
+
+#ifndef XorgLoader
+extern _X_EXPORT unsigned long XvExtensionGeneration;
+extern _X_EXPORT unsigned long XvScreenGeneration;
+extern _X_EXPORT unsigned long XvResourceGeneration;
+
+extern _X_EXPORT int XvReqCode;
+extern _X_EXPORT int XvEventBase;
+extern _X_EXPORT int XvErrorBase;
+
+extern _X_EXPORT unsigned long XvRTPort;
+extern _X_EXPORT unsigned long XvRTEncoding;
+extern _X_EXPORT unsigned long XvRTGrab;
+extern _X_EXPORT unsigned long XvRTVideoNotify;
+extern _X_EXPORT unsigned long XvRTVideoNotifyList;
+extern _X_EXPORT unsigned long XvRTPortNotify;
+#endif
+
+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 VALIDATE_XV_PORT(portID, pPort, mode)\
+ {\
+ int rc = dixLookupResourceByType((pointer *)&(pPort), portID,\
+ XvRTPort, client, mode);\
+ if (rc != Success)\
+ return rc;\
+ }
+
+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)
+
+#ifndef XorgLoader
+extern _X_EXPORT int ProcXvDispatch(ClientPtr);
+extern _X_EXPORT int SProcXvDispatch(ClientPtr);
+
+extern _X_EXPORT void XvExtensionInit(void);
+extern _X_EXPORT int XvScreenInit(ScreenPtr);
+extern _X_EXPORT DevPrivateKey XvGetScreenKey(void);
+extern _X_EXPORT unsigned long XvGetRTPort(void);
+extern _X_EXPORT int XvdiSendPortNotify(XvPortPtr, Atom, INT32);
+extern _X_EXPORT int XvdiVideoStopped(XvPortPtr, int);
+
+extern _X_EXPORT int XvdiPutVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+extern _X_EXPORT int XvdiPutStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+extern _X_EXPORT int XvdiGetVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+extern _X_EXPORT int XvdiGetStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+extern _X_EXPORT int XvdiPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16,
+ XvImagePtr, unsigned char*, Bool,
+ CARD16, CARD16);
+extern _X_EXPORT int XvdiSelectVideoNotify(ClientPtr, DrawablePtr, BOOL);
+extern _X_EXPORT int XvdiSelectPortNotify(ClientPtr, XvPortPtr, BOOL);
+extern _X_EXPORT int XvdiSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32);
+extern _X_EXPORT int XvdiGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*);
+extern _X_EXPORT int XvdiStopVideo(ClientPtr, XvPortPtr, DrawablePtr);
+extern _X_EXPORT int XvdiPreemptVideo(ClientPtr, XvPortPtr, DrawablePtr);
+extern _X_EXPORT int XvdiMatchPort(XvPortPtr, DrawablePtr);
+extern _X_EXPORT int XvdiGrabPort(ClientPtr, XvPortPtr, Time, int *);
+extern _X_EXPORT int XvdiUngrabPort( ClientPtr, XvPortPtr, Time);
+#endif /* XorgLoader */
+
+#endif /* XVDIX_H */
+
diff --git a/Xext/xvmain.c b/Xext/xvmain.c
new file mode 100644
index 0000000..12b4c51
--- /dev/null
+++ b/Xext/xvmain.c
@@ -0,0 +1,1185 @@
+/***********************************************************
+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 DevPrivateKeyRec XvScreenKeyRec;
+#define XvScreenKey (&XvScreenKeyRec)
+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 */
+
+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;
+
+ if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
+ return;
+
+ /* 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;
+
+ SetResourceTypeErrorValue(XvRTPort, _XvBadPort);
+ (void)MakeAtom(XvName, strlen(XvName), xTrue);
+
+ }
+}
+
+static Bool
+CreateResourceTypes(void)
+
+{
+
+ if (XvResourceGeneration == serverGeneration) return TRUE;
+
+ XvResourceGeneration = serverGeneration;
+
+ if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort, "XvRTPort")))
+ {
+ ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
+ return FALSE;
+ }
+
+ if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab, "XvRTGrab")))
+ {
+ ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
+ return FALSE;
+ }
+
+ if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding,
+ "XvRTEncoding")))
+ {
+ ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
+ return FALSE;
+ }
+
+ if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify,
+ "XvRTVideoNotify")))
+ {
+ ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n");
+ return FALSE;
+ }
+
+ if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList,
+ "XvRTVideoNotifyList")))
+ {
+ ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n");
+ return FALSE;
+ }
+
+ if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify,
+ "XvRTPortNotify")))
+ {
+ ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+
+}
+
+int
+XvScreenInit(ScreenPtr pScreen)
+{
+ XvScreenPtr pxvs;
+
+ if (XvScreenGeneration != serverGeneration)
+ {
+ if (!CreateResourceTypes())
+ {
+ ErrorF("XvScreenInit: Unable to allocate resource types\n");
+ return BadAlloc;
+ }
+#ifdef PANORAMIX
+ XineramaRegisterConnectionBlockCallback(XineramifyXv);
+#endif
+ XvScreenGeneration = serverGeneration;
+ }
+
+ if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
+ return BadAlloc;
+
+ if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey))
+ {
+ ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
+ }
+
+ /* ALLOCATE SCREEN PRIVATE RECORD */
+
+ pxvs = malloc(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);
+
+ free(pxvs);
+
+ dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL);
+
+ return (*pScreen->CloseScreen)(ii, pScreen);
+}
+
+static void
+XvResetProc(ExtensionEntry* extEntry)
+{
+ XvResetProcVector();
+}
+
+DevPrivateKey
+XvGetScreenKey(void)
+{
+ return XvScreenKey;
+}
+
+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)(NULL, pp, pp->pDraw);
+
+ pp->pDraw = NULL;
+ pp->client = 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)(NULL, pp, pp->pDraw);
+
+ pp->pDraw = NULL;
+ pp->client = 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 = NULL;
+ pPort->client = 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 = NULL;
+ return Success;
+}
+
+static int
+XvdiDestroyVideoNotify(pointer pn, XID id)
+{
+ /* JUST CLEAR OUT THE client POINTER FIELD */
+
+ ((XvVideoNotifyPtr)pn)->client = NULL;
+ return Success;
+}
+
+static int
+XvdiDestroyPortNotify(pointer pn, XID id)
+{
+ /* JUST CLEAR OUT THE client POINTER FIELD */
+
+ ((XvPortNotifyPtr)pn)->client = 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);
+ free(cpn);
+ cpn = npn;
+ }
+ return Success;
+}
+
+static int
+XvdiDestroyEncoding(pointer value, XID id)
+{
+ return Success;
+}
+
+static int
+XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason)
+{
+ xvEvent event;
+ XvVideoNotifyPtr pn;
+
+ dixLookupResourceByType((pointer *)&pn, pDraw->id, XvRTVideoNotifyList,
+ serverClient, DixReadAccess);
+
+ while (pn)
+ {
+ event.u.u.type = XvEventBase + XvVideoNotify;
+ event.u.videoNotify.time = currentTime.milliseconds;
+ event.u.videoNotify.drawable = pDraw->id;
+ event.u.videoNotify.port = pPort->id;
+ event.u.videoNotify.reason = reason;
+ WriteEventsToClient(pn->client, 1, (xEventPtr)&event);
+ pn = pn->next;
+ }
+
+ return Success;
+
+}
+
+
+int
+XvdiSendPortNotify(
+ XvPortPtr pPort,
+ Atom attribute,
+ INT32 value
+){
+ xvEvent event;
+ XvPortNotifyPtr pn;
+
+ pn = pPort->pNotify;
+
+ while (pn)
+ {
+ event.u.u.type = XvEventBase + XvPortNotify;
+ event.u.portNotify.time = currentTime.milliseconds;
+ event.u.portNotify.port = pPort->id;
+ event.u.portNotify.attribute = attribute;
+ event.u.portNotify.value = value;
+ WriteEventsToClient(pn->client, 1, (xEventPtr)&event);
+ 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))
+ {
+ XvdiStopVideo(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 = NULL;
+
+ pPort->time = currentTime;
+
+ return Success;
+
+}
+
+
+int
+XvdiSelectVideoNotify(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ BOOL onoff
+){
+ XvVideoNotifyPtr pn,tpn,fpn;
+ int rc;
+
+ /* FIND VideoNotify LIST */
+
+ rc = dixLookupResourceByType((pointer *)&pn, pDraw->id, XvRTVideoNotifyList,
+ client, DixWriteAccess);
+ if (rc != Success && rc != BadValue)
+ return rc;
+
+ /* 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 = malloc(sizeof(XvVideoNotifyRec))))
+ return BadAlloc;
+ tpn->next = NULL;
+ if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
+ {
+ free(tpn);
+ return BadAlloc;
+ }
+ }
+ else
+ {
+ /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
+
+ fpn = NULL;
+ tpn = pn;
+ while (tpn)
+ {
+ if (tpn->client == client)
+ {
+ if (!onoff) tpn->client = 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 = malloc(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 = 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 = 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 = 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 = malloc(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 = 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 = 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
+){
+ int status;
+
+ status = (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value);
+ if (status == Success)
+ XvdiSendPortNotify(pPort, attribute, value);
+
+ return status;
+}
+
+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/Xext/xvmc.c b/Xext/xvmc.c
new file mode 100644
index 0000000..8fbdfae
--- /dev/null
+++ b/Xext/xvmc.c
@@ -0,0 +1,789 @@
+
+#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"
+#include "protocol-versions.h"
+
+#ifdef HAS_XVMCSHM
+#include <sys/ipc.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#endif /* HAS_XVMCSHM */
+
+
+
+#define DR_CLIENT_DRIVER_NAME_SIZE 48
+#define DR_BUSID_SIZE 48
+
+static DevPrivateKeyRec XvMCScreenKeyRec;
+#define XvMCScreenKey (&XvMCScreenKeyRec)
+static Bool XvMCInUse;
+
+unsigned long XvMCGeneration = 0;
+
+int XvMCReqCode;
+int XvMCEventBase;
+
+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);
+ free(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);
+ free(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);
+ free(pSubpict);
+
+ XvMCDestroyContextRes((pointer)pContext, pContext->context_id);
+
+ return Success;
+}
+
+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 = SERVER_XVMC_MAJOR_VERSION;
+ rep.minor = SERVER_XVMC_MINOR_VERSION;
+ 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);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ if(XvMCInUse) { /* 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 = bytes_to_int32(rep.num * sizeof(xvmcSurfaceInfo));
+
+ 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);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ pScreen = pPort->pAdaptor->pScreen;
+
+ if(!XvMCInUse) /* 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 = malloc(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) {
+ free(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);
+
+ free(data);
+
+ return Success;
+}
+
+static int
+ProcXvMCDestroyContext(ClientPtr client)
+{
+ pointer val;
+ int rc;
+ REQUEST(xvmcDestroyContextReq);
+ REQUEST_SIZE_MATCH(xvmcDestroyContextReq);
+
+ rc = dixLookupResourceByType(&val, stuff->context_id, XvMCRTContext,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ 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);
+
+ result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id,
+ XvMCRTContext, client, DixUseAccess);
+ if (result != Success)
+ return result;
+
+ pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
+
+ if(!(pSurface = malloc(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) {
+ free(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);
+
+ free(data);
+
+ pContext->refcnt++;
+
+ return Success;
+}
+
+static int
+ProcXvMCDestroySurface(ClientPtr client)
+{
+ pointer val;
+ int rc;
+ REQUEST(xvmcDestroySurfaceReq);
+ REQUEST_SIZE_MATCH(xvmcDestroySurfaceReq);
+
+ rc = dixLookupResourceByType(&val, stuff->surface_id, XvMCRTSurface,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ 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);
+
+ result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id,
+ XvMCRTContext, client, DixUseAccess);
+ if (result != Success)
+ return result;
+
+ 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 = malloc(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) {
+ free(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);
+
+ free(data);
+
+ pContext->refcnt++;
+
+ return Success;
+}
+
+static int
+ProcXvMCDestroySubpicture(ClientPtr client)
+{
+ pointer val;
+ int rc;
+ REQUEST(xvmcDestroySubpictureReq);
+ REQUEST_SIZE_MATCH(xvmcDestroySubpictureReq);
+
+ rc = dixLookupResourceByType(&val, stuff->subpicture_id, XvMCRTSubpicture,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ 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);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ 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 = bytes_to_int32(rep.num * sizeof(xvImageFormatInfo));
+
+ 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);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ 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 = bytes_to_int32(strlen(pScreenPriv->clientDriverName) + 1);
+ rep.busIDLen = bytes_to_int32(strlen(pScreenPriv->busID) + 1);
+
+ 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) {
+ volatile CARD32 *patternC = patternP;
+ 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,
+ "XvMCRTContext")))
+ return;
+
+ if(!(XvMCRTSurface = CreateNewResourceType(XvMCDestroySurfaceRes,
+ "XvMCRTSurface")))
+ return;
+
+ if(!(XvMCRTSubpicture = CreateNewResourceType(XvMCDestroySubpictureRes,
+ "XvMCRTSubpicture")))
+ return;
+
+ extEntry = AddExtension(XvMCName, XvMCNumEvents, XvMCNumErrors,
+ ProcXvMCDispatch, SProcXvMCDispatch,
+ NULL, StandardMinorOpcode);
+
+ if(!extEntry) return;
+
+ XvMCReqCode = extEntry->base;
+ XvMCEventBase = extEntry->eventBase;
+ SetResourceTypeErrorValue(XvMCRTContext, extEntry->errorBase + XvMCBadContext);
+ SetResourceTypeErrorValue(XvMCRTSurface, extEntry->errorBase + XvMCBadSurface);
+ SetResourceTypeErrorValue(XvMCRTSubpicture, extEntry->errorBase + XvMCBadSubpicture);
+}
+
+static Bool
+XvMCCloseScreen (int i, ScreenPtr pScreen)
+{
+ XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen);
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+
+ free(pScreenPriv);
+
+ return (*pScreen->CloseScreen)(i, pScreen);
+}
+
+
+int
+XvMCScreenInit(ScreenPtr pScreen, int num, XvMCAdaptorPtr pAdapt)
+{
+ XvMCScreenPtr pScreenPriv;
+
+ if (!dixRegisterPrivateKey(&XvMCScreenKeyRec, PRIVATE_SCREEN, 0))
+ return BadAlloc;
+
+ if(!(pScreenPriv = malloc(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;
+
+ XvMCInUse = TRUE;
+
+ 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/Xext/xvmcext.h b/Xext/xvmcext.h
new file mode 100644
index 0000000..5b43126
--- /dev/null
+++ b/Xext/xvmcext.h
@@ -0,0 +1,118 @@
+
+#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;
+
+#ifndef XorgLoader
+extern _X_EXPORT void XvMCExtensionInit(void);
+
+extern _X_EXPORT int XvMCScreenInit(ScreenPtr pScreen,
+ int num,
+ XvMCAdaptorPtr adapt);
+
+extern _X_EXPORT XvImagePtr XvMCFindXvImage(XvPortPtr pPort, CARD32 id);
+
+extern _X_EXPORT int xf86XvMCRegisterDRInfo(ScreenPtr pScreen, char *name,
+ char *busID, int major, int minor,
+ int patchLevel);
+#endif
+
+#endif /* _XVMC_H */
contact: Jan Huwald // Impressum