1.Moved all xinput2 functionality to its own file
authorDimitris Zenios <dimitris.zenios@gmail.com>
Thu, 31 May 2012 13:37:02 +0300
changeset 6316 a89c79a3f0cd
parent 6315 ad9087c284e9
child 6317 df009b78a763
1.Moved all xinput2 functionality to its own file 2.Implement touch events using Xinput2.Leave evtouch as a fallback when xinput2 is not supported
configure.in
include/SDL_config.h.in
include/SDL_config_macosx.h
src/video/x11/SDL_x11events.c
src/video/x11/SDL_x11mouse.c
src/video/x11/SDL_x11touch.c
src/video/x11/SDL_x11touch.h
src/video/x11/SDL_x11video.c
src/video/x11/SDL_x11video.h
src/video/x11/SDL_x11window.c
src/video/x11/SDL_x11xinput2.c
src/video/x11/SDL_x11xinput2.h
test/testrelative.c
--- a/configure.in	Wed May 30 15:21:13 2012 -0400
+++ b/configure.in	Thu May 31 13:37:02 2012 +0300
@@ -1192,6 +1192,23 @@
             fi
             if test x$definitely_enable_video_x11_xinput = xyes; then
                 AC_DEFINE(SDL_VIDEO_DRIVER_X11_XINPUT2, 1, [ ])
+                AC_MSG_CHECKING(for xinput2 multitouch)
+            	have_xinput2_multitouch=no
+            	AC_TRY_COMPILE([
+              		#include <X11/Xlib.h>
+             		#include <X11/Xproto.h>
+			#include <X11/extensions/XInput2.h>
+            	],[
+Status 
+XIAllowTouchEvents(Display *a,int b,unsigned int c,Window d,int f)
+{
+    return (Status)0;
+}
+            	],[
+            	have_xinput2_multitouch=yes
+            	AC_DEFINE(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH)
+            	])
+            	AC_MSG_RESULT($have_xinput2_multitouch)
             fi
             AC_ARG_ENABLE(video-x11-xrandr,
 AC_HELP_STRING([--enable-video-x11-xrandr], [enable X11 Xrandr extension for fullscreen [[default=yes]]]),
--- a/include/SDL_config.h.in	Wed May 30 15:21:13 2012 -0400
+++ b/include/SDL_config.h.in	Thu May 31 13:37:02 2012 +0300
@@ -264,6 +264,7 @@
 #undef SDL_VIDEO_DRIVER_X11_XCURSOR
 #undef SDL_VIDEO_DRIVER_X11_XINERAMA
 #undef SDL_VIDEO_DRIVER_X11_XINPUT2
+#undef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
 #undef SDL_VIDEO_DRIVER_X11_XRANDR
 #undef SDL_VIDEO_DRIVER_X11_XSCRNSAVER
 #undef SDL_VIDEO_DRIVER_X11_XSHAPE
--- a/include/SDL_config_macosx.h	Wed May 30 15:21:13 2012 -0400
+++ b/include/SDL_config_macosx.h	Thu May 31 13:37:02 2012 +0300
@@ -140,6 +140,7 @@
 #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE "/usr/X11R6/lib/libXxf86vm.1.dylib"
 #define SDL_VIDEO_DRIVER_X11_XINERAMA 1
 #define SDL_VIDEO_DRIVER_X11_XINPUT2 1
+#define SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH 1
 #define SDL_VIDEO_DRIVER_X11_XRANDR 1
 #define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
 #define SDL_VIDEO_DRIVER_X11_XSHAPE 1
--- a/src/video/x11/SDL_x11events.c	Wed May 30 15:21:13 2012 -0400
+++ b/src/video/x11/SDL_x11events.c	Thu May 31 13:37:02 2012 +0300
@@ -30,6 +30,7 @@
 
 #include "SDL_x11video.h"
 #include "SDL_x11touch.h"
+#include "SDL_x11xinput2.h"
 #include "../../events/SDL_events_c.h"
 #include "../../events/SDL_mouse_c.h"
 #include "../../events/SDL_touch_c.h"
@@ -94,50 +95,13 @@
     return SDL_FALSE;
 }
 
