summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-12-29 21:46:17 -0800
committerAnas Nashif <anas.nashif@intel.com>2012-12-29 21:46:17 -0800
commit6420d9368cb487bb5ea354863830153574d2207d (patch)
tree4ccfeda93b41826c67bc4298a4fc1807deed77fa /src
downloadxinput-6420d9368cb487bb5ea354863830153574d2207d.tar.gz
xinput-6420d9368cb487bb5ea354863830153574d2207d.tar.bz2
xinput-6420d9368cb487bb5ea354863830153574d2207d.zip
Imported Upstream version 1.6.0upstream/1.6.0
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am46
-rw-r--r--src/Makefile.in570
-rw-r--r--src/buttonmap.c156
-rw-r--r--src/feedback.c186
-rw-r--r--src/hierarchy.c205
-rw-r--r--src/list.c407
-rw-r--r--src/property.c838
-rw-r--r--src/setcp.c58
-rw-r--r--src/setint.c66
-rw-r--r--src/setmode.c71
-rw-r--r--src/setptr.c67
-rw-r--r--src/state.c107
-rw-r--r--src/test.c199
-rw-r--r--src/test_xi2.c461
-rw-r--r--src/transform.c289
-rw-r--r--src/xinput.c413
-rw-r--r--src/xinput.h84
17 files changed, 4223 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..985207b
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,46 @@
+# Copyright © 2007 Peter Hutterer
+# Copyright © 2009 Red Hat, Inc.
+#
+# 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.
+
+bin_PROGRAMS = xinput
+
+AM_CFLAGS = $(XINPUT_CFLAGS)
+xinput_LDADD = $(XINPUT_LIBS)
+
+
+if HAVE_XI2
+xinput2_files = hierarchy.c setcp.c test_xi2.c transform.c
+endif
+
+xinput_SOURCES = \
+ buttonmap.c \
+ feedback.c \
+ list.c \
+ setint.c \
+ setmode.c \
+ setptr.c \
+ state.c \
+ property.c \
+ test.c \
+ xinput.c \
+ xinput.h \
+ $(xinput2_files)
+
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..545c0b1
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,570 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Copyright © 2007 Peter Hutterer
+# Copyright © 2009 Red Hat, Inc.
+#
+# 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.
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = xinput$(EXEEXT)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am__xinput_SOURCES_DIST = buttonmap.c feedback.c list.c setint.c \
+ setmode.c setptr.c state.c property.c test.c xinput.c xinput.h \
+ hierarchy.c setcp.c test_xi2.c transform.c
+@HAVE_XI2_TRUE@am__objects_1 = hierarchy.$(OBJEXT) setcp.$(OBJEXT) \
+@HAVE_XI2_TRUE@ test_xi2.$(OBJEXT) transform.$(OBJEXT)
+am_xinput_OBJECTS = buttonmap.$(OBJEXT) feedback.$(OBJEXT) \
+ list.$(OBJEXT) setint.$(OBJEXT) setmode.$(OBJEXT) \
+ setptr.$(OBJEXT) state.$(OBJEXT) property.$(OBJEXT) \
+ test.$(OBJEXT) xinput.$(OBJEXT) $(am__objects_1)
+xinput_OBJECTS = $(am_xinput_OBJECTS)
+am__DEPENDENCIES_1 =
+xinput_DEPENDENCIES = $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(xinput_SOURCES)
+DIST_SOURCES = $(am__xinput_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADMIN_MAN_DIR = @ADMIN_MAN_DIR@
+ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APP_MAN_DIR = @APP_MAN_DIR@
+APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASE_CFLAGS = @BASE_CFLAGS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHANGELOG_CMD = @CHANGELOG_CMD@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CWARNFLAGS = @CWARNFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DRIVER_MAN_DIR = @DRIVER_MAN_DIR@
+DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FILE_MAN_DIR = @FILE_MAN_DIR@
+FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+GREP = @GREP@
+HAVE_XI2 = @HAVE_XI2@
+INSTALL = @INSTALL@
+INSTALL_CMD = @INSTALL_CMD@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIB_MAN_DIR = @LIB_MAN_DIR@
+LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN_SUBSTS = @MAN_SUBSTS@
+MISC_MAN_DIR = @MISC_MAN_DIR@
+MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRICT_CFLAGS = @STRICT_CFLAGS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+XI21_CFLAGS = @XI21_CFLAGS@
+XI21_LIBS = @XI21_LIBS@
+XI22_CFLAGS = @XI22_CFLAGS@
+XI22_LIBS = @XI22_LIBS@
+XI2_CFLAGS = @XI2_CFLAGS@
+XI2_LIBS = @XI2_LIBS@
+XINPUT_CFLAGS = @XINPUT_CFLAGS@
+XINPUT_LIBS = @XINPUT_LIBS@
+XORG_MAN_PAGE = @XORG_MAN_PAGE@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CFLAGS = $(XINPUT_CFLAGS)
+xinput_LDADD = $(XINPUT_LIBS)
+@HAVE_XI2_TRUE@xinput2_files = hierarchy.c setcp.c test_xi2.c transform.c
+xinput_SOURCES = \
+ buttonmap.c \
+ feedback.c \
+ list.c \
+ setint.c \
+ setmode.c \
+ setptr.c \
+ state.c \
+ property.c \
+ test.c \
+ xinput.c \
+ xinput.h \
+ $(xinput2_files)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+xinput$(EXEEXT): $(xinput_OBJECTS) $(xinput_DEPENDENCIES) $(EXTRA_xinput_DEPENDENCIES)
+ @rm -f xinput$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(xinput_OBJECTS) $(xinput_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buttonmap.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/feedback.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hierarchy.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/property.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setcp.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setint.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setmode.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setptr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/state.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_xi2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transform.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xinput.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic ctags distclean distclean-compile \
+ distclean-generic distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-binPROGRAMS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/buttonmap.c b/src/buttonmap.c
new file mode 100644
index 0000000..3396e75
--- /dev/null
+++ b/src/buttonmap.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "xinput.h"
+
+
+int
+get_button_map(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+ XDeviceInfo *info;
+ XDevice *device;
+ XAnyClassPtr ip;
+ int i;
+ int nbuttons;
+
+ if (argc != 1) {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ info = find_device_info(display, argv[0], False);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ ip = (XAnyClassPtr) info->inputclassinfo;
+ nbuttons = 0;
+
+ /* try to find the number of buttons */
+ for(i=0; i<info->num_classes; i++) {
+ if (ip->class == ButtonClass) {
+ nbuttons = ((XButtonInfoPtr)ip)->num_buttons;
+ break;
+ }
+ ip = (XAnyClassPtr) ((char *) ip + ip->length);
+ }
+ if (nbuttons == 0) {
+ fprintf(stderr, "device has no buttons\n");
+ return EXIT_FAILURE;
+ }
+
+ device = XOpenDevice(display, info->id);
+ if (device) {
+ int idx;
+ unsigned char *map;
+
+ map = (unsigned char *) malloc(sizeof(unsigned char) * nbuttons);
+
+ XGetDeviceButtonMapping(display, device, map, nbuttons);
+
+ for(idx=1; idx < nbuttons + 1; idx++) {
+ printf("%d ", map[idx - 1]);
+ }
+ printf("\n");
+ XCloseDevice(display, device);
+ return EXIT_SUCCESS;
+ } else {
+ fprintf(stderr, "Unable to open device\n");
+ return EXIT_FAILURE;
+ }
+}
+
+
+
+int
+set_button_map(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+ XDeviceInfo *info;
+ XDevice *device;
+ XAnyClassPtr ip;
+ int i;
+ int nbuttons;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ info = find_device_info(display, argv[0], False);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ ip = (XAnyClassPtr) info->inputclassinfo;
+ nbuttons = 0;
+
+ /* try to find the number of buttons */
+ for(i=0; i<info->num_classes; i++) {
+ if (ip->class == ButtonClass) {
+ nbuttons = ((XButtonInfoPtr)ip)->num_buttons;
+ break;
+ }
+ ip = (XAnyClassPtr) ((char *) ip + ip->length);
+ }
+ if (nbuttons == 0) {
+ fprintf(stderr, "device has no buttons\n");
+ return EXIT_FAILURE;
+ }
+
+ device = XOpenDevice(display, info->id);
+ if (device) {
+ int idx;
+ unsigned char *map;
+ int min;
+
+ map = (unsigned char *) malloc(sizeof(unsigned char) * nbuttons);
+
+ XGetDeviceButtonMapping(display, device, map, nbuttons);
+
+ min = (argc > nbuttons + 1) ? nbuttons + 1 : argc;
+
+ for(idx=1; idx < min; idx++) {
+ map[idx - 1] = atoi(argv[idx]);
+ }
+ XSetDeviceButtonMapping(display, device, map, nbuttons);
+ XCloseDevice(display, device);
+ return EXIT_SUCCESS;
+ } else {
+ fprintf(stderr, "Unable to open device\n");
+ return EXIT_FAILURE;
+ }
+}
+
+/* end of buttonmap.c */
diff --git a/src/feedback.c b/src/feedback.c
new file mode 100644
index 0000000..71eb155
--- /dev/null
+++ b/src/feedback.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "xinput.h"
+
+int
+set_ptr_feedback(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+ XDeviceInfo *info;
+ XDevice *device;
+ XPtrFeedbackControl feedback;
+ XFeedbackState *state;
+ int num_feedbacks;
+ int loop;
+ int id;
+
+ if (argc != 4) {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return 1;
+ }
+
+ info = find_device_info(display, argv[0], True);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return 1;
+ }
+
+ device = XOpenDevice(display, info->id);
+
+ if (!device) {
+ fprintf(stderr, "unable to open device '%s'\n", argv[0]);
+ return 1;
+ }
+
+ /* We will match the first Ptr Feedback class. Can there be more? */
+ id = -1;
+ state = XGetFeedbackControl(display, device, &num_feedbacks);
+ for(loop=0; loop<num_feedbacks; loop++) {
+ if (state->class == PtrFeedbackClass) {
+ id = state->id;
+ }
+ state = (XFeedbackState*) ((char*) state + state->length);
+ }
+
+ if (id == -1) {
+ fprintf(stderr, "unable to find PtrFeedbackClass for '%s'\n", argv[0]);
+ return 1;
+ }
+
+ feedback.class = PtrFeedbackClass;
+ feedback.length = sizeof(XPtrFeedbackControl);
+ feedback.id = id;
+ feedback.threshold = atoi(argv[1]);
+ feedback.accelNum = atoi(argv[2]);
+ feedback.accelDenom = atoi(argv[3]);
+
+ XChangeFeedbackControl(display, device, DvAccelNum|DvAccelDenom|DvThreshold,
+ (XFeedbackControl*) &feedback);
+ return EXIT_SUCCESS;
+}
+
+
+int
+get_feedbacks(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+ XDeviceInfo *info;
+ XDevice *device;
+ XFeedbackState *state;
+ int num_feedbacks;
+ int loop;
+ XPtrFeedbackState *p;
+ XKbdFeedbackState *k;
+ XBellFeedbackState *b;
+ XLedFeedbackState *l;
+ XIntegerFeedbackState *i;
+ XStringFeedbackState *s;
+
+ if (argc != 1) {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return 1;
+ }
+
+ info = find_device_info(display, argv[0], True);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return 1;
+ }
+
+ device = XOpenDevice(display, info->id);
+
+ if (!device) {
+ fprintf(stderr, "unable to open device '%s'\n", argv[0]);
+ return 1;
+ }
+
+ state = XGetFeedbackControl(display, device, &num_feedbacks);
+
+ printf("%d feedback class%s\n", num_feedbacks,
+ (num_feedbacks > 1) ? "es" : "");
+
+ for(loop=0; loop<num_feedbacks; loop++) {
+ switch (state->class) {
+ case KbdFeedbackClass:
+ k = (XKbdFeedbackState*) state;
+ printf("KbdFeedbackClass id=%ld\n", state->id);
+ printf("\tclick is %d\n", k->click);
+ printf("\tpercent is %d\n", k->percent);
+ printf("\tpitch is %d\n", k->pitch);
+ printf("\tduration is %d\n", k->duration);
+ printf("\tled_mask is %d\n", k->led_mask);
+ printf("\tglobal_auto_repeat is %d\n", k->global_auto_repeat);
+ break;
+
+ case PtrFeedbackClass:
+ p = (XPtrFeedbackState*) state;
+ printf("PtrFeedbackClass id=%ld\n", state->id);
+ printf("\taccelNum is %d\n", p->accelNum);
+ printf("\taccelDenom is %d\n", p->accelDenom);
+ printf("\tthreshold is %d\n", p->threshold);
+ break;
+
+ case StringFeedbackClass:
+ s = (XStringFeedbackState*) state;
+ printf("XStringFeedbackControl id=%ld\n", state->id);
+ printf("\tmax_symbols is %d\n", s->max_symbols);
+ printf("\tnum_syms_supported is %d\n", s->num_syms_supported);
+ break;
+
+ case IntegerFeedbackClass:
+ i = (XIntegerFeedbackState*) state;
+ printf("XIntegerFeedbackControl id=%ld\n", state->id);
+ printf("\tresolution is %d\n", i->resolution);
+ printf("\tminVal is %d\n", i->minVal);
+ printf("\tmaxVal is %d\n", i->maxVal);
+ break;
+
+ case LedFeedbackClass:
+ l = (XLedFeedbackState*) state;
+ printf("XLedFeedbackState id=%ld\n", state->id);
+ printf("\tled_values is %d\n", l->led_values);
+ break;
+
+ case BellFeedbackClass:
+ b = (XBellFeedbackState*) state;
+ printf("XBellFeedbackControl id=%ld\n", state->id);
+ printf("\tpercent is %d\n", b->percent);
+ printf("\tpitch is %d\n", b->pitch);
+ printf("\tduration is %d\n", b->duration);
+ break;
+ }
+ state = (XFeedbackState*) ((char*) state + state->length);
+ }
+ return EXIT_SUCCESS;
+}
+
+/* end of ptrfdbk.c */
diff --git a/src/hierarchy.c b/src/hierarchy.c
new file mode 100644
index 0000000..f3eb378
--- /dev/null
+++ b/src/hierarchy.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright © 2007 Peter Hutterer
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#include "xinput.h"
+#include <string.h>
+
+#define Error(error, ...) \
+{ \
+ fprintf(stderr, __VA_ARGS__); \
+ return error;\
+}
+/**
+ * Create a new master device. Name must be supplied, other values are
+ * optional.
+ */
+int
+create_master(Display* dpy, int argc, char** argv, char* name, char *desc)
+{
+ XIAddMasterInfo c;
+
+ if (argc == 0)
+ {
+ fprintf(stderr, "Usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ c.type = XIAddMaster;
+ c.name = argv[0];
+ c.send_core = (argc >= 2) ? atoi(argv[1]) : 1;
+ c.enable = (argc >= 3) ? atoi(argv[2]) : 1;
+
+ return XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&c, 1);
+}
+
+/**
+ * Remove a master device.
+ * By default, all attached devices are set to Floating, unless parameters are
+ * given.
+ */
+int
+remove_master(Display* dpy, int argc, char** argv, char *name, char *desc)
+{
+ XIRemoveMasterInfo r;
+ XIDeviceInfo *info;
+ int ret;
+
+ if (argc == 0)
+ {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ info = xi2_find_device_info(dpy, argv[0]);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ r.type = XIRemoveMaster;
+ r.deviceid = info->deviceid;
+ if (argc >= 2)
+ {
+ if (!strcmp(argv[1], "Floating"))
+ r.return_mode = XIFloating;
+ else if (!strcmp(argv[1], "AttachToMaster"))
+ r.return_mode = XIAttachToMaster;
+ else
+ Error(BadValue, "Invalid return_mode.\n");
+ } else
+ r.return_mode = XIFloating;
+
+ if (r.return_mode == XIAttachToMaster)
+ {
+ r.return_pointer = 0;
+ if (argc >= 3) {
+ info = xi2_find_device_info(dpy, argv[2]);
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+
+ r.return_pointer = info->deviceid;
+ }
+
+ r.return_keyboard = 0;
+ if (argc >= 4) {
+ info = xi2_find_device_info(dpy, argv[3]);
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[3]);
+ return EXIT_FAILURE;
+ }
+
+ r.return_keyboard = info->deviceid;
+ }
+
+ if (!r.return_pointer || !r.return_keyboard) {
+ int i, ndevices;
+ info = XIQueryDevice(dpy, XIAllMasterDevices, &ndevices);
+ for(i = 0; i < ndevices; i++) {
+ if (info[i].use == XIMasterPointer && !r.return_pointer)
+ r.return_pointer = info[i].deviceid;
+ if (info[i].use == XIMasterKeyboard && !r.return_keyboard)
+ r.return_keyboard = info[i].deviceid;
+ if (r.return_pointer && r.return_keyboard)
+ break;
+ }
+
+ XIFreeDeviceInfo(info);
+ }
+ }
+
+ ret = XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&r, 1);
+ return ret;
+}
+
+/**
+ * Swap a device from one master to another.
+ */
+int
+change_attachment(Display* dpy, int argc, char** argv, char *name, char* desc)
+{
+ XIDeviceInfo *sd_info, *md_info;
+ XIAttachSlaveInfo c;
+ int ret;
+
+ if (argc < 2)
+ {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ sd_info = xi2_find_device_info(dpy, argv[0]);
+ md_info= xi2_find_device_info(dpy, argv[1]);
+
+ if (!sd_info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ if (!md_info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ c.type = XIAttachSlave;
+ c.deviceid = sd_info->deviceid;
+ c.new_master = md_info->deviceid;
+
+ ret = XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&c, 1);
+ return ret;
+}
+
+/**
+ * Set a device floating.
+ */
+int
+float_device(Display* dpy, int argc, char** argv, char* name, char* desc)
+{
+ XIDeviceInfo *info;
+ XIDetachSlaveInfo c;
+ int ret;
+
+ if (argc < 1)
+ {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ info = xi2_find_device_info(dpy, argv[0]);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ c.type = XIDetachSlave;
+ c.deviceid = info->deviceid;
+
+ ret = XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&c, 1);
+ return ret;
+}
+
+
diff --git a/src/list.c b/src/list.c
new file mode 100644
index 0000000..cc39bd3
--- /dev/null
+++ b/src/list.c
@@ -0,0 +1,407 @@
+/*
+ * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "xinput.h"
+#include <string.h>
+
+enum print_format {
+ FORMAT_NONE,
+ FORMAT_SHORT,
+ FORMAT_LONG,
+ FORMAT_NAME,
+ FORMAT_ID,
+};
+
+
+static void
+print_info(Display* dpy, XDeviceInfo *info, enum print_format format)
+{
+ int i,j;
+ XAnyClassPtr any;
+ XKeyInfoPtr k;
+ XButtonInfoPtr b;
+ XValuatorInfoPtr v;
+ XAxisInfoPtr a;
+
+ if (format == FORMAT_NAME)
+ {
+ printf("%s\n", info->name);
+ return;
+ } else if (format == FORMAT_ID)
+ {
+ printf("%ld\n", info->id);
+ return;
+ }
+
+ printf("\"%s\"\tid=%ld\t[", info->name, info->id);
+
+ switch (info->use) {
+ case IsXPointer:
+ printf("XPointer");
+ break;
+ case IsXKeyboard:
+ printf("XKeyboard");
+ break;
+ case IsXExtensionDevice:
+ printf("XExtensionDevice");
+ break;
+ case IsXExtensionKeyboard:
+ printf("XExtensionKeyboard");
+ break;
+ case IsXExtensionPointer:
+ printf("XExtensionPointer");
+ break;
+ default:
+ printf("Unknown class");
+ break;
+ }
+ printf("]\n");
+
+ if (format == FORMAT_SHORT)
+ return;
+
+ if(info->type != None)
+ printf("\tType is %s\n", XGetAtomName(dpy, info->type));
+
+ if (info->num_classes > 0) {
+ any = (XAnyClassPtr) (info->inputclassinfo);
+ for (i=0; i<info->num_classes; i++) {
+ switch (any->class) {
+ case KeyClass:
+ k = (XKeyInfoPtr) any;
+ printf("\tNum_keys is %d\n", k->num_keys);
+ printf("\tMin_keycode is %d\n", k->min_keycode);
+ printf("\tMax_keycode is %d\n", k->max_keycode);
+ break;
+
+ case ButtonClass:
+ b = (XButtonInfoPtr) any;
+ printf("\tNum_buttons is %d\n", b->num_buttons);
+ break;
+
+ case ValuatorClass:
+ v = (XValuatorInfoPtr) any;
+ a = (XAxisInfoPtr) ((char *) v +
+ sizeof (XValuatorInfo));
+ printf("\tNum_axes is %d\n", v->num_axes);
+ printf("\tMode is %s\n", (v->mode == Absolute) ? "Absolute" : "Relative");
+ printf("\tMotion_buffer is %ld\n", v->motion_buffer);
+ for (j=0; j<v->num_axes; j++, a++) {
+ printf("\tAxis %d :\n", j);
+ printf("\t\tMin_value is %d\n", a->min_value);
+ printf("\t\tMax_value is %d\n", a->max_value);
+ printf ("\t\tResolution is %d\n", a->resolution);
+ }
+ break;
+ default:
+ printf ("unknown class\n");
+ }
+ any = (XAnyClassPtr) ((char *) any + any->length);
+ }
+ }
+}
+
+static int list_xi1(Display *display,
+ enum print_format format)
+{
+ XDeviceInfo *info;
+ int loop;
+ int num_devices;
+
+ info = XListInputDevices(display, &num_devices);
+ for(loop=0; loop<num_devices; loop++) {
+ print_info(display, info+loop, format);
+ }
+ return EXIT_SUCCESS;
+}
+
+#ifdef HAVE_XI2
+/* also used from test_xi2.c */
+void
+print_classes_xi2(Display* display, XIAnyClassInfo **classes,
+ int num_classes)
+{
+ int i, j;
+
+ printf("\tReporting %d classes:\n", num_classes);
+ for (i = 0; i < num_classes; i++)
+ {
+ printf("\t\tClass originated from: %d. Type: ", classes[i]->sourceid);
+ switch(classes[i]->type)
+ {
+ case XIButtonClass:
+ {
+ XIButtonClassInfo *b = (XIButtonClassInfo*)classes[i];
+ char *name;
+ printf("XIButtonClass\n");
+ printf("\t\tButtons supported: %d\n", b->num_buttons);
+ printf("\t\tButton labels:");
+ for (j = 0; j < b->num_buttons; j++)
+ {
+ name = (b->labels[j]) ? XGetAtomName(display, b->labels[j]) : NULL;
+ if (name)
+ printf(" \"%s\"", name);
+ else
+ printf(" None");
+ XFree(name);
+ }
+ printf("\n");
+ printf("\t\tButton state:");
+ for (j = 0; j < b->state.mask_len * 8; j++)
+ if (XIMaskIsSet(b->state.mask, j))
+ printf(" %d", j);
+ printf("\n");
+
+ }
+ break;
+ case XIKeyClass:
+ {
+ XIKeyClassInfo *k = (XIKeyClassInfo*)classes[i];
+ printf("XIKeyClass\n");
+ printf("\t\tKeycodes supported: %d\n", k->num_keycodes);
+ }
+ break;
+ case XIValuatorClass:
+ {
+ XIValuatorClassInfo *v = (XIValuatorClassInfo*)classes[i];
+ char *name = v->label ? XGetAtomName(display, v->label) : NULL;
+
+ /* Bug in X servers 1.7..1.8.1, mode was | OutOfProximity */
+ v->mode &= DeviceMode;
+
+ printf("XIValuatorClass\n");
+ printf("\t\tDetail for Valuator %d:\n", v->number);
+ printf("\t\t Label: %s\n", (name) ? name : "None");
+ printf("\t\t Range: %f - %f\n", v->min, v->max);
+ printf("\t\t Resolution: %d units/m\n", v->resolution);
+ printf("\t\t Mode: %s\n", v->mode == Absolute ? "absolute" :
+ "relative");
+ if (v->mode == Absolute)
+ printf("\t\t Current value: %f\n", v->value);
+ XFree(name);
+ }
+ break;
+#if HAVE_XI21
+ case XIScrollClass:
+ {
+ XIScrollClassInfo *s = (XIScrollClassInfo*)classes[i];
+
+ printf("XIScrollClass\n");
+ printf("\t\tScroll info for Valuator %d\n", s->number);
+ printf("\t\t type: %d (%s)\n", s->scroll_type,
+ (s->scroll_type == XIScrollTypeHorizontal) ? "horizontal" :
+ (s->scroll_type == XIScrollTypeVertical) ? "vertical" : "unknown");
+ printf("\t\t increment: %f\n", s->increment);
+ printf("\t\t flags: 0x%x", s->flags);
+ if (s->flags) {
+ printf(" (");
+ if (s->flags & XIScrollFlagNoEmulation)
+ printf(" no-emulation ");
+ if (s->flags & XIScrollFlagPreferred)
+ printf(" preferred ");
+ printf(")");
+ }
+ printf("\n");
+ }
+ break;
+#endif
+#if HAVE_XI22
+ case XITouchClass:
+ {
+ XITouchClassInfo *t = (XITouchClassInfo*)classes[i];
+
+ printf("XITouchClass\n");
+ printf("\t\tTouch mode: %s\n",
+ (t->mode == XIDirectTouch) ? "direct" : "dependent");
+ printf("\t\tMax number of touches: %d\n", t->num_touches);
+ }
+#endif
+ }
+ }
+
+ printf("\n");
+}
+
+static void
+print_info_xi2(Display* display, XIDeviceInfo *dev, enum print_format format)
+{
+ if (format == FORMAT_NAME)
+ {
+ printf("%s\n", dev->name);
+ return;
+ } else if (format == FORMAT_ID)
+ {
+ printf("%d\n", dev->deviceid);
+ return;
+ }
+
+ printf("%-40s\tid=%d\t[", dev->name, dev->deviceid);
+ switch(dev->use)
+ {
+ case XIMasterPointer:
+ printf("master pointer (%d)]\n", dev->attachment);
+ break;
+ case XIMasterKeyboard:
+ printf("master keyboard (%d)]\n", dev->attachment);
+ break;
+ case XISlavePointer:
+ printf("slave pointer (%d)]\n", dev->attachment);
+ break;
+ case XISlaveKeyboard:
+ printf("slave keyboard (%d)]\n", dev->attachment);
+ break;
+ case XIFloatingSlave:
+ printf("floating slave]\n");
+ break;
+ }
+
+ if (format == FORMAT_SHORT)
+ return;
+
+ if (!dev->enabled)
+ printf("\tThis device is disabled\n");
+
+ print_classes_xi2(display, dev->classes, dev->num_classes);
+}
+
+
+static int
+list_xi2(Display *display,
+ enum print_format format)
+{
+ int ndevices;
+ int i, j;
+ XIDeviceInfo *info, *dev;
+
+ info = XIQueryDevice(display, XIAllDevices, &ndevices);
+
+ for(i = 0; i < ndevices; i++)
+ {
+ dev = &info[i];
+ if (dev->use == XIMasterPointer || dev->use == XIMasterKeyboard)
+ {
+ if (format == FORMAT_SHORT || format == FORMAT_LONG)
+ {
+ if (dev->use == XIMasterPointer)
+ printf("⎡ ");
+ else
+ printf("⎣ ");
+ }
+
+ print_info_xi2(display, dev, format);
+ for (j = 0; j < ndevices; j++)
+ {
+ XIDeviceInfo* sd = &info[j];
+
+ if ((sd->use == XISlavePointer || sd->use == XISlaveKeyboard) &&
+ (sd->attachment == dev->deviceid))
+ {
+ if (format == FORMAT_SHORT || format == FORMAT_LONG)
+ printf("%s ↳ ", dev->use == XIMasterPointer ? "⎜" : " ");
+ print_info_xi2(display, sd, format);
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < ndevices; i++)
+ {
+ dev = &info[i];
+ if (dev->use == XIFloatingSlave)
+ {
+ printf("∼ ");
+ print_info_xi2(display, dev, format);
+ }
+ }
+
+
+ XIFreeDeviceInfo(info);
+ return EXIT_SUCCESS;
+}
+#endif
+
+int
+list(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+ enum print_format format = FORMAT_NONE;
+ int arg_dev = 1;
+
+ if (argc >= 1)
+ {
+ if (strcmp(argv[0], "--short") == 0)
+ format = FORMAT_SHORT;
+ else if (strcmp(argv[0], "--long") == 0)
+ format = FORMAT_LONG;
+ else if (strcmp(argv[0], "--name-only") == 0)
+ format = FORMAT_NAME;
+ else if (strcmp(argv[0], "--id-only") == 0)
+ format = FORMAT_ID;
+ else
+ arg_dev--;
+ }
+
+ if (argc > arg_dev)
+ {
+ if (format == FORMAT_NONE)
+ format = FORMAT_LONG;
+#ifdef HAVE_XI2
+ if (xinput_version(display) == XI_2_Major)
+ {
+ XIDeviceInfo *info = xi2_find_device_info(display, argv[arg_dev]);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device %s\n", argv[arg_dev]);
+ return EXIT_FAILURE;
+ } else {
+ print_info_xi2(display, info, format);
+ return EXIT_SUCCESS;
+ }
+ } else
+#endif
+ {
+ XDeviceInfo *info = find_device_info(display, argv[arg_dev], False);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device %s\n", argv[arg_dev]);
+ return EXIT_FAILURE;
+ } else {
+ print_info(display, info, format);
+ return EXIT_SUCCESS;
+ }
+ }
+ } else {
+ if (format == FORMAT_NONE)
+ format = FORMAT_SHORT;
+#ifdef HAVE_XI2
+ if (xinput_version(display) == XI_2_Major)
+ return list_xi2(display, format);
+#endif
+ return list_xi1(display, format);
+ }
+}
+
+/* end of list.c */
diff --git a/src/property.c b/src/property.c
new file mode 100644
index 0000000..14e4308
--- /dev/null
+++ b/src/property.c
@@ -0,0 +1,838 @@
+/*
+ * Copyright © 2007 Peter Hutterer
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/XIproto.h>
+
+#include "xinput.h"
+
+static Atom parse_atom(Display *dpy, char *name) {
+ Bool is_atom = True;
+ int i;
+
+ for (i = 0; name[i] != '\0'; i++) {
+ if (!isdigit(name[i])) {
+ is_atom = False;
+ break;
+ }
+ }
+
+ if (is_atom)
+ return atoi(name);
+ else
+ return XInternAtom(dpy, name, False);
+}
+
+static void
+print_property(Display *dpy, XDevice* dev, Atom property)
+{
+ Atom act_type;
+ char *name;
+ int act_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data, *ptr;
+ int j, done = False, size = 0;
+
+ name = XGetAtomName(dpy, property);
+ printf("\t%s (%ld):\t", name, property);
+
+ if (XGetDeviceProperty(dpy, dev, property, 0, 1000, False,
+ AnyPropertyType, &act_type, &act_format,
+ &nitems, &bytes_after, &data) == Success)
+ {
+ Atom float_atom = XInternAtom(dpy, "FLOAT", True);
+
+ ptr = data;
+
+ if (nitems == 0)
+ printf("<no items>");
+
+ switch(act_format)
+ {
+ case 8: size = sizeof(char); break;
+ case 16: size = sizeof(short); break;
+ case 32: size = sizeof(long); break;
+ }
+
+ for (j = 0; j < nitems; j++)
+ {
+ switch(act_type)
+ {
+ case XA_INTEGER:
+ switch(act_format)
+ {
+ case 8:
+ printf("%d", *((char*)ptr));
+ break;
+ case 16:
+ printf("%d", *((short*)ptr));
+ break;
+ case 32:
+ printf("%ld", *((long*)ptr));
+ break;
+ }
+ break;
+ case XA_CARDINAL:
+ switch(act_format)
+ {
+ case 8:
+ printf("%u", *((unsigned char*)ptr));
+ break;
+ case 16:
+ printf("%u", *((unsigned short*)ptr));
+ break;
+ case 32:
+ printf("%lu", *((unsigned long*)ptr));
+ break;
+ }
+ break;
+ case XA_STRING:
+ if (act_format != 8)
+ {
+ printf("Unknown string format.\n");
+ done = True;
+ break;
+ }
+ printf("\"%s\"", ptr);
+ j += strlen((char*)ptr); /* The loop's j++ jumps over the
+ terminating 0 */
+ ptr += strlen((char*)ptr); /* ptr += size below jumps over
+ the terminating 0 */
+ break;
+ case XA_ATOM:
+ {
+ Atom a = *(Atom*)ptr;
+ printf("\"%s\" (%d)",
+ (a) ? XGetAtomName(dpy, a) : "None",
+ (int)a);
+ break;
+ }
+ default:
+ if (float_atom != None && act_type == float_atom)
+ {
+ printf("%f", *((float*)ptr));
+ break;
+ }
+
+ printf("\t... of unknown type '%s'\n",
+ XGetAtomName(dpy, act_type));
+ done = True;
+ break;
+ }
+
+ ptr += size;
+
+ if (done == True)
+ break;
+ if (j < nitems - 1)
+ printf(", ");
+ }
+ printf("\n");
+ XFree(data);
+ } else
+ printf("\tFetch failure\n");
+
+}
+
+static int
+list_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc)
+{
+ XDeviceInfo *info;
+ XDevice *dev;
+ int i;
+ int nprops;
+ Atom *props;
+
+ if (argc == 0)
+ {
+ fprintf(stderr, "Usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ for (i = 0; i < argc; i++)
+ {
+ info = find_device_info(dpy, argv[i], False);
+ if (!info)
+ {
+ fprintf(stderr, "unable to find device '%s'\n", argv[i]);
+ continue;
+ }
+
+ dev = XOpenDevice(dpy, info->id);
+ if (!dev)
+ {
+ fprintf(stderr, "unable to open device '%s'\n", info->name);
+ continue;
+ }
+
+ props = XListDeviceProperties(dpy, dev, &nprops);
+ if (!nprops)
+ {
+ printf("Device '%s' does not report any properties.\n", info->name);
+ continue;
+ }
+
+ printf("Device '%s':\n", info->name);
+ while(nprops--)
+ {
+ print_property(dpy, dev, props[nprops]);
+ }
+
+ XFree(props);
+ XCloseDevice(dpy, dev);
+ }
+ return EXIT_SUCCESS;
+}
+
+
+int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc)
+{
+ XDevice *dev;
+ XDeviceInfo *info;
+ XEvent ev;
+ XDevicePropertyNotifyEvent *dpev;
+ char *name;
+ int type_prop;
+ XEventClass cls_prop;
+
+ if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS)
+ return EXIT_FAILURE;
+
+ info = find_device_info(dpy, argv[0], False);
+ if (!info)
+ {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ dev = XOpenDevice(dpy, info->id);
+ if (!dev)
+ {
+ fprintf(stderr, "unable to open device '%s'\n", info->name);
+ return EXIT_FAILURE;
+ }
+
+ DevicePropertyNotify(dev, type_prop, cls_prop);
+ XSelectExtensionEvent(dpy, DefaultRootWindow(dpy), &cls_prop, 1);
+
+ while(1)
+ {
+ XNextEvent(dpy, &ev);
+
+ dpev = (XDevicePropertyNotifyEvent*)&ev;
+ if (dpev->type != type_prop)
+ continue;
+
+ name = XGetAtomName(dpy, dpev->atom);
+ printf("Property '%s' changed.\n", name);
+ print_property(dpy, dev, dpev->atom);
+ }
+
+ XCloseDevice(dpy, dev);
+}
+
+static int
+delete_prop_xi1(Display *dpy, int argc, char** argv, char* n, char *desc)
+{
+ XDevice *dev;
+ XDeviceInfo *info;
+ char *name;
+ Atom prop;
+
+ info = find_device_info(dpy, argv[0], False);
+ if (!info)
+ {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ dev = XOpenDevice(dpy, info->id);
+ if (!dev)
+ {
+ fprintf(stderr, "unable to open device '%s'\n", info->name);
+ return EXIT_FAILURE;
+ }
+
+ name = argv[1];
+
+ prop = parse_atom(dpy, name);
+
+ XDeleteDeviceProperty(dpy, dev, prop);
+
+ XCloseDevice(dpy, dev);
+ return EXIT_SUCCESS;
+}
+
+static int
+do_set_prop_xi1(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc)
+{
+ XDeviceInfo *info;
+ XDevice *dev;
+ Atom prop;
+ Atom old_type;
+ char *name;
+ int i;
+ Atom float_atom;
+ int old_format, nelements = 0;
+ unsigned long act_nitems, bytes_after;
+ char *endptr;
+ union {
+ unsigned char *c;
+ short *s;
+ long *l;
+ Atom *a;
+ } data;
+
+ if (argc < 3)
+ {
+ fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
+ return EXIT_FAILURE;
+ }
+
+ info = find_device_info(dpy, argv[0], False);
+ if (!info)
+ {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ dev = XOpenDevice(dpy, info->id);
+ if (!dev)
+ {
+ fprintf(stderr, "unable to open device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ name = argv[1];
+
+ prop = parse_atom(dpy, name);
+
+ if (prop == None) {
+ fprintf(stderr, "invalid property '%s'\n", name);
+ return EXIT_FAILURE;
+ }
+
+ float_atom = XInternAtom(dpy, "FLOAT", False);
+
+ nelements = argc - 2;
+ if (type == None || format == 0) {
+ if (XGetDeviceProperty(dpy, dev, prop, 0, 0, False, AnyPropertyType,
+ &old_type, &old_format, &act_nitems,
+ &bytes_after, &data.c) != Success) {
+ fprintf(stderr, "failed to get property type and format for '%s'\n",
+ name);
+ return EXIT_FAILURE;
+ } else {
+ if (type == None)
+ type = old_type;
+ if (format == 0)
+ format = old_format;
+ }
+
+ XFree(data.c);
+ }
+
+ if (type == None) {
+ fprintf(stderr, "property '%s' doesn't exist, you need to specify "
+ "its type and format\n", name);
+ return EXIT_FAILURE;
+ }
+
+ data.c = calloc(nelements, sizeof(long));
+
+ for (i = 0; i < nelements; i++)
+ {
+ if (type == XA_INTEGER || type == XA_CARDINAL) {
+ switch (format)
+ {
+ case 8:
+ data.c[i] = atoi(argv[2 + i]);
+ break;
+ case 16:
+ data.s[i] = atoi(argv[2 + i]);
+ break;
+ case 32:
+ data.l[i] = atoi(argv[2 + i]);
+ break;
+ default:
+ fprintf(stderr, "unexpected size for property '%s'", name);
+ return EXIT_FAILURE;
+ }
+ } else if (type == float_atom) {
+ if (format != 32) {
+ fprintf(stderr, "unexpected format %d for property '%s'\n",
+ format, name);
+ return EXIT_FAILURE;
+ }
+ *(float *)(data.l + i) = strtod(argv[2 + i], &endptr);
+ if (endptr == argv[2 + i]) {
+ fprintf(stderr, "argument '%s' could not be parsed\n", argv[2 + i]);
+ return EXIT_FAILURE;
+ }
+ } else if (type == XA_ATOM) {
+ if (format != 32) {
+ fprintf(stderr, "unexpected format %d for property '%s'\n",
+ format, name);
+ return EXIT_FAILURE;
+ }
+ data.a[i] = parse_atom(dpy, argv[2 + i]);
+ } else {
+ fprintf(stderr, "unexpected type for property '%s'\n", name);
+ return EXIT_FAILURE;
+ }
+ }
+
+ XChangeDeviceProperty(dpy, dev, prop, type, format, PropModeReplace,
+ data.c, nelements);
+ free(data.c);
+ XCloseDevice(dpy, dev);
+ return EXIT_SUCCESS;
+}
+
+#if HAVE_XI2
+static void
+print_property_xi2(Display *dpy, int deviceid, Atom property)
+{
+ Atom act_type;
+ char *name;
+ int act_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data, *ptr;
+ int j, done = False;
+
+ name = XGetAtomName(dpy, property);
+ printf("\t%s (%ld):\t", name, property);
+
+ if (XIGetProperty(dpy, deviceid, property, 0, 1000, False,
+ AnyPropertyType, &act_type, &act_format,
+ &nitems, &bytes_after, &data) == Success)
+ {
+ Atom float_atom = XInternAtom(dpy, "FLOAT", True);
+
+ ptr = data;
+
+ if (nitems == 0)
+ printf("<no items>");
+
+ for (j = 0; j < nitems; j++)
+ {
+ switch(act_type)
+ {
+ case XA_INTEGER:
+ switch(act_format)
+ {
+ case 8:
+ printf("%d", *((int8_t*)ptr));
+ break;
+ case 16:
+ printf("%d", *((int16_t*)ptr));
+ break;
+ case 32:
+ printf("%d", *((int32_t*)ptr));
+ break;
+ }
+ break;
+ case XA_CARDINAL:
+ switch(act_format)
+ {
+ case 8:
+ printf("%u", *((uint8_t*)ptr));
+ break;
+ case 16:
+ printf("%u", *((uint16_t*)ptr));
+ break;
+ case 32:
+ printf("%u", *((uint32_t*)ptr));
+ break;
+ }
+ break;
+ case XA_STRING:
+ if (act_format != 8)
+ {
+ printf("Unknown string format.\n");
+ done = True;
+ break;
+ }
+ printf("\"%s\"", ptr);
+ j += strlen((char*)ptr); /* The loop's j++ jumps over the
+ terminating 0 */
+ ptr += strlen((char*)ptr); /* ptr += size below jumps over
+ the terminating 0 */
+ break;
+ case XA_ATOM:
+ {
+ Atom a = *(uint32_t*)ptr;
+ printf("\"%s\" (%ld)",
+ (a) ? XGetAtomName(dpy, a) : "None",
+ a);
+ break;
+ }
+ break;
+ default:
+ if (float_atom != None && act_type == float_atom)
+ {
+ printf("%f", *((float*)ptr));
+ break;
+ }
+
+ printf("\t... of unknown type %s\n",
+ XGetAtomName(dpy, act_type));
+ done = True;
+ break;
+ }
+
+ ptr += act_format/8;
+
+ if (done == True)
+ break;
+ if (j < nitems - 1)
+ printf(", ");
+ }
+ printf("\n");
+ XFree(data);
+ } else
+ printf("\tFetch failure\n");
+
+}
+
+static int
+list_props_xi2(Display *dpy, int argc, char** argv, char* name, char *desc)
+{
+ XIDeviceInfo *info;
+ int i;
+ int nprops;
+ Atom *props;
+
+ if (argc == 0)
+ {
+ fprintf(stderr, "Usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ for (i = 0; i < argc; i++)
+ {
+ info = xi2_find_device_info(dpy, argv[i]);
+ if (!info)
+ {
+ fprintf(stderr, "unable to find device %s\n", argv[i]);
+ continue;
+ }
+
+ props = XIListProperties(dpy, info->deviceid, &nprops);
+ if (!nprops)
+ {
+ printf("Device '%s' does not report any properties.\n", info->name);
+ continue;
+ }
+
+ printf("Device '%s':\n", info->name);
+ while(nprops--)
+ {
+ print_property_xi2(dpy, info->deviceid, props[nprops]);
+ }
+
+ XFree(props);
+ }
+ return EXIT_SUCCESS;
+}
+
+static int
+delete_prop_xi2(Display *dpy, int argc, char** argv, char* n, char *desc)
+{
+ XIDeviceInfo *info;
+ char *name;
+ Atom prop;
+
+ info = xi2_find_device_info(dpy, argv[0]);
+ if (!info)
+ {
+ fprintf(stderr, "unable to find device %s\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ name = argv[1];
+
+ prop = parse_atom(dpy, name);
+
+ XIDeleteProperty(dpy, info->deviceid, prop);
+
+ return EXIT_SUCCESS;
+}
+
+static int
+do_set_prop_xi2(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc)
+{
+ XIDeviceInfo *info;
+ Atom prop;
+ Atom old_type;
+ char *name;
+ int i;
+ Atom float_atom;
+ int old_format, nelements = 0;
+ unsigned long act_nitems, bytes_after;
+ char *endptr;
+ union {
+ unsigned char *c;
+ int16_t *s;
+ int32_t *l;
+ } data;
+
+ if (argc < 3)
+ {
+ fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
+ return EXIT_FAILURE;
+ }
+
+ info = xi2_find_device_info(dpy, argv[0]);
+ if (!info)
+ {
+ fprintf(stderr, "unable to find device %s\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ name = argv[1];
+
+ prop = parse_atom(dpy, name);
+
+ if (prop == None) {
+ fprintf(stderr, "invalid property '%s'\n", name);
+ return EXIT_FAILURE;
+ }
+
+ float_atom = XInternAtom(dpy, "FLOAT", False);
+
+ nelements = argc - 2;
+ if (type == None || format == 0) {
+ if (XIGetProperty(dpy, info->deviceid, prop, 0, 0, False,
+ AnyPropertyType, &old_type, &old_format, &act_nitems,
+ &bytes_after, &data.c) != Success) {
+ fprintf(stderr, "failed to get property type and format for '%s'\n",
+ name);
+ return EXIT_FAILURE;
+ } else {
+ if (type == None)
+ type = old_type;
+ if (format == 0)
+ format = old_format;
+ }
+
+ XFree(data.c);
+ }
+
+ if (type == None) {
+ fprintf(stderr, "property '%s' doesn't exist, you need to specify "
+ "its type and format\n", name);
+ return EXIT_FAILURE;
+ }
+
+ data.c = calloc(nelements, sizeof(int32_t));
+
+ for (i = 0; i < nelements; i++)
+ {
+ if (type == XA_INTEGER || type == XA_CARDINAL) {
+ switch (format)
+ {
+ case 8:
+ data.c[i] = atoi(argv[2 + i]);
+ break;
+ case 16:
+ data.s[i] = atoi(argv[2 + i]);
+ break;
+ case 32:
+ data.l[i] = atoi(argv[2 + i]);
+ break;
+ default:
+ fprintf(stderr, "unexpected size for property %s", name);
+ return EXIT_FAILURE;
+ }
+ } else if (type == float_atom) {
+ if (format != 32) {
+ fprintf(stderr, "unexpected format %d for property '%s'\n",
+ format, name);
+ return EXIT_FAILURE;
+ }
+ *(float *)(data.l + i) = strtod(argv[2 + i], &endptr);
+ if (endptr == argv[2 + i]) {
+ fprintf(stderr, "argument %s could not be parsed\n", argv[2 + i]);
+ return EXIT_FAILURE;
+ }
+ } else if (type == XA_ATOM) {
+ if (format != 32) {
+ fprintf(stderr, "unexpected format %d for property '%s'\n",
+ format, name);
+ return EXIT_FAILURE;
+ }
+ data.l[i] = parse_atom(dpy, argv[2 + i]);
+ } else {
+ fprintf(stderr, "unexpected type for property '%s'\n", name);
+ return EXIT_FAILURE;
+ }
+ }
+
+ XIChangeProperty(dpy, info->deviceid, prop, type, format, PropModeReplace,
+ data.c, nelements);
+ free(data.c);
+ return EXIT_SUCCESS;
+}
+#endif
+
+int list_props(Display *display, int argc, char *argv[], char *name,
+ char *desc)
+{
+#ifdef HAVE_XI2
+ if (xinput_version(display) == XI_2_Major)
+ return list_props_xi2(display, argc, argv, name, desc);
+#endif
+ return list_props_xi1(display, argc, argv, name, desc);
+
+}
+
+int delete_prop(Display *display, int argc, char *argv[], char *name,
+ char *desc)
+{
+#ifdef HAVE_XI2
+ if (xinput_version(display) == XI_2_Major)
+ return delete_prop_xi2(display, argc, argv, name, desc);
+#endif
+ return delete_prop_xi1(display, argc, argv, name, desc);
+
+}
+
+static int
+do_set_prop(Display *display, Atom type, int format, int argc, char *argv[], char *name, char *desc)
+{
+#ifdef HAVE_XI2
+ if (xinput_version(display) == XI_2_Major)
+ return do_set_prop_xi2(display, type, format, argc, argv, name, desc);
+#endif
+ return do_set_prop_xi1(display, type, format, argc, argv, name, desc);
+}
+
+int
+set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
+{
+ return do_set_prop(dpy, XA_ATOM, 32, argc, argv, n, desc);
+}
+
+int
+set_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
+{
+ int i;
+ int format;
+
+ if (argc < 3)
+ {
+ fprintf(stderr, "Usage: xinput %s %s\n", n, desc);
+ return EXIT_FAILURE;
+ }
+
+ format = atoi(argv[2]);
+ if (format != 8 && format != 16 && format != 32)
+ {
+ fprintf(stderr, "Invalid format %d\n", format);
+ return EXIT_FAILURE;
+ }
+
+ for (i = 3; i < argc; i++)
+ argv[i - 1] = argv[i];
+
+ return do_set_prop(dpy, XA_INTEGER, format, argc - 1, argv, n, desc);
+}
+
+int
+set_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc)
+{
+ Atom float_atom = XInternAtom(dpy, "FLOAT", False);
+
+ if (sizeof(float) != 4)
+ {
+ fprintf(stderr, "sane FP required\n");
+ return EXIT_FAILURE;
+ }
+
+ return do_set_prop(dpy, float_atom, 32, argc, argv, n, desc);
+}
+
+int set_prop(Display *display, int argc, char *argv[], char *name,
+ char *desc)
+{
+ Atom type = None;
+ int format = 0;
+ int i = 0, j;
+
+ while (i < argc) {
+ char *option = strchr(argv[i], '=');
+ /* skip non-option arguments */
+ if (strncmp(argv[i], "--", 2) || !option) {
+ i++;
+ continue;
+ }
+
+ if (!strncmp(argv[i], "--type=", strlen("--type="))) {
+ if (!strcmp(option + 1, "int")) {
+ type = XA_INTEGER;
+ } else if (!strcmp(option + 1, "float")) {
+ type = XInternAtom(display, "FLOAT", False);
+ format = 32;
+ } else if (!strcmp(option + 1, "atom")) {
+ type = XA_ATOM;
+ format = 32;
+ } else {
+ fprintf(stderr, "unknown property type %s\n", option + 1);
+ return EXIT_FAILURE;
+ }
+ } else if (!strncmp(argv[i], "--format=", strlen("--format="))) {
+ format = atoi(option + 1);
+ if (format != 8 && format != 16 && format != 32) {
+ fprintf(stderr, "invalid property format '%s'\n", option + 1);
+ return EXIT_FAILURE;
+ }
+ } else {
+ fprintf(stderr, "invalid option '%s'\n", argv[i]);
+ return EXIT_FAILURE;
+ }
+
+ for (j = i; j + 1 < argc; j++)
+ argv[j] = argv[j + 1];
+ argc--;
+ }
+
+ return do_set_prop(display, type, format, argc, argv, name, desc);
+}
+
+int disable(Display *display, int argc, char *argv[], char *name, char *desc)
+{
+ char *new_argv[3] = { argv[0], "Device Enabled", "0" };
+ return set_prop(display, 3, new_argv, name, desc);
+}
+
+int enable(Display *display, int argc, char *argv[], char *name, char *desc)
+{
+ char *new_argv[3] = { argv[0], "Device Enabled", "1" };
+ return set_prop(display, 3, new_argv, name, desc);
+}
diff --git a/src/setcp.c b/src/setcp.c
new file mode 100644
index 0000000..649f301
--- /dev/null
+++ b/src/setcp.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2007 Peter Hutterer
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * 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.
+ */
+
+
+#include "xinput.h"
+#include <string.h>
+
+int
+set_clientpointer(Display* dpy, int argc, char** argv, char* name, char *desc)
+{
+ XIDeviceInfo *info;
+ XID window;
+ char* id;
+ char* dummy;
+
+ if (argc <= 1)
+ {
+ fprintf(stderr, "Usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ id = argv[0];
+
+ while(*id == '0') id++;
+
+ window = strtol(argv[0], &dummy, (*id == 'x') ? 16 : 10);
+
+ info = xi2_find_device_info(dpy, argv[1]);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ XISetClientPointer(dpy, window, info->deviceid);
+ return 0;
+}
diff --git a/src/setint.c b/src/setint.c
new file mode 100644
index 0000000..050a411
--- /dev/null
+++ b/src/setint.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "xinput.h"
+
+int
+set_integer_feedback(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+ XDeviceInfo *info;
+ XDevice *device;
+ XIntegerFeedbackControl control;
+
+ if (argc != 3) {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ control.class = IntegerFeedbackClass;
+ control.length = sizeof(XIntegerFeedbackControl);
+ control.id = atoi(argv[1]);
+ control.int_to_display = atoi(argv[2]);
+
+ info = find_device_info(display, argv[0], True);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ device = XOpenDevice(display, info->id);
+
+ if (device) {
+ XChangeFeedbackControl(display, device, DvInteger, (XFeedbackControl *) &control);
+
+ return EXIT_SUCCESS;
+ } else {
+ fprintf(stderr, "Unable to open device\n");
+ return EXIT_FAILURE;
+ }
+}
+
+/* end of setint.c */
diff --git a/src/setmode.c b/src/setmode.c
new file mode 100644
index 0000000..4008a74
--- /dev/null
+++ b/src/setmode.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "xinput.h"
+#include <string.h>
+
+int
+set_mode(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+ XDeviceInfo *info;
+ XDevice *device;
+ int mode;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ info = find_device_info(display, argv[0], True);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ if (strcmp(argv[1], "ABSOLUTE") == 0) {
+ mode = Absolute;
+ } else if (strcmp(argv[1], "RELATIVE") == 0) {
+ mode = Relative;
+ } else {
+ fprintf(stderr, "Invalid mode, use ABSOLUTE or RELATIVE.\n");
+ return EXIT_FAILURE;
+ }
+
+ device = XOpenDevice(display, info->id);
+
+ if (device) {
+ XSetDeviceMode(display, device, mode);
+
+ return EXIT_SUCCESS;
+ } else {
+ fprintf(stderr, "Unable to open device\n");
+ return EXIT_FAILURE;
+ }
+}
+
+/* end of setmode.c */
diff --git a/src/setptr.c b/src/setptr.c
new file mode 100644
index 0000000..3dcf1ec
--- /dev/null
+++ b/src/setptr.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "xinput.h"
+
+int
+set_pointer(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+ XDeviceInfo *info;
+ XDevice *device;
+ int xaxis = 0;
+ int yaxis = 1;
+
+ if ((argc != 1) && (argc != 3)) {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ if (argc == 3) {
+ xaxis = atoi(argv[1]);
+ yaxis = atoi(argv[2]);
+ }
+
+ info = find_device_info(display, argv[0], True);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ device = XOpenDevice(display, info->id);
+
+ if (device) {
+ XChangePointerDevice(display, device, xaxis, yaxis);
+
+ return EXIT_SUCCESS;
+ } else {
+ fprintf(stderr, "Unable to open device\n");
+ return EXIT_FAILURE;
+ }
+}
+
+/* end of setptr.c */
diff --git a/src/state.c b/src/state.c
new file mode 100644
index 0000000..a160e30
--- /dev/null
+++ b/src/state.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright 1996-1997 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "xinput.h"
+
+int
+query_state(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+ XDeviceInfo *info;
+ XDevice *device;
+ XDeviceState *state;
+ int loop;
+ int loop2;
+ XInputClass *cls;
+ XValuatorState *val_state;
+ XKeyState *key_state;
+ XButtonState *but_state;
+
+ if (argc != 1) {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return 1;
+ }
+
+ info = find_device_info(display, argv[0], True);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return 1;
+ }
+
+ device = XOpenDevice(display, info->id);
+
+ if (!device) {
+ fprintf(stderr, "unable to open device '%s'\n", argv[0]);
+ return 1;
+ }
+
+ state = XQueryDeviceState(display, device);
+
+ if (state) {
+ cls = state->data;
+ printf("%d class%s :\n", state->num_classes,
+ (state->num_classes > 1) ? "es" : "");
+ for(loop=0; loop<state->num_classes; loop++) {
+ switch(cls->class) {
+ case ValuatorClass:
+ val_state = (XValuatorState *) cls;
+ printf("ValuatorClass Mode=%s Proximity=%s\n",
+ val_state->mode & 1 ? "Absolute" : "Relative",
+ val_state->mode & 2 ? "Out" : "In");
+ for(loop2=0; loop2<val_state->num_valuators; loop2++) {
+ printf("\tvaluator[%d]=%d\n", loop2, val_state->valuators[loop2]);
+ }
+ break;
+
+ case ButtonClass:
+ but_state = (XButtonState *) cls;
+ printf("ButtonClass\n");
+ for(loop2=1; loop2<=but_state->num_buttons; loop2++) {
+ printf("\tbutton[%d]=%s\n", loop2,
+ (but_state->buttons[loop2 / 8] & (1 << (loop2 % 8))) ? "down" : "up" );
+ }
+ break;
+
+ case KeyClass:
+ key_state = (XKeyState *) cls;
+ printf("KeyClass\n");
+ for(loop2=0; loop2<key_state->num_keys; loop2++) {
+ printf("\tkey[%d]=%s\n", loop2,
+ (key_state->keys[loop2 / 8] & (1 << (loop2 % 8))) ? "down" : "up" );
+ }
+
+ break;
+
+ }
+ cls = (XInputClass *) ((char *) cls + cls->length);
+ }
+ XFreeDeviceState(state);
+ }
+ return EXIT_SUCCESS;
+}
+
+/* end of state.c */
diff --git a/src/test.c b/src/test.c
new file mode 100644
index 0000000..97305c5
--- /dev/null
+++ b/src/test.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "xinput.h"
+#include <string.h>
+
+#define INVALID_EVENT_TYPE -1
+
+static int motion_type = INVALID_EVENT_TYPE;
+static int button_press_type = INVALID_EVENT_TYPE;
+static int button_release_type = INVALID_EVENT_TYPE;
+static int key_press_type = INVALID_EVENT_TYPE;
+static int key_release_type = INVALID_EVENT_TYPE;
+static int proximity_in_type = INVALID_EVENT_TYPE;
+static int proximity_out_type = INVALID_EVENT_TYPE;
+
+static int
+register_events(Display *dpy,
+ XDeviceInfo *info,
+ char *dev_name,
+ Bool handle_proximity)
+{
+ int number = 0; /* number of events registered */
+ XEventClass event_list[7];
+ int i;
+ XDevice *device;
+ Window root_win;
+ unsigned long screen;
+ XInputClassInfo *ip;
+
+ screen = DefaultScreen(dpy);
+ root_win = RootWindow(dpy, screen);
+
+ device = XOpenDevice(dpy, info->id);
+
+ if (!device) {
+ fprintf(stderr, "unable to open device '%s'\n", dev_name);
+ return 0;
+ }
+
+ if (device->num_classes > 0) {
+ for (ip = device->classes, i=0; i<info->num_classes; ip++, i++) {
+ switch (ip->input_class) {
+ case KeyClass:
+ DeviceKeyPress(device, key_press_type, event_list[number]); number++;
+ DeviceKeyRelease(device, key_release_type, event_list[number]); number++;
+ break;
+
+ case ButtonClass:
+ DeviceButtonPress(device, button_press_type, event_list[number]); number++;
+ DeviceButtonRelease(device, button_release_type, event_list[number]); number++;
+ break;
+
+ case ValuatorClass:
+ DeviceMotionNotify(device, motion_type, event_list[number]); number++;
+ if (handle_proximity) {
+ ProximityIn(device, proximity_in_type, event_list[number]); number++;
+ ProximityOut(device, proximity_out_type, event_list[number]); number++;
+ }
+ break;
+
+ default:
+ fprintf(stderr, "unknown class\n");
+ break;
+ }
+ }
+
+ if (XSelectExtensionEvent(dpy, root_win, event_list, number)) {
+ fprintf(stderr, "error selecting extended events\n");
+ return 0;
+ }
+ }
+ return number;
+}
+
+static void
+print_events(Display *dpy)
+{
+ XEvent Event;
+
+ while(1) {
+ XNextEvent(dpy, &Event);
+
+ if (Event.type == motion_type) {
+ int loop;
+ XDeviceMotionEvent *motion = (XDeviceMotionEvent *) &Event;
+
+ printf("motion ");
+
+ for(loop=0; loop<motion->axes_count; loop++) {
+ printf("a[%d]=%d ", motion->first_axis + loop, motion->axis_data[loop]);
+ }
+ printf("\n");
+ } else if ((Event.type == button_press_type) ||
+ (Event.type == button_release_type)) {
+ int loop;
+ XDeviceButtonEvent *button = (XDeviceButtonEvent *) &Event;
+
+ printf("button %s %d ", (Event.type == button_release_type) ? "release" : "press ",
+ button->button);
+
+ for(loop=0; loop<button->axes_count; loop++) {
+ printf("a[%d]=%d ", button->first_axis + loop, button->axis_data[loop]);
+ }
+ printf("\n");
+ } else if ((Event.type == key_press_type) ||
+ (Event.type == key_release_type)) {
+ int loop;
+ XDeviceKeyEvent *key = (XDeviceKeyEvent *) &Event;
+
+ printf("key %s %d ", (Event.type == key_release_type) ? "release" : "press ",
+ key->keycode);
+
+ for(loop=0; loop<key->axes_count; loop++) {
+ printf("a[%d]=%d ", key->first_axis + loop, key->axis_data[loop]);
+ }
+ printf("\n");
+ } else if ((Event.type == proximity_out_type) ||
+ (Event.type == proximity_in_type)) {
+ int loop;
+ XProximityNotifyEvent *prox = (XProximityNotifyEvent *) &Event;
+
+ printf("proximity %s ", (Event.type == proximity_in_type) ? "in " : "out");
+
+ for(loop=0; loop<prox->axes_count; loop++) {
+ printf("a[%d]=%d ", prox->first_axis + loop, prox->axis_data[loop]);
+ }
+ printf("\n");
+ }
+ else {
+ printf("what's that %d\n", Event.type);
+ }
+ }
+}
+
+int
+test(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+ XDeviceInfo *info;
+
+ if (argc != 1 && argc != 2) {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ } else {
+ Bool handle_proximity = False;
+ int idx = 0;
+
+ if (argc == 2) {
+ if (strcmp("-proximity", argv[0]) != 0) {
+ fprintf(stderr, "usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+ handle_proximity = 1;
+ idx = 1;
+ }
+
+ info = find_device_info(display, argv[idx], True);
+
+ if (!info) {
+ fprintf(stderr, "unable to find device '%s'\n", argv[idx]);
+ return EXIT_FAILURE;
+ } else {
+ if (register_events(display, info, argv[idx], handle_proximity)) {
+ print_events(display);
+ }
+ else {
+ fprintf(stderr, "no event registered...\n");
+ return EXIT_FAILURE;
+ }
+ }
+ }
+ return EXIT_FAILURE;
+}
+
+/* end of test.c */
diff --git a/src/test_xi2.c b/src/test_xi2.c
new file mode 100644
index 0000000..bcb4880
--- /dev/null
+++ b/src/test_xi2.c
@@ -0,0 +1,461 @@
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * 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.
+ *
+ */
+
+
+#include "xinput.h"
+#include <string.h>
+
+extern void print_classes_xi2(Display*, XIAnyClassInfo **classes,
+ int num_classes);
+
+static Window create_win(Display *dpy)
+{
+ Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 200,
+ 200, 0, 0, WhitePixel(dpy, 0));
+ Window subwindow = XCreateSimpleWindow(dpy, win, 50, 50, 50, 50, 0, 0,
+ BlackPixel(dpy, 0));
+
+ XMapWindow(dpy, subwindow);
+ XSelectInput(dpy, win, ExposureMask);
+ return win;
+}
+
+static void print_deviceevent(XIDeviceEvent* event)
+{
+ double *val;
+ int i;
+
+ printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
+ printf(" detail: %d\n", event->detail);
+ switch(event->evtype) {
+ case XI_KeyPress:
+ case XI_KeyRelease:
+ printf(" flags: %s\n", (event->flags & XIKeyRepeat) ? "repeat" : "");
+ break;
+#if HAVE_XI21
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ case XI_Motion:
+ printf(" flags: %s\n", (event->flags & XIPointerEmulated) ? "emulated" : "");
+ break;
+#endif
+ }
+
+ printf(" root: %.2f/%.2f\n", event->root_x, event->root_y);
+ printf(" event: %.2f/%.2f\n", event->event_x, event->event_y);
+
+ printf(" buttons:");
+ for (i = 0; i < event->buttons.mask_len * 8; i++)
+ if (XIMaskIsSet(event->buttons.mask, i))
+ printf(" %d", i);
+ printf("\n");
+
+ printf(" modifiers: locked %#x latched %#x base %#x effective: %#x\n",
+ event->mods.locked, event->mods.latched,
+ event->mods.base, event->mods.effective);
+ printf(" group: locked %#x latched %#x base %#x effective: %#x\n",
+ event->group.locked, event->group.latched,
+ event->group.base, event->group.effective);
+ printf(" valuators:\n");
+
+ val = event->valuators.values;
+ for (i = 0; i < event->valuators.mask_len * 8; i++)
+ if (XIMaskIsSet(event->valuators.mask, i))
+ printf(" %i: %.2f\n", i, *val++);
+
+ printf(" windows: root 0x%lx event 0x%lx child 0x%lx\n",
+ event->root, event->event, event->child);
+}
+
+static void print_devicechangedevent(Display *dpy, XIDeviceChangedEvent *event)
+{
+ printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
+ printf(" reason: %s\n", (event->reason == XISlaveSwitch) ? "SlaveSwitch" :
+ "DeviceChanged");
+ print_classes_xi2(dpy, event->classes, event->num_classes);
+}
+
+static void print_hierarchychangedevent(XIHierarchyEvent *event)
+{
+ int i;
+ printf(" Changes happened: %s %s %s %s %s %s %s %s\n",
+ (event->flags & XIMasterAdded) ? "[new master]" : "",
+ (event->flags & XIMasterRemoved) ? "[master removed]" : "",
+ (event->flags & XISlaveAdded) ? "[new slave]" : "",
+ (event->flags & XISlaveRemoved) ? "[slave removed]" : "",
+ (event->flags & XISlaveAttached) ? "[slave attached]" : "",
+ (event->flags & XISlaveDetached) ? "[slave detached]" : "",
+ (event->flags & XIDeviceEnabled) ? "[device enabled]" : "",
+ (event->flags & XIDeviceDisabled) ? "[device disabled]" : "");
+
+ for (i = 0; i < event->num_info; i++)
+ {
+ char *use = "<undefined>";
+ switch(event->info[i].use)
+ {
+ case XIMasterPointer: use = "master pointer"; break;
+ case XIMasterKeyboard: use = "master keyboard"; break;
+ case XISlavePointer: use = "slave pointer"; break;
+ case XISlaveKeyboard: use = "slave keyboard"; break;
+ case XIFloatingSlave: use = "floating slave"; break;
+ break;
+ }
+
+ printf(" device %d [%s (%d)] is %s\n",
+ event->info[i].deviceid,
+ use,
+ event->info[i].attachment,
+ (event->info[i].enabled) ? "enabled" : "disabled");
+ if (event->info[i].flags)
+ {
+ printf(" changes: %s %s %s %s %s %s %s %s\n",
+ (event->info[i].flags & XIMasterAdded) ? "[new master]" : "",
+ (event->info[i].flags & XIMasterRemoved) ? "[master removed]" : "",
+ (event->info[i].flags & XISlaveAdded) ? "[new slave]" : "",
+ (event->info[i].flags & XISlaveRemoved) ? "[slave removed]" : "",
+ (event->info[i].flags & XISlaveAttached) ? "[slave attached]" : "",
+ (event->info[i].flags & XISlaveDetached) ? "[slave detached]" : "",
+ (event->info[i].flags & XIDeviceEnabled) ? "[device enabled]" : "",
+ (event->info[i].flags & XIDeviceDisabled) ? "[device disabled]" : "");
+ }
+ }
+}
+
+static void print_rawevent(XIRawEvent *event)
+{
+ int i;
+ double *val, *raw_val;
+
+ printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
+ printf(" detail: %d\n", event->detail);
+ printf(" valuators:\n");
+#if HAVE_XI21
+ switch(event->evtype) {
+ case XI_RawButtonPress:
+ case XI_RawButtonRelease:
+ case XI_RawMotion:
+ printf(" flags: %s\n", (event->flags & XIPointerEmulated) ? "emulated" : "");
+ break;
+ }
+#endif
+
+ val = event->valuators.values;
+ raw_val = event->raw_values;
+ for (i = 0; i < event->valuators.mask_len * 8; i++)
+ if (XIMaskIsSet(event->valuators.mask, i))
+ printf(" %2d: %.2f (%.2f)\n", i, *val++, *raw_val++);
+ printf("\n");
+}
+
+static void print_enterleave(XILeaveEvent* event)
+{
+ char *mode = "<undefined>",
+ *detail = "<undefined>";
+ int i;
+
+ printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
+ printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
+ event->root, event->event, event->child);
+ switch(event->mode)
+ {
+ case XINotifyNormal: mode = "NotifyNormal"; break;
+ case XINotifyGrab: mode = "NotifyGrab"; break;
+ case XINotifyUngrab: mode = "NotifyUngrab"; break;
+ case XINotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break;
+ case XINotifyPassiveGrab: mode = "NotifyPassiveGrab"; break;
+ case XINotifyPassiveUngrab:mode = "NotifyPassiveUngrab"; break;
+ }
+ switch (event->detail)
+ {
+ case XINotifyAncestor: detail = "NotifyAncestor"; break;
+ case XINotifyVirtual: detail = "NotifyVirtual"; break;
+ case XINotifyInferior: detail = "NotifyInferior"; break;
+ case XINotifyNonlinear: detail = "NotifyNonlinear"; break;
+ case XINotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
+ case XINotifyPointer: detail = "NotifyPointer"; break;
+ case XINotifyPointerRoot: detail = "NotifyPointerRoot"; break;
+ case XINotifyDetailNone: detail = "NotifyDetailNone"; break;
+ }
+ printf(" mode: %s (detail %s)\n", mode, detail);
+ printf(" flags: %s %s\n", event->focus ? "[focus]" : "",
+ event->same_screen ? "[same screen]" : "");
+ printf(" buttons:");
+ for (i = 0; i < event->buttons.mask_len * 8; i++)
+ if (XIMaskIsSet(event->buttons.mask, i))
+ printf(" %d", i);
+ printf("\n");
+
+ printf(" modifiers: locked %#x latched %#x base %#x effective: %#x\n",
+ event->mods.locked, event->mods.latched,
+ event->mods.base, event->mods.effective);
+ printf(" group: locked %#x latched %#x base %#x effective: %#x\n",
+ event->group.locked, event->group.latched,
+ event->group.base, event->group.effective);
+
+ printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
+ printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
+
+}
+
+static void print_propertyevent(Display *display, XIPropertyEvent* event)
+{
+ char *changed;
+ char *name;
+
+ if (event->what == XIPropertyDeleted)
+ changed = "deleted";
+ else if (event->what == XIPropertyCreated)
+ changed = "created";
+ else
+ changed = "modified";
+ name = XGetAtomName(display, event->property);
+ printf(" property: %ld '%s'\n", event->property, name);
+ printf(" changed: %s\n", changed);
+
+ XFree(name);
+}
+void
+test_sync_grab(Display *display, Window win)
+{
+ int loop = 3;
+ int rc;
+ XIEventMask mask;
+
+ /* Select for motion events */
+ mask.deviceid = XIAllDevices;
+ mask.mask_len = 2;
+ mask.mask = calloc(2, sizeof(char));
+ XISetMask(mask.mask, XI_ButtonPress);
+
+ if ((rc = XIGrabDevice(display, 2, win, CurrentTime, None, GrabModeSync,
+ GrabModeAsync, False, &mask)) != GrabSuccess)
+ {
+ fprintf(stderr, "Grab failed with %d\n", rc);
+ return;
+ }
+ free(mask.mask);
+
+ XSync(display, True);
+ XIAllowEvents(display, 2, SyncPointer, CurrentTime);
+ XFlush(display);
+
+ printf("Holding sync grab for %d button presses.\n", loop);
+
+ while(loop--)
+ {
+ XIEvent ev;
+
+ XNextEvent(display, (XEvent*)&ev);
+ if (ev.type == GenericEvent && ev.extension == xi_opcode )
+ {
+ XIDeviceEvent *event = (XIDeviceEvent*)&ev;
+ print_deviceevent(event);
+ XIAllowEvents(display, 2, SyncPointer, CurrentTime);
+ }
+ }
+
+ XIUngrabDevice(display, 2, CurrentTime);
+ printf("Done\n");
+}
+
+static const char* type_to_name(int evtype)
+{
+ const char *name;
+
+ switch(evtype) {
+ case XI_DeviceChanged: name = "DeviceChanged"; break;
+ case XI_KeyPress: name = "KeyPress"; break;
+ case XI_KeyRelease: name = "KeyRelease"; break;
+ case XI_ButtonPress: name = "ButtonPress"; break;
+ case XI_ButtonRelease: name = "ButtonRelease"; break;
+ case XI_Motion: name = "Motion"; break;
+ case XI_Enter: name = "Enter"; break;
+ case XI_Leave: name = "Leave"; break;
+ case XI_FocusIn: name = "FocusIn"; break;
+ case XI_FocusOut: name = "FocusOut"; break;
+ case XI_HierarchyChanged: name = "HierarchyChanged"; break;
+ case XI_PropertyEvent: name = "PropertyEvent"; break;
+ case XI_RawKeyPress: name = "RawKeyPress"; break;
+ case XI_RawKeyRelease: name = "RawKeyRelease"; break;
+ case XI_RawButtonPress: name = "RawButtonPress"; break;
+ case XI_RawButtonRelease: name = "RawButtonRelease"; break;
+ case XI_RawMotion: name = "RawMotion"; break;
+ case XI_TouchBegin: name = "TouchBegin"; break;
+ case XI_TouchUpdate: name = "TouchUpdate"; break;
+ case XI_TouchEnd: name = "TouchEnd"; break;
+ case XI_RawTouchBegin: name = "RawTouchBegin"; break;
+ case XI_RawTouchUpdate: name = "RawTouchUpdate"; break;
+ case XI_RawTouchEnd: name = "RawTouchEnd"; break;
+ default:
+ name = "unknown event type"; break;
+ }
+ return name;
+}
+
+
+int
+test_xi2(Display *display,
+ int argc,
+ char *argv[],
+ char *name,
+ char *desc)
+{
+ XIEventMask mask;
+ Window win;
+ int deviceid = -1;
+ int rc;
+
+ rc = list(display, argc, argv, name, desc);
+ if (rc != EXIT_SUCCESS)
+ return rc;
+
+ if (argc >= 1) {
+ XIDeviceInfo *info;
+ info = xi2_find_device_info(display, argv[0]);
+ deviceid = info->deviceid;
+ }
+ win = create_win(display);
+
+ /* Select for motion events */
+ mask.deviceid = (deviceid == -1) ? XIAllDevices : deviceid;
+ mask.mask_len = XIMaskLen(XI_LASTEVENT);
+ mask.mask = calloc(mask.mask_len, sizeof(char));
+ XISetMask(mask.mask, XI_ButtonPress);
+ XISetMask(mask.mask, XI_ButtonRelease);
+ XISetMask(mask.mask, XI_KeyPress);
+ XISetMask(mask.mask, XI_KeyRelease);
+ XISetMask(mask.mask, XI_Motion);
+ XISetMask(mask.mask, XI_DeviceChanged);
+ XISetMask(mask.mask, XI_Enter);
+ XISetMask(mask.mask, XI_Leave);
+ XISetMask(mask.mask, XI_FocusIn);
+ XISetMask(mask.mask, XI_FocusOut);
+#ifdef HAVE_XI22
+ XISetMask(mask.mask, XI_TouchBegin);
+ XISetMask(mask.mask, XI_TouchUpdate);
+ XISetMask(mask.mask, XI_TouchEnd);
+#endif
+ if (mask.deviceid == XIAllDevices)
+ XISetMask(mask.mask, XI_HierarchyChanged);
+ XISetMask(mask.mask, XI_PropertyEvent);
+ XISelectEvents(display, win, &mask, 1);
+ XMapWindow(display, win);
+ XSync(display, False);
+
+ {
+ XIGrabModifiers modifiers[] = {{0, 0}, {0, 0x10}, {0, 0x1}, {0, 0x11}};
+ int nmods = sizeof(modifiers)/sizeof(modifiers[0]);
+
+ mask.deviceid = 2;
+ memset(mask.mask, 0, mask.mask_len);
+ XISetMask(mask.mask, XI_KeyPress);
+ XISetMask(mask.mask, XI_KeyRelease);
+ XISetMask(mask.mask, XI_ButtonPress);
+ XISetMask(mask.mask, XI_ButtonRelease);
+ XISetMask(mask.mask, XI_Motion);
+ XIGrabButton(display, 2, 1, win, None, GrabModeAsync, GrabModeAsync,
+ False, &mask, nmods, modifiers);
+ XIGrabKeycode(display, 3, 24 /* q */, win, GrabModeAsync, GrabModeAsync,
+ False, &mask, nmods, modifiers);
+ XIUngrabButton(display, 3, 1, win, nmods - 2, &modifiers[2]);
+ XIUngrabKeycode(display, 3, 24 /* q */, win, nmods - 2, &modifiers[2]);
+ }
+
+ mask.deviceid = (deviceid == -1) ? XIAllMasterDevices : deviceid;
+ memset(mask.mask, 0, mask.mask_len);
+ XISetMask(mask.mask, XI_RawKeyPress);
+ XISetMask(mask.mask, XI_RawKeyRelease);
+ XISetMask(mask.mask, XI_RawButtonPress);
+ XISetMask(mask.mask, XI_RawButtonRelease);
+ XISetMask(mask.mask, XI_RawMotion);
+#ifdef HAVE_XI22
+ XISetMask(mask.mask, XI_RawTouchBegin);
+ XISetMask(mask.mask, XI_RawTouchUpdate);
+ XISetMask(mask.mask, XI_RawTouchEnd);
+#endif
+ XISelectEvents(display, DefaultRootWindow(display), &mask, 1);
+
+ free(mask.mask);
+
+ {
+ XEvent event;
+ XMaskEvent(display, ExposureMask, &event);
+ XSelectInput(display, win, 0);
+ }
+
+ /*
+ test_sync_grab(display, win);
+ */
+
+ while(1)
+ {
+ XEvent ev;
+ XGenericEventCookie *cookie = (XGenericEventCookie*)&ev.xcookie;
+ XNextEvent(display, (XEvent*)&ev);
+
+ if (XGetEventData(display, cookie) &&
+ cookie->type == GenericEvent &&
+ cookie->extension == xi_opcode)
+ {
+ printf("EVENT type %d (%s)\n", cookie->evtype, type_to_name(cookie->evtype));
+ switch (cookie->evtype)
+ {
+ case XI_DeviceChanged:
+ print_devicechangedevent(display, cookie->data);
+ break;
+ case XI_HierarchyChanged:
+ print_hierarchychangedevent(cookie->data);
+ break;
+ case XI_RawKeyPress:
+ case XI_RawKeyRelease:
+ case XI_RawButtonPress:
+ case XI_RawButtonRelease:
+ case XI_RawMotion:
+ case XI_RawTouchBegin:
+ case XI_RawTouchUpdate:
+ case XI_RawTouchEnd:
+ print_rawevent(cookie->data);
+ break;
+ case XI_Enter:
+ case XI_Leave:
+ case XI_FocusIn:
+ case XI_FocusOut:
+ print_enterleave(cookie->data);
+ break;
+ case XI_PropertyEvent:
+ print_propertyevent(display, cookie->data);
+ break;
+ default:
+ print_deviceevent(cookie->data);
+ break;
+ }
+ }
+
+ XFreeEventData(display, cookie);
+ }
+
+ XDestroyWindow(display, win);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/transform.c b/src/transform.c
new file mode 100644
index 0000000..f80a592
--- /dev/null
+++ b/src/transform.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright © 2011 Red Hat, Inc.
+ *
+ * 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.
+ *
+ */
+
+
+#include "xinput.h"
+#include <string.h>
+#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/Xinerama.h>
+
+
+typedef struct Matrix {
+ float m[9];
+} Matrix;
+
+static void matrix_set(Matrix *m, int row, int col, float val)
+{
+ m->m[row * 3 + col] = val;
+}
+
+static void matrix_set_unity(Matrix *m)
+{
+ memset(m, 0, sizeof(m->m));
+ matrix_set(m, 0, 0, 1);
+ matrix_set(m, 1, 1, 1);
+ matrix_set(m, 2, 2, 1);
+}
+
+#if DEBUG
+static void matrix_print(const Matrix *m)
+{
+ printf("[ %3.3f %3.3f %3.3f ]\n", m->m[0], m->m[1], m->m[2]);
+ printf("[ %3.3f %3.3f %3.3f ]\n", m->m[3], m->m[4], m->m[5]);
+ printf("[ %3.3f %3.3f %3.3f ]\n", m->m[6], m->m[7], m->m[8]);
+}
+#endif
+
+static int
+apply_matrix(Display *dpy, int deviceid, Matrix *m)
+{
+ Atom prop_float, prop_matrix;
+
+ union {
+ unsigned char *c;
+ float *f;
+ } data;
+ int format_return;
+ Atom type_return;
+ unsigned long nitems;
+ unsigned long bytes_after;
+
+ int rc;
+
+ prop_float = XInternAtom(dpy, "FLOAT", False);
+ prop_matrix = XInternAtom(dpy, "Coordinate Transformation Matrix", False);
+
+ if (!prop_float)
+ {
+ fprintf(stderr, "Float atom not found. This server is too old.\n");
+ return EXIT_FAILURE;
+ }
+ if (!prop_matrix)
+ {
+ fprintf(stderr, "Coordinate transformation matrix not found. This "
+ "server is too old\n");
+ return EXIT_FAILURE;
+ }
+
+ rc = XIGetProperty(dpy, deviceid, prop_matrix, 0, 9, False, prop_float,
+ &type_return, &format_return, &nitems, &bytes_after,
+ &data.c);
+ if (rc != Success || prop_float != type_return || format_return != 32 ||
+ nitems != 9 || bytes_after != 0)
+ {
+ fprintf(stderr, "Failed to retrieve current property values\n");
+ return EXIT_FAILURE;
+ }
+
+ memcpy(data.f, m->m, sizeof(m->m));
+
+ XIChangeProperty(dpy, deviceid, prop_matrix, prop_float,
+ format_return, PropModeReplace, data.c, nitems);
+
+ XFree(data.c);
+
+ return EXIT_SUCCESS;
+}
+
+static void
+set_transformation_matrix(Display *dpy, Matrix *m, int offset_x, int offset_y,
+ int screen_width, int screen_height)
+{
+ /* offset */
+ int width = DisplayWidth(dpy, DefaultScreen(dpy));
+ int height = DisplayHeight(dpy, DefaultScreen(dpy));
+
+ /* offset */
+ float x = 1.0 * offset_x/width;
+ float y = 1.0 * offset_y/height;
+
+ /* mapping */
+ float w = 1.0 * screen_width/width;
+ float h = 1.0 * screen_height/height;
+
+ matrix_set_unity(m);
+
+ matrix_set(m, 0, 2, x);
+ matrix_set(m, 1, 2, y);
+
+ matrix_set(m, 0, 0, w);
+ matrix_set(m, 1, 1, h);
+
+#if DEBUG
+ matrix_print(m);
+#endif
+}
+
+/* Caller must free return value */
+static XRROutputInfo*
+find_output_xrandr(Display *dpy, const char *output_name)
+{
+ XRRScreenResources *res;
+ XRROutputInfo *output_info = NULL;
+ int i;
+ int found = 0;
+
+ res = XRRGetScreenResources(dpy, DefaultRootWindow(dpy));
+
+ for (i = 0; i < res->noutput && !found; i++)
+ {
+ output_info = XRRGetOutputInfo(dpy, res, res->outputs[i]);
+
+ if (output_info->crtc && output_info->connection == RR_Connected &&
+ strcmp(output_info->name, output_name) == 0)
+ {
+ found = 1;
+ break;
+ }
+
+ XRRFreeOutputInfo(output_info);
+ }
+
+ XRRFreeScreenResources(res);
+
+ if (!found)
+ output_info = NULL;
+
+ return output_info;
+}
+
+static int
+map_output_xrandr(Display *dpy, int deviceid, const char *output_name)
+{
+ int rc = EXIT_FAILURE;
+ XRRScreenResources *res;
+ XRROutputInfo *output_info;
+
+ res = XRRGetScreenResources(dpy, DefaultRootWindow(dpy));
+ output_info = find_output_xrandr(dpy, output_name);
+
+ /* crtc holds our screen info, need to compare to actual screen size */
+ if (output_info)
+ {
+ XRRCrtcInfo *crtc_info;
+ Matrix m;
+ matrix_set_unity(&m);
+ crtc_info = XRRGetCrtcInfo (dpy, res, output_info->crtc);
+ set_transformation_matrix(dpy, &m, crtc_info->x, crtc_info->y,
+ crtc_info->width, crtc_info->height);
+ rc = apply_matrix(dpy, deviceid, &m);
+ XRRFreeCrtcInfo(crtc_info);
+ XRRFreeOutputInfo(output_info);
+ } else
+ printf("Unable to find output '%s'. "
+ "Output may not be connected.\n", output_name);
+
+ XRRFreeScreenResources(res);
+
+ return rc;
+}
+
+static int
+map_output_xinerama(Display *dpy, int deviceid, const char *output_name)
+{
+ const char *prefix = "HEAD-";
+ XineramaScreenInfo *screens = NULL;
+ int rc = EXIT_FAILURE;
+ int event, error;
+ int nscreens;
+ int head;
+ Matrix m;
+
+ if (!XineramaQueryExtension(dpy, &event, &error))
+ {
+ fprintf(stderr, "Unable to set screen mapping. Xinerama extension not found\n");
+ goto out;
+ }
+
+ if (strlen(output_name) < strlen(prefix) + 1 ||
+ strncmp(output_name, prefix, strlen(prefix)) != 0)
+ {
+ fprintf(stderr, "Please specify the output name as HEAD-X,"
+ "where X is the screen number\n");
+ goto out;
+ }
+
+ head = output_name[strlen(prefix)] - '0';
+
+ screens = XineramaQueryScreens(dpy, &nscreens);
+
+ if (nscreens == 0)
+ {
+ fprintf(stderr, "Xinerama failed to query screens.\n");
+ goto out;
+ } else if (nscreens <= head)
+ {
+ fprintf(stderr, "Found %d screens, but you requested %s.\n",
+ nscreens, output_name);
+ goto out;
+ }
+
+ matrix_set_unity(&m);
+ set_transformation_matrix(dpy, &m,
+ screens[head].x_org, screens[head].y_org,
+ screens[head].width, screens[head].height);
+ rc = apply_matrix(dpy, deviceid, &m);
+
+out:
+ XFree(screens);
+ return rc;
+}
+
+int
+map_to_output(Display *dpy, int argc, char *argv[], char *name, char *desc)
+{
+ char *output_name;
+ XIDeviceInfo *info;
+ XRROutputInfo *output_info;
+
+ if (argc < 2)
+ {
+ fprintf(stderr, "Usage: xinput %s %s\n", name, desc);
+ return EXIT_FAILURE;
+ }
+
+ info = xi2_find_device_info(dpy, argv[0]);
+ if (!info)
+ {
+ fprintf(stderr, "unable to find device '%s'\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ output_name = argv[1];
+ output_info = find_output_xrandr(dpy, output_name);
+ if (!output_info)
+ {
+ /* Output doesn't exist. Is this a (partial) non-RandR setup? */
+ output_info = find_output_xrandr(dpy, "default");
+ if (output_info)
+ {
+ XRRFreeOutputInfo(output_info);
+ if (strncmp("HEAD-", output_name, strlen("HEAD-")) == 0)
+ return map_output_xinerama(dpy, info->deviceid, output_name);
+ }
+ } else
+ XRRFreeOutputInfo(output_info);
+
+ return map_output_xrandr(dpy, info->deviceid, output_name);
+}
diff --git a/src/xinput.c b/src/xinput.c
new file mode 100644
index 0000000..0f86720
--- /dev/null
+++ b/src/xinput.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "xinput.h"
+#include <ctype.h>
+#include <string.h>
+
+int xi_opcode;
+
+typedef int (*prog)(Display* display, int argc, char *argv[],
+ char *prog_name, char *prog_desc);
+
+typedef struct
+{
+ char *func_name;
+ char *arg_desc;
+ prog func;
+} entry;
+
+static entry drivers[] =
+{
+ {"get-feedbacks",
+ "<device name>",
+ get_feedbacks
+ },
+ {"set-ptr-feedback",
+ "<device name> <threshold> <num> <denom>",
+ set_ptr_feedback
+ },
+ {"set-integer-feedback",
+ "<device name> <feedback id> <value>",
+ set_integer_feedback
+ },
+ {"get-button-map",
+ "<device name>",
+ get_button_map
+ },
+ {"set-button-map",
+ "<device name> <map button 1> [<map button 2> [...]]",
+ set_button_map
+ },
+ {"set-pointer",
+ "<device name> [<x index> <y index>]",
+ set_pointer
+ },
+ {"set-mode",
+ "<device name> ABSOLUTE|RELATIVE",
+ set_mode
+ },
+ {"list",
+ "[--short || --long || --name-only || --id-only] [<device name>...]",
+ list
+ },
+ {"query-state",
+ "<device name>",
+ query_state
+ },
+ {"test",
+ "[-proximity] <device name>",
+ test
+ },
+#if HAVE_XI2
+ { "create-master",
+ "<id> [<sendCore (dflt:1)>] [<enable (dflt:1)>]",
+ create_master
+ },
+ { "remove-master",
+ "<id> [Floating|AttachToMaster (dflt:Floating)] [<returnPointer>] [<returnKeyboard>]",
+ remove_master
+ },
+ { "reattach",
+ "<id> <master>",
+ change_attachment
+ },
+ { "float",
+ "<id>",
+ float_device
+ },
+ { "set-cp",
+ "<window> <device>",
+ set_clientpointer
+ },
+ { "test-xi2",
+ "<device>",
+ test_xi2,
+ },
+ { "map-to-output",
+ "<device> <output name>",
+ map_to_output,
+ },
+#endif
+ { "list-props",
+ "<device> [<device> ...]",
+ list_props
+ },
+ { "set-int-prop",
+ "<device> <property> <format (8, 16, 32)> <val> [<val> ...]",
+ set_int_prop
+ },
+ { "set-float-prop",
+ "<device> <property> <val> [<val> ...]",
+ set_float_prop
+ },
+ { "set-atom-prop",
+ "<device> <property> <val> [<val> ...]",
+ set_atom_prop
+ },
+ { "watch-props",
+ "<device>",
+ watch_props
+ },
+ { "delete-prop",
+ "<device> <property>",
+ delete_prop
+ },
+ { "set-prop",
+ "<device> [--type=atom|float|int] [--format=8|16|32] <property> <val> [<val> ...]",
+ set_prop
+ },
+ {
+ "disable",
+ "<device>",
+ disable,
+ },
+ {
+ "enable",
+ "<device>",
+ enable,
+ },
+ {NULL, NULL, NULL
+ }
+};
+
+static const char version_id[] = VERSION;
+
+static int
+print_version(void)
+{
+ XExtensionVersion *version;
+ Display *display;
+
+ printf("xinput version %s\n", version_id);
+
+ display = XOpenDisplay(NULL);
+
+ printf("XI version on server: ");
+
+ if (display == NULL)
+ printf("Failed to open display.\n");
+ else {
+ version = XGetExtensionVersion(display, INAME);
+ if (!version || (version == (XExtensionVersion*) NoSuchExtension))
+ printf(" Extension not supported.\n");
+ else {
+ printf("%d.%d\n", version->major_version,
+ version->minor_version);
+ XFree(version);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+int
+xinput_version(Display *display)
+{
+ XExtensionVersion *version;
+ static int vers = -1;
+
+ if (vers != -1)
+ return vers;
+
+ version = XGetExtensionVersion(display, INAME);
+
+ if (version && (version != (XExtensionVersion*) NoSuchExtension)) {
+ vers = version->major_version;
+ XFree(version);
+ }
+
+#if HAVE_XI2
+ /* Announce our supported version so the server treats us correctly. */
+ if (vers >= XI_2_Major)
+ {
+ int maj = 2,
+ min = 0;
+
+#if HAVE_XI21
+ min = 1;
+#elif HAVE_XI22
+ min = 2;
+#endif
+
+ XIQueryVersion(display, &maj, &min);
+ }
+#endif
+
+ return vers;
+}
+
+XDeviceInfo*
+find_device_info(Display *display,
+ char *name,
+ Bool only_extended)
+{
+ XDeviceInfo *devices;
+ XDeviceInfo *found = NULL;
+ int loop;
+ int num_devices;
+ int len = strlen(name);
+ Bool is_id = True;
+ XID id = (XID)-1;
+
+ for(loop=0; loop<len; loop++) {
+ if (!isdigit(name[loop])) {
+ is_id = False;
+ break;
+ }
+ }
+
+ if (is_id) {
+ id = atoi(name);
+ }
+
+ devices = XListInputDevices(display, &num_devices);
+
+ for(loop=0; loop<num_devices; loop++) {
+ if ((!only_extended || (devices[loop].use >= IsXExtensionDevice)) &&
+ ((!is_id && strcmp(devices[loop].name, name) == 0) ||
+ (is_id && devices[loop].id == id))) {
+ if (found) {
+ fprintf(stderr,
+ "Warning: There are multiple devices named '%s'.\n"
+ "To ensure the correct one is selected, please use "
+ "the device ID instead.\n\n", name);
+ return NULL;
+ } else {
+ found = &devices[loop];
+ }
+ }
+ }
+ return found;
+}
+
+#ifdef HAVE_XI2
+Bool is_pointer(int use)
+{
+ return use == XIMasterPointer || use == XISlavePointer;
+}
+
+Bool is_keyboard(int use)
+{
+ return use == XIMasterKeyboard || use == XISlaveKeyboard;
+}
+
+Bool device_matches(XIDeviceInfo *info, char *name)
+{
+ if (strcmp(info->name, name) == 0) {
+ return True;
+ }
+
+ if (strncmp(name, "pointer:", strlen("pointer:")) == 0 &&
+ strcmp(info->name, name + strlen("pointer:")) == 0 &&
+ is_pointer(info->use)) {
+ return True;
+ }
+
+ if (strncmp(name, "keyboard:", strlen("keyboard:")) == 0 &&
+ strcmp(info->name, name + strlen("keyboard:")) == 0 &&
+ is_keyboard(info->use)) {
+ return True;
+ }
+
+ return False;
+}
+
+XIDeviceInfo*
+xi2_find_device_info(Display *display, char *name)
+{
+ XIDeviceInfo *info;
+ XIDeviceInfo *found = NULL;
+ int ndevices;
+ Bool is_id = True;
+ int i, id = -1;
+
+ for(i = 0; i < strlen(name); i++) {
+ if (!isdigit(name[i])) {
+ is_id = False;
+ break;
+ }
+ }
+
+ if (is_id) {
+ id = atoi(name);
+ }
+
+ info = XIQueryDevice(display, XIAllDevices, &ndevices);
+ for(i = 0; i < ndevices; i++)
+ {
+ if (is_id ? info[i].deviceid == id : device_matches (&info[i], name)) {
+ if (found) {
+ fprintf(stderr,
+ "Warning: There are multiple devices matching '%s'.\n"
+ "To ensure the correct one is selected, please use "
+ "the device ID, or prefix the\ndevice name with "
+ "'pointer:' or 'keyboard:' as appropriate.\n\n", name);
+ XIFreeDeviceInfo(info);
+ return NULL;
+ } else {
+ found = &info[i];
+ }
+ }
+ }
+
+ return found;
+}
+#endif
+
+static void
+usage(void)
+{
+ entry *pdriver = drivers;
+
+ fprintf(stderr, "usage :\n");
+
+ while(pdriver->func_name) {
+ fprintf(stderr, "\txinput %s %s\n", pdriver->func_name,
+ pdriver->arg_desc);
+ pdriver++;
+ }
+}
+
+int
+main(int argc, char * argv[])
+{
+ Display *display;
+ entry *driver = drivers;
+ char *func;
+ int event, error;
+
+ if (argc > 1) {
+ func = argv[1];
+ while(func[0] == '-') func++;
+ } else {
+ func = "list";
+ }
+
+ if (strcmp("version", func) == 0) {
+ return print_version();
+ }
+
+ if (strcmp("help", func) == 0) {
+ usage();
+ return 0;
+ }
+
+ display = XOpenDisplay(NULL);
+
+ if (display == NULL) {
+ fprintf(stderr, "Unable to connect to X server\n");
+ goto out;
+ }
+
+ if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) {
+ printf("X Input extension not available.\n");
+ goto out;
+ }
+
+ if (!xinput_version(display)) {
+ fprintf(stderr, "%s extension not available\n", INAME);
+ goto out;
+ }
+
+ while(driver->func_name) {
+ if (strcmp(driver->func_name, func) == 0) {
+ int r = (*driver->func)(display, argc-2, argv+2,
+ driver->func_name, driver->arg_desc);
+ XSync(display, False);
+ XCloseDisplay(display);
+ return r;
+ }
+ driver++;
+ }
+
+ usage();
+
+out:
+ if (display)
+ XCloseDisplay(display);
+ return EXIT_FAILURE;
+}
+
+/* end of xinput.c */
diff --git a/src/xinput.h b/src/xinput.h
new file mode 100644
index 0000000..c37e6e6
--- /dev/null
+++ b/src/xinput.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 1996 by Frederic Lepied, France. <Frederic.Lepied@sugix.frmug.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
+#ifdef HAVE_XI2
+#include <X11/extensions/XInput2.h>
+#endif
+#include <X11/Xutil.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS 1
+#endif
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 0
+#endif
+
+extern int xi_opcode; /* xinput extension op code */
+XDeviceInfo* find_device_info( Display *display, char *name, Bool only_extended);
+#if HAVE_XI2
+XIDeviceInfo* xi2_find_device_info(Display *display, char *name);
+int xinput_version(Display* display);
+#endif
+
+int get_feedbacks( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int set_ptr_feedback( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int get_button_map( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int set_button_map( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int set_pointer( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+
+int set_mode( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int list( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int test( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int version( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int set_integer_feedback( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int query_state( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+
+/* X Input 1.5 */
+int list_props( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int set_int_prop( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int set_float_prop( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int set_atom_prop( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int watch_props( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int delete_prop( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int set_prop( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int disable( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int enable( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+
+/* X Input 2.0 */
+int create_master( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int remove_master( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int change_attachment( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int float_device( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int set_clientpointer( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int test_xi2( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+int map_to_output( Display* display, int argc, char *argv[], char *prog_name, char *prog_desc);
+
+/* end of xinput.h */