aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/Xi
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/Xi')
-rw-r--r--xorg-server/Xi/Makefile.am4
-rw-r--r--xorg-server/Xi/Makefile.in83
-rw-r--r--xorg-server/Xi/allowev.c12
-rw-r--r--xorg-server/Xi/chgdctl.c20
-rw-r--r--xorg-server/Xi/closedev.c6
-rw-r--r--xorg-server/Xi/exevents.c1113
-rw-r--r--xorg-server/Xi/exglobals.h9
-rw-r--r--xorg-server/Xi/extinit.c379
-rw-r--r--xorg-server/Xi/getvers.c16
-rw-r--r--xorg-server/Xi/grabdev.c22
-rw-r--r--xorg-server/Xi/grabdevb.c2
-rw-r--r--xorg-server/Xi/grabdevk.c2
-rw-r--r--xorg-server/Xi/gtmotion.c16
-rw-r--r--xorg-server/Xi/listdev.c80
-rw-r--r--xorg-server/Xi/listdev.h13
-rw-r--r--xorg-server/Xi/opendev.c9
-rw-r--r--xorg-server/Xi/queryst.c5
-rw-r--r--xorg-server/Xi/selectev.c4
-rw-r--r--xorg-server/Xi/sendexev.c3
-rw-r--r--xorg-server/Xi/setdval.c2
-rw-r--r--xorg-server/Xi/setmode.c2
-rw-r--r--xorg-server/Xi/ungrdev.c8
-rw-r--r--xorg-server/Xi/ungrdevb.c2
-rw-r--r--xorg-server/Xi/ungrdevk.c2
-rw-r--r--xorg-server/Xi/xiproperty.c918
-rw-r--r--xorg-server/Xi/xiproperty.h48
26 files changed, 2308 insertions, 472 deletions
diff --git a/xorg-server/Xi/Makefile.am b/xorg-server/Xi/Makefile.am
index fbe438543..557e20728 100644
--- a/xorg-server/Xi/Makefile.am
+++ b/xorg-server/Xi/Makefile.am
@@ -75,6 +75,8 @@ libXi_la_SOURCES = \
ungrdevb.c \
ungrdevb.h \
ungrdevk.c \
- ungrdevk.h
+ ungrdevk.h \
+ xiproperty.c \
+ xiproperty.h
EXTRA_DIST = stubs.c
diff --git a/xorg-server/Xi/Makefile.in b/xorg-server/Xi/Makefile.in
index 291a6112a..1e47a1879 100644
--- a/xorg-server/Xi/Makefile.in
+++ b/xorg-server/Xi/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -43,7 +43,6 @@ mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/do-not-use-config.h \
$(top_builddir)/include/xorg-server.h \
$(top_builddir)/include/dix-config.h \
- $(top_builddir)/include/xgl-config.h \
$(top_builddir)/include/xorg-config.h \
$(top_builddir)/include/xkb-config.h \
$(top_builddir)/include/xwin-config.h \
@@ -58,16 +57,13 @@ am_libXi_la_OBJECTS = allowev.lo chgdctl.lo chgfctl.lo chgkbd.lo \
getvers.lo grabdev.lo grabdevb.lo grabdevk.lo gtmotion.lo \
listdev.lo opendev.lo queryst.lo selectev.lo sendexev.lo \
setbmap.lo setdval.lo setfocus.lo setmmap.lo setmode.lo \
- ungrdev.lo ungrdevb.lo ungrdevk.lo
+ ungrdev.lo ungrdevb.lo ungrdevk.lo xiproperty.lo
libXi_la_OBJECTS = $(am_libXi_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
@@ -82,8 +78,9 @@ ADMIN_MAN_DIR = @ADMIN_MAN_DIR@
ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
-APPDEFAULTDIR = @APPDEFAULTDIR@
APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@
+APPLE_APPLICATION_ID = @APPLE_APPLICATION_ID@
+APPLE_APPLICATION_NAME = @APPLE_APPLICATION_NAME@
APP_MAN_DIR = @APP_MAN_DIR@
APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
AR = @AR@
@@ -104,10 +101,6 @@ CFLAGS = @CFLAGS@
COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
-CXX = @CXX@
-CXXCPP = @CXXCPP@
-CXXDEPMODE = @CXXDEPMODE@
-CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DARWIN_LIBS = @DARWIN_LIBS@
DBUS_CFLAGS = @DBUS_CFLAGS@
@@ -129,6 +122,7 @@ DMXXIEXAMPLES_DEP_CFLAGS = @DMXXIEXAMPLES_DEP_CFLAGS@
DMXXIEXAMPLES_DEP_LIBS = @DMXXIEXAMPLES_DEP_LIBS@
DMXXMUEXAMPLES_DEP_CFLAGS = @DMXXMUEXAMPLES_DEP_CFLAGS@
DMXXMUEXAMPLES_DEP_LIBS = @DMXXMUEXAMPLES_DEP_LIBS@
+DOLT_BASH = @DOLT_BASH@
DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@
DRI2PROTO_LIBS = @DRI2PROTO_LIBS@
DRIPROTO_CFLAGS = @DRIPROTO_CFLAGS@
@@ -138,18 +132,15 @@ DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
DRI_DRIVER_PATH = @DRI_DRIVER_PATH@
DSYMUTIL = @DSYMUTIL@
DTRACE = @DTRACE@
-ECHO = @ECHO@
+DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
-F77 = @F77@
-FFLAGS = @FFLAGS@
+FGREP = @FGREP@
FILE_MAN_DIR = @FILE_MAN_DIR@
FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
-FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
-FREETYPE_LIBS = @FREETYPE_LIBS@
GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@
GLX_DEFINES = @GLX_DEFINES@
GL_CFLAGS = @GL_CFLAGS@
@@ -168,7 +159,7 @@ KDRIVE_LIBS = @KDRIVE_LIBS@
KDRIVE_LOCAL_LIBS = @KDRIVE_LOCAL_LIBS@
KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@
KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@
-LAUNCHD = @LAUNCHD@
+LD = @LD@
LDFLAGS = @LDFLAGS@
LD_EXPORT_SYMBOLS_FLAG = @LD_EXPORT_SYMBOLS_FLAG@
LEX = @LEX@
@@ -182,7 +173,10 @@ LIBTOOL = @LIBTOOL@
LIB_MAN_DIR = @LIB_MAN_DIR@
LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
LINUXDOC = @LINUXDOC@
+LIPO = @LIPO@
LN_S = @LN_S@
+LTCOMPILE = @LTCOMPILE@
+LTCXXCOMPILE = @LTCXXCOMPILE@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
@@ -194,8 +188,7 @@ MESA_SOURCE = @MESA_SOURCE@
MISC_MAN_DIR = @MISC_MAN_DIR@
MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
MKDIR_P = @MKDIR_P@
-MKFONTDIR = @MKFONTDIR@
-MKFONTSCALE = @MKFONTSCALE@
+NM = @NM@
NMEDIT = @NMEDIT@
OBJC = @OBJC@
OBJCCLD = @OBJCCLD@
@@ -204,8 +197,8 @@ OBJCFLAGS = @OBJCFLAGS@
OBJCLINK = @OBJCLINK@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
-OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
-OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
@@ -238,7 +231,6 @@ VENDOR_NAME = @VENDOR_NAME@
VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@
VENDOR_RELEASE = @VENDOR_RELEASE@
VERSION = @VERSION@
-X11APP_ARCHS = @X11APP_ARCHS@
X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@
X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@
XDMCP_CFLAGS = @XDMCP_CFLAGS@
@@ -248,27 +240,12 @@ XDMXCONFIG_DEP_LIBS = @XDMXCONFIG_DEP_LIBS@
XDMX_CFLAGS = @XDMX_CFLAGS@
XDMX_LIBS = @XDMX_LIBS@
XDMX_SYS_LIBS = @XDMX_SYS_LIBS@
-XEGLMODULES_CFLAGS = @XEGLMODULES_CFLAGS@
-XEGL_LIBS = @XEGL_LIBS@
-XEGL_SYS_LIBS = @XEGL_SYS_LIBS@
XEPHYR_CFLAGS = @XEPHYR_CFLAGS@
-XEPHYR_DRI_LIBS = @XEPHYR_DRI_LIBS@
XEPHYR_INCS = @XEPHYR_INCS@
XEPHYR_LIBS = @XEPHYR_LIBS@
XF86CONFIGFILE = @XF86CONFIGFILE@
-XF86MISC_CFLAGS = @XF86MISC_CFLAGS@
-XF86MISC_LIBS = @XF86MISC_LIBS@
XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@
XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@
-XGLMODULES_CFLAGS = @XGLMODULES_CFLAGS@
-XGLMODULES_LIBS = @XGLMODULES_LIBS@
-XGLXMODULES_CFLAGS = @XGLXMODULES_CFLAGS@
-XGLXMODULES_LIBS = @XGLXMODULES_LIBS@
-XGLX_LIBS = @XGLX_LIBS@
-XGLX_SYS_LIBS = @XGLX_SYS_LIBS@
-XGL_LIBS = @XGL_LIBS@
-XGL_MODULE_PATH = @XGL_MODULE_PATH@
-XGL_SYS_LIBS = @XGL_SYS_LIBS@
XKB_BASE_DIRECTORY = @XKB_BASE_DIRECTORY@
XKB_BIN_DIRECTORY = @XKB_BIN_DIRECTORY@
XKB_COMPILED_DIR = @XKB_COMPILED_DIR@
@@ -279,10 +256,6 @@ XNESTMODULES_CFLAGS = @XNESTMODULES_CFLAGS@
XNESTMODULES_LIBS = @XNESTMODULES_LIBS@
XNEST_LIBS = @XNEST_LIBS@
XNEST_SYS_LIBS = @XNEST_SYS_LIBS@
-XORGCFG_DEP_CFLAGS = @XORGCFG_DEP_CFLAGS@
-XORGCFG_DEP_LIBS = @XORGCFG_DEP_LIBS@
-XORGCONFIG_DEP_CFLAGS = @XORGCONFIG_DEP_CFLAGS@
-XORGCONFIG_DEP_LIBS = @XORGCONFIG_DEP_LIBS@
XORG_CFLAGS = @XORG_CFLAGS@
XORG_INCS = @XORG_INCS@
XORG_LIBS = @XORG_LIBS@
@@ -291,13 +264,8 @@ XORG_MODULES_LIBS = @XORG_MODULES_LIBS@
XORG_OS = @XORG_OS@
XORG_OS_SUBDIR = @XORG_OS_SUBDIR@
XORG_SYS_LIBS = @XORG_SYS_LIBS@
-XPRINTMODULES_CFLAGS = @XPRINTMODULES_CFLAGS@
-XPRINTMODULES_LIBS = @XPRINTMODULES_LIBS@
-XPRINTPROTO_CFLAGS = @XPRINTPROTO_CFLAGS@
-XPRINTPROTO_LIBS = @XPRINTPROTO_LIBS@
-XPRINT_CFLAGS = @XPRINT_CFLAGS@
-XPRINT_LIBS = @XPRINT_LIBS@
-XPRINT_SYS_LIBS = @XPRINT_SYS_LIBS@
+XPBPROXY_CFLAGS = @XPBPROXY_CFLAGS@
+XPBPROXY_LIBS = @XPBPROXY_LIBS@
XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@
XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@
XSDL_INCS = @XSDL_INCS@
@@ -330,8 +298,7 @@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
-ac_ct_CXX = @ac_ct_CXX@
-ac_ct_F77 = @ac_ct_F77@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -351,7 +318,6 @@ driverdir = @driverdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
extdir = @extdir@
-ft_config = @ft_config@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
@@ -361,12 +327,12 @@ htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
-launchagentsdir = @launchagentsdir@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
logdir = @logdir@
+lt_ECHO = @lt_ECHO@
mandir = @mandir@
mkdir_p = @mkdir_p@
moduledir = @moduledir@
@@ -384,8 +350,6 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-xglmoduledir = @xglmoduledir@
-xpconfigdir = @xpconfigdir@
noinst_LTLIBRARIES = libXi.la
AM_CFLAGS = $(DIX_CFLAGS)
libXi_la_SOURCES = \
@@ -461,7 +425,9 @@ libXi_la_SOURCES = \
ungrdevb.c \
ungrdevb.h \
ungrdevk.c \
- ungrdevk.h
+ ungrdevk.h \
+ xiproperty.c \
+ xiproperty.h
EXTRA_DIST = stubs.c
all: all-am
@@ -472,8 +438,8 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
@@ -552,6 +518,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ungrdev.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ungrdevb.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ungrdevk.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xiproperty.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -585,7 +552,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
- $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
diff --git a/xorg-server/Xi/allowev.c b/xorg-server/Xi/allowev.c
index 0043cb138..36b6caad5 100644
--- a/xorg-server/Xi/allowev.c
+++ b/xorg-server/Xi/allowev.c
@@ -106,22 +106,22 @@ ProcXAllowDeviceEvents(ClientPtr client)
switch (stuff->mode) {
case ReplayThisDevice:
- AllowSome(client, time, thisdev, NOT_GRABBED);
+ AllowSome(client, time, thisdev, NOT_GRABBED, FALSE);
break;
case SyncThisDevice:
- AllowSome(client, time, thisdev, FREEZE_NEXT_EVENT);
+ AllowSome(client, time, thisdev, FREEZE_NEXT_EVENT, FALSE);
break;
case AsyncThisDevice:
- AllowSome(client, time, thisdev, THAWED);
+ AllowSome(client, time, thisdev, THAWED, FALSE);
break;
case AsyncOtherDevices:
- AllowSome(client, time, thisdev, THAW_OTHERS);
+ AllowSome(client, time, thisdev, THAW_OTHERS, FALSE);
break;
case SyncAll:
- AllowSome(client, time, thisdev, FREEZE_BOTH_NEXT_EVENT);
+ AllowSome(client, time, thisdev, FREEZE_BOTH_NEXT_EVENT, FALSE);
break;
case AsyncAll:
- AllowSome(client, time, thisdev, THAWED_BOTH);
+ AllowSome(client, time, thisdev, THAWED_BOTH, FALSE);
break;
default:
client->errorValue = stuff->mode;
diff --git a/xorg-server/Xi/chgdctl.c b/xorg-server/Xi/chgdctl.c
index 8df40fea0..6044f6cd6 100644
--- a/xorg-server/Xi/chgdctl.c
+++ b/xorg-server/Xi/chgdctl.c
@@ -138,7 +138,6 @@ ProcXChangeDeviceControl(ClientPtr client)
CARD32 *resolution;
xDeviceAbsCalibCtl *calib;
xDeviceAbsAreaCtl *area;
- xDeviceCoreCtl *c;
xDeviceEnableCtl *e;
devicePresenceNotify dpn;
@@ -167,7 +166,7 @@ ProcXChangeDeviceControl(ClientPtr client)
ret = BadMatch;
goto out;
}
- if ((dev->grab) && !SameClient(dev->grab, client)) {
+ if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client)) {
rep.status = AlreadyGrabbed;
ret = Success;
goto out;
@@ -245,20 +244,9 @@ ProcXChangeDeviceControl(ClientPtr client)
break;
case DEVICE_CORE:
- c = (xDeviceCoreCtl *)&stuff[1];
-
- status = ChangeDeviceControl(client, dev, (xDeviceCtl *) c);
-
- if (status == Success) {
- dev->coreEvents = c->status;
- ret = Success;
- } else if (status == DeviceBusy) {
- rep.status = DeviceBusy;
- ret = Success;
- } else {
- ret = BadMatch;
- }
-
+ /* Sorry, no device core switching no more. If you want a device to
+ * send core events, attach it to a master device */
+ ret = BadMatch;
break;
case DEVICE_ENABLE:
e = (xDeviceEnableCtl *)&stuff[1];
diff --git a/xorg-server/Xi/closedev.c b/xorg-server/Xi/closedev.c
index 94b7391fb..2be908c4a 100644
--- a/xorg-server/Xi/closedev.c
+++ b/xorg-server/Xi/closedev.c
@@ -150,10 +150,10 @@ ProcXCloseDevice(ClientPtr client)
if (rc != Success)
return rc;
- if (d->grab && SameClient(d->grab, client))
- (*d->DeactivateGrab) (d); /* release active grab */
+ if (d->deviceGrab.grab && SameClient(d->deviceGrab.grab, client))
+ (*d->deviceGrab.DeactivateGrab) (d); /* release active grab */
- /* Remove event selections from all windows for events from this device
+ /* Remove event selections from all windows for events from this device
* and selected by this client.
* Delete passive grabs from all windows for this device. */
diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c
index 641bead33..398a26b20 100644
--- a/xorg-server/Xi/exevents.c
+++ b/xorg-server/Xi/exevents.c
@@ -61,6 +61,7 @@ SOFTWARE.
#include <X11/Xproto.h>
#include <X11/extensions/XI.h>
#include <X11/extensions/XIproto.h>
+#include <X11/extensions/geproto.h>
#include "inputstr.h"
#include "windowstr.h"
#include "miscstruct.h"
@@ -71,10 +72,13 @@ SOFTWARE.
#include "dixevents.h" /* DeliverFocusedEvent */
#include "dixgrabs.h" /* CreateGrab() */
#include "scrnintstr.h"
+#include "listdev.h" /* for CopySwapXXXClass */
#include "xace.h"
#ifdef XKB
+#include <X11/extensions/XKBproto.h>
#include "xkbsrv.h"
+extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
#endif
#define WID(w) ((w) ? ((w)->drawable.id) : 0)
@@ -86,115 +90,769 @@ SOFTWARE.
#define Motion_Filter(class) (DevicePointerMotionMask | \
(class)->state | (class)->motionMask)
-static Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
+Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
Bool /* ignoreSelectedEvents */
);
static Bool MakeInputMasks(WindowPtr /* pWin */
);
-/**************************************************************************
- *
- * Procedures for extension device event routing.
- *
- */
+/* Used to sture classes currently not in use by an MD */
+extern DevPrivateKey UnusedClassesPrivateKey;
+
void
RegisterOtherDevice(DeviceIntPtr device)
{
device->public.processInputProc = ProcessOtherEvent;
device->public.realInputProc = ProcessOtherEvent;
- (device)->ActivateGrab = ActivateKeyboardGrab;
- (device)->DeactivateGrab = DeactivateKeyboardGrab;
}
- /*ARGSUSED*/ void
-ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
+Bool
+IsPointerEvent(xEvent* xE)
+{
+ switch(xE->u.u.type)
+ {
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ case EnterNotify:
+ case LeaveNotify:
+ return TRUE;
+ default:
+ if (xE->u.u.type == DeviceButtonPress ||
+ xE->u.u.type == DeviceButtonRelease ||
+ xE->u.u.type == DeviceMotionNotify ||
+ xE->u.u.type == ProximityIn ||
+ xE->u.u.type == ProximityOut)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * @return the device matching the deviceid of the device set in the event, or
+ * NULL if the event is not an XInput event.
+ */
+DeviceIntPtr
+XIGetDevice(xEvent* xE)
+{
+ DeviceIntPtr pDev = NULL;
+
+ if (xE->u.u.type == DeviceButtonPress ||
+ xE->u.u.type == DeviceButtonRelease ||
+ xE->u.u.type == DeviceMotionNotify ||
+ xE->u.u.type == ProximityIn ||
+ xE->u.u.type == ProximityOut ||
+ xE->u.u.type == DevicePropertyNotify)
+ {
+ int rc;
+ int id;
+
+ id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
+
+ rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
+ if (rc != Success)
+ ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
+ }
+ return pDev;
+}
+
+
+/**
+ * Copy the device->key into master->key and send a mapping notify to the
+ * clients if appropriate.
+ * master->key needs to be allocated by the caller.
+ *
+ * Device is the slave device. If it is attached to a master device, we may
+ * need to send a mapping notify to the client because it causes the MD
+ * to change state.
+ *
+ * Mapping notify needs to be sent in the following cases:
+ * - different slave device on same master
+ * - different master
+ *
+ * XXX: They way how the code is we also send a map notify if the slave device
+ * stays the same, but the master changes. This isn't really necessary though.
+ *
+ * XXX: this gives you funny behaviour with the ClientPointer. When a
+ * MappingNotify is sent to the client, the client usually responds with a
+ * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
+ * mapping, regardless of which keyboard sent the last mapping notify request.
+ * So depending on the CP setting, your keyboard may change layout in each
+ * app...
+ *
+ * This code is basically the old SwitchCoreKeyboard.
+ */
+
+void
+CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
{
- BYTE *kptr;
+ static DeviceIntPtr lastMapNotifyDevice = NULL;
+ KeyClassPtr mk, dk; /* master, device */
+ BOOL sendNotify = FALSE;
int i;
- CARD16 modifiers;
- CARD16 mask;
- GrabPtr grab = other->grab;
- Bool deactivateDeviceGrab = FALSE;
- int key = 0, bit = 0, rootX, rootY;
- ButtonClassPtr b = other->button;
- KeyClassPtr k = other->key;
- ValuatorClassPtr v = other->valuator;
- deviceValuator *xV = (deviceValuator *) xE;
-
- if (xE->u.u.type != DeviceValuator) {
- GetSpritePosition(&rootX, &rootY);
- xE->u.keyButtonPointer.rootX = rootX;
- xE->u.keyButtonPointer.rootY = rootY;
- key = xE->u.u.detail;
- NoticeEventTime(xE);
- xE->u.keyButtonPointer.state = inputInfo.keyboard->key->state |
- inputInfo.pointer->button->state;
- bit = 1 << (key & 7);
+
+ if (device == master)
+ return;
+
+ dk = device->key;
+ mk = master->key;
+
+ if (device != dixLookupPrivate(&master->devPrivates,
+ CoreDevicePrivateKey)) {
+ memcpy(mk->modifierMap, dk->modifierMap, MAP_LENGTH);
+
+ if (dk->maxKeysPerModifier)
+ {
+ mk->modifierKeyMap = xrealloc(mk->modifierKeyMap,
+ 8 * dk->maxKeysPerModifier);
+ if (!mk->modifierKeyMap)
+ FatalError("[Xi] no memory for class shift.\n");
+ memcpy(mk->modifierKeyMap, dk->modifierKeyMap,
+ (8 * dk->maxKeysPerModifier));
+ } else
+ {
+ xfree(mk->modifierKeyMap);
+ mk->modifierKeyMap = NULL;
+ }
+
+ mk->maxKeysPerModifier = dk->maxKeysPerModifier;
+ mk->curKeySyms.minKeyCode = dk->curKeySyms.minKeyCode;
+ mk->curKeySyms.maxKeyCode = dk->curKeySyms.maxKeyCode;
+ SetKeySymsMap(&mk->curKeySyms, &dk->curKeySyms);
+
+ /*
+ * Copy state from the extended keyboard to core. If you omit this,
+ * holding Ctrl on keyboard one, and pressing Q on keyboard two, will
+ * cause your app to quit. This feels wrong to me, hence the below
+ * code.
+ *
+ * XXX: If you synthesise core modifier events, the state will get
+ * clobbered here. You'll have to work out something sensible
+ * to fix that. Good luck.
+ */
+
+#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \
+ Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
+ mk->state &= ~(KEYBOARD_MASK);
+ mk->state |= (dk->state & KEYBOARD_MASK);
+#undef KEYBOARD_MASK
+ for (i = 0; i < 8; i++)
+ mk->modifierKeyCount[i] = dk->modifierKeyCount[i];
+
+#ifdef XKB
+ if (!noXkbExtension && dk->xkbInfo && dk->xkbInfo->desc) {
+ if (!mk->xkbInfo || !mk->xkbInfo->desc)
+ {
+ XkbInitDevice(master);
+ XkbFinishDeviceInit(master);
+ }
+ if (!XkbCopyKeymap(dk->xkbInfo->desc, mk->xkbInfo->desc, True))
+ FatalError("Couldn't pivot keymap from device to core!\n");
+ }
+#endif
+
+ dixSetPrivate(&master->devPrivates, CoreDevicePrivateKey, device);
+ sendNotify = TRUE;
+ } else if (lastMapNotifyDevice != master)
+ sendNotify = TRUE;
+
+ if (sendNotify)
+ {
+ SendMappingNotify(master, MappingKeyboard,
+ mk->curKeySyms.minKeyCode,
+ (mk->curKeySyms.maxKeyCode -
+ mk->curKeySyms.minKeyCode),
+ serverClient);
+ lastMapNotifyDevice = master;
}
- if (DeviceEventCallback) {
- DeviceEventInfoRec eventinfo;
+}
- eventinfo.events = (xEventPtr) xE;
- eventinfo.count = count;
- CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
+/**
+ * Copies the feedback classes from device "from" into device "to". Classes
+ * are duplicated (not just flipping the pointers). All feedback classes are
+ * linked lists, the full list is duplicated.
+ */
+static void
+DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+ ClassesPtr classes;
+
+ if (from->kbdfeed)
+ {
+ KbdFeedbackPtr *k, it;
+
+ if (!to->kbdfeed)
+ {
+ classes = dixLookupPrivate(&to->devPrivates,
+ UnusedClassesPrivateKey);
+ to->kbdfeed = classes->kbdfeed;
+ }
+
+ k = &to->kbdfeed;
+ for(it = from->kbdfeed; it; it = it->next)
+ {
+ if (!(*k))
+ {
+ *k = xcalloc(1, sizeof(KbdFeedbackClassRec));
+ if (!*k)
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*k)->BellProc = it->BellProc;
+ (*k)->CtrlProc = it->CtrlProc;
+ (*k)->ctrl = it->ctrl;
+#ifdef XKB
+ if ((*k)->xkb_sli)
+ XkbFreeSrvLedInfo((*k)->xkb_sli);
+ (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
+#endif
+
+ k = &(*k)->next;
+ }
+ } else if (to->kbdfeed && !from->kbdfeed)
+ {
+ ClassesPtr classes;
+ classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+ classes->kbdfeed = to->kbdfeed;
+ to->kbdfeed = NULL;
+ }
+
+ if (from->ptrfeed)
+ {
+ PtrFeedbackPtr *p, it;
+ if (!to->ptrfeed)
+ {
+ classes = dixLookupPrivate(&to->devPrivates,
+ UnusedClassesPrivateKey);
+ to->ptrfeed = classes->ptrfeed;
+ }
+
+ p = &to->ptrfeed;
+ for (it = from->ptrfeed; it; it = it->next)
+ {
+ if (!(*p))
+ {
+ *p = xcalloc(1, sizeof(PtrFeedbackClassRec));
+ if (!*p)
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*p)->CtrlProc = it->CtrlProc;
+ (*p)->ctrl = it->ctrl;
+
+ p = &(*p)->next;
+ }
+ } else if (to->ptrfeed && !from->ptrfeed)
+ {
+ ClassesPtr classes;
+ classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+ classes->ptrfeed = to->ptrfeed;
+ to->ptrfeed = NULL;
+ }
+
+ if (from->intfeed)
+ {
+ IntegerFeedbackPtr *i, it;
+
+ if (!to->intfeed)
+ {
+ classes = dixLookupPrivate(&to->devPrivates,
+ UnusedClassesPrivateKey);
+ to->intfeed = classes->intfeed;
+ }
+
+ i = &to->intfeed;
+ for (it = from->intfeed; it; it = it->next)
+ {
+ if (!(*i))
+ {
+ *i = xcalloc(1, sizeof(IntegerFeedbackClassRec));
+ if (!(*i))
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*i)->CtrlProc = it->CtrlProc;
+ (*i)->ctrl = it->ctrl;
+
+ i = &(*i)->next;
+ }
+ } else if (to->intfeed && !from->intfeed)
+ {
+ ClassesPtr classes;
+ classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+ classes->intfeed = to->intfeed;
+ to->intfeed = NULL;
}
- for (i = 1; i < count; i++)
+
+ if (from->stringfeed)
+ {
+ StringFeedbackPtr *s, it;
+
+ if (!to->stringfeed)
+ {
+ classes = dixLookupPrivate(&to->devPrivates,
+ UnusedClassesPrivateKey);
+ to->stringfeed = classes->stringfeed;
+ }
+
+ s = &to->stringfeed;
+ for (it = from->stringfeed; it; it = it->next)
+ {
+ if (!(*s))
+ {
+ *s = xcalloc(1, sizeof(StringFeedbackClassRec));
+ if (!(*s))
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*s)->CtrlProc = it->CtrlProc;
+ (*s)->ctrl = it->ctrl;
+
+ s = &(*s)->next;
+ }
+ } else if (to->stringfeed && !from->stringfeed)
+ {
+ ClassesPtr classes;
+ classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+ classes->stringfeed = to->stringfeed;
+ to->stringfeed = NULL;
+ }
+
+ if (from->bell)
+ {
+ BellFeedbackPtr *b, it;
+
+ if (!to->bell)
+ {
+ classes = dixLookupPrivate(&to->devPrivates,
+ UnusedClassesPrivateKey);
+ to->bell = classes->bell;
+ }
+
+ b = &to->bell;
+ for (it = from->bell; it; it = it->next)
+ {
+ if (!(*b))
+ {
+ *b = xcalloc(1, sizeof(BellFeedbackClassRec));
+ if (!(*b))
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*b)->BellProc = it->BellProc;
+ (*b)->CtrlProc = it->CtrlProc;
+ (*b)->ctrl = it->ctrl;
+
+ b = &(*b)->next;
+ }
+ } else if (to->bell && !from->bell)
+ {
+ ClassesPtr classes;
+ classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+ classes->bell = to->bell;
+ to->bell = NULL;
+ }
+
+ if (from->leds)
+ {
+ LedFeedbackPtr *l, it;
+
+ if (!to->leds)
+ {
+ classes = dixLookupPrivate(&to->devPrivates,
+ UnusedClassesPrivateKey);
+ to->leds = classes->leds;
+ }
+
+ l = &to->leds;
+ for (it = from->leds; it; it = it->next)
+ {
+ if (!(*l))
+ {
+ *l = xcalloc(1, sizeof(LedFeedbackClassRec));
+ if (!(*l))
+ {
+ ErrorF("[Xi] Cannot alloc memory for class copy.");
+ return;
+ }
+ }
+ (*l)->CtrlProc = it->CtrlProc;
+ (*l)->ctrl = it->ctrl;
+#ifdef XKB
+ if ((*l)->xkb_sli)
+ XkbFreeSrvLedInfo((*l)->xkb_sli);
+ (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
+#endif
+
+ l = &(*l)->next;
+ }
+ } else if (to->leds && !from->leds)
+ {
+ ClassesPtr classes;
+ classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+ classes->leds = to->leds;
+ to->leds = NULL;
+ }
+}
+
+/**
+ * Copies the CONTENT of the classes of device from into the classes in device
+ * to. From and to are identical after finishing.
+ *
+ * If to does not have classes from currenly has, the classes are stored in
+ * to's devPrivates system. Later, we recover it again from there if needed.
+ * Saves a few memory allocations.
+ */
+
+void
+DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+ ClassesPtr classes;
+
+ /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
+ * kbdfeed to be set up properly, so let's do the feedback classes first.
+ */
+ DeepCopyFeedbackClasses(from, to);
+
+ if (from->key)
+ {
+ KeyCode *oldModKeyMap;
+ KeySym *oldMap;
+#ifdef XKB
+ struct _XkbSrvInfo *oldXkbInfo;
+#endif
+ if (!to->key)
+ {
+ classes = dixLookupPrivate(&to->devPrivates,
+ UnusedClassesPrivateKey);
+ to->key = classes->key;
+ if (!to->key)
+ {
+ to->key = xcalloc(1, sizeof(KeyClassRec));
+ if (!to->key)
+ FatalError("[Xi] no memory for class shift.\n");
+ } else
+ classes->key = NULL;
+ }
+
+ oldModKeyMap = to->key->modifierKeyMap;
+ oldMap = to->key->curKeySyms.map;
+#ifdef XKB
+ oldXkbInfo = to->key->xkbInfo;
+#endif
+
+ if (!oldMap) /* newly created key struct */
+ {
+ int bytes = (to->key->curKeySyms.maxKeyCode -
+ to->key->curKeySyms.minKeyCode + 1) *
+ to->key->curKeySyms.mapWidth;
+ oldMap = (KeySym *)xcalloc(sizeof(KeySym), bytes);
+ memcpy(oldMap, from->key->curKeySyms.map, bytes);
+ }
+
+ to->key->modifierKeyMap = oldModKeyMap;
+ to->key->curKeySyms.map = oldMap;
+#ifdef XKB
+ to->key->xkbInfo = oldXkbInfo;
+#endif
+
+ CopyKeyClass(from, to);
+ } else if (to->key && !from->key)
+ {
+ ClassesPtr classes;
+ classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+ classes->key = to->key;
+ to->key = NULL;
+ }
+
+ if (from->valuator)
+ {
+ ValuatorClassPtr v;
+ if (!to->valuator)
+ {
+ classes = dixLookupPrivate(&to->devPrivates,
+ UnusedClassesPrivateKey);
+ to->valuator = classes->valuator;
+ if (to->valuator)
+ classes->valuator = NULL;
+ }
+
+ to->valuator = xrealloc(to->valuator, sizeof(ValuatorClassRec) +
+ from->valuator->numAxes * sizeof(AxisInfo) +
+ from->valuator->numAxes * sizeof(unsigned int));
+ v = to->valuator;
+ if (!v)
+ FatalError("[Xi] no memory for class shift.\n");
+
+ v->numAxes = from->valuator->numAxes;
+ v->axes = (AxisInfoPtr)&v[1];
+ memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
+
+ v->axisVal = (int*)(v->axes + from->valuator->numAxes);
+ } else if (to->valuator && !from->valuator)
+ {
+ ClassesPtr classes;
+ classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+ classes->valuator = to->valuator;
+ to->valuator = NULL;
+ }
+
+ if (from->button)
+ {
+ if (!to->button)
+ {
+ classes = dixLookupPrivate(&to->devPrivates,
+ UnusedClassesPrivateKey);
+ to->button = classes->button;
+ if (!to->button)
+ {
+ to->button = xcalloc(1, sizeof(ButtonClassRec));
+ if (!to->button)
+ FatalError("[Xi] no memory for class shift.\n");
+ } else
+ classes->button = NULL;
+ }
+
+#ifdef XKB
+ if (from->button->xkb_acts)
+ {
+ if (!to->button->xkb_acts)
+ {
+ to->button->xkb_acts = xcalloc(1, sizeof(XkbAction));
+ if (!to->button->xkb_acts)
+ FatalError("[Xi] not enough memory for xkb_acts.\n");
+ }
+ memcpy(to->button->xkb_acts, from->button->xkb_acts,
+ sizeof(XkbAction));
+ } else
+ xfree(to->button->xkb_acts);
+#endif
+ } else if (to->button && !from->button)
+ {
+ ClassesPtr classes;
+ classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+ classes->button = to->button;
+ to->button = NULL;
+ }
+
+
+ /* We can't just copy over the focus class. When an app sets the focus,
+ * it'll do so on the master device. Copying the SDs focus means losing
+ * the focus.
+ * So we only copy the focus class if the device didn't have one,
+ * otherwise we leave it as it is.
+ */
+ if (from->focus)
+ {
+ if (!to->focus)
+ {
+ WindowPtr *oldTrace;
+
+ classes = dixLookupPrivate(&to->devPrivates,
+ UnusedClassesPrivateKey);
+ to->focus = classes->focus;
+ if (!to->focus)
+ {
+ to->focus = xcalloc(1, sizeof(FocusClassRec));
+ if (!to->focus)
+ FatalError("[Xi] no memory for class shift.\n");
+ } else
+ classes->focus = NULL;
+
+ oldTrace = to->focus->trace;
+ memcpy(to->focus, from->focus, sizeof(FocusClassRec));
+ to->focus->trace = xrealloc(oldTrace,
+ to->focus->traceSize * sizeof(WindowPtr));
+ if (!to->focus->trace && to->focus->traceSize)
+ FatalError("[Xi] no memory for trace.\n");
+ memcpy(to->focus->trace, from->focus->trace,
+ from->focus->traceSize * sizeof(WindowPtr));
+ }
+ } else if (to->focus)
+ {
+ ClassesPtr classes;
+ classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+ classes->focus = to->focus;
+ to->focus = NULL;
+ }
+
+ if (from->proximity)
+ {
+ if (!to->proximity)
+ {
+ classes = dixLookupPrivate(&to->devPrivates,
+ UnusedClassesPrivateKey);
+ to->proximity = classes->proximity;
+ if (!to->proximity)
+ {
+ to->proximity = xcalloc(1, sizeof(ProximityClassRec));
+ if (!to->proximity)
+ FatalError("[Xi] no memory for class shift.\n");
+ } else
+ classes->proximity = NULL;
+ }
+ memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
+ } else if (to->proximity)
+ {
+ ClassesPtr classes;
+ classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+ classes->proximity = to->proximity;
+ to->proximity = NULL;
+ }
+
+ if (from->absolute)
+ {
+ if (!to->absolute)
+ {
+ classes = dixLookupPrivate(&to->devPrivates,
+ UnusedClassesPrivateKey);
+ to->absolute = classes->absolute;
+ if (!to->absolute)
+ {
+ to->absolute = xcalloc(1, sizeof(AbsoluteClassRec));
+ if (!to->absolute)
+ FatalError("[Xi] no memory for class shift.\n");
+ } else
+ classes->absolute = NULL;
+ }
+ memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
+ } else if (to->absolute)
+ {
+ ClassesPtr classes;
+ classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+ classes->absolute = to->absolute;
+ to->absolute = NULL;
+ }
+}
+
+
+/**
+ * Update the device state according to the data in the event.
+ *
+ * return values are
+ * DEFAULT ... process as normal
+ * DONT_PROCESS ... return immediately from caller
+ * IS_REPEAT .. event is a repeat event.
+ */
+#define DEFAULT 0
+#define DONT_PROCESS 1
+#define IS_REPEAT 2
+int
+UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
+{
+ int i;
+ int key = 0,
+ bit = 0;
+
+ KeyClassPtr k = NULL;
+ ButtonClassPtr b = NULL;
+ ValuatorClassPtr v = NULL;
+ deviceValuator *xV = (deviceValuator *) xE;
+ BYTE *kptr = NULL;
+ CARD16 modifiers = 0,
+ mask = 0;
+
+ /* currently no other generic event modifies the device */
+ if (xE->u.u.type == GenericEvent)
+ return DEFAULT;
+
+ k = device->key;
+ v = device->valuator;
+ b = device->button;
+
+
+ if (xE->u.u.type != DeviceValuator)
+ {
+ key = xE->u.u.detail;
+ bit = 1 << (key & 7);
+ }
+
+ /* Update device axis */
+ /* Don't update valuators for the VCP, it never sends XI events anyway */
+ for (i = 1; !device->isMaster && i < count; i++) {
if ((++xV)->type == DeviceValuator) {
- int first = xV->first_valuator;
int *axisvals;
+ int first = xV->first_valuator;
+ BOOL change = FALSE;
- if (xV->num_valuators
- && (!v
- || (xV->num_valuators
- && (first + xV->num_valuators > v->numAxes))))
+
+ if (xV->num_valuators &&
+ (!v || (xV->num_valuators &&
+ (first + xV->num_valuators > v->numAxes))))
FatalError("Bad valuators reported for device %s\n",
- other->name);
- xV->device_state = 0;
- if (k)
- xV->device_state |= k->state;
- if (b)
- xV->device_state |= b->state;
+ device->name);
if (v && v->axisVal) {
- axisvals = v->axisVal;
- switch (xV->num_valuators) {
- case 6:
- *(axisvals + first + 5) = xV->valuator5;
- case 5:
- *(axisvals + first + 4) = xV->valuator4;
- case 4:
- *(axisvals + first + 3) = xV->valuator3;
- case 3:
- *(axisvals + first + 2) = xV->valuator2;
- case 2:
- *(axisvals + first + 1) = xV->valuator1;
- case 1:
- *(axisvals + first) = xV->valuator0;
- case 0:
- default:
- break;
- }
+ /* v->axisVal is always in absolute coordinates. Only the
+ * delivery mode changes.
+ * If device is mode Absolute
+ * dev = event
+ * If device is mode Relative
+ * swap = (event - device)
+ * dev = event
+ * event = delta
+ */
+ int delta;
+ axisvals = v->axisVal;
+ if (v->mode == Relative) /* device reports relative */
+ change = TRUE;
+
+ switch (xV->num_valuators) {
+ case 6:
+ if (change) delta = xV->valuator5 - *(axisvals + first + 5);
+ *(axisvals + first + 5) = xV->valuator5;
+ if (change) xV->valuator5 = delta;
+ case 5:
+ if (change) delta = xV->valuator4 - *(axisvals + first + 4);
+ *(axisvals + first + 4) = xV->valuator4;
+ if (change) xV->valuator4 = delta;
+ case 4:
+ if (change) delta = xV->valuator3 - *(axisvals + first + 3);
+ *(axisvals + first + 3) = xV->valuator3;
+ if (change) xV->valuator3 = delta;
+ case 3:
+ if (change) delta = xV->valuator2 - *(axisvals + first + 2);
+ *(axisvals + first + 2) = xV->valuator2;
+ if (change) xV->valuator2 = delta;
+ case 2:
+ if (change) delta = xV->valuator1 - *(axisvals + first + 1);
+ *(axisvals + first + 1) = xV->valuator1;
+ if (change) xV->valuator1 = delta;
+ case 1:
+ if (change) delta = xV->valuator0 - *(axisvals + first);
+ *(axisvals + first) = xV->valuator0;
+ if (change) xV->valuator0 = delta;
+ case 0:
+ default:
+ break;
+ }
}
}
+ }
if (xE->u.u.type == DeviceKeyPress) {
if (!k)
- return;
+ return DONT_PROCESS;
modifiers = k->modifierMap[key];
kptr = &k->down[key >> 3];
if (*kptr & bit) { /* allow ddx to generate multiple downs */
- if (!modifiers) {
- xE->u.u.type = DeviceKeyRelease;
- ProcessOtherEvent(xE, other, count);
- xE->u.u.type = DeviceKeyPress;
- /* release can have side effects, don't fall through */
- ProcessOtherEvent(xE, other, count);
- }
- return;
+ return IS_REPEAT;
}
- if (other->valuator)
- other->valuator->motionHintWindow = NullWindow;
+ if (device->valuator)
+ device->valuator->motionHintWindow = NullWindow;
*kptr |= bit;
k->prev_state = k->state;
for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
@@ -205,20 +863,16 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
modifiers &= ~mask;
}
}
- if (!grab && CheckDeviceGrabs(other, xE, 0, count)) {
- other->activatingKey = key;
- return;
- }
} else if (xE->u.u.type == DeviceKeyRelease) {
if (!k)
- return;
+ return DONT_PROCESS;
kptr = &k->down[key >> 3];
if (!(*kptr & bit)) /* guard against duplicates */
- return;
+ return DONT_PROCESS;
modifiers = k->modifierMap[key];
- if (other->valuator)
- other->valuator->motionHintWindow = NullWindow;
+ if (device->valuator)
+ device->valuator->motionHintWindow = NullWindow;
*kptr &= ~bit;
k->prev_state = k->state;
for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
@@ -231,64 +885,205 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
modifiers &= ~mask;
}
}
-
- if (other->fromPassiveGrab && (key == other->activatingKey))
- deactivateDeviceGrab = TRUE;
} else if (xE->u.u.type == DeviceButtonPress) {
if (!b)
- return;
-
- kptr = &b->down[key >> 3];
- *kptr |= bit;
- if (other->valuator)
- other->valuator->motionHintWindow = NullWindow;
- b->buttonsDown++;
+ return DONT_PROCESS;
+
+ kptr = &b->down[key >> 3];
+ if ((*kptr & bit) != 0)
+ return DONT_PROCESS;
+ *kptr |= bit;
+ if (device->valuator)
+ device->valuator->motionHintWindow = NullWindow;
+ if (!b->map[key])
+ return DONT_PROCESS;
+ b->buttonsDown++;
b->motionMask = DeviceButtonMotionMask;
- xE->u.u.detail = key;
- if (xE->u.u.detail == 0)
- return;
- if (xE->u.u.detail <= 5)
- b->state |= (Button1Mask >> 1) << xE->u.u.detail;
- SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
- if (!grab)
- if (CheckDeviceGrabs(other, xE, 0, count))
- /* if a passive grab was activated, the event has been sent
- * already */
- return;
-
+ if (b->map[key] <= 5)
+ b->state |= (Button1Mask >> 1) << b->map[key];
+ SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify);
} else if (xE->u.u.type == DeviceButtonRelease) {
if (!b)
- return;
-
- kptr = &b->down[key >> 3];
- *kptr &= ~bit;
- if (other->valuator)
- other->valuator->motionHintWindow = NullWindow;
+ return DONT_PROCESS;
+
+ kptr = &b->down[key>>3];
+ if (!(*kptr & bit))
+ return DONT_PROCESS;
+ if (device->isMaster) {
+ DeviceIntPtr sd;
+
+ /*
+ * Leave the button down if any slave has the
+ * button still down. Note that this depends on the
+ * event being delivered through the slave first
+ */
+ for (sd = inputInfo.devices; sd; sd = sd->next) {
+ if (sd->isMaster || sd->u.master != device)
+ continue;
+ if ((sd->button->down[key>>3] & bit) != 0)
+ return DONT_PROCESS;
+ }
+ }
+ *kptr &= ~bit;
+ if (device->valuator)
+ device->valuator->motionHintWindow = NullWindow;
+ if (!b->map[key])
+ return DONT_PROCESS;
if (b->buttonsDown >= 1 && !--b->buttonsDown)
b->motionMask = 0;
- xE->u.u.detail = key;
- if (xE->u.u.detail == 0)
- return;
- if (xE->u.u.detail <= 5)
- b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
- SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
- if (!b->state && other->fromPassiveGrab)
- deactivateDeviceGrab = TRUE;
+ if (b->map[key] <= 5)
+ b->state &= ~((Button1Mask >> 1) << b->map[key]);
+ SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify);
} else if (xE->u.u.type == ProximityIn)
- other->valuator->mode &= ~OutOfProximity;
+ device->valuator->mode &= ~OutOfProximity;
else if (xE->u.u.type == ProximityOut)
- other->valuator->mode |= OutOfProximity;
+ device->valuator->mode |= OutOfProximity;
+
+ return DEFAULT;
+}
+
+/**
+ * Main device event processing function.
+ * Called from when processing the events from the event queue.
+ *
+ */
+void
+ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
+{
+ int i;
+ CARD16 modifiers;
+ GrabPtr grab = device->deviceGrab.grab;
+ Bool deactivateDeviceGrab = FALSE;
+ int key = 0, rootX, rootY;
+ ButtonClassPtr b;
+ KeyClassPtr k;
+ ValuatorClassPtr v;
+ deviceValuator *xV = (deviceValuator *) xE;
+ int ret = 0;
+ int state;
+ DeviceIntPtr mouse = NULL, kbd = NULL;
+
+ if (IsPointerDevice(device))
+ {
+ kbd = GetPairedDevice(device);
+ mouse = device;
+ if (!kbd->key) /* can happen with floating SDs */
+ kbd = NULL;
+ } else
+ {
+ mouse = GetPairedDevice(device);
+ kbd = device;
+ if (!mouse->valuator || !mouse->button) /* may be float. SDs */
+ mouse = NULL;
+ }
+
+ /* State needs to be assembled BEFORE the device is updated. */
+ state = (kbd) ? kbd->key->state : 0;
+ state |= (mouse) ? (mouse->button->state) : 0;
+
+ ret = UpdateDeviceState(device, xE, count);
+ if (ret == DONT_PROCESS)
+ return;
+
+ v = device->valuator;
+ b = device->button;
+ k = device->key;
+
+ if (device->isMaster)
+ CheckMotion(xE, device);
+
+ if (xE->u.u.type != DeviceValuator && xE->u.u.type != GenericEvent) {
+ GetSpritePosition(device, &rootX, &rootY);
+ xE->u.keyButtonPointer.rootX = rootX;
+ xE->u.keyButtonPointer.rootY = rootY;
+ NoticeEventTime(xE);
+
+ xE->u.keyButtonPointer.state = state;
+
+ key = xE->u.u.detail;
+ }
+ if (DeviceEventCallback) {
+ DeviceEventInfoRec eventinfo;
+
+ eventinfo.events = (xEventPtr) xE;
+ eventinfo.count = count;
+ CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
+ }
+
+ /* Valuator event handling */
+ /* Don't care about valuators for the VCP, it never sends XI events */
+
+ for (i = 1; !device->isMaster && i < count; i++) {
+ if ((++xV)->type == DeviceValuator) {
+ int first = xV->first_valuator;
+ if (xV->num_valuators
+ && (!v
+ || (xV->num_valuators
+ && (first + xV->num_valuators > v->numAxes))))
+ FatalError("Bad valuators reported for device %s\n",
+ device->name);
+ xV->device_state = 0;
+ if (k)
+ xV->device_state |= k->state;
+ if (b)
+ xV->device_state |= b->state;
+ }
+ }
+
+ if (xE->u.u.type == DeviceKeyPress) {
+ if (ret == IS_REPEAT) { /* allow ddx to generate multiple downs */
+ modifiers = k->modifierMap[key];
+ if (!modifiers) {
+ xE->u.u.type = DeviceKeyRelease;
+ ProcessOtherEvent(xE, device, count);
+ xE->u.u.type = DeviceKeyPress;
+ /* release can have side effects, don't fall through */
+ ProcessOtherEvent(xE, device, count);
+ }
+ return;
+ }
+ if (!grab && CheckDeviceGrabs(device, xE, 0, count)) {
+ device->deviceGrab.activatingKey = key;
+ return;
+ }
+ } else if (xE->u.u.type == DeviceKeyRelease) {
+ if (device->deviceGrab.fromPassiveGrab &&
+ (key == device->deviceGrab.activatingKey))
+ deactivateDeviceGrab = TRUE;
+ } else if (xE->u.u.type == DeviceButtonPress) {
+ xE->u.u.detail = b->map[key];
+ if (xE->u.u.detail == 0) {
+ xE->u.u.detail = key;
+ return;
+ }
+ if (!grab && CheckDeviceGrabs(device, xE, 0, count))
+ {
+ /* if a passive grab was activated, the event has been sent
+ * already */
+ return;
+ }
+
+ } else if (xE->u.u.type == DeviceButtonRelease) {
+ xE->u.u.detail = b->map[key];
+ if (xE->u.u.detail == 0) {
+ xE->u.u.detail = key;
+ return;
+ }
+ if (!b->buttonsDown && device->deviceGrab.fromPassiveGrab)
+ deactivateDeviceGrab = TRUE;
+ }
if (grab)
- DeliverGrabbedEvent(xE, other, deactivateDeviceGrab, count);
- else if (other->focus)
- DeliverFocusedEvent(other, xE, GetSpriteWindow(), count);
+ DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count);
+ else if (device->focus && !IsPointerEvent(xE))
+ DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count);
else
- DeliverDeviceEvents(GetSpriteWindow(), xE, NullGrab, NullWindow,
- other, count);
+ DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow,
+ device, count);
if (deactivateDeviceGrab == TRUE)
- (*other->DeactivateGrab) (other);
+ (*device->deviceGrab.DeactivateGrab) (device);
+ xE->u.u.detail = key;
}
_X_EXPORT int
@@ -303,13 +1098,22 @@ InitProximityClassDeviceStruct(DeviceIntPtr dev)
return TRUE;
}
+/**
+ * Initialise the device's valuators. The memory must already be allocated,
+ * this function merely inits the matching axis (specified through axnum) to
+ * sane values.
+ *
+ * It is a condition that (minval < maxval).
+ *
+ * @see InitValuatorClassDeviceStruct
+ */
_X_EXPORT void
InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval,
int resolution, int min_res, int max_res)
{
AxisInfoPtr ax;
-
- if (!dev || !dev->valuator)
+
+ if (!dev || !dev->valuator || minval > maxval)
return;
ax = dev->valuator->axes + axnum;
@@ -336,7 +1140,7 @@ FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
if (b) {
ev->classes_reported |= (1 << ButtonClass);
ev->num_buttons = b->numButtons;
- memmove((char *)&ev->buttons[0], (char *)b->down, 4);
+ memcpy((char*)ev->buttons, (char*)b->down, 4);
} else if (k) {
ev->classes_reported |= (1 << KeyClass);
ev->num_keys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode;
@@ -400,7 +1204,7 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
event.window = pWin->drawable.id;
event.time = currentTime.milliseconds;
- (void)DeliverEventsToWindow(pWin, (xEvent *) & event, 1,
+ (void)DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
DeviceFocusChangeMask, NullGrab, dev->id);
if ((type == DeviceFocusIn) &&
@@ -455,7 +1259,7 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
bev = (deviceButtonStateNotify *) ev++;
bev->type = DeviceButtonStateNotify;
bev->deviceid = dev->id;
- memmove((char *)&bev->buttons[0], (char *)&b->down[4], 28);
+ memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
}
if (nval > 0) {
(ev - 1)->deviceid |= MORE_EVENTS;
@@ -496,7 +1300,7 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
}
}
- (void)DeliverEventsToWindow(pWin, (xEvent *) sev, evcount,
+ (void)DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
DeviceStateNotifyMask, NullGrab, dev->id);
xfree(sev);
}
@@ -679,7 +1483,7 @@ SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
if (dev->valuator)
if ((dev->valuator->motionHintWindow == pWin) &&
(mask & DevicePointerMotionHintMask) &&
- !(check & DevicePointerMotionHintMask) && !dev->grab)
+ !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
dev->valuator->motionHintWindow = NullWindow;
RecalculateDeviceDeliverableEvents(pWin);
return Success;
@@ -692,12 +1496,11 @@ AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
if (!pWin->optional && !MakeWindowOptional(pWin))
return BadAlloc;
- others = (InputClients *) xalloc(sizeof(InputClients));
+ others = xcalloc(1, sizeof(InputClients));
if (!others)
return BadAlloc;
if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
return BadAlloc;
- bzero((char *)&others->mask[0], sizeof(Mask) * EMASKSIZE);
others->mask[mskidx] = mask;
others->resource = FakeClientID(client->index);
others->next = pWin->optional->inputMasks->inputClients;
@@ -712,11 +1515,9 @@ MakeInputMasks(WindowPtr pWin)
{
struct _OtherInputMasks *imasks;
- imasks = (struct _OtherInputMasks *)
- xalloc(sizeof(struct _OtherInputMasks));
+ imasks = xcalloc(1, sizeof(struct _OtherInputMasks));
if (!imasks)
return FALSE;
- bzero((char *)imasks, sizeof(struct _OtherInputMasks));
pWin->optional->inputMasks = imasks;
return TRUE;
}
@@ -804,7 +1605,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
{
WindowPtr pWin;
WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
- WindowPtr spriteWin = GetSpriteWindow();
+ WindowPtr spriteWin = GetSpriteWindow(d);
if (dest == PointerWindow)
pWin = spriteWin;
@@ -825,7 +1626,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
/* If the input focus is PointerRootWin, send the event to where
* the pointer is if possible, then perhaps propogate up to root. */
if (inputFocus == PointerRootWin)
- inputFocus = GetCurrentRootWindow();
+ inputFocus = GetCurrentRootWindow(d);
if (IsParent(inputFocus, spriteWin)) {
effectiveFocus = inputFocus;
@@ -843,7 +1644,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
ev->u.u.type |= 0x80;
if (propagate) {
for (; pWin; pWin = pWin->parent) {
- if (DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id))
+ if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id))
return Success;
if (pWin == effectiveFocus)
return Success;
@@ -853,7 +1654,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
break;
}
} else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
- (void)(DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id));
+ (void)(DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id));
return Success;
}
@@ -977,7 +1778,8 @@ SendDeviceMappingNotify(ClientPtr client, CARD8 request,
}
#ifdef XKB
- if (request == MappingKeyboard || request == MappingModifier)
+ if (!noXkbExtension && (request == MappingKeyboard ||
+ request == MappingModifier))
XkbApplyMappingChange(dev, request, firstKeyCode, count, client);
#endif
@@ -1029,10 +1831,10 @@ DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
* any input focus changes.
* Deactivating a device grab should cause focus events. */
- if (dev->grab && (dev->grab->window == pWin))
- (*dev->DeactivateGrab) (dev);
+ if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
+ (*dev->deviceGrab.DeactivateGrab) (dev);
- /* If the focus window is a root window (ie. has no parent)
+ /* If the focus window is a root window (ie. has no parent)
* then don't delete the focus from it. */
if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
@@ -1040,7 +1842,7 @@ DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
/* If a grab is in progress, then alter the mode of focus events. */
- if (dev->grab)
+ if (dev->deviceGrab.grab)
focusEventMode = NotifyWhileGrabbed;
switch (dev->focus->revert) {
@@ -1162,7 +1964,9 @@ CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
tempGrab.pointerMode = GrabModeAsync;
tempGrab.confineTo = NullWindow;
tempGrab.cursor = NullCursor;
- (*dev->ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
+ tempGrab.genericMasks = NULL;
+ tempGrab.next = NULL;
+ (*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
}
}
@@ -1185,7 +1989,7 @@ void
MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
{
WindowPtr pWin;
- GrabPtr grab = dev->grab;
+ GrabPtr grab = dev->deviceGrab.grab;
pWin = dev->valuator->motionHintWindow;
@@ -1226,7 +2030,7 @@ DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
return Success;
}
-static Bool
+Bool
ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
{
int i;
@@ -1259,7 +2063,7 @@ FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
while (p1) {
p2 = p1->firstChild;
- (void)DeliverEventsToWindow(p1, ev, count, mask, NullGrab, dev->id);
+ (void)DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab, dev->id);
FindInterestedChildren(dev, p2, mask, ev, count);
p1 = p1->nextSib;
}
@@ -1281,8 +2085,9 @@ SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
pWin = WindowTable[i];
if (!pWin)
continue;
- (void)DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, dev->id);
+ (void)DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab, dev->id);
p1 = pWin->firstChild;
FindInterestedChildren(dev, p1, mask, ev, count);
}
}
+
diff --git a/xorg-server/Xi/exglobals.h b/xorg-server/Xi/exglobals.h
index 50bb33fdc..42a695356 100644
--- a/xorg-server/Xi/exglobals.h
+++ b/xorg-server/Xi/exglobals.h
@@ -31,11 +31,13 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
+#include "privates.h"
#ifndef EXGLOBALS_H
#define EXGLOBALS_H 1
extern int IReqCode;
+extern int IEventBase;
extern int BadDevice;
extern int BadMode;
extern int DeviceBusy;
@@ -50,6 +52,9 @@ extern Mask DeviceOwnerGrabButtonMask;
extern Mask DeviceButtonGrabMask;
extern Mask DeviceButtonMotionMask;
extern Mask DevicePresenceNotifyMask;
+extern Mask DevicePropertyNotifyMask;
+extern Mask DeviceEnterWindowMask;
+extern Mask DeviceLeaveWindowMask;
extern Mask PropagateMask[];
extern int DeviceValuator;
@@ -68,7 +73,11 @@ extern int DeviceButtonStateNotify;
extern int DeviceMappingNotify;
extern int ChangeDeviceNotify;
extern int DevicePresenceNotify;
+extern int DevicePropertyNotify;
+extern int DeviceEnterNotify;
+extern int DeviceLeaveNotify;
extern int RT_INPUTCLIENT;
+extern DevPrivateKey XIClientPrivateKey;
#endif /* EXGLOBALS_H */
diff --git a/xorg-server/Xi/extinit.c b/xorg-server/Xi/extinit.c
index 2ffdafbc1..14eb3cbe1 100644
--- a/xorg-server/Xi/extinit.c
+++ b/xorg-server/Xi/extinit.c
@@ -63,6 +63,8 @@ SOFTWARE.
#include "extnsionst.h" /* extension entry */
#include <X11/extensions/XI.h>
#include <X11/extensions/XIproto.h>
+#include <X11/extensions/geproto.h>
+#include "geext.h" /* extension interfaces for ge */
#include "dixevents.h"
#include "exevents.h"
@@ -70,6 +72,7 @@ SOFTWARE.
#include "exglobals.h"
#include "swaprep.h"
#include "registry.h"
+#include "privates.h"
/* modules local to Xi */
#include "allowev.h"
@@ -109,6 +112,8 @@ SOFTWARE.
#include "ungrdev.h"
#include "ungrdevb.h"
#include "ungrdevk.h"
+#include "xiproperty.h"
+
static Mask lastExtEventMask = 1;
int ExtEventIndex;
@@ -143,6 +148,98 @@ static struct dev_type
CARD8 event_base[numInputClasses];
XExtEventInfo EventInfo[32];
+/**
+ * Dispatch vector. Functions defined in here will be called when the matching
+ * request arrives.
+ */
+static int (*ProcIVector[])(ClientPtr) = {
+ NULL, /* 0 */
+ ProcXGetExtensionVersion, /* 1 */
+ ProcXListInputDevices, /* 2 */
+ ProcXOpenDevice, /* 3 */
+ ProcXCloseDevice, /* 4 */
+ ProcXSetDeviceMode, /* 5 */
+ ProcXSelectExtensionEvent, /* 6 */
+ ProcXGetSelectedExtensionEvents, /* 7 */
+ ProcXChangeDeviceDontPropagateList, /* 8 */
+ ProcXGetDeviceDontPropagateList, /* 9 */
+ ProcXGetDeviceMotionEvents, /* 10 */
+ ProcXChangeKeyboardDevice, /* 11 */
+ ProcXChangePointerDevice, /* 12 */
+ ProcXGrabDevice, /* 13 */
+ ProcXUngrabDevice, /* 14 */
+ ProcXGrabDeviceKey, /* 15 */
+ ProcXUngrabDeviceKey, /* 16 */
+ ProcXGrabDeviceButton, /* 17 */
+ ProcXUngrabDeviceButton, /* 18 */
+ ProcXAllowDeviceEvents, /* 19 */
+ ProcXGetDeviceFocus, /* 20 */
+ ProcXSetDeviceFocus, /* 21 */
+ ProcXGetFeedbackControl, /* 22 */
+ ProcXChangeFeedbackControl, /* 23 */
+ ProcXGetDeviceKeyMapping, /* 24 */
+ ProcXChangeDeviceKeyMapping, /* 25 */
+ ProcXGetDeviceModifierMapping, /* 26 */
+ ProcXSetDeviceModifierMapping, /* 27 */
+ ProcXGetDeviceButtonMapping, /* 28 */
+ ProcXSetDeviceButtonMapping, /* 29 */
+ ProcXQueryDeviceState, /* 30 */
+ ProcXSendExtensionEvent, /* 31 */
+ ProcXDeviceBell, /* 32 */
+ ProcXSetDeviceValuators, /* 33 */
+ ProcXGetDeviceControl, /* 34 */
+ ProcXChangeDeviceControl, /* 35 */
+ /* XI 1.5 */
+ ProcXListDeviceProperties, /* 36 */
+ ProcXChangeDeviceProperty, /* 37 */
+ ProcXDeleteDeviceProperty, /* 38 */
+ ProcXGetDeviceProperty /* 39 */
+};
+
+/* For swapped clients */
+static int (*SProcIVector[])(ClientPtr) = {
+ NULL, /* 0 */
+ SProcXGetExtensionVersion, /* 1 */
+ SProcXListInputDevices, /* 2 */
+ SProcXOpenDevice, /* 3 */
+ SProcXCloseDevice, /* 4 */
+ SProcXSetDeviceMode, /* 5 */
+ SProcXSelectExtensionEvent, /* 6 */
+ SProcXGetSelectedExtensionEvents, /* 7 */
+ SProcXChangeDeviceDontPropagateList, /* 8 */
+ SProcXGetDeviceDontPropagateList, /* 9 */
+ SProcXGetDeviceMotionEvents, /* 10 */
+ SProcXChangeKeyboardDevice, /* 11 */
+ SProcXChangePointerDevice, /* 12 */
+ SProcXGrabDevice, /* 13 */
+ SProcXUngrabDevice, /* 14 */
+ SProcXGrabDeviceKey, /* 15 */
+ SProcXUngrabDeviceKey, /* 16 */
+ SProcXGrabDeviceButton, /* 17 */
+ SProcXUngrabDeviceButton, /* 18 */
+ SProcXAllowDeviceEvents, /* 19 */
+ SProcXGetDeviceFocus, /* 20 */
+ SProcXSetDeviceFocus, /* 21 */
+ SProcXGetFeedbackControl, /* 22 */
+ SProcXChangeFeedbackControl, /* 23 */
+ SProcXGetDeviceKeyMapping, /* 24 */
+ SProcXChangeDeviceKeyMapping, /* 25 */
+ SProcXGetDeviceModifierMapping, /* 26 */
+ SProcXSetDeviceModifierMapping, /* 27 */
+ SProcXGetDeviceButtonMapping, /* 28 */
+ SProcXSetDeviceButtonMapping, /* 29 */
+ SProcXQueryDeviceState, /* 30 */
+ SProcXSendExtensionEvent, /* 31 */
+ SProcXDeviceBell, /* 32 */
+ SProcXSetDeviceValuators, /* 33 */
+ SProcXGetDeviceControl, /* 34 */
+ SProcXChangeDeviceControl, /* 35 */
+ SProcXListDeviceProperties, /* 36 */
+ SProcXChangeDeviceProperty, /* 37 */
+ SProcXDeleteDeviceProperty, /* 38 */
+ SProcXGetDeviceProperty /* 39 */
+};
+
/*****************************************************************
*
* Globals referenced elsewhere in the server.
@@ -150,6 +247,7 @@ XExtEventInfo EventInfo[32];
*/
int IReqCode = 0;
+int IEventBase = 0;
int BadDevice = 0;
static int BadEvent = 1;
int BadMode = 2;
@@ -166,6 +264,7 @@ Mask DeviceOwnerGrabButtonMask;
Mask DeviceButtonGrabMask;
Mask DeviceButtonMotionMask;
Mask DevicePresenceNotifyMask;
+Mask DevicePropertyNotifyMask;
int DeviceValuator;
int DeviceKeyPress;
@@ -183,6 +282,7 @@ int DeviceButtonStateNotify;
int DeviceMappingNotify;
int ChangeDeviceNotify;
int DevicePresenceNotify;
+int DevicePropertyNotify;
int RT_INPUTCLIENT;
@@ -194,19 +294,44 @@ int RT_INPUTCLIENT;
extern XExtensionVersion AllExtensionVersions[];
-Mask PropagateMask[MAX_DEVICES];
+
+Mask PropagateMask[MAXDEVICES];
/*****************************************************************
*
- * Declarations of local routines.
+ * Versioning support
*
*/
+static int XIClientPrivateKeyIndex;
+DevPrivateKey XIClientPrivateKey = &XIClientPrivateKeyIndex;
+
static XExtensionVersion thisversion = { XI_Present,
- XI_Add_DevicePresenceNotify_Major,
- XI_Add_DevicePresenceNotify_Minor
+ XI_Add_DeviceProperties_Major,
+ XI_Add_DeviceProperties_Minor
};
+
+/*****************************************************************
+ *
+ * Declarations of local routines.
+ *
+ */
+
+static void
+XIClientCallback(CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec*)data;
+ ClientPtr pClient = clientinfo->client;
+ XIClientPtr pXIClient;
+
+ pXIClient = dixLookupPrivate(&pClient->devPrivates, XIClientPrivateKey);
+ pXIClient->major_version = 0;
+ pXIClient->minor_version = 0;
+}
+
/*************************************************************************
*
* ProcIDispatch - main dispatch routine for requests to this extension.
@@ -218,83 +343,15 @@ static int
ProcIDispatch(ClientPtr client)
{
REQUEST(xReq);
- if (stuff->data == X_GetExtensionVersion)
- return (ProcXGetExtensionVersion(client));
- if (stuff->data == X_ListInputDevices)
- return (ProcXListInputDevices(client));
- else if (stuff->data == X_OpenDevice)
- return (ProcXOpenDevice(client));
- else if (stuff->data == X_CloseDevice)
- return (ProcXCloseDevice(client));
- else if (stuff->data == X_SetDeviceMode)
- return (ProcXSetDeviceMode(client));
- else if (stuff->data == X_SelectExtensionEvent)
- return (ProcXSelectExtensionEvent(client));
- else if (stuff->data == X_GetSelectedExtensionEvents)
- return (ProcXGetSelectedExtensionEvents(client));
- else if (stuff->data == X_ChangeDeviceDontPropagateList)
- return (ProcXChangeDeviceDontPropagateList(client));
- else if (stuff->data == X_GetDeviceDontPropagateList)
- return (ProcXGetDeviceDontPropagateList(client));
- else if (stuff->data == X_GetDeviceMotionEvents)
- return (ProcXGetDeviceMotionEvents(client));
- else if (stuff->data == X_ChangeKeyboardDevice)
- return (ProcXChangeKeyboardDevice(client));
- else if (stuff->data == X_ChangePointerDevice)
- return (ProcXChangePointerDevice(client));
- else if (stuff->data == X_GrabDevice)
- return (ProcXGrabDevice(client));
- else if (stuff->data == X_UngrabDevice)
- return (ProcXUngrabDevice(client));
- else if (stuff->data == X_GrabDeviceKey)
- return (ProcXGrabDeviceKey(client));
- else if (stuff->data == X_UngrabDeviceKey)
- return (ProcXUngrabDeviceKey(client));
- else if (stuff->data == X_GrabDeviceButton)
- return (ProcXGrabDeviceButton(client));
- else if (stuff->data == X_UngrabDeviceButton)
- return (ProcXUngrabDeviceButton(client));
- else if (stuff->data == X_AllowDeviceEvents)
- return (ProcXAllowDeviceEvents(client));
- else if (stuff->data == X_GetDeviceFocus)
- return (ProcXGetDeviceFocus(client));
- else if (stuff->data == X_SetDeviceFocus)
- return (ProcXSetDeviceFocus(client));
- else if (stuff->data == X_GetFeedbackControl)
- return (ProcXGetFeedbackControl(client));
- else if (stuff->data == X_ChangeFeedbackControl)
- return (ProcXChangeFeedbackControl(client));
- else if (stuff->data == X_GetDeviceKeyMapping)
- return (ProcXGetDeviceKeyMapping(client));
- else if (stuff->data == X_ChangeDeviceKeyMapping)
- return (ProcXChangeDeviceKeyMapping(client));
- else if (stuff->data == X_GetDeviceModifierMapping)
- return (ProcXGetDeviceModifierMapping(client));
- else if (stuff->data == X_SetDeviceModifierMapping)
- return (ProcXSetDeviceModifierMapping(client));
- else if (stuff->data == X_GetDeviceButtonMapping)
- return (ProcXGetDeviceButtonMapping(client));
- else if (stuff->data == X_SetDeviceButtonMapping)
- return (ProcXSetDeviceButtonMapping(client));
- else if (stuff->data == X_QueryDeviceState)
- return (ProcXQueryDeviceState(client));
- else if (stuff->data == X_SendExtensionEvent)
- return (ProcXSendExtensionEvent(client));
- else if (stuff->data == X_DeviceBell)
- return (ProcXDeviceBell(client));
- else if (stuff->data == X_SetDeviceValuators)
- return (ProcXSetDeviceValuators(client));
- else if (stuff->data == X_GetDeviceControl)
- return (ProcXGetDeviceControl(client));
- else if (stuff->data == X_ChangeDeviceControl)
- return (ProcXChangeDeviceControl(client));
-
- return (BadRequest);
+ if (stuff->data > IREQUESTS || !ProcIVector[stuff->data])
+ return BadRequest;
+
+ return (*ProcIVector[stuff->data])(client);
}
/*******************************************************************************
*
- * SProcXDispatch
+ * SProcXDispatch
*
* Main swapped dispatch routine for requests to this extension.
* This routine is used if server and client do not have the same byte ordering.
@@ -305,78 +362,10 @@ static int
SProcIDispatch(ClientPtr client)
{
REQUEST(xReq);
- if (stuff->data == X_GetExtensionVersion)
- return (SProcXGetExtensionVersion(client));
- if (stuff->data == X_ListInputDevices)
- return (SProcXListInputDevices(client));
- else if (stuff->data == X_OpenDevice)
- return (SProcXOpenDevice(client));
- else if (stuff->data == X_CloseDevice)
- return (SProcXCloseDevice(client));
- else if (stuff->data == X_SetDeviceMode)
- return (SProcXSetDeviceMode(client));
- else if (stuff->data == X_SelectExtensionEvent)
- return (SProcXSelectExtensionEvent(client));
- else if (stuff->data == X_GetSelectedExtensionEvents)
- return (SProcXGetSelectedExtensionEvents(client));
- else if (stuff->data == X_ChangeDeviceDontPropagateList)
- return (SProcXChangeDeviceDontPropagateList(client));
- else if (stuff->data == X_GetDeviceDontPropagateList)
- return (SProcXGetDeviceDontPropagateList(client));
- else if (stuff->data == X_GetDeviceMotionEvents)
- return (SProcXGetDeviceMotionEvents(client));
- else if (stuff->data == X_ChangeKeyboardDevice)
- return (SProcXChangeKeyboardDevice(client));
- else if (stuff->data == X_ChangePointerDevice)
- return (SProcXChangePointerDevice(client));
- else if (stuff->data == X_GrabDevice)
- return (SProcXGrabDevice(client));
- else if (stuff->data == X_UngrabDevice)
- return (SProcXUngrabDevice(client));
- else if (stuff->data == X_GrabDeviceKey)
- return (SProcXGrabDeviceKey(client));
- else if (stuff->data == X_UngrabDeviceKey)
- return (SProcXUngrabDeviceKey(client));
- else if (stuff->data == X_GrabDeviceButton)
- return (SProcXGrabDeviceButton(client));
- else if (stuff->data == X_UngrabDeviceButton)
- return (SProcXUngrabDeviceButton(client));
- else if (stuff->data == X_AllowDeviceEvents)
- return (SProcXAllowDeviceEvents(client));
- else if (stuff->data == X_GetDeviceFocus)
- return (SProcXGetDeviceFocus(client));
- else if (stuff->data == X_SetDeviceFocus)
- return (SProcXSetDeviceFocus(client));
- else if (stuff->data == X_GetFeedbackControl)
- return (SProcXGetFeedbackControl(client));
- else if (stuff->data == X_ChangeFeedbackControl)
- return (SProcXChangeFeedbackControl(client));
- else if (stuff->data == X_GetDeviceKeyMapping)
- return (SProcXGetDeviceKeyMapping(client));
- else if (stuff->data == X_ChangeDeviceKeyMapping)
- return (SProcXChangeDeviceKeyMapping(client));
- else if (stuff->data == X_GetDeviceModifierMapping)
- return (SProcXGetDeviceModifierMapping(client));
- else if (stuff->data == X_SetDeviceModifierMapping)
- return (SProcXSetDeviceModifierMapping(client));
- else if (stuff->data == X_GetDeviceButtonMapping)
- return (SProcXGetDeviceButtonMapping(client));
- else if (stuff->data == X_SetDeviceButtonMapping)
- return (SProcXSetDeviceButtonMapping(client));
- else if (stuff->data == X_QueryDeviceState)
- return (SProcXQueryDeviceState(client));
- else if (stuff->data == X_SendExtensionEvent)
- return (SProcXSendExtensionEvent(client));
- else if (stuff->data == X_DeviceBell)
- return (SProcXDeviceBell(client));
- else if (stuff->data == X_SetDeviceValuators)
- return (SProcXSetDeviceValuators(client));
- else if (stuff->data == X_GetDeviceControl)
- return (SProcXGetDeviceControl(client));
- else if (stuff->data == X_ChangeDeviceControl)
- return (SProcXChangeDeviceControl(client));
-
- return (BadRequest);
+ if (stuff->data > IREQUESTS || !SProcIVector[stuff->data])
+ return BadRequest;
+
+ return (*SProcIVector[stuff->data])(client);
}
/**********************************************************************
@@ -386,11 +375,6 @@ SProcIDispatch(ClientPtr client)
*
*/
-/* FIXME: this would be more concise and readable in ANSI C */
-#define DISPATCH(code) \
- if (rep->RepType == X_##code) \
- SRepX##code (client, len, (x##code##Reply *) rep)
-
static void
SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
/* All we look at is the type field */
@@ -445,6 +429,10 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
else if (rep->RepType == X_ChangeDeviceControl)
SRepXChangeDeviceControl(client, len,
(xChangeDeviceControlReply *) rep);
+ else if (rep->RepType == X_ListDeviceProperties)
+ SRepXListDeviceProperties(client, len, (xListDevicePropertiesReply*)rep);
+ else if (rep->RepType == X_GetDeviceProperty)
+ SRepXGetDeviceProperty(client, len, (xGetDevicePropertyReply *) rep);
else {
FatalError("XINPUT confused sending swapped reply");
}
@@ -550,6 +538,17 @@ SDevicePresenceNotifyEvent (devicePresenceNotify *from, devicePresenceNotify *to
swaps(&to->control, n);
}
+static void
+SDevicePropertyNotifyEvent (devicePropertyNotify *from, devicePropertyNotify *to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber,n);
+ swapl(&to->time, n);
+ swapl(&to->atom, n);
+}
+
/**************************************************************************
*
* Allow the specified event to have its propagation suppressed.
@@ -562,7 +561,7 @@ AllowPropagateSuppress(Mask mask)
{
int i;
- for (i = 0; i < MAX_DEVICES; i++)
+ for (i = 0; i < MAXDEVICES; i++)
PropagateMask[i] |= mask;
}
@@ -583,7 +582,7 @@ GetNextExtEventMask(void)
}
lastExtEventMask <<= 1;
- for (i = 0; i < MAX_DEVICES; i++)
+ for (i = 0; i < MAXDEVICES; i++)
ExtValidMasks[i] |= mask;
return mask;
}
@@ -596,7 +595,7 @@ GetNextExtEventMask(void)
*
* Since extension event types will never be less than 64, we can use
* 0-63 in the EventInfo array as the "type" to be used to look up this
- * mask. This means that the corresponding macros such as
+ * mask. This means that the corresponding macros such as
* DevicePointerMotionHint must have access to the same constants.
*
*/
@@ -621,7 +620,7 @@ SetExclusiveAccess(Mask mask)
{
int i;
- for (i = 0; i < MAX_DEVICES; i++)
+ for (i = 0; i < MAXDEVICES; i++)
ExtExclusiveMasks[i] |= mask;
}
@@ -634,13 +633,16 @@ SetExclusiveAccess(Mask mask)
static void
SetMaskForExtEvent(Mask mask, int event)
{
+ int i;
EventInfo[ExtEventIndex].mask = mask;
EventInfo[ExtEventIndex++].type = event;
if ((event < LASTEvent) || (event >= 128))
FatalError("MaskForExtensionEvent: bogus event number");
- SetMaskForEvent(mask, event);
+
+ for (i = 0; i < MAXDEVICES; i++)
+ SetMaskForEvent(i, mask, event);
}
/************************************************************************
@@ -670,6 +672,7 @@ FixExtensionEvents(ExtensionEntry * extEntry)
DeviceKeyStateNotify = ChangeDeviceNotify + 1;
DeviceButtonStateNotify = DeviceKeyStateNotify + 1;
DevicePresenceNotify = DeviceButtonStateNotify + 1;
+ DevicePropertyNotify = DevicePresenceNotify + 1;
event_base[KeyClass] = DeviceKeyPress;
event_base[ButtonClass] = DeviceButtonPress;
@@ -721,8 +724,20 @@ FixExtensionEvents(ExtensionEntry * extEntry)
SetEventInfo(GetNextExtEventMask(), _deviceButton3Motion);
SetEventInfo(GetNextExtEventMask(), _deviceButton4Motion);
SetEventInfo(GetNextExtEventMask(), _deviceButton5Motion);
+
+ /* If DeviceButtonMotionMask is != ButtonMotionMask, event delivery
+ * breaks down. The device needs the dev->button->motionMask. If DBMM is
+ * the same as BMM, we can ensure that both core and device events can be
+ * delivered, without the need for extra structures in the DeviceIntRec.
+ */
DeviceButtonMotionMask = GetNextExtEventMask();
SetEventInfo(DeviceButtonMotionMask, _deviceButtonMotion);
+ if (DeviceButtonMotionMask != ButtonMotionMask)
+ {
+ /* This should never happen, but if it does, hide under the
+ * bed and cry for help. */
+ ErrorF("[Xi] DeviceButtonMotionMask != ButtonMotionMask. Trouble!\n");
+ }
DeviceFocusChangeMask = GetNextExtEventMask();
SetMaskForExtEvent(DeviceFocusChangeMask, DeviceFocusIn);
@@ -745,12 +760,16 @@ FixExtensionEvents(ExtensionEntry * extEntry)
DevicePresenceNotifyMask = GetNextExtEventMask();
SetEventInfo(DevicePresenceNotifyMask, _devicePresence);
+
+ DevicePropertyNotifyMask = GetNextExtEventMask();
+ SetMaskForExtEvent(DevicePropertyNotifyMask, DevicePropertyNotify);
+
SetEventInfo(0, _noExtensionEvent);
}
/************************************************************************
*
- * This function restores extension event types and masks to their
+ * This function restores extension event types and masks to their
* initial state.
*
*/
@@ -758,13 +777,17 @@ FixExtensionEvents(ExtensionEntry * extEntry)
static void
RestoreExtensionEvents(void)
{
- int i;
+ int i, j;
IReqCode = 0;
+ IEventBase = 0;
for (i = 0; i < ExtEventIndex - 1; i++) {
if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128))
- SetMaskForEvent(0, EventInfo[i].type);
+ {
+ for (j = 0; j < MAXDEVICES; j++)
+ SetMaskForEvent(j, 0, EventInfo[i].type);
+ }
EventInfo[i].mask = 0;
EventInfo[i].type = 0;
}
@@ -786,6 +809,7 @@ RestoreExtensionEvents(void)
DeviceKeyStateNotify = 13;
DeviceButtonStateNotify = 13;
DevicePresenceNotify = 14;
+ DevicePropertyNotify = 15;
BadDevice = 0;
BadEvent = 1;
@@ -824,16 +848,33 @@ IResetProc(ExtensionEntry * unused)
EventSwapVector[DeviceMappingNotify] = NotImplemented;
EventSwapVector[ChangeDeviceNotify] = NotImplemented;
EventSwapVector[DevicePresenceNotify] = NotImplemented;
+ EventSwapVector[DevicePropertyNotify] = NotImplemented;
RestoreExtensionEvents();
}
+/*****************************************************************
+ *
+ * Returns TRUE if the device has some sort of pointer type.
+ *
+ */
+
+Bool
+DeviceIsPointerType(DeviceIntPtr dev)
+{
+ if (dev_type[1].type == dev->type)
+ return TRUE;
+
+ return FALSE;
+}
+
+
/***********************************************************************
*
* Assign an id and type to an input device.
*
*/
-_X_EXPORT void
+void
AssignTypeAndName(DeviceIntPtr dev, Atom type, char *name)
{
dev->type = type;
@@ -909,6 +950,8 @@ SEventIDispatch(xEvent * from, xEvent * to)
DO_SWAP(SChangeDeviceNotifyEvent, changeDeviceNotify);
else if (type == DevicePresenceNotify)
DO_SWAP(SDevicePresenceNotifyEvent, devicePresenceNotify);
+ else if (type == DevicePropertyNotify)
+ DO_SWAP(SDevicePropertyNotifyEvent, devicePropertyNotify);
else {
FatalError("XInputExtension: Impossible event!\n");
}
@@ -923,6 +966,7 @@ SEventIDispatch(xEvent * from, xEvent * to)
*
* This extension has several events and errors.
*
+ * XI is mandatory nowadays, so if we fail to init XI, we die.
*/
void
@@ -930,12 +974,20 @@ XInputExtensionInit(void)
{
ExtensionEntry *extEntry;
+ if (!dixRequestPrivate(XIClientPrivateKey, sizeof(XIClientRec)))
+ FatalError("Cannot request private for XI.\n");
+
+ if (!AddCallback(&ClientStateCallback, XIClientCallback, 0))
+ FatalError("Failed to add callback to XI.\n");
+
extEntry = AddExtension(INAME, IEVENTS, IERRORS, ProcIDispatch,
SProcIDispatch, IResetProc, StandardMinorOpcode);
if (extEntry) {
IReqCode = extEntry->base;
+ IEventBase = extEntry->eventBase;
AllExtensionVersions[IReqCode - 128] = thisversion;
MakeDeviceTypeAtoms();
+ XIInitKnownProperties();
RT_INPUTCLIENT = CreateNewResourceType((DeleteType) InputClientGone);
RegisterResourceName(RT_INPUTCLIENT, "INPUTCLIENT");
FixExtensionEvents(extEntry);
@@ -956,6 +1008,7 @@ XInputExtensionInit(void)
EventSwapVector[DeviceMappingNotify] = SEventIDispatch;
EventSwapVector[ChangeDeviceNotify] = SEventIDispatch;
EventSwapVector[DevicePresenceNotify] = SEventIDispatch;
+
} else {
FatalError("IExtensionInit: AddExtensions failed\n");
}
diff --git a/xorg-server/Xi/getvers.c b/xorg-server/Xi/getvers.c
index a4afe808f..88ff1991a 100644
--- a/xorg-server/Xi/getvers.c
+++ b/xorg-server/Xi/getvers.c
@@ -59,6 +59,7 @@ SOFTWARE.
#include "inputstr.h" /* DeviceIntPtr */
#include <X11/extensions/XI.h>
#include <X11/extensions/XIproto.h>
+#include "exevents.h"
#include "exglobals.h"
#include "getvers.h"
@@ -85,7 +86,7 @@ SProcXGetExtensionVersion(ClientPtr client)
/***********************************************************************
*
- * This procedure lists the input devices available to the server.
+ * This procedure returns the major/minor version of the X Input extension.
*
*/
@@ -93,6 +94,7 @@ int
ProcXGetExtensionVersion(ClientPtr client)
{
xGetExtensionVersionReply rep;
+ XIClientPtr pXIClient;
REQUEST(xGetExtensionVersionReq);
REQUEST_AT_LEAST_SIZE(xGetExtensionVersionReq);
@@ -101,18 +103,16 @@ ProcXGetExtensionVersion(ClientPtr client)
stuff->nbytes + 3) >> 2)
return BadLength;
+ pXIClient = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
+
rep.repType = X_Reply;
rep.RepType = X_GetExtensionVersion;
rep.length = 0;
rep.sequenceNumber = client->sequence;
- rep.major_version = 0;
- rep.minor_version = 0;
-
rep.present = TRUE;
- if (rep.present) {
- rep.major_version = AllExtensionVersions[IReqCode - 128].major_version;
- rep.minor_version = AllExtensionVersions[IReqCode - 128].minor_version;
- }
+ rep.major_version = AllExtensionVersions[IReqCode - 128].major_version;
+ rep.minor_version = AllExtensionVersions[IReqCode - 128].minor_version;
+
WriteReplyToClient(client, sizeof(xGetExtensionVersionReply), &rep);
return Success;
diff --git a/xorg-server/Xi/grabdev.c b/xorg-server/Xi/grabdev.c
index 0671e0ea7..8217a9928 100644
--- a/xorg-server/Xi/grabdev.c
+++ b/xorg-server/Xi/grabdev.c
@@ -131,7 +131,7 @@ ProcXGrabDevice(ClientPtr client)
rc = GrabDevice(client, dev, stuff->this_device_mode,
stuff->other_devices_mode, stuff->grabWindow,
stuff->ownerEvents, stuff->time,
- tmp[stuff->deviceid].mask, &rep.status);
+ tmp[stuff->deviceid].mask, &rep.status, FALSE);
if (rc != Success)
return rc;
@@ -144,6 +144,24 @@ ProcXGrabDevice(ClientPtr client)
*
* This procedure creates an event mask from a list of XEventClasses.
*
+ * Procedure is as follows:
+ * An XEventClass is (deviceid << 8 | eventtype). For each entry in the list,
+ * get the device. Then run through all available event indices (those are
+ * set when XI starts up) and binary OR's the device's mask to whatever the
+ * event mask for the given event type was.
+ * If an error occurs, it is sent to the client. Errors are generated if
+ * - if the device given in the event classs is invalid
+ * - if the device in the class list is not the device given as parameter (no
+ * error if parameter is NULL)
+ *
+ * mask has to be size EMASKSIZE and pre-allocated.
+ *
+ * @param client The client to send the error to (if one occurs)
+ * @param list List of event classes as sent from the client.
+ * @param count Number of elements in list.
+ * @param mask Preallocated mask (size EMASKSIZE).
+ * @param dev The device we're creating masks for.
+ * @param req The request we're processing. Used to fill in error fields.
*/
int
@@ -161,7 +179,7 @@ CreateMaskFromList(ClientPtr client, XEventClass * list, int count,
for (i = 0; i < count; i++, list++) {
device = *list >> 8;
- if (device > 255)
+ if (device > 255) /* FIXME: we only use 7 bit for devices? */
return BadClass;
rc = dixLookupDevice(&tdev, device, client, DixReadAccess);
diff --git a/xorg-server/Xi/grabdevb.c b/xorg-server/Xi/grabdevb.c
index ce0dcc5f9..98f7e117d 100644
--- a/xorg-server/Xi/grabdevb.c
+++ b/xorg-server/Xi/grabdevb.c
@@ -125,7 +125,7 @@ ProcXGrabDeviceButton(ClientPtr client)
if (mdev->key == NULL)
return BadMatch;
} else {
- mdev = inputInfo.keyboard;
+ mdev = PickKeyboard(client);
ret = XaceHook(XACE_DEVICE_ACCESS, client, mdev, DixReadAccess);
if (ret != Success)
return ret;
diff --git a/xorg-server/Xi/grabdevk.c b/xorg-server/Xi/grabdevk.c
index d4b7fe815..6a245f25a 100644
--- a/xorg-server/Xi/grabdevk.c
+++ b/xorg-server/Xi/grabdevk.c
@@ -122,7 +122,7 @@ ProcXGrabDeviceKey(ClientPtr client)
if (mdev->key == NULL)
return BadMatch;
} else {
- mdev = inputInfo.keyboard;
+ mdev = PickKeyboard(client);
ret = XaceHook(XACE_DEVICE_ACCESS, client, mdev, DixReadAccess);
if (ret != Success)
return ret;
diff --git a/xorg-server/Xi/gtmotion.c b/xorg-server/Xi/gtmotion.c
index 4f4d7cb77..8fa0cca29 100644
--- a/xorg-server/Xi/gtmotion.c
+++ b/xorg-server/Xi/gtmotion.c
@@ -95,7 +95,7 @@ ProcXGetDeviceMotionEvents(ClientPtr client)
INT32 *coords = NULL, *bufptr;
xGetDeviceMotionEventsReply rep;
unsigned long i;
- int rc, num_events, axes, size = 0, tsize;
+ int rc, num_events, axes, size = 0;
unsigned long nEvents;
DeviceIntPtr dev;
TimeStamp start, stop;
@@ -119,7 +119,7 @@ ProcXGetDeviceMotionEvents(ClientPtr client)
rep.sequenceNumber = client->sequence;
rep.nEvents = 0;
rep.axes = axes;
- rep.mode = v->mode & DeviceMode;
+ rep.mode = Absolute; /* XXX we don't do relative at the moment */
rep.length = 0;
start = ClientTimeToServerTime(stuff->start);
stop = ClientTimeToServerTime(stuff->stop);
@@ -132,14 +132,10 @@ ProcXGetDeviceMotionEvents(ClientPtr client)
stop = currentTime;
num_events = v->numMotionEvents;
if (num_events) {
- size = sizeof(Time) + (axes * sizeof(INT32));
- tsize = num_events * size;
- coords = (INT32 *) xalloc(tsize);
- if (!coords)
- return BadAlloc;
- rep.nEvents = (v->GetMotionProc) (dev, (xTimecoord *) coords, /* XXX */
- start.milliseconds, stop.milliseconds,
- (ScreenPtr) NULL);
+ size = sizeof(Time) + (axes * sizeof(INT32));
+ rep.nEvents = GetMotionHistory(dev, (xTimecoord **) &coords,/* XXX */
+ start.milliseconds, stop.milliseconds,
+ (ScreenPtr) NULL, FALSE);
}
if (rep.nEvents > 0) {
length = (rep.nEvents * size + 3) >> 2;
diff --git a/xorg-server/Xi/listdev.c b/xorg-server/Xi/listdev.c
index 041de7635..56ba2f6eb 100644
--- a/xorg-server/Xi/listdev.c
+++ b/xorg-server/Xi/listdev.c
@@ -64,11 +64,11 @@ SOFTWARE.
#include "XIstubs.h"
#include "extnsionst.h"
#include "exglobals.h" /* FIXME */
+#include "exevents.h"
#include "xace.h"
#include "listdev.h"
-#define VPC 20 /* Max # valuators per chunk */
/***********************************************************************
*
@@ -93,7 +93,7 @@ SProcXListInputDevices(ClientPtr client)
*
*/
-static void
+void
SizeDeviceInfo(DeviceIntPtr d, int *namesize, int *size)
{
int chunks;
@@ -153,7 +153,7 @@ CopySwapButtonClass(ClientPtr client, ButtonClassPtr b, char **buf)
b2->class = ButtonClass;
b2->length = sizeof(xButtonInfo);
b2->num_buttons = b->numButtons;
- if (client->swapped) {
+ if (client && client->swapped) {
swaps(&b2->num_buttons, n); /* macro - braces are required */
}
*buf += sizeof(xButtonInfo);
@@ -177,9 +177,9 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes,
dev->id = d->id;
dev->type = d->type;
dev->num_classes = num_classes;
- if (d == inputInfo.keyboard)
+ if (d->isMaster && IsKeyboardDevice(d))
dev->use = IsXKeyboard;
- else if (d == inputInfo.pointer)
+ else if (d->isMaster && IsPointerDevice(d))
dev->use = IsXPointer;
else if (d->key && d->kbdfeed)
dev->use = IsXExtensionKeyboard;
@@ -187,6 +187,7 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes,
dev->use = IsXExtensionPointer;
else
dev->use = IsXExtensionDevice;
+
if (client->swapped) {
swapl(&dev->type, n); /* macro - braces are required */
}
@@ -211,7 +212,7 @@ CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf)
k2->min_keycode = k->curKeySyms.minKeyCode;
k2->max_keycode = k->curKeySyms.maxKeyCode;
k2->num_keys = k2->max_keycode - k2->min_keycode + 1;
- if (client->swapped) {
+ if (client && client->swapped) {
swaps(&k2->num_keys, n);
}
*buf += sizeof(xKeyInfo);
@@ -223,7 +224,7 @@ CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf)
*
* Devices may have up to 255 valuators. The length of a ValuatorClass is
* defined to be sizeof(ValuatorClassInfo) + num_axes * sizeof (xAxisInfo).
- * The maximum length is therefore (8 + 255 * 12) = 3068. However, the
+ * The maximum length is therefore (8 + 255 * 12) = 3068. However, the
* length field is one byte. If a device has more than 20 valuators, we
* must therefore return multiple valuator classes to the client.
*
@@ -249,7 +250,7 @@ CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf)
v2->num_axes = t_axes;
v2->mode = v->mode & DeviceMode;
v2->motion_buffer_size = v->numMotionEvents;
- if (client->swapped) {
+ if (client && client->swapped) {
swapl(&v2->motion_buffer_size, n);
}
*buf += sizeof(xValuatorInfo);
@@ -259,7 +260,7 @@ CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf)
a2->min_value = a->min_value;
a2->max_value = a->max_value;
a2->resolution = a->resolution;
- if (client->swapped) {
+ if (client && client->swapped) {
swapl(&a2->min_value, n);
swapl(&a2->max_value, n);
swapl(&a2->resolution, n);
@@ -284,17 +285,24 @@ ListDeviceInfo(ClientPtr client, DeviceIntPtr d, xDeviceInfoPtr dev,
{
CopyDeviceName(namebuf, d->name);
CopySwapDevice(client, d, 0, devbuf);
- if (d->key != NULL) {
- CopySwapKeyClass(client, d->key, classbuf);
- dev->num_classes++;
+ CopySwapClasses(client, d, &dev->num_classes, classbuf);
+}
+
+void
+CopySwapClasses(ClientPtr client, DeviceIntPtr dev, CARD8 *num_classes,
+ char** classbuf)
+{
+ if (dev->key != NULL) {
+ CopySwapKeyClass(client, dev->key, classbuf);
+ (*num_classes)++;
}
- if (d->button != NULL) {
- CopySwapButtonClass(client, d->button, classbuf);
- dev->num_classes++;
+ if (dev->button != NULL) {
+ CopySwapButtonClass(client, dev->button, classbuf);
+ (*num_classes)++;
}
- if (d->valuator != NULL) {
- dev->num_classes +=
- CopySwapValuatorClass(client, d->valuator, classbuf);
+ if (dev->valuator != NULL) {
+ (*num_classes) +=
+ CopySwapValuatorClass(client, dev->valuator, classbuf);
}
}
@@ -302,12 +310,17 @@ ListDeviceInfo(ClientPtr client, DeviceIntPtr d, xDeviceInfoPtr dev,
*
* This procedure lists the input devices available to the server.
*
+ * If this request is called by a client that has not issued a
+ * GetExtensionVersion request with major/minor version set, we don't send the
+ * complete device list. Instead, we only send the VCP, the VCK and floating
+ * SDs. This resembles the setup found on XI 1.x machines.
*/
int
ProcXListInputDevices(ClientPtr client)
{
xListInputDevicesReply rep;
+ XIClientPtr pXIClient;
int numdevs = 0;
int namesize = 1; /* need 1 extra byte for strcpy */
int rc, size = 0;
@@ -326,20 +339,23 @@ ProcXListInputDevices(ClientPtr client)
rep.length = 0;
rep.sequenceNumber = client->sequence;
+ pXIClient = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
+
AddOtherInputDevices();
for (d = inputInfo.devices; d; d = d->next) {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
- if (rc != Success)
- return rc;
- SizeDeviceInfo(d, &namesize, &size);
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ SizeDeviceInfo(d, &namesize, &size);
numdevs++;
}
+
for (d = inputInfo.off_devices; d; d = d->next) {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
- if (rc != Success)
- return rc;
- SizeDeviceInfo(d, &namesize, &size);
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ SizeDeviceInfo(d, &namesize, &size);
numdevs++;
}
@@ -350,11 +366,15 @@ ProcXListInputDevices(ClientPtr client)
savbuf = devbuf;
dev = (xDeviceInfoPtr) devbuf;
- for (d = inputInfo.devices; d; d = d->next, dev++)
- ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf);
- for (d = inputInfo.off_devices; d; d = d->next, dev++)
- ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf);
+ for (d = inputInfo.devices; d; d = d->next)
+ {
+ ListDeviceInfo(client, d, dev++, &devbuf, &classbuf, &namebuf);
+ }
+ for (d = inputInfo.off_devices; d; d = d->next)
+ {
+ ListDeviceInfo(client, d, dev++, &devbuf, &classbuf, &namebuf);
+ }
rep.ndevices = numdevs;
rep.length = (total_length + 3) >> 2;
WriteReplyToClient(client, sizeof(xListInputDevicesReply), &rep);
diff --git a/xorg-server/Xi/listdev.h b/xorg-server/Xi/listdev.h
index db376decf..39ea2d635 100644
--- a/xorg-server/Xi/listdev.h
+++ b/xorg-server/Xi/listdev.h
@@ -30,6 +30,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#ifndef LISTDEV_H
#define LISTDEV_H 1
+#define VPC 20 /* Max # valuators per chunk */
+
int SProcXListInputDevices(ClientPtr /* client */
);
@@ -41,4 +43,15 @@ void SRepXListInputDevices(ClientPtr /* client */ ,
xListInputDevicesReply * /* rep */
);
+void
+CopySwapClasses(ClientPtr /* client */,
+ DeviceIntPtr /* dev */,
+ CARD8* /* num_classes */,
+ char** /* classbuf */);
+
+void
+SizeDeviceInfo(DeviceIntPtr /* dev */,
+ int* /* namesize */,
+ int* /* size */);
+
#endif /* LISTDEV_H */
diff --git a/xorg-server/Xi/opendev.c b/xorg-server/Xi/opendev.c
index acda38530..8d249278d 100644
--- a/xorg-server/Xi/opendev.c
+++ b/xorg-server/Xi/opendev.c
@@ -62,6 +62,7 @@ SOFTWARE.
#include "XIstubs.h"
#include "windowstr.h" /* window structure */
#include "exglobals.h"
+#include "exevents.h"
#include "opendev.h"
@@ -102,11 +103,8 @@ ProcXOpenDevice(ClientPtr client)
REQUEST(xOpenDeviceReq);
REQUEST_SIZE_MATCH(xOpenDeviceReq);
- if (stuff->deviceid == inputInfo.pointer->id ||
- stuff->deviceid == inputInfo.keyboard->id)
- return BadDevice;
-
status = dixLookupDevice(&dev, stuff->deviceid, client, DixUseAccess);
+
if (status == BadDevice) { /* not open */
for (dev = inputInfo.off_devices; dev; dev = dev->next)
if (dev->id == stuff->deviceid)
@@ -116,6 +114,9 @@ ProcXOpenDevice(ClientPtr client)
} else if (status != Success)
return status;
+ if (dev->isMaster)
+ return BadDevice;
+
OpenInputDevice(dev, client, &status);
if (status != Success)
return status;
diff --git a/xorg-server/Xi/queryst.c b/xorg-server/Xi/queryst.c
index 71ab79be8..21de843f3 100644
--- a/xorg-server/Xi/queryst.c
+++ b/xorg-server/Xi/queryst.c
@@ -119,7 +119,7 @@ ProcXQueryDeviceState(ClientPtr client)
total_length += (sizeof(xValuatorState) + (v->numAxes * sizeof(int)));
num_classes++;
}
- buf = (char *)xalloc(total_length);
+ buf = (char *)xcalloc(total_length, 1);
if (!buf)
return BadAlloc;
savbuf = buf;
@@ -139,8 +139,7 @@ ProcXQueryDeviceState(ClientPtr client)
tb->class = ButtonClass;
tb->length = sizeof(xButtonState);
tb->num_buttons = b->numButtons;
- for (i = 0; i < 32; i++)
- tb->buttons[i] = b->down[i];
+ memcpy(tb->buttons, b->down, sizeof(b->down));
buf += sizeof(xButtonState);
}
diff --git a/xorg-server/Xi/selectev.c b/xorg-server/Xi/selectev.c
index d3670ab1b..9c336fce5 100644
--- a/xorg-server/Xi/selectev.c
+++ b/xorg-server/Xi/selectev.c
@@ -106,10 +106,10 @@ HandleDevicePresenceMask(ClientPtr client, WindowPtr win,
if (mask == 0)
return Success;
- /* We always only use mksidx = 0 for events not bound to
+ /* We always only use mksidx = MAXDEVICES for events not bound to
* devices */
- if (AddExtensionClient (win, client, mask, 0) != Success)
+ if (AddExtensionClient (win, client, mask, MAXDEVICES) != Success)
return BadAlloc;
RecalculateDeviceDeliverableEvents(win);
diff --git a/xorg-server/Xi/sendexev.c b/xorg-server/Xi/sendexev.c
index 588c91023..9b37de307 100644
--- a/xorg-server/Xi/sendexev.c
+++ b/xorg-server/Xi/sendexev.c
@@ -50,7 +50,6 @@ SOFTWARE.
*
*/
-#define EXTENSION_EVENT_BASE 64
#define NEED_EVENTS
#define NEED_REPLIES
#ifdef HAVE_DIX_CONFIG_H
@@ -112,7 +111,7 @@ SProcXSendExtensionEvent(ClientPtr client)
/***********************************************************************
*
- * Send an event to some client, as if it had come from an extension input
+ * Send an event to some client, as if it had come from an extension input
* device.
*
*/
diff --git a/xorg-server/Xi/setdval.c b/xorg-server/Xi/setdval.c
index b1e22fc21..20584629a 100644
--- a/xorg-server/Xi/setdval.c
+++ b/xorg-server/Xi/setdval.c
@@ -115,7 +115,7 @@ ProcXSetDeviceValuators(ClientPtr client)
if (stuff->first_valuator + stuff->num_valuators > dev->valuator->numAxes)
return BadValue;
- if ((dev->grab) && !SameClient(dev->grab, client))
+ if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client))
rep.status = AlreadyGrabbed;
else
rep.status = SetDeviceValuators(client, dev, (int *)&stuff[1],
diff --git a/xorg-server/Xi/setmode.c b/xorg-server/Xi/setmode.c
index 8b6003ad0..2badb5161 100644
--- a/xorg-server/Xi/setmode.c
+++ b/xorg-server/Xi/setmode.c
@@ -106,7 +106,7 @@ ProcXSetDeviceMode(ClientPtr client)
return rc;
if (dev->valuator == NULL)
return BadMatch;
- if ((dev->grab) && !SameClient(dev->grab, client))
+ if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client))
rep.status = AlreadyGrabbed;
else
rep.status = SetDeviceMode(client, dev, stuff->mode);
diff --git a/xorg-server/Xi/ungrdev.c b/xorg-server/Xi/ungrdev.c
index 7abb1d061..f6525a287 100644
--- a/xorg-server/Xi/ungrdev.c
+++ b/xorg-server/Xi/ungrdev.c
@@ -101,12 +101,12 @@ ProcXUngrabDevice(ClientPtr client)
rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
if (rc != Success)
return rc;
- grab = dev->grab;
+ grab = dev->deviceGrab.grab;
time = ClientTimeToServerTime(stuff->time);
if ((CompareTimeStamps(time, currentTime) != LATER) &&
- (CompareTimeStamps(time, dev->grabTime) != EARLIER) &&
- (grab) && SameClient(grab, client))
- (*dev->DeactivateGrab) (dev);
+ (CompareTimeStamps(time, dev->deviceGrab.grabTime) != EARLIER) &&
+ (grab) && SameClient(grab, client) && !grab->coreGrab)
+ (*dev->deviceGrab.DeactivateGrab) (dev);
return Success;
}
diff --git a/xorg-server/Xi/ungrdevb.c b/xorg-server/Xi/ungrdevb.c
index 590699f05..d1aef5f13 100644
--- a/xorg-server/Xi/ungrdevb.c
+++ b/xorg-server/Xi/ungrdevb.c
@@ -120,7 +120,7 @@ ProcXUngrabDeviceButton(ClientPtr client)
if (mdev->key == NULL)
return BadMatch;
} else
- mdev = inputInfo.keyboard;
+ mdev = PickKeyboard(client);
rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
if (rc != Success)
diff --git a/xorg-server/Xi/ungrdevk.c b/xorg-server/Xi/ungrdevk.c
index 521765ea3..bc3ada987 100644
--- a/xorg-server/Xi/ungrdevk.c
+++ b/xorg-server/Xi/ungrdevk.c
@@ -120,7 +120,7 @@ ProcXUngrabDeviceKey(ClientPtr client)
if (mdev->key == NULL)
return BadMatch;
} else
- mdev = inputInfo.keyboard;
+ mdev = PickKeyboard(client);
rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
if (rc != Success)
diff --git a/xorg-server/Xi/xiproperty.c b/xorg-server/Xi/xiproperty.c
new file mode 100644
index 000000000..b04ee9433
--- /dev/null
+++ b/xorg-server/Xi/xiproperty.c
@@ -0,0 +1,918 @@
+/*
+ * Copyright © 2006 Keith Packard
+ * Copyright © 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 WAXIANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WAXIANTIES 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.
+ *
+ */
+
+/* This code is a modified version of randr/rrproperty.c */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "dix.h"
+#include "inputstr.h"
+#include <X11/extensions/XI.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/XIproto.h>
+#include "exglobals.h"
+#include "exevents.h"
+#include "swaprep.h"
+
+#include "xiproperty.h"
+#include "xserver-properties.h"
+
+/**
+ * Properties used or alloced from inside the server.
+ */
+static struct dev_properties
+{
+ Atom type;
+ char *name;
+} dev_properties[] = {
+ {0, XI_PROP_ENABLED},
+ {0, XATOM_FLOAT}
+};
+
+static long XIPropHandlerID = 1;
+
+/**
+ * Return the type assigned to the specified atom or 0 if the atom isn't known
+ * to the DIX.
+ *
+ * If name is NULL, None is returned.
+ */
+_X_EXPORT Atom
+XIGetKnownProperty(char *name)
+{
+ int i;
+
+ if (!name)
+ return None;
+
+ for (i = 0; i < (sizeof(dev_properties)/sizeof(struct dev_properties)); i++)
+ {
+ if (strcmp(name, dev_properties[i].name) == 0)
+ return dev_properties[i].type;
+ }
+
+ return 0;
+}
+
+/**
+ * Convert the given property's value(s) into @nelem_return integer values and
+ * store them in @buf_return. If @nelem_return is larger than the number of
+ * values in the property, @nelem_return is set to the number of values in the
+ * property.
+ *
+ * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
+ * automatically and must be freed by the caller.
+ *
+ * Possible return codes.
+ * Success ... No error.
+ * BadMatch ... Wrong atom type, atom is not XA_INTEGER
+ * BadAlloc ... NULL passed as buffer and allocation failed.
+ * BadLength ... @buff is NULL but @nelem_return is non-zero.
+ *
+ * @param val The property value
+ * @param nelem_return The maximum number of elements to return.
+ * @param buf_return Pointer to an array of at least @nelem_return values.
+ * @return Success or the error code if an error occured.
+ */
+_X_EXPORT int
+XIPropToInt(XIPropertyValuePtr val, int *nelem_return, int **buf_return)
+{
+ int i;
+ int *buf;
+
+ if (val->type != XA_INTEGER)
+ return BadMatch;
+ if (!*buf_return && *nelem_return)
+ return BadLength;
+
+ switch(val->format)
+ {
+ case 8:
+ case 16:
+ case 32:
+ break;
+ default:
+ return BadValue;
+ }
+
+ buf = *buf_return;
+
+ if (!buf && !(*nelem_return))
+ {
+ buf = xcalloc(val->size, sizeof(int));
+ if (!buf)
+ return BadAlloc;
+ *buf_return = buf;
+ *nelem_return = val->size;
+ } else if (val->size < *nelem_return)
+ *nelem_return = val->size;
+
+ for (i = 0; i < val->size && i < *nelem_return; i++)
+ {
+ switch(val->format)
+ {
+ case 8: buf[i] = ((CARD8*)val->data)[i]; break;
+ case 16: buf[i] = ((CARD16*)val->data)[i]; break;
+ case 32: buf[i] = ((CARD32*)val->data)[i]; break;
+ }
+ }
+
+ return Success;
+}
+
+/**
+ * Convert the given property's value(s) into @nelem_return float values and
+ * store them in @buf_return. If @nelem_return is larger than the number of
+ * values in the property, @nelem_return is set to the number of values in the
+ * property.
+ *
+ * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
+ * automatically and must be freed by the caller.
+ *
+ * Possible errors returned:
+ * Success
+ * BadMatch ... Wrong atom type, atom is not XA_FLOAT
+ * BadValue ... Wrong format, format is not 32
+ * BadAlloc ... NULL passed as buffer and allocation failed.
+ * BadLength ... @buff is NULL but @nelem_return is non-zero.
+ *
+ * @param val The property value
+ * @param nelem_return The maximum number of elements to return.
+ * @param buf_return Pointer to an array of at least @nelem_return values.
+ * @return Success or the error code if an error occured.
+ */
+_X_EXPORT int
+XIPropToFloat(XIPropertyValuePtr val, int *nelem_return, float **buf_return)
+{
+ int i;
+ float *buf;
+
+ if (!val->type || val->type != XIGetKnownProperty(XATOM_FLOAT))
+ return BadMatch;
+
+ if (val->format != 32)
+ return BadValue;
+ if (!*buf_return && *nelem_return)
+ return BadLength;
+
+ buf = *buf_return;
+
+ if (!buf && !(*nelem_return))
+ {
+ buf = xcalloc(val->size, sizeof(float));
+ if (!buf)
+ return BadAlloc;
+ *buf_return = buf;
+ *nelem_return = val->size;
+ } else if (val->size < *nelem_return)
+ *nelem_return = val->size;
+
+ for (i = 0; i < val->size && i < *nelem_return; i++)
+ buf[i] = ((float*)val->data)[i];
+
+ return Success;
+}
+
+/**
+ * Init those properties that are allocated by the server and most likely used
+ * by the DIX or the DDX.
+ */
+void
+XIInitKnownProperties(void)
+{
+ int i;
+ for (i = 0; i < (sizeof(dev_properties)/sizeof(struct dev_properties)); i++)
+ {
+ dev_properties[i].type =
+ MakeAtom(dev_properties[i].name,
+ strlen(dev_properties[i].name),
+ TRUE);
+ }
+}
+
+
+/* Registers a new property handler on the given device and returns a unique
+ * identifier for this handler. This identifier is required to unregister the
+ * property handler again.
+ * @return The handler's identifier or 0 if an error occured.
+ */
+long
+XIRegisterPropertyHandler(DeviceIntPtr dev,
+ int (*SetProperty) (DeviceIntPtr dev,
+ Atom property,
+ XIPropertyValuePtr prop,
+ BOOL checkonly),
+ int (*GetProperty) (DeviceIntPtr dev,
+ Atom property),
+ int (*DeleteProperty) (DeviceIntPtr dev,
+ Atom property))
+{
+ XIPropertyHandlerPtr new_handler;
+
+ new_handler = xcalloc(1, sizeof(XIPropertyHandler));
+ if (!new_handler)
+ return 0;
+
+ new_handler->id = XIPropHandlerID++;
+ new_handler->SetProperty = SetProperty;
+ new_handler->GetProperty = GetProperty;
+ new_handler->DeleteProperty = DeleteProperty;
+ new_handler->next = dev->properties.handlers;
+ dev->properties.handlers = new_handler;
+
+ return new_handler->id;
+}
+
+void
+XIUnregisterPropertyHandler(DeviceIntPtr dev, long id)
+{
+ XIPropertyHandlerPtr curr, prev = NULL;
+
+ curr = dev->properties.handlers;
+ while(curr && curr->id != id)
+ {
+ prev = curr;
+ curr = curr->next;
+ }
+
+ if (!curr)
+ return;
+
+ if (!prev) /* first one */
+ dev->properties.handlers = curr->next;
+ else
+ prev->next = curr->next;
+
+ xfree(curr);
+}
+
+static XIPropertyPtr
+XICreateDeviceProperty (Atom property)
+{
+ XIPropertyPtr prop;
+
+ prop = (XIPropertyPtr)xalloc(sizeof(XIPropertyRec));
+ if (!prop)
+ return NULL;
+
+ prop->next = NULL;
+ prop->propertyName = property;
+ prop->value.type = None;
+ prop->value.format = 0;
+ prop->value.size = 0;
+ prop->value.data = NULL;
+ prop->deletable = TRUE;
+
+ return prop;
+}
+
+static XIPropertyPtr
+XIFetchDeviceProperty(DeviceIntPtr dev, Atom property)
+{
+ XIPropertyPtr prop;
+
+ for (prop = dev->properties.properties; prop; prop = prop->next)
+ if (prop->propertyName == property)
+ return prop;
+ return NULL;
+}
+
+static void
+XIDestroyDeviceProperty (XIPropertyPtr prop)
+{
+ if (prop->value.data)
+ xfree(prop->value.data);
+ xfree(prop);
+}
+
+/* This function destroys all of the device's property-related stuff,
+ * including removing all device handlers.
+ * DO NOT CALL FROM THE DRIVER.
+ */
+void
+XIDeleteAllDeviceProperties (DeviceIntPtr device)
+{
+ XIPropertyPtr prop, next;
+ XIPropertyHandlerPtr curr_handler, next_handler;
+ devicePropertyNotify event;
+
+ for (prop = device->properties.properties; prop; prop = next)
+ {
+ next = prop->next;
+
+ event.type = DevicePropertyNotify;
+ event.deviceid = device->id;
+ event.state = PropertyDelete;
+ event.atom = prop->propertyName;
+ event.time = currentTime.milliseconds;
+ SendEventToAllWindows(device, DevicePropertyNotifyMask,
+ (xEvent*)&event, 1);
+
+ XIDestroyDeviceProperty(prop);
+ }
+
+ /* Now free all handlers */
+ curr_handler = device->properties.handlers;
+ while(curr_handler)
+ {
+ next_handler = curr_handler->next;
+ xfree(curr_handler);
+ curr_handler = next_handler;
+ }
+}
+
+
+int
+XIDeleteDeviceProperty (DeviceIntPtr device, Atom property, Bool fromClient)
+{
+ XIPropertyPtr prop, *prev;
+ devicePropertyNotify event;
+ int rc = Success;
+
+ for (prev = &device->properties.properties; (prop = *prev); prev = &(prop->next))
+ if (prop->propertyName == property)
+ break;
+
+ if (fromClient && !prop->deletable)
+ return BadAccess;
+
+ /* Ask handlers if we may delete the property */
+ if (device->properties.handlers)
+ {
+ XIPropertyHandlerPtr handler = device->properties.handlers;
+ while(handler)
+ {
+ if (handler->DeleteProperty)
+ rc = handler->DeleteProperty(device, prop->propertyName);
+ if (rc != Success)
+ return (rc);
+ handler = handler->next;
+ }
+ }
+
+ if (prop)
+ {
+ *prev = prop->next;
+ event.type = DevicePropertyNotify;
+ event.deviceid = device->id;
+ event.state = PropertyDelete;
+ event.atom = prop->propertyName;
+ event.time = currentTime.milliseconds;
+ SendEventToAllWindows(device, DevicePropertyNotifyMask,
+ (xEvent*)&event, 1);
+ XIDestroyDeviceProperty (prop);
+ }
+
+ return Success;
+}
+
+int
+XIChangeDeviceProperty (DeviceIntPtr dev, Atom property, Atom type,
+ int format, int mode, unsigned long len,
+ pointer value, Bool sendevent)
+{
+ XIPropertyPtr prop;
+ devicePropertyNotify event;
+ int size_in_bytes;
+ int total_size;
+ unsigned long total_len;
+ XIPropertyValuePtr prop_value;
+ XIPropertyValueRec new_value;
+ Bool add = FALSE;
+ int rc;
+
+ size_in_bytes = format >> 3;
+
+ /* first see if property already exists */
+ prop = XIFetchDeviceProperty (dev, property);
+ if (!prop) /* just add to list */
+ {
+ prop = XICreateDeviceProperty (property);
+ if (!prop)
+ return(BadAlloc);
+ add = TRUE;
+ mode = PropModeReplace;
+ }
+ prop_value = &prop->value;
+
+ /* To append or prepend to a property the request format and type
+ must match those of the already defined property. The
+ existing format and type are irrelevant when using the mode
+ "PropModeReplace" since they will be written over. */
+
+ if ((format != prop_value->format) && (mode != PropModeReplace))
+ return(BadMatch);
+ if ((prop_value->type != type) && (mode != PropModeReplace))
+ return(BadMatch);
+ new_value = *prop_value;
+ if (mode == PropModeReplace)
+ total_len = len;
+ else
+ total_len = prop_value->size + len;
+
+ if (mode == PropModeReplace || len > 0)
+ {
+ pointer new_data = NULL, old_data = NULL;
+
+ total_size = total_len * size_in_bytes;
+ new_value.data = (pointer)xalloc (total_size);
+ if (!new_value.data && total_size)
+ {
+ if (add)
+ XIDestroyDeviceProperty (prop);
+ return BadAlloc;
+ }
+ new_value.size = len;
+ new_value.type = type;
+ new_value.format = format;
+
+ switch (mode) {
+ case PropModeReplace:
+ new_data = new_value.data;
+ old_data = NULL;
+ break;
+ case PropModeAppend:
+ new_data = (pointer) (((char *) new_value.data) +
+ (prop_value->size * size_in_bytes));
+ old_data = new_value.data;
+ break;
+ case PropModePrepend:
+ new_data = new_value.data;
+ old_data = (pointer) (((char *) new_value.data) +
+ (prop_value->size * size_in_bytes));
+ break;
+ }
+ if (new_data)
+ memcpy ((char *) new_data, (char *) value, len * size_in_bytes);
+ if (old_data)
+ memcpy ((char *) old_data, (char *) prop_value->data,
+ prop_value->size * size_in_bytes);
+
+ if (dev->properties.handlers)
+ {
+ XIPropertyHandlerPtr handler;
+ BOOL checkonly = TRUE;
+ /* run through all handlers with checkonly TRUE, then again with
+ * checkonly FALSE. Handlers MUST return error codes on the
+ * checkonly run, errors on the second run are ignored */
+ do
+ {
+ handler = dev->properties.handlers;
+ while(handler)
+ {
+ if (handler->SetProperty)
+ {
+ rc = handler->SetProperty(dev, prop->propertyName,
+ &new_value, checkonly);
+ if (checkonly && rc != Success)
+ {
+ if (new_value.data)
+ xfree (new_value.data);
+ return (rc);
+ }
+ }
+ handler = handler->next;
+ }
+ checkonly = !checkonly;
+ } while (!checkonly);
+ }
+ if (prop_value->data)
+ xfree (prop_value->data);
+ *prop_value = new_value;
+ } else if (len == 0)
+ {
+ /* do nothing */
+ }
+
+ if (add)
+ {
+ prop->next = dev->properties.properties;
+ dev->properties.properties = prop;
+ }
+
+ if (sendevent)
+ {
+ event.type = DevicePropertyNotify;
+ event.deviceid = dev->id;
+ event.state = PropertyNewValue;
+ event.atom = prop->propertyName;
+ event.time = currentTime.milliseconds;
+ SendEventToAllWindows(dev, DevicePropertyNotifyMask,
+ (xEvent*)&event, 1);
+ }
+ return(Success);
+}
+
+int
+XIGetDeviceProperty (DeviceIntPtr dev, Atom property, XIPropertyValuePtr *value)
+{
+ XIPropertyPtr prop = XIFetchDeviceProperty (dev, property);
+ int rc;
+
+ if (!prop)
+ {
+ *value = NULL;
+ return BadAtom;
+ }
+
+ /* If we can, try to update the property value first */
+ if (dev->properties.handlers)
+ {
+ XIPropertyHandlerPtr handler = dev->properties.handlers;
+ while(handler)
+ {
+ if (handler->GetProperty)
+ {
+ rc = handler->GetProperty(dev, prop->propertyName);
+ if (rc != Success)
+ {
+ *value = NULL;
+ return rc;
+ }
+ }
+ handler = handler->next;
+ }
+ }
+
+ *value = &prop->value;
+ return Success;
+}
+
+int
+XISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable)
+{
+ XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
+
+ if (!prop)
+ return BadAtom;
+
+ prop->deletable = deletable;
+ return Success;
+}
+
+int
+ProcXListDeviceProperties (ClientPtr client)
+{
+ Atom *pAtoms = NULL, *temppAtoms;
+ xListDevicePropertiesReply rep;
+ int numProps = 0;
+ DeviceIntPtr dev;
+ XIPropertyPtr prop;
+ int rc = Success;
+
+ REQUEST(xListDevicePropertiesReq);
+ REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ for (prop = dev->properties.properties; prop; prop = prop->next)
+ numProps++;
+ if (numProps)
+ if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom))))
+ return(BadAlloc);
+
+ rep.repType = X_Reply;
+ rep.RepType = X_ListDeviceProperties;
+ rep.length = (numProps * sizeof(Atom)) >> 2;
+ rep.sequenceNumber = client->sequence;
+ rep.nAtoms = numProps;
+ temppAtoms = pAtoms;
+ for (prop = dev->properties.properties; prop; prop = prop->next)
+ *temppAtoms++ = prop->propertyName;
+
+ WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep);
+ if (numProps)
+ {
+ client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
+ WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
+ xfree(pAtoms);
+ }
+ return rc;
+}
+
+int
+ProcXChangeDeviceProperty (ClientPtr client)
+{
+ REQUEST(xChangeDevicePropertyReq);
+ DeviceIntPtr dev;
+ char format, mode;
+ unsigned long len;
+ int sizeInBytes;
+ int totalSize;
+ int rc;
+
+ REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
+ UpdateCurrentTime();
+ format = stuff->format;
+ mode = stuff->mode;
+ if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
+ (mode != PropModePrepend))
+ {
+ client->errorValue = mode;
+ return BadValue;
+ }
+ if ((format != 8) && (format != 16) && (format != 32))
+ {
+ client->errorValue = format;
+ return BadValue;
+ }
+ len = stuff->nUnits;
+ if (len > ((0xffffffff - sizeof(xChangeDevicePropertyReq)) >> 2))
+ return BadLength;
+ sizeInBytes = format>>3;
+ totalSize = len * sizeInBytes;
+ REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize);
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return(BadAtom);
+ }
+ if (!ValidAtom(stuff->type))
+ {
+ client->errorValue = stuff->type;
+ return(BadAtom);
+ }
+
+ rc = XIChangeDeviceProperty(dev, stuff->property,
+ stuff->type, (int)format,
+ (int)mode, len, (pointer)&stuff[1], TRUE);
+
+ if (rc != Success)
+ client->errorValue = stuff->property;
+ return rc;
+}
+
+int
+ProcXDeleteDeviceProperty (ClientPtr client)
+{
+ REQUEST(xDeleteDevicePropertyReq);
+ DeviceIntPtr dev;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
+ UpdateCurrentTime();
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return (BadAtom);
+ }
+
+ rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
+ return rc;
+}
+
+int
+ProcXGetDeviceProperty (ClientPtr client)
+{
+ REQUEST(xGetDevicePropertyReq);
+ XIPropertyPtr prop, *prev;
+ XIPropertyValuePtr prop_value;
+ unsigned long n, len, ind;
+ DeviceIntPtr dev;
+ xGetDevicePropertyReply reply;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
+ if (stuff->delete)
+ UpdateCurrentTime();
+ rc = dixLookupDevice (&dev, stuff->deviceid, client,
+ stuff->delete ? DixWriteAccess :
+ DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return(BadAtom);
+ }
+ if ((stuff->delete != xTrue) && (stuff->delete != xFalse))
+ {
+ client->errorValue = stuff->delete;
+ return(BadValue);
+ }
+ if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type))
+ {
+ client->errorValue = stuff->type;
+ return(BadAtom);
+ }
+
+ for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next)
+ if (prop->propertyName == stuff->property)
+ break;
+
+ reply.repType = X_Reply;
+ reply.RepType = X_GetDeviceProperty;
+ reply.sequenceNumber = client->sequence;
+ reply.deviceid = dev->id;
+ if (!prop)
+ {
+ reply.nItems = 0;
+ reply.length = 0;
+ reply.bytesAfter = 0;
+ reply.propertyType = None;
+ reply.format = 0;
+ WriteReplyToClient(client, sizeof(xGetDevicePropertyReply), &reply);
+ return(client->noClientException);
+ }
+
+ rc = XIGetDeviceProperty(dev, stuff->property, &prop_value);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->property;
+ return rc;
+ }
+
+ /* If the request type and actual type don't match. Return the
+ property information, but not the data. */
+
+ if (((stuff->type != prop_value->type) &&
+ (stuff->type != AnyPropertyType))
+ )
+ {
+ reply.bytesAfter = prop_value->size;
+ reply.format = prop_value->format;
+ reply.length = 0;
+ reply.nItems = 0;
+ reply.propertyType = prop_value->type;
+ WriteReplyToClient(client, sizeof(xGetDevicePropertyReply), &reply);
+ return(client->noClientException);
+ }
+
+/*
+ * Return type, format, value to client
+ */
+ n = (prop_value->format/8) * prop_value->size; /* size (bytes) of prop */
+ ind = stuff->longOffset << 2;
+
+ /* If longOffset is invalid such that it causes "len" to
+ be negative, it's a value error. */
+
+ if (n < ind)
+ {
+ client->errorValue = stuff->longOffset;
+ return BadValue;
+ }
+
+ len = min(n - ind, 4 * stuff->longLength);
+
+ reply.bytesAfter = n - (ind + len);
+ reply.format = prop_value->format;
+ reply.length = (len + 3) >> 2;
+ if (prop_value->format)
+ reply.nItems = len / (prop_value->format / 8);
+ else
+ reply.nItems = 0;
+ reply.propertyType = prop_value->type;
+
+ if (stuff->delete && (reply.bytesAfter == 0))
+ {
+ devicePropertyNotify event;
+
+ event.type = DevicePropertyNotify;
+ event.deviceid = dev->id;
+ event.state = PropertyDelete;
+ event.atom = prop->propertyName;
+ event.time = currentTime.milliseconds;
+ SendEventToAllWindows(dev, DevicePropertyNotifyMask,
+ (xEvent*)&event, 1);
+ }
+
+ WriteReplyToClient(client, sizeof(xGenericReply), &reply);
+ if (len)
+ {
+ switch (reply.format) {
+ case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
+ case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
+ default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
+ }
+ WriteSwappedDataToClient(client, len,
+ (char *)prop_value->data + ind);
+ }
+
+ if (stuff->delete && (reply.bytesAfter == 0))
+ { /* delete the Property */
+ *prev = prop->next;
+ XIDestroyDeviceProperty (prop);
+ }
+ return(client->noClientException);
+}
+
+
+int
+SProcXListDeviceProperties (ClientPtr client)
+{
+ char n;
+ REQUEST(xListDevicePropertiesReq);
+
+ swaps(&stuff->length, n);
+
+ REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
+ return (ProcXListDeviceProperties(client));
+}
+
+int
+SProcXChangeDeviceProperty (ClientPtr client)
+{
+ char n;
+ REQUEST(xChangeDevicePropertyReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->nUnits, n);
+ REQUEST_SIZE_MATCH(xChangeDevicePropertyReq);
+ return (ProcXChangeDeviceProperty(client));
+}
+
+int
+SProcXDeleteDeviceProperty (ClientPtr client)
+{
+ char n;
+ REQUEST(xDeleteDevicePropertyReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->property, n);
+ REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
+ return (ProcXDeleteDeviceProperty(client));
+}
+
+int
+SProcXGetDeviceProperty (ClientPtr client)
+{
+ char n;
+ REQUEST(xGetDevicePropertyReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->longOffset, n);
+ swapl(&stuff->longLength, n);
+ REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
+ return (ProcXGetDeviceProperty(client));
+}
+
+
+/* Reply swapping */
+
+void
+SRepXListDeviceProperties(ClientPtr client, int size,
+ xListDevicePropertiesReply *rep)
+{
+ char n;
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->nAtoms, n);
+ /* properties will be swapped later, see ProcXListDeviceProperties */
+ WriteToClient(client, size, (char*)rep);
+}
+
+void
+SRepXGetDeviceProperty(ClientPtr client, int size,
+ xGetDevicePropertyReply *rep)
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swapl(&rep->propertyType, n);
+ swapl(&rep->bytesAfter, n);
+ swapl(&rep->nItems, n);
+ /* data will be swapped, see ProcXGetDeviceProperty */
+ WriteToClient(client, size, (char*)rep);
+}
diff --git a/xorg-server/Xi/xiproperty.h b/xorg-server/Xi/xiproperty.h
new file mode 100644
index 000000000..12026e9e8
--- /dev/null
+++ b/xorg-server/Xi/xiproperty.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 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
+ */
+
+#ifndef XIPROPERTY_C
+#define XIPROPERTY_C
+
+int ProcXListDeviceProperties (ClientPtr client);
+int ProcXChangeDeviceProperty (ClientPtr client);
+int ProcXDeleteDeviceProperty (ClientPtr client);
+int ProcXGetDeviceProperty (ClientPtr client);
+
+/* request swapping */
+int SProcXListDeviceProperties (ClientPtr client);
+int SProcXChangeDeviceProperty (ClientPtr client);
+int SProcXDeleteDeviceProperty (ClientPtr client);
+int SProcXGetDeviceProperty (ClientPtr client);
+
+/* reply swapping */
+void SRepXListDeviceProperties(ClientPtr client, int size,
+ xListDevicePropertiesReply *rep);
+void SRepXGetDeviceProperty(ClientPtr client, int size,
+ xGetDevicePropertyReply *rep);
+
+void XIInitKnownProperties(void);
+
+#endif /* XIPROPERTY_C */