diff options
Diffstat (limited to 'xorg-server/Xi')
-rw-r--r-- | xorg-server/Xi/Makefile.am | 4 | ||||
-rw-r--r-- | xorg-server/Xi/Makefile.in | 83 | ||||
-rw-r--r-- | xorg-server/Xi/allowev.c | 12 | ||||
-rw-r--r-- | xorg-server/Xi/chgdctl.c | 20 | ||||
-rw-r--r-- | xorg-server/Xi/closedev.c | 6 | ||||
-rw-r--r-- | xorg-server/Xi/exevents.c | 1113 | ||||
-rw-r--r-- | xorg-server/Xi/exglobals.h | 9 | ||||
-rw-r--r-- | xorg-server/Xi/extinit.c | 379 | ||||
-rw-r--r-- | xorg-server/Xi/getvers.c | 16 | ||||
-rw-r--r-- | xorg-server/Xi/grabdev.c | 22 | ||||
-rw-r--r-- | xorg-server/Xi/grabdevb.c | 2 | ||||
-rw-r--r-- | xorg-server/Xi/grabdevk.c | 2 | ||||
-rw-r--r-- | xorg-server/Xi/gtmotion.c | 16 | ||||
-rw-r--r-- | xorg-server/Xi/listdev.c | 80 | ||||
-rw-r--r-- | xorg-server/Xi/listdev.h | 13 | ||||
-rw-r--r-- | xorg-server/Xi/opendev.c | 9 | ||||
-rw-r--r-- | xorg-server/Xi/queryst.c | 5 | ||||
-rw-r--r-- | xorg-server/Xi/selectev.c | 4 | ||||
-rw-r--r-- | xorg-server/Xi/sendexev.c | 3 | ||||
-rw-r--r-- | xorg-server/Xi/setdval.c | 2 | ||||
-rw-r--r-- | xorg-server/Xi/setmode.c | 2 | ||||
-rw-r--r-- | xorg-server/Xi/ungrdev.c | 8 | ||||
-rw-r--r-- | xorg-server/Xi/ungrdevb.c | 2 | ||||
-rw-r--r-- | xorg-server/Xi/ungrdevk.c | 2 | ||||
-rw-r--r-- | xorg-server/Xi/xiproperty.c | 918 | ||||
-rw-r--r-- | xorg-server/Xi/xiproperty.h | 48 |
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 */ |