698 lines
25 KiB
Diff
698 lines
25 KiB
Diff
|
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
|
||
|
#
|