summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter@cs.unisa.edu.au>2006-11-29 17:55:15 +1030
committerPeter Hutterer <whot@hyena.localdomain>2006-11-29 17:55:15 +1030
commitafd6af65510b0147f16f08314045b3506bfa9d89 (patch)
tree8b21de45c5dc80fa152eee2784f90abb4cef6b87
parentbdf718907b3202815a04ec28a868689708f43da9 (diff)
mpx: Infrastructure for MPX extension, GetExtensionVersion request works.
-rw-r--r--Changelog17
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac19
-rw-r--r--include/globals.h4
-rw-r--r--mi/miinitext.c9
-rw-r--r--mpx/Makefile.am9
-rw-r--r--mpx/extinit.c287
-rw-r--r--mpx/getvers.c80
-rw-r--r--mpx/getvers.h22
-rw-r--r--mpx/mpxglobals.h15
-rw-r--r--mpx/selectev.c16
-rw-r--r--os/utils.c3
12 files changed, 475 insertions, 8 deletions
diff --git a/Changelog b/Changelog
index 7d0d80c65..c818bce63 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,21 @@
MPX Changelog file
+== 29.11.206 ==
+mpx: Infrastructure for MPX extension, GetExtensionVersion request works.
+
+Files:
+ mpx/
+ mpx/Makefile.am
+ mpx/extinit.c
+ mpx/getvers.c
+ mpx/getvers.h
+ mpxglobals.h
+ mpx/selectev.c
+ configure.ac
+ Makefile.am
+ os/utils.c
+ mi/miinitext.c
+ include/globals.h
+
== 28.11.06 ==
mi: Bugfix: FreeCursor ignores negative refcounts.
diff --git a/Makefile.am b/Makefile.am
index f35539e49..572d0882f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -42,6 +42,7 @@ SUBDIRS = \
randr \
render \
Xi \
+ mpx \
xkb \
$(DBE_DIR) \
$(MFB_DIR) \
@@ -78,6 +79,7 @@ DIST_SUBDIRS = \
randr \
render \
Xi \
+ mpx \
xkb \
dbe \
mfb \
diff --git a/configure.ac b/configure.ac
index 706df9137..e5d2f5ea2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -791,6 +791,8 @@ AM_CONDITIONAL(MPX, [test "x$MPX" = xyes])
if test "x$MPX" = xyes; then
AC_DEFINE(MPX, 1, [Support MPX multipointer extension])
+ MPX_LIB='$(top_builddir)/mpx/libmpx.la'
+ MPX_INC='-I$(top_srcdir)/mpx'
fi
AM_CONDITIONAL(XF86UTILS, test "x$XF86UTILS" = xyes)
@@ -1026,7 +1028,7 @@ if test "x$DMX" = xyes; then
modules not found.])
fi
DMX_INCLUDES="$XEXT_INC $RENDER_INC $XTRAP_INC $RECORD_INC"
- XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $XTRAP_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $OS_LIB $CWRAP_LIB"
+ XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $XTRAP_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $OS_LIB $CWRAP_LIB $MPX_LIB"
AC_SUBST([XDMX_LIBS])
dnl USB sources in DMX require <linux/input.h>
@@ -1065,7 +1067,7 @@ AC_MSG_RESULT([$XVFB])
AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes])
if test "x$XVFB" = xyes; then
- XVFB_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS"
+ XVFB_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS $MPX_LIB"
AC_SUBST([XVFB_LIBS])
fi
@@ -1081,7 +1083,7 @@ AC_MSG_RESULT([$XNEST])
AM_CONDITIONAL(XNEST, [test "x$XNEST" = xyes])
if test "x$XNEST" = xyes; then
- XNEST_LIBS="$XSERVER_LIBS $FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS"
+ XNEST_LIBS="$XSERVER_LIBS $FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS $MPX_LIB"
AC_SUBST([XNEST_LIBS])
fi
@@ -1110,7 +1112,7 @@ AC_MSG_RESULT([$XGL])
AM_CONDITIONAL(XGL, [test "x$XGL" = xyes])
if test "x$XGL" = xyes; then
- XGL_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB"
+ XGL_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $MPX_LIB"
AC_SUBST([XGL_LIBS])
AC_DEFINE(XGL_MODULAR, 1, [Use loadable XGL modules])
@@ -1131,7 +1133,7 @@ AC_MSG_RESULT([$XEGL])
AM_CONDITIONAL(XEGL, [test "x$XEGL" = xyes])
if test "x$XEGL" = xyes; then
- XEGL_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB"
+ XEGL_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $MPX_LIB"
AC_SUBST([XEGL_LIBS])
fi
@@ -1147,7 +1149,7 @@ AC_MSG_RESULT([$XGLX])
AM_CONDITIONAL(XGLX, [test "x$XGLX" = xyes])
if test "x$XGLX" = xyes; then
- XGLX_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB"
+ XGLX_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $MPX_LIB"
AC_SUBST([XGLX_LIBS])
fi
@@ -1168,7 +1170,7 @@ if test "x$XORG" = xyes -o "x$XGL" = xyes; then
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
- XORG_LIBS="$COMPOSITE_LIB $MI_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XPSTUBS_LIB $OS_LIB"
+ XORG_LIBS="$COMPOSITE_LIB $MI_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XPSTUBS_LIB $OS_LIB $MPX_LIB"
if test "x$DGA" = xauto; then
PKG_CHECK_MODULES(DGA, xf86dgaproto, [DGA=yes], [DGA=no])
@@ -1633,7 +1635,7 @@ if test "$KDRIVE" = yes; then
# dix os fb mi extension glx (NOTYET) damage shadow xpstubs
#KDRIVE_PURE_LIBS="$DIX_LIB $OS_LIB $FB_LIB $XEXT_LIB $MIEXT_DAMAGE_LIB \
# $MIEXT_SHADOW_LIB $XPSTUBS_LIB"
- KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $OS_LIB"
+ KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $OS_LIB $MPX_LIB"
KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.a'
case $host_os in
*linux*)
@@ -1826,6 +1828,7 @@ render/Makefile
xkb/Makefile
Xext/Makefile
Xi/Makefile
+mpx/Makefile
xfixes/Makefile
exa/Makefile
hw/Makefile
diff --git a/include/globals.h b/include/globals.h
index 821b12bdb..ef2256199 100644
--- a/include/globals.h
+++ b/include/globals.h
@@ -63,6 +63,10 @@ extern Bool noCompositeExtension;
extern Bool noDamageExtension;
#endif
+#ifdef MPX
+extern Bool noMPXExtension;
+#endif
+
#ifdef DBE
extern Bool noDbeExtension;
#endif
diff --git a/mi/miinitext.c b/mi/miinitext.c
index cb3447372..3d9522d78 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -384,6 +384,9 @@ extern void DamageExtensionInit(INITARGS);
#ifdef COMPOSITE
extern void CompositeExtensionInit(INITARGS);
#endif
+#ifdef MPX
+extern void MPXExtensionInit(INITARGS);
+#endif
/* The following is only a small first step towards run-time
* configurable extensions.
@@ -663,6 +666,9 @@ InitExtensions(argc, argv)
#ifdef DAMAGE
if (!noDamageExtension) DamageExtensionInit();
#endif
+#ifdef MPX
+ if (!noMPXExtension) MPXExtensionInit();
+#endif
}
void
@@ -733,6 +739,9 @@ static ExtensionModule staticExtensions[] = {
#ifdef XEVIE
{ XevieExtensionInit, "XEVIE", &noXevieExtension, NULL },
#endif
+#ifdef MPX
+ { MPXExtensionInit, "MPX", &noMPXExtension, NULL },
+#endif
{ NULL, NULL, NULL, NULL, NULL }
};
diff --git a/mpx/Makefile.am b/mpx/Makefile.am
new file mode 100644
index 000000000..db75eb53e
--- /dev/null
+++ b/mpx/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LTLIBRARIES = libmpx.la
+
+AM_CFLAGS = $(DIX_CFLAGS)
+
+libmpx_la_SOURCES = \
+ extinit.c \
+ getvers.c \
+ getvers.h
+
diff --git a/mpx/extinit.c b/mpx/extinit.c
new file mode 100644
index 000000000..59bc49448
--- /dev/null
+++ b/mpx/extinit.c
@@ -0,0 +1,287 @@
+/* Copyright 2006 by Peter Hutterer <peter@cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "inputstr.h"
+//#include "gcstruct.h" /* pointer for extnsionst.h */
+#include "extnsionst.h" /* extension entry */
+#include <X11/extensions/MPX.h>
+#include <X11/extensions/MPXproto.h>
+
+#include "mpxextinit.h"
+#include "swaprep.h"
+
+#include "getvers.h"
+
+static Mask lastExtEventMask = 1;
+int ExtEventIndex;
+Mask ExtValidMasks[EMASKSIZE];
+
+XExtEventInfo EventInfo[32];
+
+/*****************************************************************
+ *
+ * Externs defined elsewhere in the X server.
+ *
+ */
+
+extern XExtensionVersion AllExtensionVersions[];
+
+Mask PropagateMask[MAX_DEVICES];
+
+/*****************************************************************
+ *
+ * Globals referenced elsewhere in the server.
+ *
+ */
+
+int MPXReqCode = 0;
+int MPXEventBase = 0;
+int MPXErrorBase = 0;
+
+int MPXButtonPress;
+int MPXButtonRelease;
+int MPXMotionNotify;
+
+/*****************************************************************
+ *
+ * Declarations of local routines.
+ *
+ */
+
+static XExtensionVersion thisversion = { MPX_Present,
+ MPX_Major,
+ MPX_Minor
+};
+
+/**********************************************************************
+ *
+ * MPXExtensionInit - initialize the input extension.
+ *
+ * Called from InitExtensions in main() or from QueryExtension() if the
+ * extension is dynamically loaded.
+ *
+ * This extension has several events and errors.
+ *
+ */
+
+void
+MPXExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+
+ extEntry = AddExtension(MPXNAME, MPXEVENTS, MPXERRORS,
+ ProcMPXDispatch, SProcMPXDispatch,
+ MPXResetProc, StandardMinorOpcode);
+ if (extEntry) {
+ MPXReqCode = extEntry->base;
+ MPXEventBase = extEntry->eventBase;
+ MPXErrorBase = extEntry->errorBase;
+
+ AllExtensionVersions[MPXReqCode - 128] = thisversion;
+ MPXFixExtensionEvents(extEntry);
+ ReplySwapVector[MPXReqCode] = (ReplySwapPtr) SReplyMPXDispatch;
+ EventSwapVector[MPXButtonPress] = SEventMPXDispatch;
+ EventSwapVector[MPXButtonRelease] = SEventMPXDispatch;
+ EventSwapVector[MPXMotionNotify] = SEventMPXDispatch;
+ } else {
+ FatalError("MPXExtensionInit: AddExtensions failed\n");
+ }
+}
+
+/*************************************************************************
+ *
+ * ProcMPXDispatch - main dispatch routine for requests to this extension.
+ * This routine is used if server and client have the same byte ordering.
+ *
+ */
+
+int
+ProcMPXDispatch(register ClientPtr client)
+{
+ REQUEST(xReq);
+ if (stuff->data == MPX_GetExtensionVersion)
+ return (ProcMPXGetExtensionVersion(client));
+ else {
+ SendErrorToClient(client, MPXReqCode, stuff->data, 0, BadRequest);
+ }
+
+ return (BadRequest);
+}
+
+/*******************************************************************************
+ *
+ * SProcMPXDispatch
+ *
+ * Main swapped dispatch routine for requests to this extension.
+ * This routine is used if server and client do not have the same byte ordering.
+ *
+ */
+
+int
+SProcMPXDispatch(register ClientPtr client)
+{
+ REQUEST(xReq);
+ if (stuff->data == MPX_GetExtensionVersion)
+ return (SProcMPXGetExtensionVersion(client));
+ else {
+ SendErrorToClient(client, MPXReqCode, stuff->data, 0, BadRequest);
+ }
+
+ return (BadRequest);
+}
+
+/***********************************************************************
+ *
+ * MPXResetProc.
+ * Remove reply-swapping routine.
+ * Remove event-swapping routine.
+ *
+ */
+
+void
+MPXResetProc(ExtensionEntry* unused)
+{
+ ReplySwapVector[MPXReqCode] = ReplyNotSwappd;
+ EventSwapVector[MPXButtonPress] = NotImplemented;
+ EventSwapVector[MPXButtonRelease] = NotImplemented;
+ EventSwapVector[MPXMotionNotify] = NotImplemented;
+
+}
+
+void SReplyMPXDispatch(ClientPtr client, int len, mpxGetExtensionVersionReply* rep)
+{
+ if (rep->RepType == MPX_GetExtensionVersion)
+ SRepMPXGetExtensionVersion(client, len,
+ (mpxGetExtensionVersionReply*) rep);
+ else {
+ FatalError("MPX confused sending swapped reply");
+ }
+}
+
+void
+SEventMPXDispatch(xEvent* from, xEvent* to)
+{
+ int type = from->u.u.type & 0177;
+ if (type == MPXButtonPress) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == MPXButtonRelease) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == MPXMotionNotify) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else {
+ FatalError("XInputExtension: Impossible event!\n");
+ }
+}
+
+void
+MPXFixExtensionEvents(ExtensionEntry* extEntry)
+{
+ Mask mask;
+
+ MPXButtonPress = extEntry->eventBase;
+ MPXButtonRelease = MPXButtonPress + 1;
+ MPXMotionNotify = MPXButtonRelease + 1;
+
+ mask = MPXGetNextExtEventMask();
+ MPXSetMaskForExtEvent(mask, MPXButtonPress);
+ MPXAllowPropagateSuppress(mask);
+
+ mask = MPXGetNextExtEventMask();
+ MPXSetMaskForExtEvent(mask, MPXButtonRelease);
+ MPXAllowPropagateSuppress(mask);
+
+ mask = MPXGetNextExtEventMask();
+ MPXSetMaskForExtEvent(mask, MPXMotionNotify);
+ MPXAllowPropagateSuppress(mask);
+
+}
+
+/**************************************************************************
+ *
+ * Return the next available extension event mask.
+ *
+ */
+Mask
+MPXGetNextExtEventMask(void)
+{
+ int i;
+ Mask mask = lastExtEventMask;
+
+ if (lastExtEventMask == 0) {
+ FatalError("MPXGetNextExtEventMask: no more events are available.");
+ }
+ lastExtEventMask <<= 1;
+
+ for (i = 0; i < MAX_DEVICES; i++)
+ ExtValidMasks[i] |= mask;
+ return mask;
+}
+
+/**************************************************************************
+ *
+ * Assign the specified mask to the specified event.
+ *
+ */
+
+void
+MPXSetMaskForExtEvent(Mask mask, int event)
+{
+
+ EventInfo[ExtEventIndex].mask = mask;
+ EventInfo[ExtEventIndex++].type = event;
+
+ if ((event < LASTEvent) || (event >= 128))
+ FatalError("MaskForExtensionEvent: bogus event number");
+ SetMaskForEvent(mask, event);
+}
+
+/************************************************************************
+ *
+ * This function restores extension event types and masks to their
+ * initial state.
+ *
+ */
+
+void
+MPXRestoreExtensionEvents(void)
+{
+ int i;
+
+ MPXReqCode = 0;
+ for (i = 0; i < ExtEventIndex - 1; i++) {
+ if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128))
+ SetMaskForEvent(0, EventInfo[i].type);
+ EventInfo[i].mask = 0;
+ EventInfo[i].type = 0;
+ }
+
+ ExtEventIndex = 0;
+ lastExtEventMask = 1;
+ MPXButtonPress = 0;
+ MPXButtonRelease = 1;
+ MPXMotionNotify = 2;
+}
+
+/**************************************************************************
+ *
+ * Allow the specified event to have its propagation suppressed.
+ * The default is to not allow suppression of propagation.
+ *
+ */
+
+void
+MPXAllowPropagateSuppress(Mask mask)
+{
+ int i;
+
+ for (i = 0; i < MAX_DEVICES; i++)
+ PropagateMask[i] |= mask;
+}
diff --git a/mpx/getvers.c b/mpx/getvers.c
new file mode 100644
index 000000000..4663c5459
--- /dev/null
+++ b/mpx/getvers.c
@@ -0,0 +1,80 @@
+/* Copyright 2006 by Peter Hutterer <peter@cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h> /* for inputstr.h */
+#include <X11/Xproto.h> /* Request macro */
+#include "inputstr.h" /* DeviceIntPtr */
+#include <X11/extensions/MPX.h>
+#include <X11/extensions/MPXproto.h>
+
+#include "mpxglobals.h"
+#include "getvers.h"
+
+XExtensionVersion AllExtensionVersions[128];
+
+/***********************************************************************
+ *
+ * Handle a request from a client with a different byte order than us.
+ *
+ */
+
+int
+SProcMPXGetExtensionVersion(register ClientPtr client)
+{
+ register char n;
+
+ REQUEST(mpxGetExtensionVersionReq);
+ swaps(&stuff->length, n);
+ swaps(&stuff->major_version, n);
+ swaps(&stuff->minor_version, n);
+ REQUEST_AT_LEAST_SIZE(mpxGetExtensionVersionReq);
+ return (ProcMPXGetExtensionVersion(client));
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the XGetExtensionVersion function.
+ */
+
+int
+ProcMPXGetExtensionVersion(register ClientPtr client)
+{
+ mpxGetExtensionVersionReply rep;
+
+ REQUEST(mpxGetExtensionVersionReq);
+ REQUEST_SIZE_MATCH(mpxGetExtensionVersionReq);
+
+ rep.repType = X_Reply;
+ rep.RepType = MPX_GetExtensionVersion;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ rep.major_version = AllExtensionVersions[MPXReqCode - 128].major_version;
+ rep.minor_version = AllExtensionVersions[MPXReqCode - 128].minor_version;
+ WriteReplyToClient(client, sizeof(mpxGetExtensionVersionReply), &rep);
+
+ return Success;
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the MPXGetExtensionVersion function,
+ * if the client and server have a different byte ordering.
+ *
+ */
+
+void
+SRepMPXGetExtensionVersion(ClientPtr client, int size,
+ mpxGetExtensionVersionReply * rep)
+{
+ register char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->major_version, n);
+ swaps(&rep->minor_version, n);
+ WriteToClient(client, size, (char *)rep);
+}
diff --git a/mpx/getvers.h b/mpx/getvers.h
new file mode 100644
index 000000000..da2401818
--- /dev/null
+++ b/mpx/getvers.h
@@ -0,0 +1,22 @@
+/* Copyright 2006 by Peter Hutterer <peter@cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef GETVERS_H
+#define GETVERS_H 1
+
+int SProcMPXGetExtensionVersion(ClientPtr /* client */
+ );
+
+int ProcMPXGetExtensionVersion(ClientPtr /* client */
+ );
+
+void SRepMPXGetExtensionVersion(ClientPtr /* client */ ,
+ int /* size */ ,
+ mpxGetExtensionVersionReply * /* rep */
+ );
+
+#endif
+
diff --git a/mpx/mpxglobals.h b/mpx/mpxglobals.h
new file mode 100644
index 000000000..d74710c96
--- /dev/null
+++ b/mpx/mpxglobals.h
@@ -0,0 +1,15 @@
+/* Copyright 2006 by Peter Hutterer <peter@cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+extern int MPXReqCode;
+extern int MPXEventBase;
+extern int MPXErrorBase;
+
+extern int MPXButtonPress;
+extern int MPXButtonRelease;
+extern int MPXMotionNotify;
+
+extern Mask PropagateMask[];
diff --git a/mpx/selectev.c b/mpx/selectev.c
new file mode 100644
index 000000000..d29d3f15b
--- /dev/null
+++ b/mpx/selectev.c
@@ -0,0 +1,16 @@
+/* Copyright 2006 by Peter Hutterer <peter@cs.unisa.edu.au> */
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h> /* for inputstr.h */
+#include <X11/Xproto.h> /* Request macro */
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include <X11/extensions/MPX.h>
+#include <X11/extensions/MPXproto.h>
+#include "extnsionst.h"
+#include "extinit.h" /* LookupDeviceIntRec */
+
diff --git a/os/utils.c b/os/utils.c
index 9824501e7..42d41ce85 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -252,6 +252,9 @@ _X_EXPORT Bool noXIdleExtension = FALSE;
#ifdef XV
_X_EXPORT Bool noXvExtension = FALSE;
#endif
+#ifdef MPX
+_X_EXPORT Bool noMPXExtension = FALSE;
+#endif
#define X_INCLUDE_NETDB_H
#include <X11/Xos_r.h>