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
This commit is contained in:
Sam Lantinga 2012-05-30 11:25:35 -04:00
parent 36feea4efd
commit 6accd81680
14 changed files with 258 additions and 42 deletions

View file

@ -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,7 +1152,7 @@ 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>
@ -1158,7 +1160,7 @@ AC_HELP_STRING([--enable-video-x11-xinput], [enable X11 XInput extension for man
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]]]),

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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}

View file

@ -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>

View file

@ -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,11 +393,15 @@ 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);
#endif
SDL_SendMouseMotion(data->window, 0, xevent.xmotion.x, xevent.xmotion.y);
}
}
break;
case ButtonPress:{

View file

@ -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

View file

@ -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);

View file

@ -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 */

View file

@ -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;
}

View file

@ -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);

View file

@ -22,6 +22,7 @@ TARGETS = \
testiconv$(EXE) \
testime$(EXE) \
testintersections$(EXE) \
testrelative$(EXE) \
testjoystick$(EXE) \
testkeys$(EXE) \
testloadso$(EXE) \
@ -71,6 +72,9 @@ testatomic$(EXE): $(srcdir)/testatomic.c
testintersections$(EXE): $(srcdir)/testintersections.c $(srcdir)/common.c
$(CC) -o $@ $(srcdir)/testintersections.c $(srcdir)/common.c $(CFLAGS) $(LIBS)
testrelative$(EXE): $(srcdir)/testrelative.c $(srcdir)/common.c
$(CC) -o $@ $(srcdir)/testrelative.c $(srcdir)/common.c $(CFLAGS) $(LIBS)
testdraw2$(EXE): $(srcdir)/testdraw2.c $(srcdir)/common.c
$(CC) -o $@ $(srcdir)/testdraw2.c $(srcdir)/common.c $(CFLAGS) $(LIBS)

95
test/testrelative.c Normal file
View file

@ -0,0 +1,95 @@
/*
Copyright (C) 1997-2011 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.
*/
/* Simple program: Test relative mouse motion */
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "common.h"
static CommonState *state;
static SDL_Rect rect;
static void
DrawRects(SDL_Renderer * renderer)
{
SDL_SetRenderDrawColor(renderer, 255, 127, 0, 255);
SDL_RenderFillRect(renderer,&rect);
}
int
main(int argc, char *argv[])
{
int i, done;
SDL_Event event;
/* Initialize test framework */
state = CommonCreateState(argv, SDL_INIT_VIDEO);
if (!state) {
return 1;
}
if (!CommonInit(state)) {
return 2;
}
/* Create the windows and initialize the renderers */
for (i = 0; i < state->num_windows; ++i) {
SDL_Renderer *renderer = state->renderers[i];
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
SDL_RenderClear(renderer);
}
srand((unsigned int)time(NULL));
SDL_SetRelativeMouseMode(SDL_TRUE);
rect.x = DEFAULT_WINDOW_WIDTH / 2;
rect.y = DEFAULT_WINDOW_HEIGHT / 2;
rect.w = 10;
rect.h = 10;
/* Main render loop */
done = 0;
while (!done) {
/* Check for events */
while (SDL_PollEvent(&event)) {
CommonEvent(state, &event, &done);
switch(event.type) {
case SDL_MOUSEMOTION:
{
/*printf("mouse motion ABS x %d y %d REL x %d y %d\n",event.motion.x,event.motion.y,event.motion.xrel,event.motion.yrel);*/
rect.x += event.motion.xrel;
rect.y += event.motion.yrel;
}
break;
}
}
for (i = 0; i < state->num_windows; ++i) {
SDL_Renderer *renderer = state->renderers[i];
SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
SDL_RenderClear(renderer);
DrawRects(renderer);
SDL_RenderPresent(renderer);
}
}
CommonQuit(state);
return 0;
}
/* vi: set ts=4 sw=4 expandtab: */