1.Moved all xinput2 functionality to its own file
authorDimitris Zenios <dimitris.zenios@gmail.com>
Thu, 31 May 2012 13:37:02 +0300
changeset 6316a89c79a3f0cd
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
     1.1 --- a/configure.in	Wed May 30 15:21:13 2012 -0400
     1.2 +++ b/configure.in	Thu May 31 13:37:02 2012 +0300
     1.3 @@ -1192,6 +1192,23 @@
     1.4              fi
     1.5              if test x$definitely_enable_video_x11_xinput = xyes; then
     1.6                  AC_DEFINE(SDL_VIDEO_DRIVER_X11_XINPUT2, 1, [ ])
     1.7 +                AC_MSG_CHECKING(for xinput2 multitouch)
     1.8 +            	have_xinput2_multitouch=no
     1.9 +            	AC_TRY_COMPILE([
    1.10 +              		#include <X11/Xlib.h>
    1.11 +             		#include <X11/Xproto.h>
    1.12 +			#include <X11/extensions/XInput2.h>
    1.13 +            	],[
    1.14 +Status 
    1.15 +XIAllowTouchEvents(Display *a,int b,unsigned int c,Window d,int f)
    1.16 +{
    1.17 +    return (Status)0;
    1.18 +}
    1.19 +            	],[
    1.20 +            	have_xinput2_multitouch=yes
    1.21 +            	AC_DEFINE(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH)
    1.22 +            	])
    1.23 +            	AC_MSG_RESULT($have_xinput2_multitouch)
    1.24              fi
    1.25              AC_ARG_ENABLE(video-x11-xrandr,
    1.26  AC_HELP_STRING([--enable-video-x11-xrandr], [enable X11 Xrandr extension for fullscreen [[default=yes]]]),
     2.1 --- a/include/SDL_config.h.in	Wed May 30 15:21:13 2012 -0400
     2.2 +++ b/include/SDL_config.h.in	Thu May 31 13:37:02 2012 +0300
     2.3 @@ -264,6 +264,7 @@
     2.4  #undef SDL_VIDEO_DRIVER_X11_XCURSOR
     2.5  #undef SDL_VIDEO_DRIVER_X11_XINERAMA
     2.6  #undef SDL_VIDEO_DRIVER_X11_XINPUT2
     2.7 +#undef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
     2.8  #undef SDL_VIDEO_DRIVER_X11_XRANDR
     2.9  #undef SDL_VIDEO_DRIVER_X11_XSCRNSAVER
    2.10  #undef SDL_VIDEO_DRIVER_X11_XSHAPE
     3.1 --- a/include/SDL_config_macosx.h	Wed May 30 15:21:13 2012 -0400
     3.2 +++ b/include/SDL_config_macosx.h	Thu May 31 13:37:02 2012 +0300
     3.3 @@ -140,6 +140,7 @@
     3.4  #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE "/usr/X11R6/lib/libXxf86vm.1.dylib"
     3.5  #define SDL_VIDEO_DRIVER_X11_XINERAMA 1
     3.6  #define SDL_VIDEO_DRIVER_X11_XINPUT2 1
     3.7 +#define SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH 1
     3.8  #define SDL_VIDEO_DRIVER_X11_XRANDR 1
     3.9  #define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
    3.10  #define SDL_VIDEO_DRIVER_X11_XSHAPE 1
     4.1 --- a/src/video/x11/SDL_x11events.c	Wed May 30 15:21:13 2012 -0400
     4.2 +++ b/src/video/x11/SDL_x11events.c	Thu May 31 13:37:02 2012 +0300
     4.3 @@ -30,6 +30,7 @@
     4.4  
     4.5  #include "SDL_x11video.h"
     4.6  #include "SDL_x11touch.h"
     4.7 +#include "SDL_x11xinput2.h"
     4.8  #include "../../events/SDL_events_c.h"
     4.9  #include "../../events/SDL_mouse_c.h"
    4.10  #include "../../events/SDL_touch_c.h"
    4.11 @@ -94,50 +95,13 @@
    4.12      return SDL_FALSE;
    4.13  }
    4.14  
    4.15 -#if SDL_VIDEO_DRIVER_X11_XINPUT2
    4.16 -static void X11_HandleRawMotion(SDL_VideoData *videodata,const XIRawEvent *rawev)
    4.17 -{
    4.18 -    SDL_Mouse *mouse = SDL_GetMouse();
    4.19 -    const double *values = rawev->raw_values;
    4.20 -    int relative_cords[2] = {0,0};
    4.21 -    int i;
    4.22 -
    4.23 -    if (!mouse->relative_mode) {
    4.24 -        return;
    4.25 -    }
    4.26 -   
    4.27 -    /*2 axis,X-Y*/
    4.28 -    for (i = 0; i < 2; i++) {
    4.29 -        if (XIMaskIsSet(rawev->valuators.mask, i)) {
    4.30 -            const int value = (int) *values;
    4.31 -            relative_cords[i] = value;
    4.32 -            values++;
    4.33 -        }
    4.34 -    }
    4.35 -#ifdef DEBUG_MOTION
    4.36 -    printf("XInput relative motion: %d,%d\n", relative_cords[0],relative_cords[1]);
    4.37 -#endif
    4.38 -    SDL_SendMouseMotion(mouse->focus,1,relative_cords[0],relative_cords[1]);
    4.39 -}
    4.40 -#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
    4.41  
    4.42  #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
    4.43  static void X11_HandleGenericEvent(SDL_VideoData *videodata,XEvent event)
    4.44  {
    4.45      XGenericEventCookie *cookie = &event.xcookie;
    4.46      XGetEventData(videodata->display, cookie);
    4.47 -#if SDL_VIDEO_DRIVER_X11_XINPUT2
    4.48 -    if(cookie->extension == videodata->xinput_opcode) {
    4.49 -        switch(cookie->evtype) {
    4.50 -            case XI_RawMotion: {
    4.51 -                const XIRawEvent *rawev = (const XIRawEvent*)cookie->data;
    4.52 -                X11_HandleRawMotion(videodata,rawev);
    4.53 -                }
    4.54 -                break;
    4.55 -
    4.56 -        }
    4.57 -    }
    4.58 -#endif
    4.59 +    X11_HandleXinput2Event(videodata,cookie);
    4.60      XFreeEventData(videodata->display,cookie);
    4.61  }
    4.62  #endif /* SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */
    4.63 @@ -605,9 +569,13 @@
    4.64      while (X11_Pending(data->display)) {
    4.65          X11_DispatchEvent(_this);
    4.66      }
    4.67 +    /*Dont process evtouch events if XInput2 multitouch is supported*/
    4.68 +    if(X11_Xinput2IsMutitouchSupported()) {
    4.69 +        return;
    4.70 +    }
    4.71  
    4.72  #ifdef SDL_INPUT_LINUXEV
    4.73 -    /* Process Touch events - TODO When X gets touch support, use that instead*/
    4.74 +    /* Process Touch events*/
    4.75      int i = 0,rd;
    4.76      struct input_event ev[64];
    4.77      int size = sizeof (struct input_event);
     5.1 --- a/src/video/x11/SDL_x11mouse.c	Wed May 30 15:21:13 2012 -0400
     5.2 +++ b/src/video/x11/SDL_x11mouse.c	Thu May 31 13:37:02 2012 +0300
     5.3 @@ -25,6 +25,7 @@
     5.4  #include "SDL_assert.h"
     5.5  #include "SDL_x11video.h"
     5.6  #include "SDL_x11mouse.h"
     5.7 +#include "SDL_x11xinput2.h"
     5.8  #include "../../events/SDL_mouse_c.h"
     5.9  
    5.10  
    5.11 @@ -273,12 +274,12 @@
    5.12  X11_SetRelativeMouseMode(SDL_bool enabled)
    5.13  {
    5.14  #if SDL_VIDEO_DRIVER_X11_XINPUT2
    5.15 -    /* FIXME: Need to remember from init if XInput2 is actually supported */
    5.16 -    return 0;
    5.17 +    if(X11_Xinput2IsInitialized())
    5.18 +        return 0;
    5.19  #else
    5.20      SDL_Unsupported();
    5.21 +#endif
    5.22      return -1;
    5.23 -#endif
    5.24  }
    5.25  
    5.26  void
     6.1 --- a/src/video/x11/SDL_x11touch.c	Wed May 30 15:21:13 2012 -0400
     6.2 +++ b/src/video/x11/SDL_x11touch.c	Thu May 31 13:37:02 2012 +0300
     6.3 @@ -24,6 +24,7 @@
     6.4  
     6.5  #include "SDL_x11video.h"
     6.6  #include "SDL_x11touch.h"
     6.7 +#include "SDL_x11xinput2.h"
     6.8  #include "../../events/SDL_touch_c.h"
     6.9  
    6.10  
    6.11 @@ -35,82 +36,87 @@
    6.12  void
    6.13  X11_InitTouch(_THIS)
    6.14  {
    6.15 +    /*Initilized Xinput2 multitouch 
    6.16 +    * and return in order to not initialize
    6.17 +    * evtouch also*/
    6.18 +    if(X11_Xinput2IsMutitouchSupported()) {
    6.19 +        X11_InitXinput2Multitouch(_this);
    6.20 +        return;
    6.21 +    }
    6.22  #ifdef SDL_INPUT_LINUXEV
    6.23 -  FILE *fd;
    6.24 -  fd = fopen("/proc/bus/input/devices","r");
    6.25 +    FILE *fd;
    6.26 +    fd = fopen("/proc/bus/input/devices","r");
    6.27  
    6.28 -  int i = 0;
    6.29 -  int tsfd;
    6.30 -  char line[256];
    6.31 -  char tstr[256];
    6.32 -  int vendor = -1,product = -1,event = -1;
    6.33 -  while(!feof(fd)) {
    6.34 -    if(fgets(line,256,fd) <=0) continue;
    6.35 -    if(line[0] == '\n') {
    6.36 -      if(vendor == 1386 || vendor==1) {
    6.37 +    int i = 0;
    6.38 +    int tsfd;
    6.39 +    char line[256];
    6.40 +    char tstr[256];
    6.41 +    int vendor = -1,product = -1,event = -1;
    6.42 +    while(!feof(fd)) {
    6.43 +        if(fgets(line,256,fd) <=0) continue;
    6.44 +        if(line[0] == '\n') {
    6.45 +            if(vendor == 1386 || vendor==1) {
    6.46 +                sprintf(tstr,"/dev/input/event%i",event);
    6.47  
    6.48 -        sprintf(tstr,"/dev/input/event%i",event);
    6.49 +                tsfd = open( tstr, O_RDONLY | O_NONBLOCK );
    6.50 +                if ( tsfd == -1 )
    6.51 +                    continue;   /* Maybe not enough permissions ? */
    6.52  
    6.53 -        tsfd = open( tstr, O_RDONLY | O_NONBLOCK );
    6.54 -        if ( tsfd == -1 )
    6.55 -            continue;   /* Maybe not enough permissions ? */
    6.56 +                SDL_Touch touch;
    6.57 +                touch.pressure_max = 0;
    6.58 +                touch.pressure_min = 0;
    6.59 +                touch.id = event; 
    6.60  
    6.61 -        SDL_Touch touch;
    6.62 -        touch.pressure_max = 0;
    6.63 -        touch.pressure_min = 0;
    6.64 -        touch.id = event; 
    6.65 +                touch.driverdata = SDL_malloc(sizeof(EventTouchData));
    6.66 +                EventTouchData* data = (EventTouchData*)(touch.driverdata);
    6.67  
    6.68 -        touch.driverdata = SDL_malloc(sizeof(EventTouchData));
    6.69 -        EventTouchData* data = (EventTouchData*)(touch.driverdata);
    6.70 +                data->x = -1;
    6.71 +                data->y = -1;
    6.72 +                data->pressure = -1;
    6.73 +                data->finger = 0;
    6.74 +                data->up = SDL_FALSE;
    6.75 +                data->down = SDL_FALSE;
    6.76  
    6.77 -        data->x = -1;
    6.78 -        data->y = -1;
    6.79 -        data->pressure = -1;
    6.80 -        data->finger = 0;
    6.81 -        data->up = SDL_FALSE;
    6.82 -        data->down = SDL_FALSE;
    6.83 +                data->eventStream = tsfd;
    6.84 +                ioctl (data->eventStream, EVIOCGNAME (sizeof (tstr)), tstr);
    6.85  
    6.86 -        data->eventStream = tsfd;
    6.87 -        ioctl (data->eventStream, EVIOCGNAME (sizeof (tstr)), tstr);
    6.88 +                int abs[5];
    6.89 +                ioctl(data->eventStream,EVIOCGABS(0),abs);	
    6.90 +                touch.x_min = abs[1];
    6.91 +                touch.x_max = abs[2];
    6.92 +                touch.native_xres = touch.x_max - touch.x_min;
    6.93 +                ioctl(data->eventStream,EVIOCGABS(ABS_Y),abs);	
    6.94 +                touch.y_min = abs[1];
    6.95 +                touch.y_max = abs[2];
    6.96 +                touch.native_yres = touch.y_max - touch.y_min;
    6.97 +                ioctl(data->eventStream,EVIOCGABS(ABS_PRESSURE),abs);	
    6.98 +                touch.pressure_min = abs[1];
    6.99 +                touch.pressure_max = abs[2];
   6.100 +                touch.native_pressureres = touch.pressure_max - touch.pressure_min;
   6.101  
   6.102 -        int abs[5];
   6.103 -        ioctl(data->eventStream,EVIOCGABS(0),abs);	
   6.104 -        touch.x_min = abs[1];
   6.105 -        touch.x_max = abs[2];
   6.106 -        touch.native_xres = touch.x_max - touch.x_min;
   6.107 -        ioctl(data->eventStream,EVIOCGABS(ABS_Y),abs);	
   6.108 -        touch.y_min = abs[1];
   6.109 -        touch.y_max = abs[2];
   6.110 -        touch.native_yres = touch.y_max - touch.y_min;
   6.111 -        ioctl(data->eventStream,EVIOCGABS(ABS_PRESSURE),abs);	
   6.112 -        touch.pressure_min = abs[1];
   6.113 -        touch.pressure_max = abs[2];
   6.114 -        touch.native_pressureres = touch.pressure_max - touch.pressure_min;
   6.115 -
   6.116 -        SDL_AddTouch(&touch, tstr);
   6.117 -      }
   6.118 -      vendor = -1;
   6.119 -      product = -1;
   6.120 -      event = -1;      
   6.121 +                SDL_AddTouch(&touch, tstr);
   6.122 +            }
   6.123 +            vendor = -1;
   6.124 +            product = -1;
   6.125 +            event = -1;      
   6.126 +        }
   6.127 +        else if(line[0] == 'I') {
   6.128 +            i = 1;
   6.129 +            while(line[i]) {
   6.130 +                sscanf(&line[i],"Vendor=%x",&vendor);
   6.131 +                sscanf(&line[i],"Product=%x",&product);
   6.132 +                i++;
   6.133 +            }
   6.134 +        }
   6.135 +        else if(line[0] == 'H') {
   6.136 +            i = 1;
   6.137 +            while(line[i]) {
   6.138 +                sscanf(&line[i],"event%d",&event);
   6.139 +                i++;
   6.140 +            }
   6.141 +        }
   6.142      }
   6.143 -    else if(line[0] == 'I') {
   6.144 -      i = 1;
   6.145 -      while(line[i]) {
   6.146 -        sscanf(&line[i],"Vendor=%x",&vendor);
   6.147 -        sscanf(&line[i],"Product=%x",&product);
   6.148 -        i++;
   6.149 -      }
   6.150 -    }
   6.151 -    else if(line[0] == 'H') {
   6.152 -      i = 1;
   6.153 -      while(line[i]) {
   6.154 -        sscanf(&line[i],"event%d",&event);
   6.155 -        i++;
   6.156 -      }
   6.157 -    }
   6.158 -  }
   6.159 -
   6.160 -  fclose(fd);
   6.161 +    fclose(fd);
   6.162  #endif
   6.163  }
   6.164  
     7.1 --- a/src/video/x11/SDL_x11touch.h	Wed May 30 15:21:13 2012 -0400
     7.2 +++ b/src/video/x11/SDL_x11touch.h	Thu May 31 13:37:02 2012 +0300
     7.3 @@ -23,12 +23,6 @@
     7.4  #ifndef _SDL_x11touch_h
     7.5  #define _SDL_x11touch_h
     7.6  
     7.7 -/*
     7.8 -!!! FIXME: remove the evdev code;
     7.9 -!!! FIXME: this should be using XInput 2.1's new multitouch API.
    7.10 -*/
    7.11 -
    7.12 -/* What should this be? */
    7.13  #ifdef SDL_INPUT_LINUXEV
    7.14  typedef struct EventTouchData
    7.15  {
     8.1 --- a/src/video/x11/SDL_x11video.c	Wed May 30 15:21:13 2012 -0400
     8.2 +++ b/src/video/x11/SDL_x11video.c	Thu May 31 13:37:02 2012 +0300
     8.3 @@ -33,6 +33,7 @@
     8.4  #include "SDL_x11framebuffer.h"
     8.5  #include "SDL_x11shape.h"
     8.6  #include "SDL_x11touch.h" 
     8.7 +#include "SDL_x11xinput2.h"
     8.8  
     8.9  #if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
    8.10  #include "SDL_x11opengles.h"
    8.11 @@ -321,56 +322,6 @@
    8.12  }
    8.13  
    8.14  int
    8.15 -X11_CheckXInput2(_THIS)
    8.16 -{
    8.17 -#if SDL_VIDEO_DRIVER_X11_XINPUT2
    8.18 -    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    8.19 -
    8.20 -    if (SDL_X11_HAVE_XINPUT2) {
    8.21 -        XIEventMask eventmask;
    8.22 -        unsigned char mask[3] = { 0,0,0 };
    8.23 -        int opcode, event, err;
    8.24 -        int major = 2, minor = 0;
    8.25 -        /*
    8.26 -        * Initialize XInput 2
    8.27 -        * According to http://who-t.blogspot.com/2009/05/xi2-recipes-part-1.html its better
    8.28 -        * to inform Xserver what version of Xinput we support.The server will store the version we support. 
    8.29 -        * "As XI2 progresses it becomes important that you use this call as the server may treat the client 
    8.30 -        * differently depending on the supported version".
    8.31 -        *
    8.32 -        * FIXME:event and err are not needed but if not passed XQueryExtension returns SegmentationFault
    8.33 -        */
    8.34 -        if (!XQueryExtension(data->display, "XInputExtension", &opcode, &event, &err)) {
    8.35 -            SDL_SetError("XInput 2 extension not available.");
    8.36 -            return -1;
    8.37 -        }
    8.38 -      
    8.39 -        if (XIQueryVersion(data->display, &major, &minor) != Success) {
    8.40 -            SDL_SetError("Error supporting XInput 2 version");
    8.41 -            return -1;      
    8.42 -        }
    8.43 -
    8.44 -        /* Save the opcode for event processing */
    8.45 -        data->xinput_opcode = opcode;
    8.46 -
    8.47 -        /*Enable  Raw motion events for this display*/
    8.48 -        eventmask.deviceid = XIAllMasterDevices;
    8.49 -        eventmask.mask_len = sizeof(mask);
    8.50 -        eventmask.mask = mask;
    8.51 -
    8.52 -        XISetMask(mask, XI_RawMotion);
    8.53 -             
    8.54 -        if (XISelectEvents(data->display,DefaultRootWindow(data->display),&eventmask,1) != Success) {
    8.55 -            SDL_SetError("Error in selecting XInput 2 Raw motion events");
    8.56 -            return -1;      
    8.57 -        }
    8.58 -    }
    8.59 -#else
    8.60 -    return 0;
    8.61 -#endif
    8.62 -}
    8.63 -
    8.64 -int
    8.65  X11_VideoInit(_THIS)
    8.66  {
    8.67      SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    8.68 @@ -409,7 +360,7 @@
    8.69          return -1;
    8.70      }
    8.71  
    8.72 -    X11_CheckXInput2(_this);
    8.73 +    X11_InitXinput2(_this);
    8.74  
    8.75      if (X11_InitKeyboard(_this) != 0) {
    8.76          return -1;
     9.1 --- a/src/video/x11/SDL_x11video.h	Wed May 30 15:21:13 2012 -0400
     9.2 +++ b/src/video/x11/SDL_x11video.h	Thu May 31 13:37:02 2012 +0300
     9.3 @@ -92,16 +92,7 @@
     9.4      Atom UTF8_STRING;
     9.5  
     9.6      SDL_Scancode key_layout[256];
     9.7 -    SDL_bool selection_waiting;
     9.8 -    
     9.9 -    /* Opcode returned XQueryExtension 
    9.10 -     * It will be used in event processing
    9.11 -     * to know that the event came from
    9.12 -     * this extension */ 
    9.13 -#if SDL_VIDEO_DRIVER_X11_XINPUT2
    9.14 -    int xinput_opcode;
    9.15 -#endif
    9.16 -    
    9.17 +    SDL_bool selection_waiting;    
    9.18  } SDL_VideoData;
    9.19  
    9.20  extern SDL_bool X11_UseDirectColorVisuals(void);
    10.1 --- a/src/video/x11/SDL_x11window.c	Wed May 30 15:21:13 2012 -0400
    10.2 +++ b/src/video/x11/SDL_x11window.c	Thu May 31 13:37:02 2012 +0300
    10.3 @@ -30,6 +30,7 @@
    10.4  #include "SDL_x11video.h"
    10.5  #include "SDL_x11mouse.h"
    10.6  #include "SDL_x11shape.h"
    10.7 +#include "SDL_x11xinput2.h"
    10.8  
    10.9  #if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
   10.10  #include "SDL_x11opengles.h"
   10.11 @@ -561,6 +562,8 @@
   10.12      }
   10.13  #endif
   10.14  
   10.15 +    X11_Xinput2SelectTouch(_this, window);
   10.16 +
   10.17      XSelectInput(display, w,
   10.18                   (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
   10.19                   ExposureMask | ButtonPressMask | ButtonReleaseMask |
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/video/x11/SDL_x11xinput2.c	Thu May 31 13:37:02 2012 +0300
    11.3 @@ -0,0 +1,249 @@
    11.4 +/*
    11.5 +  Simple DirectMedia Layer
    11.6 +  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
    11.7 +
    11.8 +  This software is provided 'as-is', without any express or implied
    11.9 +  warranty.  In no event will the authors be held liable for any damages
   11.10 +  arising from the use of this software.
   11.11 +
   11.12 +  Permission is granted to anyone to use this software for any purpose,
   11.13 +  including commercial applications, and to alter it and redistribute it
   11.14 +  freely, subject to the following restrictions:
   11.15 +
   11.16 +  1. The origin of this software must not be misrepresented; you must not
   11.17 +     claim that you wrote the original software. If you use this software
   11.18 +     in a product, an acknowledgment in the product documentation would be
   11.19 +     appreciated but is not required.
   11.20 +  2. Altered source versions must be plainly marked as such, and must not be
   11.21 +     misrepresented as being the original software.
   11.22 +  3. This notice may not be removed or altered from any source distribution.
   11.23 +*/
   11.24 +#include "SDL_config.h"
   11.25 +
   11.26 +#if SDL_VIDEO_DRIVER_X11
   11.27 +
   11.28 +#include "SDL_x11video.h"
   11.29 +#include "SDL_x11xinput2.h"
   11.30 +#include "../../events/SDL_mouse_c.h"
   11.31 +#include "../../events/SDL_touch_c.h"
   11.32 +
   11.33 +#define MAX_AXIS 16
   11.34 +
   11.35 +static int xinput2_initialized = 0;
   11.36 +static int xinput2_multitouch_supported = 0;
   11.37 +/* Opcode returned XQueryExtension 
   11.38 + * It will be used in event processing
   11.39 + * to know that the event came from
   11.40 + * this extension */ 
   11.41 +static int xinput2_opcode;
   11.42 +
   11.43 +
   11.44 +#if SDL_VIDEO_DRIVER_X11_XINPUT2
   11.45 +static void parse_valuators(const double *input_values,unsigned char *mask,int mask_len,
   11.46 +                            double *output_values,int output_values_len) {
   11.47 +    int i = 0,z = 0;
   11.48 +    int top = mask_len * 8;
   11.49 +    if (top > MAX_AXIS)
   11.50 +        top = MAX_AXIS;
   11.51 +
   11.52 +    SDL_memset(output_values,0,output_values_len * sizeof(double));
   11.53 +    for (; i < top && z < output_values_len; i++) {
   11.54 +        if (XIMaskIsSet(mask, i)) {
   11.55 +            const int value = (int) *input_values;
   11.56 +            output_values[z] = value;
   11.57 +            input_values++;
   11.58 +        }
   11.59 +        z++;
   11.60 +    }
   11.61 +}
   11.62 +#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
   11.63 +
   11.64 +void 
   11.65 +X11_InitXinput2(_THIS) {
   11.66 +#if SDL_VIDEO_DRIVER_X11_XINPUT2
   11.67 +    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   11.68 +
   11.69 +    XIEventMask eventmask;
   11.70 +    unsigned char mask[3] = { 0,0,0 };
   11.71 +    int event, err;
   11.72 +    int major = 2, minor = 0;
   11.73 +    int outmajor,outminor;
   11.74 +#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
   11.75 +    minor = 2;
   11.76 +#endif
   11.77 +    /*
   11.78 +    * Initialize XInput 2
   11.79 +    * According to http://who-t.blogspot.com/2009/05/xi2-recipes-part-1.html its better
   11.80 +    * to inform Xserver what version of Xinput we support.The server will store the version we support. 
   11.81 +    * "As XI2 progresses it becomes important that you use this call as the server may treat the client 
   11.82 +    * differently depending on the supported version".
   11.83 +    *
   11.84 +    * FIXME:event and err are not needed but if not passed XQueryExtension returns SegmentationFault
   11.85 +    */
   11.86 +    if (!XQueryExtension(data->display, "XInputExtension", &xinput2_opcode, &event, &err)) {
   11.87 +        return;
   11.88 +    }
   11.89 +
   11.90 +    outmajor = major;
   11.91 +    outminor = minor;
   11.92 +    if (XIQueryVersion(data->display, &outmajor, &outminor) != Success) {
   11.93 +        return;
   11.94 +    }
   11.95 +
   11.96 +    /*Check supported version*/
   11.97 +    if(outmajor * 1000 + outminor < major * 1000 + minor) {
   11.98 +        /*X server does not support the version we want*/
   11.99 +        return;
  11.100 +    }
  11.101 +    xinput2_initialized = 1;
  11.102 +#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
  11.103 +    /*XInput 2.2*/
  11.104 +    if(outmajor * 1000 + outminor >= major * 1000 + minor) {
  11.105 +        xinput2_multitouch_supported = 1;
  11.106 +    }
  11.107 +#endif
  11.108 +
  11.109 +    /*Enable  Raw motion events for this display*/
  11.110 +    eventmask.deviceid = XIAllMasterDevices;
  11.111 +    eventmask.mask_len = sizeof(mask);
  11.112 +    eventmask.mask = mask;
  11.113 +
  11.114 +    XISetMask(mask, XI_RawMotion);
  11.115 +         
  11.116 +    if (XISelectEvents(data->display,DefaultRootWindow(data->display),&eventmask,1) != Success) {
  11.117 +        return;     
  11.118 +    }
  11.119 +#endif
  11.120 +}
  11.121 +
  11.122 +
  11.123 +
  11.124 +int 
  11.125 +X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie) {
  11.126 +#if SDL_VIDEO_DRIVER_X11_XINPUT2
  11.127 +    if(cookie->extension != xinput2_opcode) {
  11.128 +        return 0;
  11.129 +    }
  11.130 +    switch(cookie->evtype) {
  11.131 +        case XI_RawMotion: {
  11.132 +            const XIRawEvent *rawev = (const XIRawEvent*)cookie->data;
  11.133 +            SDL_Mouse *mouse = SDL_GetMouse();
  11.134 +            double relative_cords[2];
  11.135 +
  11.136 +            if (!mouse->relative_mode) {
  11.137 +                return 0;
  11.138 +            }
  11.139 +
  11.140 +            parse_valuators(rawev->raw_values,rawev->valuators.mask,
  11.141 +                            rawev->valuators.mask_len,relative_cords,2);
  11.142 +            SDL_SendMouseMotion(mouse->focus,1,(int)relative_cords[0],(int)relative_cords[1]);
  11.143 +            return 1;
  11.144 +            }
  11.145 +            break;
  11.146 +#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
  11.147 +        case XI_TouchBegin: {
  11.148 +            const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
  11.149 +            SDL_SendFingerDown(xev->sourceid,xev->detail,
  11.150 +                      SDL_TRUE, (int)xev->event_x, (int)xev->event_y,
  11.151 +		    		  1.0);
  11.152 +            return 1;
  11.153 +            }
  11.154 +            break;
  11.155 +        case XI_TouchEnd: {
  11.156 +            const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
  11.157 +            SDL_SendFingerDown(xev->sourceid,xev->detail,
  11.158 +                      SDL_FALSE, (int)xev->event_x, (int)xev->event_y,
  11.159 +		    		  1.0);
  11.160 +            return 1;
  11.161 +            }
  11.162 +            break;
  11.163 +        case XI_TouchUpdate: {
  11.164 +            const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
  11.165 +            SDL_SendTouchMotion(xev->sourceid,xev->detail,
  11.166 +                      SDL_FALSE, (int)xev->event_x, (int)xev->event_y,
  11.167 +		    		  1.0);
  11.168 +            return 1;
  11.169 +            }
  11.170 +            break;
  11.171 +#endif
  11.172 +    }
  11.173 +#endif
  11.174 +    return 0;
  11.175 +}
  11.176 +
  11.177 +void 
  11.178 +X11_InitXinput2Multitouch(_THIS) {
  11.179 +#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
  11.180 +    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
  11.181 +    XIDeviceInfo *info;
  11.182 +    int ndevices,i,j;
  11.183 +    info = XIQueryDevice(data->display, XIAllMasterDevices, &ndevices);
  11.184 +
  11.185 +    for (i = 0; i < ndevices; i++) {
  11.186 +        XIDeviceInfo *dev = &info[i];
  11.187 +        for (j = 0; j < dev->num_classes; j++) {
  11.188 +            SDL_TouchID touchId;
  11.189 +            XIAnyClassInfo *class = dev->classes[j];
  11.190 +            XITouchClassInfo *t = (XITouchClassInfo*)class;
  11.191 +
  11.192 +            /*Only touch devices*/
  11.193 +            if (class->type != XITouchClass)
  11.194 +                continue;
  11.195 +
  11.196 +            touchId = t->sourceid;
  11.197 +            /*Add the touch*/
  11.198 +            if (!SDL_GetTouch(touchId)) {
  11.199 +                SDL_Touch touch;
  11.200 +
  11.201 +                touch.id = touchId;
  11.202 +                touch.x_min = 0;
  11.203 +                touch.x_max = 1;
  11.204 +                touch.native_xres = touch.x_max - touch.x_min;
  11.205 +                touch.y_min = 0;
  11.206 +                touch.y_max = 1;
  11.207 +                touch.native_yres = touch.y_max - touch.y_min;
  11.208 +                touch.pressure_min = 0;
  11.209 +                touch.pressure_max = 1;
  11.210 +                touch.native_pressureres = touch.pressure_max - touch.pressure_min;
  11.211 +
  11.212 +                SDL_AddTouch(&touch,dev->name);
  11.213 +            }
  11.214 +        }
  11.215 +    }
  11.216 +#endif
  11.217 +}
  11.218 +
  11.219 +void 
  11.220 +X11_Xinput2SelectTouch(_THIS, SDL_Window *window) {
  11.221 +#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
  11.222 +    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
  11.223 +    XIEventMask eventmask;
  11.224 +    unsigned char mask[3] = { 0,0,0 };
  11.225 +    SDL_WindowData *window_data = (SDL_WindowData*)window->driverdata;
  11.226 +
  11.227 +    eventmask.deviceid = XIAllMasterDevices;
  11.228 +    eventmask.mask_len = sizeof(mask);
  11.229 +    eventmask.mask = mask;
  11.230 +
  11.231 +    XISetMask(mask, XI_TouchBegin);
  11.232 +    XISetMask(mask, XI_TouchUpdate);
  11.233 +    XISetMask(mask, XI_TouchEnd);
  11.234 +         
  11.235 +    XISelectEvents(data->display,window_data->xwindow,&eventmask,1);
  11.236 +#endif
  11.237 +}
  11.238 +
  11.239 +
  11.240 +int 
  11.241 +X11_Xinput2IsInitialized() {
  11.242 +    return xinput2_initialized;
  11.243 +}
  11.244 +
  11.245 +int
  11.246 +X11_Xinput2IsMutitouchSupported() {
  11.247 +    return xinput2_initialized && xinput2_multitouch_supported;
  11.248 +}
  11.249 +
  11.250 +#endif /* SDL_VIDEO_DRIVER_X11 */
  11.251 +
  11.252 +/* vi: set ts=4 sw=4 expandtab: */
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/video/x11/SDL_x11xinput2.h	Thu May 31 13:37:02 2012 +0300
    12.3 @@ -0,0 +1,42 @@
    12.4 +/*
    12.5 +  Simple DirectMedia Layer
    12.6 +  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
    12.7 +
    12.8 +  This software is provided 'as-is', without any express or implied
    12.9 +  warranty.  In no event will the authors be held liable for any damages
   12.10 +  arising from the use of this software.
   12.11 +
   12.12 +  Permission is granted to anyone to use this software for any purpose,
   12.13 +  including commercial applications, and to alter it and redistribute it
   12.14 +  freely, subject to the following restrictions:
   12.15 +
   12.16 +  1. The origin of this software must not be misrepresented; you must not
   12.17 +     claim that you wrote the original software. If you use this software
   12.18 +     in a product, an acknowledgment in the product documentation would be
   12.19 +     appreciated but is not required.
   12.20 +  2. Altered source versions must be plainly marked as such, and must not be
   12.21 +     misrepresented as being the original software.
   12.22 +  3. This notice may not be removed or altered from any source distribution.
   12.23 +*/
   12.24 +#include "SDL_config.h"
   12.25 +
   12.26 +#ifndef _SDL_x11xinput2_h
   12.27 +#define _SDL_x11xinput2_h
   12.28 +
   12.29 +#ifndef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
   12.30 +/*Define XGenericEventCookie as forward declaration when 
   12.31 + *xinput2 is not available in order to compile*/
   12.32 +struct XGenericEventCookie;
   12.33 +typedef struct XGenericEventCookie XGenericEventCookie;
   12.34 +#endif 
   12.35 +
   12.36 +extern void X11_InitXinput2(_THIS);
   12.37 +extern void X11_InitXinput2Multitouch(_THIS);
   12.38 +extern int X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie);
   12.39 +extern int X11_Xinput2IsInitialized(void);
   12.40 +extern int X11_Xinput2IsMutitouchSupported(void);
   12.41 +extern void X11_Xinput2SelectTouch(_THIS, SDL_Window *window);
   12.42 +
   12.43 +#endif /* _SDL_x11xinput2_h */
   12.44 +
   12.45 +/* vi: set ts=4 sw=4 expandtab: */
    13.1 --- a/test/testrelative.c	Wed May 30 15:21:13 2012 -0400
    13.2 +++ b/test/testrelative.c	Thu May 31 13:37:02 2012 +0300
    13.3 @@ -54,7 +54,9 @@
    13.4      }
    13.5  
    13.6      srand((unsigned int)time(NULL));
    13.7 -    SDL_SetRelativeMouseMode(SDL_TRUE);
    13.8 +    if(SDL_SetRelativeMouseMode(SDL_TRUE) < 0) {
    13.9 +        return 3;
   13.10 +    };
   13.11  
   13.12      rect.x = DEFAULT_WINDOW_WIDTH / 2;
   13.13      rect.y = DEFAULT_WINDOW_HEIGHT / 2;