-#if SDL_VIDEO_DRIVER_X11_XINPUT2
-static void X11_HandleRawMotion(SDL_VideoData *videodata,const XIRawEvent *rawev)
-{
-    SDL_Mouse *mouse = SDL_GetMouse();
-    const double *values = rawev->raw_values;
-    int relative_cords[2] = {0,0};
-    int i;
-
-    if (!mouse->relative_mode) {
-        return;
-    }
-   
-    /*2 axis,X-Y*/
-    for (i = 0; i < 2; i++) {
-        if (XIMaskIsSet(rawev->valuators.mask, i)) {
-            const int value = (int) *values;
-            relative_cords[i] = value;
-            values++;
-        }
-    }
-#ifdef DEBUG_MOTION
-    printf("XInput relative motion: %d,%d\n", relative_cords[0],relative_cords[1]);
-#endif
-    SDL_SendMouseMotion(mouse->focus,1,relative_cords[0],relative_cords[1]);
-}
-#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
 
 #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
 static void X11_HandleGenericEvent(SDL_VideoData *videodata,XEvent event)
 {
     XGenericEventCookie *cookie = &event.xcookie;
     XGetEventData(videodata->display, cookie);
-#if SDL_VIDEO_DRIVER_X11_XINPUT2
-    if(cookie->extension == videodata->xinput_opcode) {
-        switch(cookie->evtype) {
-            case XI_RawMotion: {
-                const XIRawEvent *rawev = (const XIRawEvent*)cookie->data;
-                X11_HandleRawMotion(videodata,rawev);
-                }
-                break;
-
-        }
-    }
-#endif
+    X11_HandleXinput2Event(videodata,cookie);
     XFreeEventData(videodata->display,cookie);
 }
 #endif /* SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */
@@ -605,9 +569,13 @@
     while (X11_Pending(data->display)) {
         X11_DispatchEvent(_this);
     }
+    /*Dont process evtouch events if XInput2 multitouch is supported*/
+    if(X11_Xinput2IsMutitouchSupported()) {
+        return;
+    }
 
 #ifdef SDL_INPUT_LINUXEV
-    /* Process Touch events - TODO When X gets touch support, use that instead*/
+    /* Process Touch events*/
     int i = 0,rd;
     struct input_event ev[64];
     int size = sizeof (struct input_event);
--- a/src/video/x11/SDL_x11mouse.c	Wed May 30 15:21:13 2012 -0400
+++ b/src/video/x11/SDL_x11mouse.c	Thu May 31 13:37:02 2012 +0300
@@ -25,6 +25,7 @@
 #include "SDL_assert.h"
 #include "SDL_x11video.h"
 #include "SDL_x11mouse.h"
+#include "SDL_x11xinput2.h"
 #include "../../events/SDL_mouse_c.h"
 
 
@@ -273,12 +274,12 @@
 X11_SetRelativeMouseMode(SDL_bool enabled)
 {
 #if SDL_VIDEO_DRIVER_X11_XINPUT2
-    /* FIXME: Need to remember from init if XInput2 is actually supported */
-    return 0;
+    if(X11_Xinput2IsInitialized())
+        return 0;
 #else
     SDL_Unsupported();
+#endif
     return -1;
-#endif
 }
 
 void
--- a/src/video/x11/SDL_x11touch.c	Wed May 30 15:21:13 2012 -0400
+++ b/src/video/x11/SDL_x11touch.c	Thu May 31 13:37:02 2012 +0300
@@ -24,6 +24,7 @@
 
 #include "SDL_x11video.h"
 #include "SDL_x11touch.h"
+#include "SDL_x11xinput2.h"
 #include "../../events/SDL_touch_c.h"
 
 
