Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Initial support for XInput2 by Dimitris Zenios

1.initial work on XInput2 support
2.Implemented relative mouse motion when XInput2 is enabled
3.Created a test app to test relative mouse motion
4.Fixed Bug #1498
  • Loading branch information
slouken committed May 30, 2012
1 parent dc74dd2 commit 31edc9d8a61e3ac00be3fc20bafebcca1fbb3330
@@ -1091,6 +1091,8 @@ AC_HELP_STRING([--enable-x11-shared], [dynamically load X11 support [[default=ma
fi
have_video=yes

AC_CHECK_LIB(X11, XGetEventData, AC_DEFINE(SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS, 1, [Have XGenericEvent]))

AC_ARG_ENABLE(video-x11-xcursor,
AC_HELP_STRING([--enable-video-x11-xcursor], [enable X11 Xcursor support [[default=yes]]]),
, enable_video_x11_xcursor=yes)
@@ -1150,15 +1152,15 @@ AC_HELP_STRING([--enable-video-x11-xinput], [enable X11 XInput extension for man
, enable_video_x11_xinput=yes)
if test x$enable_video_x11_xinput = xyes; then
definitely_enable_video_x11_xinput=no
AC_CHECK_HEADER(X11/extensions/XInput.h,
AC_CHECK_HEADER(X11/extensions/XInput2.h,
have_xinput_h_hdr=yes,
have_xinput_h_hdr=no,
[#include <X11/Xlib.h>
])
if test x$have_xinput_h_hdr = xyes; then
if test x$enable_x11_shared = xyes && test x$xinput_lib != x ; then
echo "-- dynamic libXi -> $xinput_lib"
AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT, "$xinput_lib", [ ])
AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2, "$xinput_lib", [ ])
definitely_enable_video_x11_xinput=yes
else
AC_CHECK_LIB(Xi, XOpenDevice, have_xinput_lib=yes)
@@ -1170,7 +1172,7 @@ AC_HELP_STRING([--enable-video-x11-xinput], [enable X11 XInput extension for man
fi
fi
if test x$definitely_enable_video_x11_xinput = xyes; then
AC_DEFINE(SDL_VIDEO_DRIVER_X11_XINPUT, 1, [ ])
AC_DEFINE(SDL_VIDEO_DRIVER_X11_XINPUT2, 1, [ ])
fi
AC_ARG_ENABLE(video-x11-xrandr,
AC_HELP_STRING([--enable-video-x11-xrandr], [enable X11 Xrandr extension for fullscreen [[default=yes]]]),
@@ -257,17 +257,18 @@
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS
#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE
#undef SDL_VIDEO_DRIVER_X11_XCURSOR
#undef SDL_VIDEO_DRIVER_X11_XINERAMA
#undef SDL_VIDEO_DRIVER_X11_XINPUT
#undef SDL_VIDEO_DRIVER_X11_XINPUT2
#undef SDL_VIDEO_DRIVER_X11_XRANDR
#undef SDL_VIDEO_DRIVER_X11_XSCRNSAVER
#undef SDL_VIDEO_DRIVER_X11_XSHAPE
#undef SDL_VIDEO_DRIVER_X11_XVIDMODE
#undef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS

#undef SDL_VIDEO_RENDER_D3D
#undef SDL_VIDEO_RENDER_OGL
@@ -134,16 +134,17 @@
#define SDL_VIDEO_DRIVER_X11_DYNAMIC "/usr/X11R6/lib/libX11.6.dylib"
#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "/usr/X11R6/lib/libXext.6.dylib"
#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA "/usr/X11R6/lib/libXinerama.1.dylib"
#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT "/usr/X11R6/lib/libXi.6.dylib"
#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "/usr/X11R6/lib/libXi.6.dylib"
#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "/usr/X11R6/lib/libXrandr.2.dylib"
#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "/usr/X11R6/lib/libXss.1.dylib"
#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_XINPUT 1
#define SDL_VIDEO_DRIVER_X11_XINPUT2 1
#define SDL_VIDEO_DRIVER_X11_XRANDR 1
#define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
#define SDL_VIDEO_DRIVER_X11_XSHAPE 1
#define SDL_VIDEO_DRIVER_X11_XVIDMODE 1
#define SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS

#ifndef SDL_VIDEO_RENDER_OGL
#define SDL_VIDEO_RENDER_OGL 1
@@ -117,7 +117,6 @@

#define SDL_VIDEO_DRIVER_DUMMY 1
#define SDL_VIDEO_DRIVER_X11 1
#define SDL_VIDEO_DRIVER_X11_XINPUT 1
#define SDL_VIDEO_DRIVER_PANDORA 1
#define SDL_VIDEO_RENDER_OGL_ES 1
#define SDL_VIDEO_OPENGL_ES 1
@@ -53,8 +53,8 @@ typedef struct
#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA
#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA NULL
#endif
#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT
#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT NULL
#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2
#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 NULL
#endif
#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR
#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR NULL
@@ -71,7 +71,7 @@ static x11dynlib x11libs[] = {
{NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT},
{NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR},
{NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA},
{NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT},
{NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2},
{NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR},
{NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS},
{NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE}
@@ -49,8 +49,8 @@
#if SDL_VIDEO_DRIVER_X11_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
#if SDL_VIDEO_DRIVER_X11_XINPUT
#include <X11/extensions/XInput.h>
#if SDL_VIDEO_DRIVER_X11_XINPUT2
#include <X11/extensions/XInput2.h>
#endif
#if SDL_VIDEO_DRIVER_X11_XRANDR
#include <X11/extensions/Xrandr.h>
@@ -44,7 +44,6 @@
#include <linux/input.h>
#include <fcntl.h>
#endif
/*#define DEBUG_XEVENTS*/

/* Check to see if this is a repeated key.
(idea shamelessly lifted from GII -- thanks guys! :)
@@ -95,6 +94,56 @@ static SDL_bool X11_IsWheelEvent(Display * display,XEvent * event,int * ticks)
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
XFreeEventData(videodata->display,cookie);
}
#endif /* SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */



static void
X11_DispatchEvent(_THIS)
{
@@ -127,6 +176,13 @@ X11_DispatchEvent(_THIS)
SDL_SendSysWMEvent(&wmmsg);
}

#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
if(xevent.type == GenericEvent) {
X11_HandleGenericEvent(videodata,xevent);
return;
}
#endif

data = NULL;
if (videodata && videodata->windowlist) {
for (i = 0; i < videodata->numwindows; ++i) {
@@ -337,10 +393,14 @@ X11_DispatchEvent(_THIS)
break;

case MotionNotify:{
SDL_Mouse *mouse = SDL_GetMouse();
if(!mouse->relative_mode) {
#ifdef DEBUG_MOTION
printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
printf("X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
#endif
SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y);

SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y);
}
}
break;

@@ -272,8 +272,13 @@ X11_WarpMouse(SDL_Window * window, int x, int y)
static int
X11_SetRelativeMouseMode(SDL_bool enabled)
{
#if SDL_VIDEO_DRIVER_X11_XINPUT2
/* FIXME: Need to remember from init if XInput2 is actually supported */
return 0;
#else
SDL_Unsupported();
return -1;
#endif
}

void
@@ -23,21 +23,6 @@
#ifndef _SDL_x11mouse_h
#define _SDL_x11mouse_h

#if SDL_VIDEO_DRIVER_X11_XINPUT
typedef struct X11_MouseData
{
Display *display;
XDevice *device;
int motion;
int button_pressed;
int button_released;
int proximity_in;
int proximity_out;
int num_xevents;
XEventClass xevents[5];
} X11_MouseData;
#endif

extern void X11_InitMouse(_THIS);
extern void X11_QuitMouse(_THIS);

@@ -103,7 +103,7 @@ SDL_X11_SYM(int,XUngrabServer,(Display* a),(a),return)
SDL_X11_SYM(int,XUnmapWindow,(Display* a,Window b),(a,b),return)
SDL_X11_SYM(int,XWarpPointer,(Display* a,Window b,Window c,int d,int e,unsigned int f,unsigned int g,int h,int i),(a,b,c,d,e,f,g,h,i),return)
SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return)
SDL_X11_SYM(XExtDisplayInfo*,XextAddDisplay,(XExtensionInfo* a,Display* b,char* c,XExtensionHooks* d,int e,XPointer f),(a,b,c,d,e,f),return)
SDL_X11_SYM(XExtDisplayInfo*,XextAddDisplay,(XExtensionInfo* a,Display* b,_Xconst char* c,XExtensionHooks* d,int e,XPointer f),(a,b,c,d,e,f),return)
SDL_X11_SYM(XExtensionInfo*,XextCreateExtension,(void),(),return)
SDL_X11_SYM(void,XextDestroyExtension,(XExtensionInfo* a),(a),)
SDL_X11_SYM(XExtDisplayInfo*,XextFindDisplay,(XExtensionInfo* a,Display* b),(a,b),return)
@@ -123,6 +123,11 @@ SDL_X11_SYM(SDL_X11_XSynchronizeRetType,XSynchronize,(Display* a,Bool b),(a,b),r
SDL_X11_SYM(SDL_X11_XESetWireToEventRetType,XESetWireToEvent,(Display* a,int b,SDL_X11_XESetWireToEventRetType c),(a,b,c),return)
SDL_X11_SYM(SDL_X11_XESetEventToWireRetType,XESetEventToWire,(Display* a,int b,SDL_X11_XESetEventToWireRetType c),(a,b,c),return)

#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
SDL_X11_SYM(Bool,XGetEventData,(Display* a,XGenericEventCookie* b),(a,b),return)
SDL_X11_SYM(void,XFreeEventData,(Display* a,XGenericEventCookie* b),(a,b),)
#endif

#if NeedWidePrototypes
SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),return)
#else
@@ -190,14 +195,14 @@ SDL_X11_SYM(Status,XineramaQueryVersion,(Display *a,int *b,int *c),(a,b,c),retur
SDL_X11_SYM(XineramaScreenInfo*,XineramaQueryScreens,(Display *a, int *b),(a,b),return)
#endif

/* XInput support for multiple mice, tablets, etc. */
#if SDL_VIDEO_DRIVER_X11_XINPUT
SDL_X11_MODULE(XINPUT)
SDL_X11_SYM(XDeviceInfo*,XListInputDevices,(Display *a,int *b),(a,b),return)
SDL_X11_SYM(void,XFreeDeviceList,(XDeviceInfo *a),(a),)
SDL_X11_SYM(int,XSelectExtensionEvent,(Display *a,Window b,XEventClass *c,int d),(a,b,c,d),return)
SDL_X11_SYM(XDevice*,XOpenDevice,(Display *a,XID b),(a,b),return)
SDL_X11_SYM(int,XCloseDevice,(Display* a,XDevice* b),(a,b),return)
/* XInput2 support for multiple mice, tablets, etc. */
#if SDL_VIDEO_DRIVER_X11_XINPUT2
SDL_X11_MODULE(XINPUT2)
SDL_X11_SYM(XIDeviceInfo*,XIQueryDevice,(Display *a,int b,int *c),(a,b,c),return)
SDL_X11_SYM(void,XIFreeDeviceInfo,(XIDeviceInfo *a),(a),)
SDL_X11_SYM(int,XISelectEvents,(Display *a,Window b,XIEventMask *c,int d),(a,b,c,d),return)
SDL_X11_SYM(Status,XIQueryVersion,(Display *a,int *b,int *c),(a,b,c),return)
SDL_X11_SYM(XIEventMask*,XIGetSelectedEvents,(Display *a,Window b,int *c),(a,b,c),return)
#endif

/* XRandR support */
@@ -320,6 +320,54 @@ X11_CheckWindowManager(_THIS)
#endif
}

int
X11_CheckXInput2(_THIS)
{
#if SDL_VIDEO_DRIVER_X11_XINPUT2
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)
{
@@ -359,6 +407,8 @@ X11_VideoInit(_THIS)
return -1;
}

X11_CheckXInput2(_this);

if (X11_InitKeyboard(_this) != 0) {
return -1;
}
@@ -37,8 +37,8 @@
#if SDL_VIDEO_DRIVER_X11_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
#if SDL_VIDEO_DRIVER_X11_XINPUT
#include <X11/extensions/XInput.h>
#if SDL_VIDEO_DRIVER_X11_XINPUT2
#include <X11/extensions/XInput2.h>
#endif
#if SDL_VIDEO_DRIVER_X11_XRANDR
#include <X11/extensions/Xrandr.h>
@@ -93,6 +93,15 @@ typedef struct SDL_VideoData

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_VideoData;

extern SDL_bool X11_UseDirectColorVisuals(void);

0 comments on commit 31edc9d

Please sign in to comment.