From 6e099855d2d58da6ade7f7f4e8c7b266f1c1cbd9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Sat, 25 Jul 2009 23:52:21 -0700 Subject: [PATCH] Initial commit --- Makefile.am | 23 ++++++++ autogen.sh | 13 +++++ configure.ac | 52 +++++++++++++++++ src/Makefile.am | 29 ++++++++++ src/tmd.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 291 insertions(+) create mode 100644 Makefile.am create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 src/Makefile.am create mode 100644 src/tmd.c diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..1dc7ea0 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,23 @@ +# Copyright 2005 Adam Jackson. +# +# 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 +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL +# ADAM JACKSON 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. + +AUTOMAKE_OPTIONS = foreign +SUBDIRS = src + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..e81f989 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,13 @@ +#! /bin/sh + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir + +autoreconf -v --install || exit 1 +cd $ORIGDIR || exit $? + +$srcdir/configure --enable-maintainer-mode "$@" + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..fda3388 --- /dev/null +++ b/configure.ac @@ -0,0 +1,52 @@ +dnl Copyright 2007 Peter Hutterer +dnl Process this file with autoconf to create configure. + +AC_PREREQ([2.57]) +AC_INIT(tmd,[1.4.99.1], [],tmd) +AM_INIT_AUTOMAKE([dist-bzip2]) +AM_MAINTAINER_MODE + +# Require xorg-macros: XORG_CWARNFLAGS, XORG_CHANGELOG +m4_ifndef([XORG_MACROS_VERSION], [AC_FATAL([must install xorg-macros 1.2 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.2) + +AM_CONFIG_HEADER(config.h) + +AC_PROG_LIBTOOL +AC_PROG_CC +AC_PROG_INSTALL + +XORG_CWARNFLAGS + +# Checks for extensions +XORG_DRIVER_CHECK_EXT(XINPUT, inputproto) + +# Checks for pkg-config packages +PKG_CHECK_MODULES(XORG, xorg-server xproto $REQUIRED_MODULES) +AC_SUBST(XORG_CFLAGS) +AC_SUBST(XORG_LIBS) + +# Checks for pkg-config packages +PKG_CHECK_MODULES(TMD, x11 xext [xi >= 1.2] [inputproto >= 1.5]) + +# XI2 support +PKG_CHECK_MODULES(XI2, [xi >= 1.2.99] [inputproto >= 1.9.99.12], + HAVE_XI2="yes"; AC_DEFINE(HAVE_XI2, 1, [XI2 available]), + HAVE_XI2="no"); +AM_CONDITIONAL(HAVE_XI2, [ test "$HAVE_XI2" = "yes" ]) + +AC_SUBST(TMD_CFLAGS) +AC_SUBST(TMD_LIBS) +AC_SUBST(HAVE_XI2) + +AC_SUBST(VERSION) + +CFLAGS="$CFLAGS $XORG_CFLAGS $TMD_CFLAGS" +LIBS="$LIBS $XORG_LIBS $TMD_LIBS" + +XORG_MANPAGE_SECTIONS +XORG_RELEASE_VERSION +XORG_CHANGELOG + +AC_OUTPUT([Makefile + src/Makefile]) diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..c942dcb --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,29 @@ +# +# Copyright 2007 Peter Hutterer +# +# 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 author not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. The author makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL THE AUTHOR 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. + +bin_PROGRAMS = tmd + +AM_CFLAGS = $(TMD_CFLAGS) +tmd_LDADD = $(TMD_LIBS) + +tmd_SOURCES = \ + tmd.c + diff --git a/src/tmd.c b/src/tmd.c new file mode 100644 index 0000000..d7ab75f --- /dev/null +++ b/src/tmd.c @@ -0,0 +1,174 @@ +/* gcc -o part2 `pkg-config --cflags --libs xi` part2.c */ +#include +#include +#include +#include +#include +#include + +#define MD_PREFIX "TUIO " + +typedef struct _attach_info { + struct _attach_info *next; + int slaveid; + char *m_name; +} AttachInfo, *AttachInfoPtr; + +static AttachInfo ais; + +/** + * Creates a new master device. + */ +int create_master(Display* dpy, char* name) +{ + XIAddMasterInfo c; + + c.type = XIAddMaster; + c.name = name; + c.send_core = 1; + c.enable = 1; + + return XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&c, 1); +} + +/** + * Attaches a slave device to a master device. + */ +int change_attachment(Display* dpy, int slaveid, int masterid) +{ + XIAttachSlaveInfo c; + + c.type = XIAttachSlave; + c.deviceid = slaveid; + c.new_master = masterid; + + return XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&c, 1); +} + +/** + * Listens for the creation of slave and master devices. When a new slave + * device is found, a new master device will be created and attached to + * when the message for the new master device comes back around. + */ +void listen(Display *dpy, int xi_opcode) +{ + int num_devices; + unsigned char hmask[2] = { 0, 0 }; + char *m_name, *s_name; + XIEvent ev; + XIEventMask evmask_h; + AttachInfoPtr ai; + + Cursor m_cur; + m_cur = XCreateFontCursor(dpy, 88); + if (m_cur == BadAlloc || m_cur == BadValue) { + printf("Unable to create cursor\n"); + } + + evmask_h.mask = hmask; + evmask_h.mask_len = sizeof(hmask); + evmask_h.deviceid = XIAllDevices; + XISetMask(hmask, XI_HierarchyChanged); + //XFlush(dpy); + + XISelectEvents(dpy, DefaultRootWindow(dpy), &evmask_h, 1); + + while (1) { + XNextEvent(dpy, (XIEvent *)&ev); + if (ev.type != GenericEvent || + ev.extension != xi_opcode) + continue; + + if (ev.evtype == XI_HierarchyChanged) { + int i; + XIHierarchyEvent *event = (XIHierarchyEvent*)&ev; + printf("Hierarchy Event.\n"); + + /* Look for slave or masters added */ + if (event->flags & XISlaveAdded) { + printf("Slave added\n"); + for (i=0; i < event->num_info; i++) { + if(event->info[i].flags & XISlaveAdded) { + s_name = XIQueryDevice(dpy, event->info[i].deviceid, &num_devices)->name; + + /* This is a hack. Xtst slave devices are created and + * attached to each new master device. If we were to + * actually create a new master device for this device + * we would end up with a recurring creation of + * master devices and slave devices. */ + if (strstr(s_name, "Xtst")) continue; + + asprintf(&m_name, MD_PREFIX"%s", s_name); + create_master(dpy, m_name); + free(m_name); + + ai = malloc(sizeof(AttachInfo)); + ai->next = ais.next; + ais.next = ai; + + asprintf(&ai->m_name, MD_PREFIX"%s pointer", s_name); + ai->slaveid = event->info[i].deviceid; + } + } + } else if (event->flags & XIMasterAdded) { + printf("Master added\n"); + + for (i=0; i < event->num_info; i++) { + if(event->info[i].flags & XIMasterAdded) { + + m_name = XIQueryDevice(dpy, event->info[i].deviceid, &num_devices)->name; + + ai = ais.next; + while (ai != NULL) { + if (strcmp(ai->m_name, m_name) == 0) { + printf(" New Master: %d %s\n", event->info[i].deviceid, + m_name); + change_attachment(dpy, ai->slaveid, event->info[i].deviceid); + XIDefineCursor(dpy, event->info[i].deviceid, + DefaultRootWindow(dpy), m_cur); + } + ai = ai->next; + } + } + } + } + } + } +} + +int main (int argc, char **argv) +{ + Display *dpy; + int xi_opcode, event, error; + int major, minor; + int ret; + + ais.next = NULL; + + /* Open X display */ + dpy = XOpenDisplay(NULL); + if (!dpy) { + printf("Failed to open display.\n"); + return -1; + } + + /* Make sure the X Input extension is available */ + if (!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error)) { + printf("X Input extension not available.\n"); + return -1; + } + + /* Check XI version, need 2.0 */ + major = 2; + minor = 0; + ret = XIQueryVersion(dpy, &major, &minor); + if (ret == BadRequest) { + printf("XInput 2.0 not supported. Server supports %i.%i.\n", major, minor); + return -1; + } + + listen(dpy, xi_opcode); + + XCloseDisplay(dpy); + return 0; +} -- 2.11.4.GIT