Fixed bug 3583 - X11 touch device can be permanently lost Volumetric In X11 the SDL error "Unknown touch device" can occur after which the application stops recognizing touch events. For a kiosk-type application this results in a hang as far as the user is concerned. This is reproducible on HP Z220/Z230/Z240 workstations by swapping USB cables for a while and it also occurs with no physical changes, probably due to USB device power management. A workaround is to make SDL re-enumerate the touch devices like it does at startup. A patch is attached.
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
diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c
index 4c98885..92e76f2 100644
--- a/src/events/SDL_touch.c
+++ b/src/events/SDL_touch.c
@@ -25,6 +25,7 @@
#include "SDL_assert.h"
#include "SDL_events.h"
#include "SDL_events_c.h"
+#include "../video/SDL_sysvideo.h"
static int SDL_num_touch = 0;
@@ -48,7 +49,7 @@ SDL_TouchID
SDL_GetTouchDevice(int index)
{
if (index < 0 || index >= SDL_num_touch) {
- SDL_SetError("Unknown touch device");
+ SDL_SetError("Unknown touch device index %d", index);
return 0;
}
return SDL_touchDevices[index]->id;
@@ -74,7 +75,12 @@ SDL_GetTouch(SDL_TouchID id)
{
int index = SDL_GetTouchIndex(id);
if (index < 0 || index >= SDL_num_touch) {
- SDL_SetError("Unknown touch device");
+ if (SDL_GetVideoDevice()->ResetTouch != NULL) {
+ SDL_SetError("Unknown touch id %d, resetting", (int) id);
+ (SDL_GetVideoDevice()->ResetTouch)(SDL_GetVideoDevice());
+ } else {
+ SDL_SetError("Unknown touch device id %d, cannot reset", (int) id);
+ }
return NULL;
}
return SDL_touchDevices[index];
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index 2778490..b440858 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -163,6 +163,11 @@ struct SDL_VideoDevice
*/
void (*VideoQuit) (_THIS);
+ /*
+ * Reinitialize the touch devices -- called if an unknown touch ID occurs.
+ */
+ void (*ResetTouch) (_THIS);
+
/* * * */
/*
* Display functions
diff --git a/src/video/x11/SDL_x11touch.c b/src/video/x11/SDL_x11touch.c
index ba841f5..12d2ef8 100644
--- a/src/video/x11/SDL_x11touch.c
+++ b/src/video/x11/SDL_x11touch.c
@@ -42,6 +42,13 @@ X11_QuitTouch(_THIS)
SDL_TouchQuit();
}
+void
+X11_ResetTouch(_THIS)
+{
+ X11_QuitTouch(_this);
+ X11_InitTouch(_this);
+}
+
#endif /* SDL_VIDEO_DRIVER_X11 */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/x11/SDL_x11touch.h b/src/video/x11/SDL_x11touch.h
index 9c0dfe6..d077f74 100644
--- a/src/video/x11/SDL_x11touch.h
+++ b/src/video/x11/SDL_x11touch.h
@@ -25,6 +25,7 @@
extern void X11_InitTouch(_THIS);
extern void X11_QuitTouch(_THIS);
+extern void X11_ResetTouch(_THIS);
#endif /* SDL_x11touch_h_ */
diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c
index e8e3372..7ced9aa 100644
--- a/src/video/x11/SDL_x11video.c
+++ b/src/video/x11/SDL_x11video.c
@@ -216,6 +216,7 @@ X11_CreateDevice(int devindex)
/* Set the function pointers */
device->VideoInit = X11_VideoInit;
device->VideoQuit = X11_VideoQuit;
+ device->ResetTouch = X11_ResetTouch;
device->GetDisplayModes = X11_GetDisplayModes;
device->GetDisplayBounds = X11_GetDisplayBounds;
device->GetDisplayUsableBounds = X11_GetDisplayUsableBounds;