From cf31ea14782f758f25fa340a145a9b576ae9727d Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 11 Feb 2017 11:14:48 -0800 Subject: [PATCH] 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. --- src/events/SDL_touch.c | 10 ++++++++-- src/video/SDL_sysvideo.h | 5 +++++ src/video/x11/SDL_x11touch.c | 7 +++++++ src/video/x11/SDL_x11touch.h | 1 + src/video/x11/SDL_x11video.c | 1 + 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c index 4c98885fe..92e76f2e4 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 2778490d5..b4408583d 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 ba841f5f1..12d2ef86a 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 9c0dfe6a7..d077f7401 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 e8e33727e..7ced9aa4b 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;