zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_x11xinput2.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22 
23 #if SDL_VIDEO_DRIVER_X11
24 
25 #include "SDL_x11video.h"
26 #include "SDL_x11xinput2.h"
27 #include "../../events/SDL_mouse_c.h"
28 #include "../../events/SDL_touch_c.h"
29 
30 #define MAX_AXIS 16
31 
32 #if SDL_VIDEO_DRIVER_X11_XINPUT2
33 static int xinput2_initialized = 0;
34 
35 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
36 static int xinput2_multitouch_supported = 0;
37 #endif
38 
39 /* Opcode returned XQueryExtension
40  * It will be used in event processing
41  * to know that the event came from
42  * this extension */
43 static int xinput2_opcode;
44 
45 static void parse_valuators(const double *input_values,unsigned char *mask,int mask_len,
46  double *output_values,int output_values_len) {
47  int i = 0,z = 0;
48  int top = mask_len * 8;
49  if (top > MAX_AXIS)
50  top = MAX_AXIS;
51 
52  SDL_memset(output_values,0,output_values_len * sizeof(double));
53  for (; i < top && z < output_values_len; i++) {
54  if (XIMaskIsSet(mask, i)) {
55  const int value = (int) *input_values;
56  output_values[z] = value;
57  input_values++;
58  }
59  z++;
60  }
61 }
62 #endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
63 
64 void
66 {
67 #if SDL_VIDEO_DRIVER_X11_XINPUT2
69 
70  XIEventMask eventmask;
71  unsigned char mask[3] = { 0,0,0 };
72  int event, err;
73  int major = 2, minor = 0;
74  int outmajor,outminor;
75 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
76  minor = 2;
77 #endif
78  /*
79  * Initialize XInput 2
80  * According to http://who-t.blogspot.com/2009/05/xi2-recipes-part-1.html its better
81  * to inform Xserver what version of Xinput we support.The server will store the version we support.
82  * "As XI2 progresses it becomes important that you use this call as the server may treat the client
83  * differently depending on the supported version".
84  *
85  * FIXME:event and err are not needed but if not passed XQueryExtension returns SegmentationFault
86  */
87  if (!SDL_X11_HAVE_XINPUT2 ||
88  !XQueryExtension(data->display, "XInputExtension", &xinput2_opcode, &event, &err)) {
89  return;
90  }
91 
92  outmajor = major;
93  outminor = minor;
94  if (XIQueryVersion(data->display, &outmajor, &outminor) != Success) {
95  return;
96  }
97 
98  /* Check supported version */
99  if(outmajor * 1000 + outminor < major * 1000 + minor) {
100  /* X server does not support the version we want */
101  return;
102  }
103  xinput2_initialized = 1;
104 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
105  /* XInput 2.2 */
106  if(outmajor * 1000 + outminor >= major * 1000 + minor) {
107  xinput2_multitouch_supported = 1;
108  }
109 #endif
110 
111  /* Enable Raw motion events for this display */
112  eventmask.deviceid = XIAllMasterDevices;
113  eventmask.mask_len = sizeof(mask);
114  eventmask.mask = mask;
115 
116  XISetMask(mask, XI_RawMotion);
117 
118  if (XISelectEvents(data->display,DefaultRootWindow(data->display),&eventmask,1) != Success) {
119  return;
120  }
121 #endif
122 }
123 
124 struct XGenericEventCookie {
125  int type;
126  unsigned long serial;
127  Bool send_event;
128  Display *display;
129  int extension;
130  int evtype;
131  unsigned int cookie;
132  void *data;
133 };
134 
135 int
137 {
138 #if SDL_VIDEO_DRIVER_X11_XINPUT2
139  if(cookie->extension != xinput2_opcode) {
140  return 0;
141  }
142  switch(cookie->evtype) {
143  case XI_RawMotion: {
144  const XIRawEvent *rawev = (const XIRawEvent*)cookie->data;
145  SDL_Mouse *mouse = SDL_GetMouse();
146  double relative_cords[2];
147 
148  if (!mouse->relative_mode) {
149  return 0;
150  }
151 
152  parse_valuators(rawev->raw_values,rawev->valuators.mask,
153  rawev->valuators.mask_len,relative_cords,2);
154  SDL_SendMouseMotion(mouse->focus,mouse->mouseID,1,(int)relative_cords[0],(int)relative_cords[1]);
155  return 1;
156  }
157  break;
158 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
159  case XI_TouchBegin: {
160  const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
161  SDL_SendTouch(xev->sourceid,xev->detail,
162  SDL_TRUE, xev->event_x, xev->event_y, 1.0);
163  return 1;
164  }
165  break;
166  case XI_TouchEnd: {
167  const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
168  SDL_SendTouch(xev->sourceid,xev->detail,
169  SDL_FALSE, xev->event_x, xev->event_y, 1.0);
170  return 1;
171  }
172  break;
173  case XI_TouchUpdate: {
174  const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
175  SDL_SendTouchMotion(xev->sourceid,xev->detail,
176  xev->event_x, xev->event_y, 1.0);
177  return 1;
178  }
179  break;
180 #endif
181  }
182 #endif
183  return 0;
184 }
185 
186 void
188 {
189 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
191  XIDeviceInfo *info;
192  int ndevices,i,j;
193  info = XIQueryDevice(data->display, XIAllMasterDevices, &ndevices);
194 
195  for (i = 0; i < ndevices; i++) {
196  XIDeviceInfo *dev = &info[i];
197  for (j = 0; j < dev->num_classes; j++) {
198  SDL_TouchID touchId;
199  XIAnyClassInfo *class = dev->classes[j];
200  XITouchClassInfo *t = (XITouchClassInfo*)class;
201 
202  /* Only touch devices */
203  if (class->type != XITouchClass)
204  continue;
205 
206  touchId = t->sourceid;
207  if (!SDL_GetTouch(touchId)) {
208  SDL_AddTouch(touchId, dev->name);
209  }
210  }
211  }
212  XIFreeDeviceInfo(info);
213 #endif
214 }
215 
216 void
218 {
219 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
220  SDL_VideoData *data = NULL;
221  XIEventMask eventmask;
222  unsigned char mask[3] = { 0,0,0 };
223  SDL_WindowData *window_data = NULL;
224 
226  return;
227  }
228 
229  data = (SDL_VideoData *) _this->driverdata;
230  window_data = (SDL_WindowData*)window->driverdata;
231 
232  eventmask.deviceid = XIAllMasterDevices;
233  eventmask.mask_len = sizeof(mask);
234  eventmask.mask = mask;
235 
236  XISetMask(mask, XI_TouchBegin);
237  XISetMask(mask, XI_TouchUpdate);
238  XISetMask(mask, XI_TouchEnd);
239 
240  XISelectEvents(data->display,window_data->xwindow,&eventmask,1);
241 #endif
242 }
243 
244 
245 int
247 {
248 #if SDL_VIDEO_DRIVER_X11_XINPUT2
249  return xinput2_initialized;
250 #else
251  return 0;
252 #endif
253 }
254 
255 int
257 {
258 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
259  return xinput2_initialized && xinput2_multitouch_supported;
260 #else
261  return 0;
262 #endif
263 }
264 
265 #endif /* SDL_VIDEO_DRIVER_X11 */
266 
267 /* vi: set ts=4 sw=4 expandtab: */
Display * display
Definition: SDL_x11video.h:75
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:62
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
Sint64 SDL_TouchID
Definition: SDL_touch.h:41
#define NULL
Definition: ftobjs.h:61
void X11_InitXinput2(_THIS)
GLdouble GLdouble t
Definition: glew.h:1384
int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, float x, float y, float pressure)
Definition: SDL_touch.c:213
int32_t j
Definition: e_log.c:102
char * display
Definition: visualinfo.c:85
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, float x, float y, float pressure)
Definition: SDL_touch.c:275
static SDL_VideoDevice * _this
Definition: SDL_video.c:92
void X11_InitXinput2Multitouch(_THIS)
int
Definition: SDL_systhread.c:37
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:178
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
#define _THIS
int X11_Xinput2IsMultitouchSupported(void)
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
GLfloat GLfloat GLfloat top
Definition: glew.h:13816
int SDL_AddTouch(SDL_TouchID touchID, const char *name)
Definition: SDL_touch.c:130
EGLSurface EGLint void ** value
Definition: eglext.h:301
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
Definition: gl2ext.h:961
GLint GLint GLint GLint z
Definition: gl2ext.h:1214
int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie)
void * driverdata
Definition: SDL_sysvideo.h:99
int X11_Xinput2IsInitialized(void)
int i
Definition: pngrutil.c:1377
char Bool
Definition: ftraster.c:307
SDL_Touch * SDL_GetTouch(SDL_TouchID id)
Definition: SDL_touch.c:73
struct XGenericEventCookie XGenericEventCookie
cl_event event
Definition: glew.h:3556
void X11_Xinput2SelectTouch(_THIS, SDL_Window *window)