@@ -35,82 +36,87 @@
 void
 X11_InitTouch(_THIS)
 {
+    /*Initilized Xinput2 multitouch 
+    * and return in order to not initialize
+    * evtouch also*/
+    if(X11_Xinput2IsMutitouchSupported()) {
+        X11_InitXinput2Multitouch(_this);
+        return;
+    }
 #ifdef SDL_INPUT_LINUXEV
-  FILE *fd;
-  fd = fopen("/proc/bus/input/devices","r");
-
-  int i = 0;
-  int tsfd;
-  char line[256];
-  char tstr[256];
-  int vendor = -1,product = -1,event = -1;
-  while(!feof(fd)) {
-    if(fgets(line,256,fd) <=0) continue;
-    if(line[0] == '\n') {
-      if(vendor == 1386 || vendor==1) {
-
-        sprintf(tstr,"/dev/input/event%i",event);
+    FILE *fd;
+    fd = fopen("/proc/bus/input/devices","r");
 
-        tsfd = open( tstr, O_RDONLY | O_NONBLOCK );
-        if ( tsfd == -1 )
-            continue;   /* Maybe not enough permissions ? */
+    int i = 0;
+    int tsfd;
+    char line[256];
+    char tstr[256];
+    int vendor = -1,product = -1,event = -1;
+    while(!feof(fd)) {
+        if(fgets(line,256,fd) <=0) continue;
+        if(line[0] == '\n') {
+            if(vendor == 1386 || vendor==1) {
+                sprintf(tstr,"/dev/input/event%i",event);
 
-        SDL_Touch touch;
-        touch.pressure_max = 0;
-        touch.pressure_min = 0;
-        touch.id = event; 
+                tsfd = open( tstr, O_RDONLY | O_NONBLOCK );
+                if ( tsfd == -1 )
+                    continue;   /* Maybe not enough permissions ? */
 
-        touch.driverdata = SDL_malloc(sizeof(EventTouchData));
-        EventTouchData* data = (EventTouchData*)(touch.driverdata);
+                SDL_Touch touch;
+                touch.pressure_max = 0;
+                touch.pressure_min = 0;
+                touch.id = event; 
 
-        data->x = -1;
-        data->y = -1;
-        data->pressure = -1;
-        data->finger = 0;
-        data->up = SDL_FALSE;
-        data->down = SDL_FALSE;
+                touch.driverdata = SDL_malloc(sizeof(EventTouchData));
+                EventTouchData* data = (EventTouchData*)(touch.driverdata);
 
-        data->eventStream = tsfd;
-        ioctl (data->eventStream, EVIOCGNAME (sizeof (tstr)), tstr);
+                data->x = -1;
+                data->y = -1;
+                data->pressure = -1;
+                data->finger = 0;
+                data->up = SDL_FALSE;
+                data->down = SDL_FALSE;
 
-        int abs[5];
-        ioctl(data->eventStream,EVIOCGABS(0),abs);	
-        touch.x_min = abs[1];
-        touch.x_max = abs[2];
-        touch.native_xres = touch.x_max - touch.x_min;
-        ioctl(data->eventStream,EVIOCGABS(ABS_Y),abs);	
-        touch.y_min = abs[1];
-        touch.y_max = abs[2];
-        touch.native_yres = touch.y_max - touch.y_min;
-        ioctl(data->eventStream,EVIOCGABS(ABS_PRESSURE),abs);	
-        touch.pressure_min = abs[1];
-        touch.pressure_max = abs[2];
-        touch.native_pressureres = touch.pressure_max - touch.pressure_min;
+                data->eventStream = tsfd;
+                ioctl (data->eventStream, EVIOCGNAME (sizeof (tstr)), tstr);
+
+                int abs[5];
+                ioctl(data->eventStream,EVIOCGABS(0),abs);	
+                touch.x_min = abs[1];
+                touch.x_max = abs[2];
+                touch.native_xres = touch.x_max - touch.x_min;
+                ioctl(data->eventStream,EVIOCGABS(ABS_Y),abs);	
+                touch.y_min = abs[1];
+                touch.y_max = abs[2];
+                touch.native_yres = touch.y_max - touch.y_min;
+                ioctl(data->eventStream,EVIOCGABS(ABS_PRESSURE),abs);	
+                touch.pressure_min = abs[1];
+                touch.pressure_max = abs[2];
+                touch.native_pressureres = touch.pressure_max - touch.pressure_min;
 
-        SDL_AddTouch(&touch, tstr);
-      }
-      vendor = -1;
-      product = -1;
-      event = -1;      
+                SDL_AddTouch(&touch, tstr);
+            }
+            vendor = -1;
+            product = -1;
+            event = -1;      
+        }
+        else if(line[0] == 'I') {
+            i = 1;
+            while(line[i]) {
+                sscanf(&line[i],"Vendor=%x",&vendor);
+                sscanf(&line[i],"Product=%x",&product);
+                i++;
+            }
+        }
+        else if(line[0] == 'H') {
+            i = 1;
+            while(line[i]) {
+                sscanf(&line[i],"event%d",&event);
+                i++;
+            }
+        }
     }
-    else if(line[0] == 'I') {
-      i = 1;
-      while(line[i]) {
-        sscanf(&line[i],"Vendor=%x",&vendor);
-        sscanf(&line[i],"Product=%x",&product);
-        i++;
-      }
-    }
-    else if(line[0] == 'H') {
-      i = 1;
-      while(line[i]) {
-        sscanf(&line[i],"event%d",&event);
-        i++;
-      }
-    }
-  }
-
-  fclose(fd);
+    fclose(fd);
 #endif
 }
 
--- a/src/video/x11/SDL_x11touch.h	Wed May 30 15:21:13 2012 -0400
+++ b/src/video/x11/SDL_x11touch.h	Thu May 31 13:37:02 2012 +0300
@@ -23,12 +23,6 @@
 #ifndef _SDL_x11touch_h
 #define _SDL_x11touch_h
 
-/*
-!!! FIXME: remove the evdev code;
-!!! FIXME: this should be using XInput 2.1's new multitouch API.
-*/
-
-/* What should this be? */
 #ifdef SDL_INPUT_LINUXEV
 typedef struct EventTouchData
 {
--- a/src/video/x11/SDL_x11video.c	Wed May 30 15:21:13 2012 -0400
+++ b/src/video/x11/SDL_x11video.c	Thu May 31 13:37:02 2012 +0300
@@ -33,6 +33,7 @@
 #include "SDL_x11framebuffer.h"
 #include "SDL_x11shape.h"
 #include "SDL_x11touch.h" 
+#include "SDL_x11xinput2.h"
 
 #if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
 #include "SDL_x11opengles.h"
@@ -321,56 +322,6 @@
 }
 
 int
-X11_CheckXInput2(_THIS)
-{
-#if SDL_VIDEO_DRIVER_X11_XINPUT2
-    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
-
-    if (SDL_X11_HAVE_XINPUT2) {
-        XIEventMask eventmask;
-        unsigned char mask[3] = { 0,0,0 };
-        int opcode, event, err;
-        int major = 2, minor = 0;
-        /*
-        * Initialize XInput 2
-        * According to http://who-t.blogspot.com/2009/05/xi2-recipes-part-1.html its better
-        * to inform Xserver what version of Xinput we support.The server will store the version we support. 
-        * "As XI2 progresses it becomes important that you use this call as the server may treat the client 
-        * differently depending on the supported version".
-        *
-        * FIXME:event and err are not needed but if not passed XQueryExtension returns SegmentationFault
-        */
-        if (!XQueryExtension(data->display, "XInputExtension", &opcode, &event, &err)) {
-            SDL_SetError("XInput 2 extension not available.");
-            return -1;
-        }
-      
-        if (XIQueryVersion(data->display, &major, &minor) != Success) {
-            SDL_SetError("Error supporting XInput 2 version");
-            return -1;      
-        }
-
-        /* Save the opcode for event processing */
-        data->xinput_opcode = opcode;
-
-        /*Enable  Raw motion events for this display*/
-        eventmask.deviceid = XIAllMasterDevices;
-        eventmask.mask_len = sizeof(mask);
-        eventmask.mask = mask;
-
-        XISetMask(mask, XI_RawMotion);
-             
-        if (XISelectEvents(data->display,DefaultRootWindow(data->display),&eventmask,1) != Success) {
-            SDL_SetError("Error in selecting XInput 2 Raw motion events");
-            return -1;      
-        }
-    }
-#else
-    return 0;
-#endif
-}
-
-int
 X11_VideoInit(_THIS)
 {
     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
@@ -409,7 +360,7 @@
         return -1;
     }
 
-    X11_CheckXInput2(_this);
+    X11_InitXinput2(_this);
 
     if (X11_InitKeyboard(_this) != 0) {
         return -1;
--- a/src/video/x11/SDL_x11video.h	Wed May 30 15:21:13 2012 -0400
+++ b/src/video/x11/SDL_x11video.h	Thu May 31 13:37:02 2012 +0300
@@ -92,16 +92,7 @@
     Atom UTF8_STRING;
 
     SDL_Scancode key_layout[256];
-    SDL_bool selection_waiting;
-    
-    /* Opcode returned XQueryExtension 
-     * It will be used in event processing
-     * to know that the event came from
-     * this extension */ 
-#if SDL_VIDEO_DRIVER_X11_XINPUT2
-    int xinput_opcode;
-#endif
-    
+    SDL_bool selection_waiting;    
 } SDL_VideoData;
 
 extern SDL_bool X11_UseDirectColorVisuals(void);
--- a/src/video/x11/SDL_x11window.c	Wed May 30 15:21:13 2012 -0400
+++ b/src/video/x11/SDL_x11window.c	Thu May 31 13:37:02 2012 +0300
@@ -30,6 +30,7 @@
 #include "SDL_x11video.h"
 #include "SDL_x11mouse.h"
 #include "SDL_x11shape.h"
+#include "SDL_x11xinput2.h"
 
 #if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
 #include "SDL_x11opengles.h"
@@ -561,6 +562,8 @@
     }
 #endif
 
