21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_X11
27 #include "../../events/SDL_mouse_c.h"
28 #include "../../events/SDL_touch_c.h"
32 #if SDL_VIDEO_DRIVER_X11_XINPUT2
33 static int xinput2_initialized = 0;
35 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
36 static int xinput2_multitouch_supported = 0;
43 static int xinput2_opcode;
45 static void parse_valuators(
const double *input_values,
const unsigned char *
mask,
int mask_len,
46 double *output_values,
int output_values_len) {
48 int top = mask_len * 8;
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;
64 query_xinput2_version(Display *
display,
int major,
int minor)
67 X11_XIQueryVersion(
display, &major, &minor);
68 return ((major * 1000) + minor);
72 xinput2_version_atleast(
const int version,
const int wantmajor,
const int wantminor)
74 return ( version >= ((wantmajor * 1000) + wantminor) );
77 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
92 xinput2_normalize_touch_coordinates(
SDL_Window *
window,
double in_x,
double in_y,
float *out_x,
float *out_y)
98 *out_x = in_x / (
window->w - 1);
103 *out_y = in_y / (
window->h - 1);
118 #if SDL_VIDEO_DRIVER_X11_XINPUT2
122 XIEventMask eventmask;
123 unsigned char mask[3] = { 0,0,0 };
135 if (!SDL_X11_HAVE_XINPUT2 ||
136 !X11_XQueryExtension(
data->display,
"XInputExtension", &xinput2_opcode, &
event, &err)) {
141 version = query_xinput2_version(
data->display, 2, 2);
142 if (!xinput2_version_atleast(version, 2, 0)) {
146 xinput2_initialized = 1;
148 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
149 xinput2_multitouch_supported = xinput2_version_atleast(version, 2, 2);
153 eventmask.deviceid = XIAllMasterDevices;
154 eventmask.mask_len =
sizeof(
mask);
155 eventmask.mask =
mask;
157 XISetMask(
mask, XI_RawMotion);
158 XISetMask(
mask, XI_RawButtonPress);
159 XISetMask(
mask, XI_RawButtonRelease);
161 if (X11_XISelectEvents(
data->display,DefaultRootWindow(
data->display),&eventmask,1) != Success) {
170 #if SDL_VIDEO_DRIVER_X11_XINPUT2
171 if(cookie->extension != xinput2_opcode) {
174 switch(cookie->evtype) {
176 const XIRawEvent *rawev = (
const XIRawEvent*)cookie->data;
178 double relative_coords[2];
179 static Time prev_time = 0;
180 static double prev_rel_coords[2];
184 if (!mouse->relative_mode || mouse->relative_mode_warp) {
188 parse_valuators(rawev->raw_values,rawev->valuators.mask,
189 rawev->valuators.mask_len,relative_coords,2);
191 if ((rawev->time == prev_time) && (relative_coords[0] == prev_rel_coords[0]) && (relative_coords[1] == prev_rel_coords[1])) {
195 SDL_SendMouseMotion(mouse->focus,mouse->mouseID,1,(
int)relative_coords[0],(
int)relative_coords[1]);
196 prev_rel_coords[0] = relative_coords[0];
197 prev_rel_coords[1] = relative_coords[1];
198 prev_time = rawev->time;
203 case XI_RawButtonPress:
204 case XI_RawButtonRelease:
208 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
212 const XIDeviceEvent *xev = (
const XIDeviceEvent *) cookie->data;
213 int pointer_emulated = (xev->flags & XIPointerEmulated);
215 if (! pointer_emulated) {
228 case XI_TouchBegin: {
229 const XIDeviceEvent *xev = (
const XIDeviceEvent *) cookie->data;
232 xinput2_normalize_touch_coordinates(
window, xev->event_x, xev->event_y, &
x, &
y);
238 const XIDeviceEvent *xev = (
const XIDeviceEvent *) cookie->data;
241 xinput2_normalize_touch_coordinates(
window, xev->event_x, xev->event_y, &
x, &
y);
246 case XI_TouchUpdate: {
247 const XIDeviceEvent *xev = (
const XIDeviceEvent *) cookie->data;
250 xinput2_normalize_touch_coordinates(
window, xev->event_x, xev->event_y, &
x, &
y);
264 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
268 info = X11_XIQueryDevice(
data->display, XIAllDevices, &ndevices);
270 for (
i = 0;
i < ndevices;
i++) {
271 XIDeviceInfo *dev = &info[
i];
272 for (
j = 0;
j < dev->num_classes;
j++) {
275 XIAnyClassInfo *
class = dev->classes[
j];
276 XITouchClassInfo *
t = (XITouchClassInfo*)
class;
279 if (class->type != XITouchClass)
282 if (
t->mode == XIDependentTouch) {
288 touchId =
t->sourceid;
292 X11_XIFreeDeviceInfo(info);
299 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
301 XIEventMask eventmask;
302 unsigned char mask[4] = { 0, 0, 0, 0 };
312 eventmask.deviceid = XIAllMasterDevices;
313 eventmask.mask_len =
sizeof(
mask);
314 eventmask.mask =
mask;
316 XISetMask(
mask, XI_TouchBegin);
317 XISetMask(
mask, XI_TouchUpdate);
318 XISetMask(
mask, XI_TouchEnd);
319 XISetMask(
mask, XI_Motion);
321 X11_XISelectEvents(
data->display,window_data->
xwindow,&eventmask,1);
329 #if SDL_VIDEO_DRIVER_X11_XINPUT2
330 return xinput2_initialized;
339 #if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
340 return xinput2_initialized && xinput2_multitouch_supported;