x11: prevent a synthetic mouse event when using a touchscreen With multitouch, register to receive XI_Motion (which desctivates MotionNotify), so that we can distinguish real mouse motions from synthetic one. (bug 4690)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c
index daf4a49..2805bf9 100644
--- a/src/video/x11/SDL_x11xinput2.c
+++ b/src/video/x11/SDL_x11xinput2.c
@@ -75,30 +75,38 @@ xinput2_version_atleast(const int version, const int wantmajor, const int wantmi
}
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
-static void
-xinput2_normalize_touch_coordinates(SDL_VideoData *videodata, Window window,
- double in_x, double in_y, float *out_x, float *out_y)
+static SDL_Window *
+xinput2_get_sdlwindow(SDL_VideoData *videodata, Window window)
{
int i;
for (i = 0; i < videodata->numwindows; i++) {
SDL_WindowData *d = videodata->windowlist[i];
if (d->xwindow == window) {
- if (d->window->w == 1) {
- *out_x = 0.5f;
- } else {
- *out_x = in_x / (d->window->w - 1);
- }
- if (d->window->h == 1) {
- *out_y = 0.5f;
- } else {
- *out_y = in_y / (d->window->h - 1);
- }
- return;
+ return d->window;
+ }
+ }
+ return NULL;
+}
+
+static void
+xinput2_normalize_touch_coordinates(SDL_Window *window, double in_x, double in_y, float *out_x, float *out_y)
+{
+ if (window) {
+ if (window->w == 1) {
+ *out_x = 0.5f;
+ } else {
+ *out_x = in_x / (window->w - 1);
}
+ if (window->h == 1) {
+ *out_y = 0.5f;
+ } else {
+ *out_y = in_y / (window->h - 1);
+ }
+ } else {
+ // couldn't find the window...
+ *out_x = in_x;
+ *out_y = in_y;
}
- // couldn't find the window...
- *out_x = in_x;
- *out_y = in_y;
}
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */
@@ -198,11 +206,30 @@ X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie)
break;
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+ /* With multitouch, register to receive XI_Motion (which desctivates MotionNotify),
+ * so that we can distinguish real mouse motions from synthetic one. */
+ case XI_Motion: {
+ const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
+ int pointer_emulated = (xev->flags & XIPointerEmulated);
+
+ if (! pointer_emulated) {
+ SDL_Mouse *mouse = SDL_GetMouse();
+ if(!mouse->relative_mode || mouse->relative_mode_warp) {
+ SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
+ if (window) {
+ SDL_SendMouseMotion(window, 0, 0, xev->event_x, xev->event_y);
+ }
+ }
+ }
+ return 1;
+ }
+ break;
+
case XI_TouchBegin: {
const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
float x, y;
- xinput2_normalize_touch_coordinates(videodata, xev->event,
- xev->event_x, xev->event_y, &x, &y);
+ SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
+ xinput2_normalize_touch_coordinates(window, xev->event_x, xev->event_y, &x, &y);
SDL_SendTouch(xev->sourceid,xev->detail, SDL_TRUE, x, y, 1.0);
return 1;
}
@@ -210,8 +237,8 @@ X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie)
case XI_TouchEnd: {
const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
float x, y;
- xinput2_normalize_touch_coordinates(videodata, xev->event,
- xev->event_x, xev->event_y, &x, &y);
+ SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
+ xinput2_normalize_touch_coordinates(window, xev->event_x, xev->event_y, &x, &y);
SDL_SendTouch(xev->sourceid,xev->detail, SDL_FALSE, x, y, 1.0);
return 1;
}
@@ -219,8 +246,8 @@ X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie)
case XI_TouchUpdate: {
const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
float x, y;
- xinput2_normalize_touch_coordinates(videodata, xev->event,
- xev->event_x, xev->event_y, &x, &y);
+ SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
+ xinput2_normalize_touch_coordinates(window, xev->event_x, xev->event_y, &x, &y);
SDL_SendTouchMotion(xev->sourceid,xev->detail, x, y, 1.0);
return 1;
}
@@ -272,9 +299,9 @@ X11_Xinput2SelectTouch(_THIS, SDL_Window *window)
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
SDL_VideoData *data = NULL;
XIEventMask eventmask;
- unsigned char mask[3] = { 0,0,0 };
+ unsigned char mask[4] = { 0, 0, 0, 0 };
SDL_WindowData *window_data = NULL;
-
+
if (!X11_Xinput2IsMultitouchSupported()) {
return;
}
@@ -289,6 +316,7 @@ X11_Xinput2SelectTouch(_THIS, SDL_Window *window)
XISetMask(mask, XI_TouchBegin);
XISetMask(mask, XI_TouchUpdate);
XISetMask(mask, XI_TouchEnd);
+ XISetMask(mask, XI_Motion);
X11_XISelectEvents(data->display,window_data->xwindow,&eventmask,1);
#endif