+    X11_Xinput2SelectTouch(_this, window);
+
     XSelectInput(display, w,
                  (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
                  ExposureMask | ButtonPressMask | ButtonReleaseMask |
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/x11/SDL_x11xinput2.c	Thu May 31 13:37:02 2012 +0300
@@ -0,0 +1,249 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include "SDL_x11video.h"
+#include "SDL_x11xinput2.h"
+#include "../../events/SDL_mouse_c.h"
+#include "../../events/SDL_touch_c.h"
+
+#define MAX_AXIS 16
+
+static int xinput2_initialized = 0;
+static int xinput2_multitouch_supported = 0;
+/* Opcode returned XQueryExtension 
+ * It will be used in event processing
+ * to know that the event came from
+ * this extension */ 
+static int xinput2_opcode;
+
+
+#if SDL_VIDEO_DRIVER_X11_XINPUT2
+static void parse_valuators(const double *input_values,unsigned char *mask,int mask_len,
+                            double *output_values,int output_values_len) {
+    int i = 0,z = 0;
+    int top = mask_len * 8;
+    if (top > MAX_AXIS)
+        top = MAX_AXIS;
+
+    SDL_memset(output_values,0,output_values_len * sizeof(double));
+    for (; i < top && z < output_values_len; i++) {
+        if (XIMaskIsSet(mask, i)) {
+            const int value = (int) *input_values;
+            output_values[z] = value;
+            input_values++;
+        }
+        z++;
+    }
+}
+#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
+
+void 
+X11_InitXinput2(_THIS) {
+#if SDL_VIDEO_DRIVER_X11_XINPUT2
+    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+    XIEventMask eventmask;
+    unsigned char mask[3] = { 0,0,0 };
+    int event, err;
+    int major = 2, minor = 0;
+    int outmajor,outminor;
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+    minor = 2;
+#endif
+    /*
+    * Initialize XInput 2
+    * According to http://who-t.blogspot.com/2009/05/xi2-recipes-part-1.html its better
+    * to inform Xserver what version of Xinput we support.The server will store the version we support. 
+    * "As XI2 progresses it becomes important that you use this call as the server may treat the client 
+    * differently depending on the supported version".
+    *
+    * FIXME:event and err are not needed but if not passed XQueryExtension returns SegmentationFault
+    */
+    if (!XQueryExtension(data->display, "XInputExtension", &xinput2_opcode, &event, &err)) {
+        return;
+    }
+
+    outmajor = major;
+    outminor = minor;
+    if (XIQueryVersion(data->display, &outmajor, &outminor) != Success) {
+        return;
+    }
+
+    /*Check supported version*/
+    if(outmajor * 1000 + outminor < major * 1000 + minor) {
+        /*X server does not support the version we want*/
+        return;
+    }
+    xinput2_initialized = 1;
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+    /*XInput 2.2*/
+    if(outmajor * 1000 + outminor >= major * 1000 + minor) {
+        xinput2_multitouch_supported = 1;
+    }
+#endif
+
+    /*Enable  Raw motion events for this display*/
+    eventmask.deviceid = XIAllMasterDevices;
+    eventmask.mask_len = sizeof(mask);
+    eventmask.mask = mask;
+
+    XISetMask(mask, XI_RawMotion);
+         
+    if (XISelectEvents(data->display,DefaultRootWindow(data->display),&eventmask,1) != Success) {
+        return;     
+    }
+#endif
+}
+
+
+
+int 
+X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie) {
+#if SDL_VIDEO_DRIVER_X11_XINPUT2
+    if(cookie->extension != xinput2_opcode) {
+        return 0;
+    }
+    switch(cookie->evtype) {
+        case XI_RawMotion: {
+            const XIRawEvent *rawev = (const XIRawEvent*)cookie->data;
+            SDL_Mouse *mouse = SDL_GetMouse();
+            double relative_cords[2];
+
+            if (!mouse->relative_mode) {
+                return 0;
+            }
+
+            parse_valuators(rawev->raw_values,rawev->valuators.mask,
+                            rawev->valuators.mask_len,relative_cords,2);
+            SDL_SendMouseMotion(mouse->focus,1,(int)relative_cords[0],(int)relative_cords[1]);
+            return 1;
+            }
+            break;
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+        case XI_TouchBegin: {
+            const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
+            SDL_SendFingerDown(xev->sourceid,xev->detail,
+                      SDL_TRUE, (int)xev->event_x, (int)xev->event_y,
+		    		  1.0);
+            return 1;
+            }
+            break;
+        case XI_TouchEnd: {
+            const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
+            SDL_SendFingerDown(xev->sourceid,xev->detail,
+                      SDL_FALSE, (int)xev->event_x, (int)xev->event_y,
+		    		  1.0);
+            return 1;
+            }
+            break;
+        case XI_TouchUpdate: {
+            const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
+            SDL_SendTouchMotion(xev->sourceid,xev->detail,
+                      SDL_FALSE, (int)xev->event_x, (int)xev->event_y,
+		    		  1.0);
+            return 1;
+            }
+            break;
+#endif
+    }
+#endif
+    return 0;
+}
+
+void 
+X11_InitXinput2Multitouch(_THIS) {
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+    XIDeviceInfo *info;
+    int ndevices,i,j;
+    info = XIQueryDevice(data->display, XIAllMasterDevices, &ndevices);
+
+    for (i = 0; i < ndevices; i++) {
+        XIDeviceInfo *dev = &info[i];
+        for (j = 0; j < dev->num_classes; j++) {
+            SDL_TouchID touchId;
+            XIAnyClassInfo *class = dev->classes[j];
+            XITouchClassInfo *t = (XITouchClassInfo*)class;
+
+            /*Only touch devices*/
+            if (class->type != XITouchClass)
+                continue;
+
+            touchId = t->sourceid;
+            /*Add the touch*/
+            if (!SDL_GetTouch(touchId)) {
+                SDL_Touch touch;
+
+                touch.id = touchId;
+                touch.x_min = 0;
+                touch.x_max = 1;
+                touch.native_xres = touch.x_max - touch.x_min;
+                touch.y_min = 0;
+                touch.y_max = 1;
+                touch.native_yres = touch.y_max - touch.y_min;
+                touch.pressure_min = 0;
+                touch.pressure_max = 1;
+                touch.native_pressureres = touch.pressure_max - touch.pressure_min;
+
+                SDL_AddTouch(&touch,dev->name);
+            }
+        }
+    }
+#endif
+}
+
+void 
+X11_Xinput2SelectTouch(_THIS, SDL_Window *window) {
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+    XIEventMask eventmask;
+    unsigned char mask[3] = { 0,0,0 };
+    SDL_WindowData *window_data = (SDL_WindowData*)window->driverdata;
+
+    eventmask.deviceid = XIAllMasterDevices;
+    eventmask.mask_len = sizeof(mask);
+    eventmask.mask = mask;
+
+    XISetMask(mask, XI_TouchBegin);
+    XISetMask(mask, XI_TouchUpdate);
+    XISetMask(mask, XI_TouchEnd);
+         
+    XISelectEvents(data->display,window_data->xwindow,&eventmask,1);
+#endif
+}
+
+
+int 
+X11_Xinput2IsInitialized() {
+    return xinput2_initialized;
+}
+
+int
+X11_Xinput2IsMutitouchSupported() {
+    return xinput2_initialized && xinput2_multitouch_supported;
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/x11/SDL_x11xinput2.h	Thu May 31 13:37:02 2012 +0300
@@ -0,0 +1,42 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_config.h"
+
+#ifndef _SDL_x11xinput2_h
+#define _SDL_x11xinput2_h
+
+#ifndef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
+/*Define XGenericEventCookie as forward declaration when 
+ *xinput2 is not available in order to compile*/
+struct XGenericEventCookie;
+typedef struct XGenericEventCookie XGenericEventCookie;
+#endif 
+
+extern void X11_InitXinput2(_THIS);
+extern void X11_InitXinput2Multitouch(_THIS);
+extern int X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie);
+extern int X11_Xinput2IsInitialized(void);
+extern int X11_Xinput2IsMutitouchSupported(void);
+extern void X11_Xinput2SelectTouch(_THIS, SDL_Window *window);
+
+#endif /* _SDL_x11xinput2_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/test/testrelative.c	Wed May 30 15:21:13 2012 -0400
+++ b/test/testrelative.c	Thu May 31 13:37:02 2012 +0300
@@ -54,7 +54,9 @@
     }
 
     srand((unsigned int)time(NULL));
-    SDL_SetRelativeMouseMode(SDL_TRUE);
+    if(SDL_SetRelativeMouseMode(SDL_TRUE) < 0) {
+        return 3;
+    };
 
     rect.x = DEFAULT_WINDOW_WIDTH / 2;
     rect.y = DEFAULT_WINDOW_HEIGHT / 2;