Merge pull request #1517 from anaximan/scummvm_touch

Touch mouse emulation patch for ScummVM
This commit is contained in:
fewtarius 2023-06-03 19:48:18 -04:00 committed by GitHub
commit 9be6af5d2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 698 additions and 1 deletions

View file

@ -14,7 +14,7 @@ PKG_LONGDESC="ScummVM is a program which allows you to run certain classic graph
pre_configure_target() {
sed -i "s|sdl-config|sdl2-config|g" ${PKG_BUILD}/configure
TARGET_CONFIGURE_OPTS="--host=${TARGET_NAME} --backend=sdl --with-sdl-prefix=${SYSROOT_PREFIX}/usr/bin --disable-debug --enable-release --enable-vkeybd --opengl-mode=gles2"
TARGET_CONFIGURE_OPTS="--host=${TARGET_NAME} --backend=sdl --with-sdl-prefix=${SYSROOT_PREFIX}/usr/bin --disable-debug --enable-release --enable-vkeybd --enable-sdl-ts-vmouse --opengl-mode=gles2"
}
post_makeinstall_target() {

View file

@ -0,0 +1,697 @@
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index e69f694ecaa..cdd21e3e393 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -95,6 +95,9 @@ SdlEventSource::SdlEventSource()
openJoystick(joystick_num);
}
+#if defined(USE_SDL_TS_VMOUSE)
+ _touchInitialize();
+#endif // defined(USE_SDL_TS_VMOUSE)
}
SdlEventSource::~SdlEventSource() {
@@ -413,6 +416,10 @@ bool SdlEventSource::pollEvent(Common::Event &event) {
}
#endif
+#if defined(USE_SDL_TS_VMOUSE)
+ _touchPeriodicUpdate();
+#endif // defined(USE_SDL_TS_VMOUSE)
+
// If the screen changed, send an Common::EVENT_SCREEN_CHANGED
int screenID = g_system->getScreenChangeID();
if (screenID != _lastScreenID) {
@@ -779,6 +786,13 @@ void SdlEventSource::closeJoystick() {
}
}
+void SdlEventSource::preprocessEvents(SDL_Event *event)
+{
+#if defined(USE_SDL_TS_VMOUSE)
+ _touchPreprocessEvent(event);
+#endif // defined(USE_SDL_TS_VMOUSE)
+}
+
int SdlEventSource::mapSDLJoystickButtonToOSystem(Uint8 sdlButton) {
Common::JoystickButton osystemButtons[] = {
Common::JOYSTICK_BUTTON_A,
@@ -1077,3 +1091,434 @@ uint32 SdlEventSource::obtainUnicode(const SDL_Keysym keySym) {
}
#endif
+
+#if defined(USE_SDL_TS_VMOUSE)
+void SdlEventSource::_touchInitialize()
+{
+ // TODO - Start with a temporary window size before getting true values
+ _touchWindowWidth = 256;
+ _touchWindowHeight = 256;
+ _touchPanelWidth = 256;
+ _touchPanelHeight = 256;
+
+ // TODO - Temporary default values - Add to configuration?
+ _touchMaxTapTime = 250;
+ _touchMaxTapSqDist = 10 * 10;
+ _touchClickDuration = 50;
+ _touchPrecisionMult = 16;
+
+ // Initialize touch tracking structure
+ for (uint32_t iii = 0u; iii < TOUCH_MAX_PORTS; ++iii)
+ {
+ _touchDragType[iii] = TOUCH_DRAG_NONE;
+ for (uint32_t jjj = 0u; jjj < TOUCH_MAX_POINTS; ++jjj)
+ {
+ _touchFingers[iii][jjj].id = -1;
+ _touchFingers[iii][jjj].posX = 0;
+ _touchFingers[iii][jjj].posY = 0;
+ _touchFingers[iii][jjj].tdTime = 0u;
+ _touchFingers[iii][jjj].tdPosX = 0;
+ _touchFingers[iii][jjj].tdPosY = 0;
+ }
+ for (uint32_t jjj = 0u; jjj < TOUCH_BUTTON_COUNT; ++jjj)
+ {
+ _touchClickTime[iii][jjj] = 0u;
+ }
+ }
+
+ // Start with no delta
+ _touchHighResDX = 0;
+ _touchHighResDY = 0;
+
+#if SDL_VERSION_ATLEAST(2,0,10)
+ // Ensure that touch doesn't create double-events
+ SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
+#endif
+}
+
+void SdlEventSource::_touchPreprocessEvent(SDL_Event *event)
+{
+ // TODO - Add checkbox to configuration which can disable function?
+
+ if (event->type == SDL_FINGERDOWN ||
+ event->type == SDL_FINGERUP ||
+ event->type == SDL_FINGERMOTION) {
+
+ // Update window size if available
+ WindowedGraphicsManager *gm = dynamic_cast<WindowedGraphicsManager *>(_graphicsManager);
+ if (gm) {
+ _touchPanelWidth = gm->getWidth();
+ _touchPanelHeight = gm->getHeight();
+ _touchWindowWidth = gm->getWindowWidth();
+ _touchWindowHeight = gm->getWindowHeight();
+ }
+
+ // Several ports can be available - e.g. PS Vita has front and back
+ SDL_TouchID port = event->tfinger.touchId;
+
+ if (port < TOUCH_MAX_PORTS && port >= 0) {
+ switch (event->type) {
+ case SDL_FINGERDOWN:
+ {
+ _touchPreprocessFingerDown(event);
+ } break;
+ case SDL_FINGERUP:
+ {
+ _touchPreprocessFingerUp(event);
+ } break;
+ case SDL_FINGERMOTION:
+ {
+ _touchPreprocessFingerMotion(event);
+ } break;
+ }
+ }
+ }
+}
+
+void SdlEventSource::_touchPreprocessFingerDown(SDL_Event *event)
+{
+ SDL_TouchID port = event->tfinger.touchId;
+ SDL_FingerID id = event->tfinger.fingerId;
+
+ // Get pixel coordinates of the touch point
+ int32_t posX = 0;
+ int32_t posY = 0;
+ _touchConvertPanelToWindow(event->tfinger.x, event->tfinger.y, posX, posY);
+
+ // Make sure each finger is not reported down multiple times
+ for (uint32_t iii = 0u; iii < TOUCH_MAX_POINTS; ++iii) {
+ if (_touchFingers[port][iii].id == id) {
+ _touchFingers[port][iii].id = -1;
+ }
+ }
+
+ // Remember touch-down position for later processing
+ for (uint32_t iii = 0u; iii < TOUCH_MAX_POINTS; ++iii) {
+ if (_touchFingers[port][iii].id == -1) {
+ // TODO - Storing ID this way is inefficient, we need to search for it later
+ _touchFingers[port][iii].id = id;
+ _touchFingers[port][iii].posX = posX;
+ _touchFingers[port][iii].posY = posY;
+ _touchFingers[port][iii].tdTime = event->tfinger.timestamp;
+ _touchFingers[port][iii].tdPosX = posX;
+ _touchFingers[port][iii].tdPosY = posY;
+ break;
+ }
+ }
+}
+
+void SdlEventSource::_touchPreprocessFingerUp(SDL_Event *event)
+{
+ SDL_TouchID port = event->tfinger.touchId;
+ SDL_FingerID id = event->tfinger.fingerId;
+
+ // Get touch count for gesture detection
+ uint32_t touchCount = 0u;
+ for (uint32_t iii = 0u; iii < TOUCH_MAX_POINTS; ++iii)
+ { if (_touchFingers[port][iii].id >= 0) { touchCount++; } }
+
+ // Get pixel coordinates of the touch point
+ int32_t posX = 0;
+ int32_t posY = 0;
+ _touchConvertPanelToWindow(event->tfinger.x, event->tfinger.y, posX, posY);
+
+ for (uint32_t iii = 0u; iii < TOUCH_MAX_POINTS; ++iii) {
+ if (_touchFingers[port][iii].id != id)
+ { continue; }
+ _touchFingers[port][iii].id = -1;
+ switch (_touchDragType[port]) {
+ case TOUCH_DRAG_NONE:
+ { // No drag in progress
+ int32_t timeDelta = event->tfinger.timestamp -
+ _touchFingers[port][iii].tdTime;
+ int32_t tdDeltaX = posX - _touchFingers[port][iii].tdPosX;
+ int32_t tdDeltaY = posY - _touchFingers[port][iii].tdPosY;
+ uint32_t sqTdDistance = (tdDeltaX * tdDeltaX) + (tdDeltaY * tdDeltaY);
+
+ if (ConfMan.getBool("touchpad_mouse_mode")) {
+ // Touchpad mode -> Use current mouse position
+ posX = _mouseX;
+ posY = _mouseY;
+ }
+
+ if (timeDelta <= static_cast<int32_t>(_touchMaxTapTime) &&
+ sqTdDistance <= _touchMaxTapSqDist) {
+ // Short tap -> Mouse click
+ switch (touchCount) {
+ case 1:
+ { // One touch point -> Left Click
+ event->type = SDL_MOUSEBUTTONDOWN;
+ event->button.button = SDL_BUTTON_LEFT;
+ event->button.x = posX;
+ event->button.y = posY;
+ _touchClickTime[port][TOUCH_BUTTON_LEFT] = event->tfinger.timestamp;
+ } break;
+ case 2:
+ { // Two touch points -> Right Click
+ event->type = SDL_MOUSEBUTTONDOWN;
+ event->button.button = SDL_BUTTON_RIGHT;
+ event->button.x = posX;
+ event->button.y = posY;
+ _touchClickTime[port][TOUCH_BUTTON_RIGHT] = event->tfinger.timestamp;
+ } break;
+ // TODO - Can add more gestures here...
+ default:
+ break;
+ }
+ }
+ } break;
+ case TOUCH_DRAG_TWO:
+ {
+ // Two-finger drag
+ if (touchCount == 1) {
+ // Ending drag
+
+ if (ConfMan.getBool("touchpad_mouse_mode")) {
+ // Touchpad mode -> Use current mouse position
+ posX = _mouseX;
+ posY = _mouseY;
+ }
+
+ event->type = SDL_MOUSEBUTTONUP;
+ event->button.button = SDL_BUTTON_LEFT;
+ event->button.x = posX;
+ event->button.y = posY;
+ _touchDragType[port] = TOUCH_DRAG_NONE;
+ }
+ } break;
+ case TOUCH_DRAG_THREE:
+ {
+ // Three-finger drag
+ if (touchCount == 1) {
+ // Ending drag
+
+ if (ConfMan.getBool("touchpad_mouse_mode")) {
+ // Touchpad mode -> Use current mouse position
+ posX = _mouseX;
+ posY = _mouseY;
+ }
+
+ event->type = SDL_MOUSEBUTTONUP;
+ event->button.button = SDL_BUTTON_RIGHT;
+ event->button.x = posX;
+ event->button.y = posY;
+ _touchDragType[port] = TOUCH_DRAG_NONE;
+ }
+ } break;
+ default:
+ break;
+ }
+ }
+}
+
+/// Get touch vmouse speed factor for given mouse speed seeeing (0 - 7)
+static float touchGetSpeedFactor(uint32_t mouseSpeed)
+{
+ // TODO - The table can be modified, otherwise simple interpolation would suffice
+ static constexpr float speedFactorTable[] =
+ { 0.25f, 0.5f, 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f };
+ static constexpr size_t speedFactorCount =
+ sizeof(speedFactorTable) / sizeof(speedFactorTable[0]);
+ return mouseSpeed < speedFactorCount ? speedFactorTable[mouseSpeed] : 1.0;
+}
+
+void SdlEventSource::_touchPreprocessFingerMotion(SDL_Event *event)
+{
+ SDL_TouchID port = event->tfinger.touchId;
+ SDL_FingerID id = event->tfinger.fingerId;
+
+ // Get touch count for gesture detection
+ uint32_t touchCount = 0u;
+ for (uint32_t iii = 0u; iii < TOUCH_MAX_POINTS; ++iii)
+ { if (_touchFingers[port][iii].id >= 0) { touchCount++; } }
+
+ // Get pixel coordinates of the touch point
+ int32_t posX = 0;
+ int32_t posY = 0;
+ _touchConvertPanelToWindow(event->tfinger.x, event->tfinger.y, posX, posY);
+
+ // Index of the current touch being processed
+ uint32_t currentTdIdx = 0;
+ // Update touch point tracking position
+ for (uint32_t iii = 0u; iii < TOUCH_MAX_POINTS; ++iii) {
+ if (_touchFingers[port][iii].id == id) {
+ _touchFingers[port][iii].posX = posX;
+ _touchFingers[port][iii].posY = posY;
+ currentTdIdx = iii;
+ }
+ }
+
+ // No touch -> No reaction
+ if (touchCount < 1)
+ { return; }
+
+ if (ConfMan.getBool("touchpad_mouse_mode")) {
+ // Position the cursor using a virtual touchpad
+ // Get speed factor from settings
+ float speedFactor = touchGetSpeedFactor(ConfMan.getInt("kbdmouse_speed"));;
+ // Add relative movement since the last sync
+ _touchHighResDX += (event->tfinger.dx *
+ 1.25f * speedFactor * _touchPrecisionMult *
+ (_touchWindowWidth - 1));
+ _touchHighResDY += (event->tfinger.dy *
+ 1.25f * speedFactor * _touchPrecisionMult *
+ (_touchWindowHeight - 1));
+
+ // Calculate integral deltas
+ int32_t dx = _touchHighResDX / static_cast<int32_t>(_touchPrecisionMult);
+ int32_t dy = _touchHighResDY / static_cast<int32_t>(_touchPrecisionMult);
+ // Remove the integral part from the high resolution accumulator
+ _touchHighResDX %= static_cast<int32_t>(_touchPrecisionMult);
+ _touchHighResDY %= static_cast<int32_t>(_touchPrecisionMult);
+
+ // Use these position to place the cursor
+ posX = _mouseX + dx;
+ posY = _mouseY + dy;
+ } else {
+ // No operation needed, use touch position for the cursor
+ }
+
+ // Clipping x to <0, width - 1>
+ if (posX >= static_cast<int32_t>(_touchWindowWidth)) {
+ posX = _touchWindowWidth - 1;
+ } else if (posX < 0) {
+ posX = 0;
+ }
+ // Clipping y to <0, height - 1>
+ if (posY >= static_cast<int32_t>(_touchWindowHeight)) {
+ posY = _touchWindowHeight - 1;
+ } else if (posY < 0) {
+ posY = 0;
+ }
+
+ // Count number of long-holding touches
+ uint32_t longTouchCount = 0;
+ // Also find the longest-running touch
+ int32_t longestTd = 0;
+ uint32_t longestTdIdx = 0;
+ for (uint32_t iii = 0u; iii < TOUCH_MAX_POINTS; ++iii) {
+ if (_touchFingers[port][iii].id >= 0) {
+ int32_t timeDelta = event->tfinger.timestamp - _touchFingers[port][iii].tdTime;
+ if (timeDelta > longestTd)
+ { longestTd = timeDelta; longestTdIdx = iii; }
+ if (timeDelta > static_cast<int32_t>(_touchMaxTapTime))
+ { longTouchCount++; }
+ }
+ }
+
+ // Starting a new multi-finger drag?
+ if (longTouchCount >= 2 && _touchDragType[port] == TOUCH_DRAG_NONE) {
+ // If there are enough of them -> Start the drag
+ // Anchor position represents the cursor under dragging action
+ int32_t anchorX = _mouseX;
+ int32_t anchorY = _mouseY;
+ if (ConfMan.getBool("touchpad_mouse_mode")) {
+ // For touchpad control, this is the current cursor position
+ anchorX = _mouseX;
+ anchorY = _mouseY;
+ } else {
+ // For direct mode, locate the oldest active touch -> the anchor
+ anchorX = _touchFingers[port][longestTdIdx].posX;
+ anchorX = _touchFingers[port][longestTdIdx].posY;
+ }
+
+ // Generate a new event.
+ SDL_Event newEvent;
+ switch (longTouchCount) {
+ default:
+ case 2:
+ { // Two-finger drag -> Left mouse drag
+ newEvent.type = SDL_MOUSEBUTTONDOWN;
+ newEvent.button.button = SDL_BUTTON_LEFT;
+ newEvent.button.x = anchorX;
+ newEvent.button.y = anchorY;
+ } break;
+ case 3:
+ { // Three-finger drag -> Right mouse drag
+ newEvent.type = SDL_MOUSEBUTTONDOWN;
+ newEvent.button.button = SDL_BUTTON_RIGHT;
+ newEvent.button.x = anchorX;
+ newEvent.button.y = anchorY;
+ } break;
+ }
+
+ /// Place the event into the queue for further processing
+ SDL_PushEvent(&newEvent);
+ } // longTouchCount >= 2 && _touchDragType[port] == TOUCH_DRAG_NONE
+
+ // Update the cursor only when moving the original anchor touch
+ if (longestTdIdx == currentTdIdx) {
+ event->type = SDL_MOUSEMOTION;
+ event->motion.x = posX;
+ event->motion.y = posY;
+ }
+}
+
+void SdlEventSource::_touchConvertPanelToWindow(
+ float panelX, float panelY,
+ int32_t &winX, int32_t &winY)
+{
+ // TODO - Cleanup, simplify and describe this part
+ // Essentially, it takes touch panel pixel coordinates
+ // and transforms them into ScummVM window coordinates
+ // Most of the values could be pre-computed every time
+ // resolution changes...
+
+ float ratio = static_cast<float>(_touchWindowWidth) / static_cast<float>(_touchWindowHeight);
+
+ int32_t ratioHeight = _touchPanelHeight;
+ int32_t ratioWidth = _touchPanelHeight * ratio;
+
+ int32_t offsetX = (_touchPanelWidth - ratioWidth) / 2;
+ int32_t offsetY = (_touchPanelHeight - ratioHeight) / 2;
+
+ float scaleX = static_cast<float>(ratioWidth) / static_cast<float>(_touchWindowWidth);
+ float scaleY = static_cast<float>(ratioHeight) / static_cast<float>(_touchWindowHeight);
+
+ float absPanelX = panelX * static_cast<float>(_touchPanelWidth);
+ float absPanelY = panelY * static_cast<float>(_touchPanelHeight);
+
+ winX = static_cast<int32_t>((absPanelX - offsetX) / scaleX);
+ winY = static_cast<int32_t>((absPanelY - offsetY) / scaleY);
+
+ // Clip to <0, width)
+ if (winX >= static_cast<int32_t>(_touchWindowWidth))
+ { winX = _touchWindowWidth - 1; }
+ else if (winX < 0)
+ { winX = 0; }
+ // Clip to <0, height)
+ if (winY >= static_cast<int32_t>(_touchWindowHeight))
+ { winY = _touchWindowHeight - 1; }
+ else if (winY < 0)
+ { winY = 0; }
+}
+
+void SdlEventSource::_touchPeriodicUpdate()
+{
+ uint32_t currentTime = SDL_GetTicks();
+
+ for (uint32_t iii = 0u; iii < TOUCH_MAX_PORTS; ++iii)
+ { // Iterate over clickc for all ports
+ for (uint32_t btn = 0u; btn < TOUCH_BUTTON_COUNT; ++btn)
+ { // Find active click timers
+ if (_touchClickTime[iii][btn] == 0)
+ { continue; }
+ // Check if the click duration elapsed
+ uint32_t timeDelta = currentTime - _touchClickTime[iii][btn];
+ if (timeDelta < _touchClickDuration)
+ { continue; }
+
+ // Click held long enough -> Release
+ SDL_Event newEvent;
+ newEvent.type = SDL_MOUSEBUTTONUP;
+ newEvent.button.button = SDL_BUTTON_LEFT;
+ newEvent.button.x = _mouseX;
+ newEvent.button.y = _mouseY;
+ SDL_PushEvent(&newEvent);
+
+ _touchClickTime[iii][btn] = 0u;
+ }
+ }
+}
+
+#endif // defined(USE_SDL_TS_VMOUSE)
diff --git a/backends/events/sdl/sdl-events.h b/backends/events/sdl/sdl-events.h
index b3f722dffd3..8b8ff27e546 100644
--- a/backends/events/sdl/sdl-events.h
+++ b/backends/events/sdl/sdl-events.h
@@ -109,7 +109,7 @@ protected:
/**
* Pre process an event before it is dispatched.
*/
- virtual void preprocessEvents(SDL_Event *event) {}
+ virtual void preprocessEvents(SDL_Event *event);
/**
* Dispatchs SDL events for each handler.
@@ -217,6 +217,104 @@ protected:
*/
Common::Event _fakeKeyUp;
#endif
+
+#if defined(USE_SDL_TS_VMOUSE)
+private:
+ /// Perform initialization of touch-related state structures.
+ void _touchInitialize();
+ /**
+ * Run pre-processing on touch-based events, otherwise null operation.
+ *
+ * @param event Input event to process.
+ */
+ void _touchPreprocessEvent(SDL_Event *event);
+
+ /// Preprocessing specific to SDL_FINGERDOWN.
+ void _touchPreprocessFingerDown(SDL_Event *event);
+ /// Preprocessing specific to SDL_FINGERUP.
+ void _touchPreprocessFingerUp(SDL_Event *event);
+ /// Preprocessing specific to SDL_FINGERMOTION.
+ void _touchPreprocessFingerMotion(SDL_Event *event);
+ /// Convert panel normalized coordinates to window pixel coordinates.
+ void _touchConvertPanelToWindow(
+ float panelX, float panelY,
+ int32_t &winX, int32_t &winY);
+ /// Run periodic processing updates - e.g. click finalization.
+ void _touchPeriodicUpdate();
+
+ /// Structure representing a single tracked touch point.
+ struct Touch {
+ /// Identifier of the touch point. -1 for no touch.
+ int32_t id;
+ /// Current pixel position of the touch point on the x-axis.
+ int32_t posX;
+ /// Current pixel position of the touch point on the y-axis.
+ int32_t posY;
+ /// Time of last touchdown.
+ uint32_t tdTime;
+ /// Touchdown pixel position on the x-axis.
+ int32_t tdPosX;
+ /// Touchdown pixel position on the y-axis.
+ int32_t tdPosY;
+ }; // struct Touch
+
+ /// Maximum number of supported touch ports.
+ static constexpr uint32_t TOUCH_MAX_PORTS = 16u;
+ /// Maximum number of supported touch points per port.
+ static constexpr uint32_t TOUCH_MAX_POINTS = 16u;
+
+ /// Recognized types of dragging operations.
+ enum TouchDragType {
+ /// No dragging
+ TOUCH_DRAG_NONE = 0,
+ /// Two-finger drag
+ TOUCH_DRAG_TWO,
+ /// Three-finger drag
+ TOUCH_DRAG_THREE
+ }; // enum TouchDragType
+
+ /// Types of simulated mouse buttons.
+ enum TouchMouseButton {
+ /// Left mouse button
+ TOUCH_BUTTON_LEFT = 0,
+ /// Right mouse button
+ TOUCH_BUTTON_RIGHT = 1,
+ /// Total number of simulated mouse buttons
+ TOUCH_BUTTON_COUNT,
+ }; // enum TouchMouseButton
+
+ /// Width of the touch panel.
+ uint32_t _touchPanelWidth;
+ /// Height of the touch panel.
+ uint32_t _touchPanelHeight;
+ /// Width of the touch window.
+ uint32_t _touchWindowWidth;
+ /// Height of the touch window.
+ uint32_t _touchWindowHeight;
+
+ /// Maximum time of contact in milliseconds which counts as a tap.
+ uint32_t _touchMaxTapTime;
+ /// Maximum distance of motion in squared pixels which counts as a tap.
+ uint32_t _touchMaxTapSqDist;
+ /// Length of a simulated mouse click in milliseconds.
+ uint32_t _touchClickDuration;
+ /// Multiplier used for sub-pixel touch precision - higher = smaller movement.
+ uint32_t _touchPrecisionMult;
+
+ /// Finger-tracking structure.
+ Touch _touchFingers[TOUCH_MAX_PORTS][TOUCH_MAX_POINTS];
+
+ /// Drag type being executed for each port.
+ TouchDragType _touchDragType[TOUCH_MAX_PORTS];
+
+ /// Tracking of start time for mouse button clicks.
+ uint32_t _touchClickTime[TOUCH_MAX_PORTS][TOUCH_BUTTON_COUNT];
+
+ /// High resolution x-axis delta for the simulated touchpad cursor.
+ int32_t _touchHighResDX;
+ /// High resolution y-axis delta for the simulated touchpad cursor.
+ int32_t _touchHighResDY;
+#endif // defined(SDL_TS_VMOUSE)
};
#endif
diff --git a/backends/platform/gph/build/clean.sh b/backends/platform/gph/build/clean.sh
old mode 100755
new mode 100644
diff --git a/backends/platform/maemo/debian/rules b/backends/platform/maemo/debian/rules
old mode 100755
new mode 100644
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 0e0821ceda3..4908e9a4af0 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -182,6 +182,9 @@ bool OSystem_SDL::hasFeature(Feature f) {
if (f == kFeatureJoystickDeadzone || f == kFeatureKbdMouseSpeed) {
return _eventSource->isJoystickConnected();
}
+#if defined(USE_SDL_TS_VMOUSE)
+ if (f == kFeatureTouchpadMode) return true;
+#endif
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
/* Even if we are using the 2D graphics manager,
* we are at one initGraphics3d call of supporting OpenGL */
@@ -191,6 +194,29 @@ bool OSystem_SDL::hasFeature(Feature f) {
return ModularGraphicsBackend::hasFeature(f);
}
+#if defined(USE_SDL_TS_VMOUSE)
+void OSystem_SDL::setFeatureState(Feature f, bool enable) {
+ switch (f) {
+ case kFeatureTouchpadMode:
+ ConfMan.setBool("touchpad_mouse_mode", enable);
+ break;
+ default:
+ ModularGraphicsBackend::setFeatureState(f, enable);
+ break;
+ }
+}
+bool OSystem_SDL::getFeatureState(Feature f) {
+ switch (f) {
+ case kFeatureTouchpadMode:
+ return ConfMan.getBool("touchpad_mouse_mode");
+ break;
+ default:
+ return ModularGraphicsBackend::getFeatureState(f);
+ break;
+ }
+}
+#endif // defined(USE_SDL_TS_VMOUSE)
+
void OSystem_SDL::initBackend() {
// Check if backend has not been initialized
assert(!_inited);
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index 28ba76a09ed..3cf1dcf021a 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -52,6 +52,10 @@ public:
void init() override;
bool hasFeature(Feature f) override;
+#if defined(USE_SDL_TS_VMOUSE)
+ void setFeatureState(Feature f, bool enable) override;
+ bool getFeatureState(Feature f) override;
+#endif // defined(USE_SDL_TS_VMOUSE)
// Override functions from ModularBackend and OSystem
void initBackend() override;
diff --git a/configure b/configure
index e9e3abe6493..f3d4aa91764 100755
--- a/configure
+++ b/configure
@@ -223,6 +223,7 @@ _nuked_opl=yes
_builtin_resources=yes
_windows_console=yes
_windows_unicode=yes
+_sdl_ts_vmouse=no
_cygwin_build=no
# Default commands
_ranlib=ranlib
@@ -978,6 +979,8 @@ Optional Features:
--disable-windows-console do not show console output on Windows
--enable-windows-unicode use Windows Unicode APIs (default)
--disable-windows-unicode use Windows ANSI APIs
+ --enable-sdl-ts-vmouse enable SDL touchscreen virtual mouse support
+ --disable-sdl-ts-vmouse disable SDL touchscreen virtual mouse support
Optional Documentation Options:
--with-manual-version=VERSION version to use when generating the manual (optional)
@@ -1285,6 +1288,8 @@ for ac_option in $@; do
--disable-eventrecorder) _eventrec=no ;;
--enable-text-console) _text_console=yes ;;
--disable-text-console) _text_console=no ;;
+ --enable-sdl-ts-vmouse) _sdl_ts_vmouse=yes ;;
+ --disable-sdl-ts-vmouse) _sdl_ts_vmouse=no ;;
--with-fluidsynth-prefix=*)
arg=`echo $ac_option | cut -d '=' -f 2`
FLUIDSYNTH_CFLAGS="-I$arg/include"
@@ -5972,6 +5977,9 @@ define_in_config_h_if_yes "$_readline" 'USE_READLINE'
define_in_config_h_if_yes "$_text_console" 'USE_TEXT_CONSOLE_FOR_DEBUGGER'
+define_in_config_h_if_yes "$_sdl_ts_vmouse" 'USE_SDL_TS_VMOUSE'
+define_in_config_if_yes "$_sdl_ts_vmouse" 'USE_SDL_TS_VMOUSE'
+
#
# Check for Unity if taskbar integration is enabled
#