Browse Source

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.
Sam Lantinga 8 years ago
parent
commit
cf31ea1478

+ 8 - 2
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];

+ 5 - 0
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

+ 7 - 0
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: */

+ 1 - 0
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_ */
 

+ 1 - 0
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;