[Scummvm-git-logs] scummvm master -> 820cbe391a5dfc2d2b6ef883eeeddcbdacb34f48
bluegr
noreply at scummvm.org
Wed Sep 25 15:44:02 UTC 2024
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
820cbe391a SDL: Merge finger handling on vita and switch
Commit: 820cbe391a5dfc2d2b6ef883eeeddcbdacb34f48
https://github.com/scummvm/scummvm/commit/820cbe391a5dfc2d2b6ef883eeeddcbdacb34f48
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2024-09-25T18:43:58+03:00
Commit Message:
SDL: Merge finger handling on vita and switch
This code is very similar and not specific to either platform but is generic
touchscreen handling with SDL
Tested on Switch and Vita
Changed paths:
A backends/events/sdl/finger-sdl-events.cpp
A backends/events/sdl/finger-sdl-events.h
backends/events/psp2sdl/psp2sdl-events.cpp
backends/events/psp2sdl/psp2sdl-events.h
backends/events/switchsdl/switchsdl-events.cpp
backends/events/switchsdl/switchsdl-events.h
backends/module.mk
diff --git a/backends/events/psp2sdl/psp2sdl-events.cpp b/backends/events/psp2sdl/psp2sdl-events.cpp
index 21642854f5b..b145dfe4650 100644
--- a/backends/events/psp2sdl/psp2sdl-events.cpp
+++ b/backends/events/psp2sdl/psp2sdl-events.cpp
@@ -36,40 +36,10 @@
#include "math.h"
-#define TOUCHSCREEN_WIDTH 960
-#define TOUCHSCREEN_HEIGHT 544
+PSP2EventSource::PSP2EventSource() : FingerSdlEventSource() {}
-PSP2EventSource::PSP2EventSource() {
- for (int port = 0; port < SCE_TOUCH_PORT_MAX_NUM; port++) {
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- _finger[port][i].id = -1;
- _finger[port][i].timeLastDown = 0;
- _finger[port][i].lastX = 0;
- _finger[port][i].lastY = 0;
- _finger[port][i].lastDownX = 0;
- _finger[port][i].lastDownY = 0;
- }
- _multiFingerDragging[port] = DRAG_NONE;
- }
-
- for (int port = 0; port < SCE_TOUCH_PORT_MAX_NUM; port++) {
- for (int i = 0; i < 2; i++) {
- _simulatedClickStartTime[port][i] = 0;
- }
- }
-
- _hiresDX = 0;
- _hiresDY = 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
-}
-
-bool PSP2EventSource::pollEvent(Common::Event &event) {
- finishSimulatedMouseClicks();
- return SdlEventSource::pollEvent(event);
+Common::Point PSP2EventSource::getTouchscreenSize() {
+ return Common::Point(960, 544);
}
void PSP2EventSource::preprocessEvents(SDL_Event *event) {
@@ -78,361 +48,14 @@ void PSP2EventSource::preprocessEvents(SDL_Event *event) {
sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_AUTO_SUSPEND);
sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_OLED_OFF);
- // Supported touch gestures:
- // left mouse click: single finger short tap
- // right mouse click: second finger short tap while first finger is still down
- // pointer motion: single finger drag
- if (event->type == SDL_FINGERDOWN || event->type == SDL_FINGERUP || event->type == SDL_FINGERMOTION) {
- // front (0) or back (1) panel
- SDL_TouchID port = event->tfinger.touchId;
- if (port < SCE_TOUCH_PORT_MAX_NUM && port >= 0) {
- // touchpad_mouse_mode off: use only front panel for direct touch control of pointer
- // touchpad_mouse_mode on: also enable rear touch with indirect touch control
- // where the finger can be somewhere else than the pointer and still move it
- if (port == 0 || ConfMan.getBool("touchpad_mouse_mode")) {
- switch (event->type) {
- case SDL_FINGERDOWN:
- preprocessFingerDown(event);
- break;
- case SDL_FINGERUP:
- preprocessFingerUp(event);
- break;
- case SDL_FINGERMOTION:
- preprocessFingerMotion(event);
- break;
- }
- }
- }
- }
+ FingerSdlEventSource::preprocessEvents(event);
}
-void PSP2EventSource::preprocessFingerDown(SDL_Event *event) {
- // front (0) or back (1) panel
- SDL_TouchID port = event->tfinger.touchId;
- // id (for multitouch)
- SDL_FingerID id = event->tfinger.fingerId;
-
- int x = _mouseX;
- int y = _mouseY;
-
- if (port == 0 && !ConfMan.getBool("frontpanel_touchpad_mode")) {
- convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
- }
-
- // make sure each finger is not reported down multiple times
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[port][i].id == id) {
- _finger[port][i].id = -1;
- }
- }
-
- // we need the timestamps to decide later if the user performed a short tap (click)
- // or a long tap (drag)
- // we also need the last coordinates for each finger to keep track of dragging
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[port][i].id == -1) {
- _finger[port][i].id = id;
- _finger[port][i].timeLastDown = event->tfinger.timestamp;
- _finger[port][i].lastDownX = event->tfinger.x;
- _finger[port][i].lastDownY = event->tfinger.y;
- _finger[port][i].lastX = x;
- _finger[port][i].lastY = y;
- break;
- }
- }
+bool PSP2EventSource::isTouchpadMode(int port) {
+ return port != 0 || ConfMan.getBool("frontpanel_touchpad_mode");
}
-void PSP2EventSource::preprocessFingerUp(SDL_Event *event) {
- // front (0) or back (1) panel
- SDL_TouchID port = event->tfinger.touchId;
- // id (for multitouch)
- SDL_FingerID id = event->tfinger.fingerId;
-
- // find out how many fingers were down before this event
- int numFingersDown = 0;
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[port][i].id >= 0) {
- numFingersDown++;
- }
- }
-
- int x = _mouseX;
- int y = _mouseY;
-
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[port][i].id == id) {
- _finger[port][i].id = -1;
- if (!_multiFingerDragging[port]) {
- if ((event->tfinger.timestamp - _finger[port][i].timeLastDown) <= MAX_TAP_TIME) {
- // short (<MAX_TAP_TIME ms) tap is interpreted as right/left mouse click depending on # fingers already down
- // but only if the finger hasn't moved since it was pressed down by more than MAX_TAP_MOTION_DISTANCE pixels
- float xrel = ((event->tfinger.x * 960.0) - (_finger[port][i].lastDownX * 960.0));
- float yrel = ((event->tfinger.y * 544.0) - (_finger[port][i].lastDownY * 544.0));
- float maxRSquared = (float) (MAX_TAP_MOTION_DISTANCE * MAX_TAP_MOTION_DISTANCE);
- if ((xrel * xrel + yrel * yrel) < maxRSquared) {
- if (numFingersDown == 2 || numFingersDown == 1) {
- Uint8 simulatedButton = 0;
- if (numFingersDown == 2) {
- simulatedButton = SDL_BUTTON_RIGHT;
- // need to raise the button later
- _simulatedClickStartTime[port][1] = event->tfinger.timestamp;
- } else if (numFingersDown == 1) {
- simulatedButton = SDL_BUTTON_LEFT;
- // need to raise the button later
- _simulatedClickStartTime[port][0] = event->tfinger.timestamp;
- if (port == 0 && !ConfMan.getBool("frontpanel_touchpad_mode")) {
- convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
- }
- }
-
- event->type = SDL_MOUSEBUTTONDOWN;
- event->button.button = simulatedButton;
- event->button.x = x;
- event->button.y = y;
- }
- }
- }
- } else if (numFingersDown == 1) {
- // when dragging, and the last finger is lifted, the drag is over
- if (port == 0 && !ConfMan.getBool("frontpanel_touchpad_mode")) {
- convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
- }
- Uint8 simulatedButton = 0;
- if (_multiFingerDragging[port] == DRAG_THREE_FINGER)
- simulatedButton = SDL_BUTTON_RIGHT;
- else {
- simulatedButton = SDL_BUTTON_LEFT;
- }
- event->type = SDL_MOUSEBUTTONUP;
- event->button.button = simulatedButton;
- event->button.x = x;
- event->button.y = y;
- _multiFingerDragging[port] = DRAG_NONE;
- }
- }
- }
-}
-
-void PSP2EventSource::preprocessFingerMotion(SDL_Event *event) {
- // front (0) or back (1) panel
- SDL_TouchID port = event->tfinger.touchId;
- // id (for multitouch)
- SDL_FingerID id = event->tfinger.fingerId;
-
- // find out how many fingers were down before this event
- int numFingersDown = 0;
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[port][i].id >= 0) {
- numFingersDown++;
- }
- }
-
- if (numFingersDown >= 1) {
- int x = _mouseX;
- int y = _mouseY;
- int xMax = dynamic_cast<WindowedGraphicsManager *>(_graphicsManager)->getWindowWidth() - 1;
- int yMax = dynamic_cast<WindowedGraphicsManager *>(_graphicsManager)->getWindowHeight() - 1;
-
- if (port == 0 && !ConfMan.getBool("frontpanel_touchpad_mode")) {
- convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
- } else {
- // for relative mode, use the pointer speed setting
- float speedFactor = 1.0;
-
- switch (ConfMan.getInt("kbdmouse_speed")) {
- // 0.25 keyboard pointer speed
- case 0:
- speedFactor = 0.25;
- break;
- // 0.5 speed
- case 1:
- speedFactor = 0.5;
- break;
- // 0.75 speed
- case 2:
- speedFactor = 0.75;
- break;
- // 1.0 speed
- case 3:
- speedFactor = 1.0;
- break;
- // 1.25 speed
- case 4:
- speedFactor = 1.25;
- break;
- // 1.5 speed
- case 5:
- speedFactor = 1.5;
- break;
- // 1.75 speed
- case 6:
- speedFactor = 1.75;
- break;
- // 2.0 speed
- case 7:
- speedFactor = 2.0;
- break;
- default:
- speedFactor = 1.0;
- }
-
- // convert touch events to relative mouse pointer events
- // track sub-pixel relative finger motion using the MULTIPLIER
- _hiresDX += (event->tfinger.dx * 1.25 * speedFactor * xMax * MULTIPLIER);
- _hiresDY += (event->tfinger.dy * 1.25 * speedFactor * yMax * MULTIPLIER);
- int xRel = _hiresDX / MULTIPLIER;
- int yRel = _hiresDY / MULTIPLIER;
- x = _mouseX + xRel;
- y = _mouseY + yRel;
- _hiresDX %= MULTIPLIER;
- _hiresDY %= MULTIPLIER;
- }
-
- if (x > xMax) {
- x = xMax;
- } else if (x < 0) {
- x = 0;
- }
- if (y > yMax) {
- y = yMax;
- } else if (y < 0) {
- y = 0;
- }
-
- // update the current finger's coordinates so we can track it later
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[port][i].id == id) {
- _finger[port][i].lastX = x;
- _finger[port][i].lastY = y;
- }
- }
-
- // If we are starting a multi-finger drag, start holding down the mouse button
- if (numFingersDown >= 2) {
- if (!_multiFingerDragging[port]) {
- // only start a multi-finger drag if at least two fingers have been down long enough
- int numFingersDownLong = 0;
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[port][i].id >= 0) {
- if (event->tfinger.timestamp - _finger[port][i].timeLastDown > MAX_TAP_TIME) {
- numFingersDownLong++;
- }
- }
- }
- if (numFingersDownLong >= 2) {
- // starting drag, so push mouse down at current location (back)
- // or location of "oldest" finger (front)
- int mouseDownX = _mouseX;
- int mouseDownY = _mouseY;
- if (port == 0 && !ConfMan.getBool("frontpanel_touchpad_mode")) {
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[port][i].id == id) {
- Uint32 earliestTime = _finger[port][i].timeLastDown;
- for (int j = 0; j < MAX_NUM_FINGERS; j++) {
- if (_finger[port][j].id >= 0 && (i != j) ) {
- if (_finger[port][j].timeLastDown < earliestTime) {
- mouseDownX = _finger[port][j].lastX;
- mouseDownY = _finger[port][j].lastY;
- earliestTime = _finger[port][j].timeLastDown;
- }
- }
- }
- break;
- }
- }
- }
- Uint8 simulatedButton = 0;
- if (numFingersDownLong == 2) {
- simulatedButton = SDL_BUTTON_LEFT;
- _multiFingerDragging[port] = DRAG_TWO_FINGER;
- } else {
- simulatedButton = SDL_BUTTON_RIGHT;
- _multiFingerDragging[port] = DRAG_THREE_FINGER;
- }
- SDL_Event ev;
- ev.type = SDL_MOUSEBUTTONDOWN;
- ev.button.button = simulatedButton;
- ev.button.x = mouseDownX;
- ev.button.y = mouseDownY;
- SDL_PushEvent(&ev);
- }
- }
- }
-
- //check if this is the "oldest" finger down (or the only finger down), otherwise it will not affect mouse motion
- bool updatePointer = true;
- if (numFingersDown > 1) {
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[port][i].id == id) {
- for (int j = 0; j < MAX_NUM_FINGERS; j++) {
- if (_finger[port][j].id >= 0 && (i != j) ) {
- if (_finger[port][j].timeLastDown < _finger[port][i].timeLastDown) {
- updatePointer = false;
- }
- }
- }
- }
- }
- }
- if (updatePointer) {
- event->type = SDL_MOUSEMOTION;
- event->motion.x = x;
- event->motion.y = y;
- }
- }
-}
-
-void PSP2EventSource::convertTouchXYToGameXY(float touchX, float touchY, int *gameX, int *gameY) {
- int screenH = dynamic_cast<WindowedGraphicsManager *>(_graphicsManager)->getWindowHeight();
- int screenW = dynamic_cast<WindowedGraphicsManager *>(_graphicsManager)->getWindowWidth();
-
- const int dispW = TOUCHSCREEN_WIDTH;
- const int dispH = TOUCHSCREEN_HEIGHT;
-
- int x, y, w, h;
- float sx, sy;
- float ratio = (float)screenW / (float)screenH;
-
- h = dispH;
- w = h * ratio;
-
- x = (dispW - w) / 2;
- y = (dispH - h) / 2;
-
- sy = (float)h / (float)screenH;
- sx = (float)w / (float)screenW;
-
- // Find touch coordinates in terms of screen pixels
- float dispTouchX = (touchX * (float)dispW);
- float dispTouchY = (touchY * (float)dispH);
-
- *gameX = CLIP((int)((dispTouchX - x) / sx), 0, screenW - 1);
- *gameY = CLIP((int)((dispTouchY - y) / sy), 0, screenH - 1);
-}
-
-void PSP2EventSource::finishSimulatedMouseClicks() {
- for (int port = 0; port < SCE_TOUCH_PORT_MAX_NUM; port++) {
- for (int i = 0; i < 2; i++) {
- if (_simulatedClickStartTime[port][i] != 0) {
- Uint32 currentTime = SDL_GetTicks();
- if (currentTime - _simulatedClickStartTime[port][i] >= SIMULATED_CLICK_DURATION) {
- int simulatedButton;
- if (i == 0) {
- simulatedButton = SDL_BUTTON_LEFT;
- } else {
- simulatedButton = SDL_BUTTON_RIGHT;
- }
- SDL_Event ev;
- ev.type = SDL_MOUSEBUTTONUP;
- ev.button.button = simulatedButton;
- ev.button.x = _mouseX;
- ev.button.y = _mouseY;
- SDL_PushEvent(&ev);
-
- _simulatedClickStartTime[port][i] = 0;
- }
- }
- }
- }
+bool PSP2EventSource::isPortActive(int port) {
+ return port == 0 || ConfMan.getBool("touchpad_mouse_mode");
}
#endif
diff --git a/backends/events/psp2sdl/psp2sdl-events.h b/backends/events/psp2sdl/psp2sdl-events.h
index ca48940c76d..0dd80db1f20 100644
--- a/backends/events/psp2sdl/psp2sdl-events.h
+++ b/backends/events/psp2sdl/psp2sdl-events.h
@@ -22,57 +22,21 @@
#if !defined(DISABLE_DEFAULT_EVENTMANAGER)
#define BACKEND_EVENTS_PSP2_H
+#include "backends/events/sdl/finger-sdl-events.h"
#include "backends/events/sdl/sdl-events.h"
#include <psp2/touch.h>
/**
* SDL Events manager for the PSP2.
*/
-class PSP2EventSource : public SdlEventSource {
+class PSP2EventSource : public FingerSdlEventSource {
public:
PSP2EventSource();
- bool pollEvent(Common::Event &event) override;
protected:
void preprocessEvents(SDL_Event *event) override;
-private:
-
- enum {
- MAX_NUM_FINGERS = 3, // number of fingers to track per panel
- MAX_TAP_TIME = 250, // taps longer than this will not result in mouse click events
- MAX_TAP_MOTION_DISTANCE = 10, // max distance finger motion in Vita screen pixels to be considered a tap
- SIMULATED_CLICK_DURATION = 50, // time in ms how long simulated mouse clicks should be
- MULTIPLIER = 16 // multiplier for sub-pixel resolution
- };
-
- typedef struct {
- int id; // -1: no touch
- Uint32 timeLastDown;
- int lastX; // last known screen coordinates
- int lastY; // last known screen coordinates
- float lastDownX; // SDL touch coordinates when last pressed down
- float lastDownY; // SDL touch coordinates when last pressed down
- } Touch;
-
- Touch _finger[SCE_TOUCH_PORT_MAX_NUM][MAX_NUM_FINGERS]; // keep track of finger status
-
- typedef enum DraggingType {
- DRAG_NONE = 0,
- DRAG_TWO_FINGER,
- DRAG_THREE_FINGER,
- } DraggingType;
-
- DraggingType _multiFingerDragging[SCE_TOUCH_PORT_MAX_NUM]; // keep track whether we are currently drag-and-dropping
-
- unsigned int _simulatedClickStartTime[SCE_TOUCH_PORT_MAX_NUM][2]; // initiation time of last simulated left or right click (zero if no click)
-
- int _hiresDX; // keep track of slow, sub-pixel, finger motion across multiple frames
- int _hiresDY;
-
- void preprocessFingerDown(SDL_Event *event);
- void preprocessFingerUp(SDL_Event *event);
- void preprocessFingerMotion(SDL_Event *event);
- void convertTouchXYToGameXY(float touchX, float touchY, int *gameX, int *gameY);
- void finishSimulatedMouseClicks(void);
+ bool isTouchpadMode(int port) override;
+ bool isPortActive(int port) override;
+ Common::Point getTouchscreenSize() override;
};
#endif /* BACKEND_EVENTS_PSP2_H */
diff --git a/backends/events/sdl/finger-sdl-events.cpp b/backends/events/sdl/finger-sdl-events.cpp
new file mode 100644
index 00000000000..17823b99719
--- /dev/null
+++ b/backends/events/sdl/finger-sdl-events.cpp
@@ -0,0 +1,431 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "backends/events/sdl/finger-sdl-events.h"
+#include "backends/platform/sdl/sdl.h"
+#include "engines/engine.h"
+
+#include "common/util.h"
+#include "common/events.h"
+#include "common/config-manager.h"
+
+#include "math.h"
+
+FingerSdlEventSource::FingerSdlEventSource() {
+ for (int port = 0; port < MAX_NUM_PORTS; port++) {
+ for (int i = 0; i < MAX_NUM_FINGERS; i++) {
+ _finger[port][i].id = -1;
+ _finger[port][i].timeLastDown = 0;
+ _finger[port][i].lastX = 0;
+ _finger[port][i].lastY = 0;
+ _finger[port][i].lastDownX = 0;
+ _finger[port][i].lastDownY = 0;
+ }
+ _multiFingerDragging[port] = DRAG_NONE;
+ }
+
+ for (int port = 0; port < MAX_NUM_PORTS; port++) {
+ for (int i = 0; i < 2; i++) {
+ _simulatedClickStartTime[port][i] = 0;
+ }
+ }
+
+ _hiresDX = 0;
+ _hiresDY = 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
+}
+
+bool FingerSdlEventSource::pollEvent(Common::Event &event) {
+ finishSimulatedMouseClicks();
+ return SdlEventSource::pollEvent(event);
+}
+
+void FingerSdlEventSource::preprocessEvents(SDL_Event *event) {
+
+ // Supported touch gestures:
+ // left mouse click: single finger short tap
+ // right mouse click: second finger short tap while first finger is still down
+ // pointer motion: single finger drag
+ if (event->type == SDL_FINGERDOWN || event->type == SDL_FINGERUP || event->type == SDL_FINGERMOTION) {
+ // front (0) or back (1) panel
+ SDL_TouchID port = event->tfinger.touchId;
+ if (port < MAX_NUM_PORTS && port >= 0) {
+ // touchpad_mouse_mode off: use only front panel for direct touch control of pointer
+ // touchpad_mouse_mode on: also enable rear touch with indirect touch control
+ // where the finger can be somewhere else than the pointer and still move it
+ if (isPortActive(port)) {
+ switch (event->type) {
+ case SDL_FINGERDOWN:
+ preprocessFingerDown(event);
+ break;
+ case SDL_FINGERUP:
+ preprocessFingerUp(event);
+ break;
+ case SDL_FINGERMOTION:
+ preprocessFingerMotion(event);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void FingerSdlEventSource::preprocessFingerDown(SDL_Event *event) {
+ // front (0) or back (1) panel
+ SDL_TouchID port = event->tfinger.touchId;
+ // id (for multitouch)
+ SDL_FingerID id = event->tfinger.fingerId;
+
+ int x = _mouseX;
+ int y = _mouseY;
+
+ if (port >= MAX_NUM_PORTS) {
+ return;
+ }
+
+ if (!isTouchpadMode(port)) {
+ convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
+ }
+
+ // make sure each finger is not reported down multiple times
+ for (int i = 0; i < MAX_NUM_FINGERS; i++) {
+ if (_finger[port][i].id == id) {
+ _finger[port][i].id = -1;
+ }
+ }
+
+ // we need the timestamps to decide later if the user performed a short tap (click)
+ // or a long tap (drag)
+ // we also need the last coordinates for each finger to keep track of dragging
+ for (int i = 0; i < MAX_NUM_FINGERS; i++) {
+ if (_finger[port][i].id == -1) {
+ _finger[port][i].id = id;
+ _finger[port][i].timeLastDown = event->tfinger.timestamp;
+ _finger[port][i].lastDownX = event->tfinger.x;
+ _finger[port][i].lastDownY = event->tfinger.y;
+ _finger[port][i].lastX = x;
+ _finger[port][i].lastY = y;
+ break;
+ }
+ }
+}
+
+void FingerSdlEventSource::preprocessFingerUp(SDL_Event *event) {
+ // front (0) or back (1) panel
+ SDL_TouchID port = event->tfinger.touchId;
+ // id (for multitouch)
+ SDL_FingerID id = event->tfinger.fingerId;
+
+ if (port >= MAX_NUM_PORTS) {
+ return;
+ }
+
+ // find out how many fingers were down before this event
+ int numFingersDown = 0;
+ for (int i = 0; i < MAX_NUM_FINGERS; i++) {
+ if (_finger[port][i].id >= 0) {
+ numFingersDown++;
+ }
+ }
+
+ int x = _mouseX;
+ int y = _mouseY;
+
+ for (int i = 0; i < MAX_NUM_FINGERS; i++) {
+ if (_finger[port][i].id == id) {
+ _finger[port][i].id = -1;
+ if (!_multiFingerDragging[port]) {
+ if ((event->tfinger.timestamp - _finger[port][i].timeLastDown) <= MAX_TAP_TIME) {
+ // short (<MAX_TAP_TIME ms) tap is interpreted as right/left mouse click depending on # fingers already down
+ // but only if the finger hasn't moved since it was pressed down by more than MAX_TAP_MOTION_DISTANCE pixels
+ Common::Point touchscreenSize = getTouchscreenSize();
+ float xrel = ((event->tfinger.x * (float) touchscreenSize.x) - (_finger[port][i].lastDownX * (float) touchscreenSize.x));
+ float yrel = ((event->tfinger.y * (float) touchscreenSize.y) - (_finger[port][i].lastDownY * (float) touchscreenSize.y));
+ float maxRSquared = (float) (MAX_TAP_MOTION_DISTANCE * MAX_TAP_MOTION_DISTANCE);
+ if ((xrel * xrel + yrel * yrel) < maxRSquared) {
+ if (numFingersDown == 2 || numFingersDown == 1) {
+ Uint8 simulatedButton = 0;
+ if (numFingersDown == 2) {
+ simulatedButton = SDL_BUTTON_RIGHT;
+ // need to raise the button later
+ _simulatedClickStartTime[port][1] = event->tfinger.timestamp;
+ } else if (numFingersDown == 1) {
+ simulatedButton = SDL_BUTTON_LEFT;
+ // need to raise the button later
+ _simulatedClickStartTime[port][0] = event->tfinger.timestamp;
+ if (!isTouchpadMode(port)) {
+ convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
+ }
+ }
+
+ event->type = SDL_MOUSEBUTTONDOWN;
+ event->button.button = simulatedButton;
+ event->button.x = x;
+ event->button.y = y;
+ }
+ }
+ }
+ } else if (numFingersDown == 1) {
+ // when dragging, and the last finger is lifted, the drag is over
+ if (!isTouchpadMode(port)) {
+ convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
+ }
+ Uint8 simulatedButton = 0;
+ if (_multiFingerDragging[port] == DRAG_THREE_FINGER)
+ simulatedButton = SDL_BUTTON_RIGHT;
+ else {
+ simulatedButton = SDL_BUTTON_LEFT;
+ }
+ event->type = SDL_MOUSEBUTTONUP;
+ event->button.button = simulatedButton;
+ event->button.x = x;
+ event->button.y = y;
+ _multiFingerDragging[port] = DRAG_NONE;
+ }
+ }
+ }
+}
+
+void FingerSdlEventSource::preprocessFingerMotion(SDL_Event *event) {
+ // front (0) or back (1) panel
+ SDL_TouchID port = event->tfinger.touchId;
+ // id (for multitouch)
+ SDL_FingerID id = event->tfinger.fingerId;
+
+ if (port >= MAX_NUM_PORTS) {
+ return;
+ }
+
+ // find out how many fingers were down before this event
+ int numFingersDown = 0;
+ for (int i = 0; i < MAX_NUM_FINGERS; i++) {
+ if (_finger[port][i].id >= 0) {
+ numFingersDown++;
+ }
+ }
+
+ if (numFingersDown >= 1) {
+ int x = _mouseX;
+ int y = _mouseY;
+ int xMax = _graphicsManager->getWindowWidth() - 1;
+ int yMax = _graphicsManager->getWindowHeight() - 1;
+
+ if (!isTouchpadMode(port)) {
+ convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
+ } else {
+ // for relative mode, use the pointer speed setting
+ float speedFactor = 1.0;
+
+ switch (ConfMan.getInt("kbdmouse_speed")) {
+ // 0.25 keyboard pointer speed
+ case 0:
+ speedFactor = 0.25;
+ break;
+ // 0.5 speed
+ case 1:
+ speedFactor = 0.5;
+ break;
+ // 0.75 speed
+ case 2:
+ speedFactor = 0.75;
+ break;
+ // 1.0 speed
+ case 3:
+ speedFactor = 1.0;
+ break;
+ // 1.25 speed
+ case 4:
+ speedFactor = 1.25;
+ break;
+ // 1.5 speed
+ case 5:
+ speedFactor = 1.5;
+ break;
+ // 1.75 speed
+ case 6:
+ speedFactor = 1.75;
+ break;
+ // 2.0 speed
+ case 7:
+ speedFactor = 2.0;
+ break;
+ default:
+ speedFactor = 1.0;
+ }
+
+ // convert touch events to relative mouse pointer events
+ // track sub-pixel relative finger motion using the FINGER_SUBPIXEL_MULTIPLIER
+ _hiresDX += (event->tfinger.dx * 1.25 * speedFactor * xMax * FINGER_SUBPIXEL_MULTIPLIER);
+ _hiresDY += (event->tfinger.dy * 1.25 * speedFactor * yMax * FINGER_SUBPIXEL_MULTIPLIER);
+ int xRel = _hiresDX / FINGER_SUBPIXEL_MULTIPLIER;
+ int yRel = _hiresDY / FINGER_SUBPIXEL_MULTIPLIER;
+ x = _mouseX + xRel;
+ y = _mouseY + yRel;
+ _hiresDX %= FINGER_SUBPIXEL_MULTIPLIER;
+ _hiresDY %= FINGER_SUBPIXEL_MULTIPLIER;
+ }
+
+ x = CLIP(x, 0, xMax);
+ y = CLIP(y, 0, yMax);
+
+ // update the current finger's coordinates so we can track it later
+ for (int i = 0; i < MAX_NUM_FINGERS; i++) {
+ if (_finger[port][i].id == id) {
+ _finger[port][i].lastX = x;
+ _finger[port][i].lastY = y;
+ }
+ }
+
+ // If we are starting a multi-finger drag, start holding down the mouse button
+ if (numFingersDown >= 2) {
+ if (!_multiFingerDragging[port]) {
+ // only start a multi-finger drag if at least two fingers have been down long enough
+ int numFingersDownLong = 0;
+ for (int i = 0; i < MAX_NUM_FINGERS; i++) {
+ if (_finger[port][i].id >= 0) {
+ if (event->tfinger.timestamp - _finger[port][i].timeLastDown > MAX_TAP_TIME) {
+ numFingersDownLong++;
+ }
+ }
+ }
+ if (numFingersDownLong >= 2) {
+ // starting drag, so push mouse down at current location (back)
+ // or location of "oldest" finger (front)
+ int mouseDownX = _mouseX;
+ int mouseDownY = _mouseY;
+ if (!isTouchpadMode(port)) {
+ for (int i = 0; i < MAX_NUM_FINGERS; i++) {
+ if (_finger[port][i].id == id) {
+ Uint32 earliestTime = _finger[port][i].timeLastDown;
+ for (int j = 0; j < MAX_NUM_FINGERS; j++) {
+ if (_finger[port][j].id >= 0 && (i != j) ) {
+ if (_finger[port][j].timeLastDown < earliestTime) {
+ mouseDownX = _finger[port][j].lastX;
+ mouseDownY = _finger[port][j].lastY;
+ earliestTime = _finger[port][j].timeLastDown;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ Uint8 simulatedButton = 0;
+ if (numFingersDownLong == 2) {
+ simulatedButton = SDL_BUTTON_LEFT;
+ _multiFingerDragging[port] = DRAG_TWO_FINGER;
+ } else {
+ simulatedButton = SDL_BUTTON_RIGHT;
+ _multiFingerDragging[port] = DRAG_THREE_FINGER;
+ }
+ SDL_Event ev;
+ ev.type = SDL_MOUSEBUTTONDOWN;
+ ev.button.button = simulatedButton;
+ ev.button.x = mouseDownX;
+ ev.button.y = mouseDownY;
+ SDL_PushEvent(&ev);
+ }
+ }
+ }
+
+ //check if this is the "oldest" finger down (or the only finger down), otherwise it will not affect mouse motion
+ bool updatePointer = true;
+ if (numFingersDown > 1) {
+ for (int i = 0; i < MAX_NUM_FINGERS; i++) {
+ if (_finger[port][i].id == id) {
+ for (int j = 0; j < MAX_NUM_FINGERS; j++) {
+ if (_finger[port][j].id >= 0 && (i != j) ) {
+ if (_finger[port][j].timeLastDown < _finger[port][i].timeLastDown) {
+ updatePointer = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (updatePointer) {
+ event->type = SDL_MOUSEMOTION;
+ event->motion.x = x;
+ event->motion.y = y;
+ }
+ }
+}
+
+void FingerSdlEventSource::convertTouchXYToGameXY(float touchX, float touchY, int *gameX, int *gameY) {
+ int screenH = _graphicsManager->getWindowHeight();
+ int screenW = _graphicsManager->getWindowWidth();
+ Common::Point touchscreenSize = getTouchscreenSize();
+
+ const int dispW = touchscreenSize.x;
+ const int dispH = touchscreenSize.y;
+
+ int x, y, w, h;
+ float sx, sy;
+ float ratio = (float)screenW / (float)screenH;
+
+ h = dispH;
+ w = h * ratio;
+
+ x = (dispW - w) / 2;
+ y = (dispH - h) / 2;
+
+ sy = (float)h / (float)screenH;
+ sx = (float)w / (float)screenW;
+
+ // Find touch coordinates in terms of screen pixels
+ float dispTouchX = (touchX * (float)dispW);
+ float dispTouchY = (touchY * (float)dispH);
+
+ *gameX = CLIP((int)((dispTouchX - x) / sx), 0, screenW - 1);
+ *gameY = CLIP((int)((dispTouchY - y) / sy), 0, screenH - 1);
+}
+
+void FingerSdlEventSource::finishSimulatedMouseClicks() {
+ for (int port = 0; port < MAX_NUM_PORTS; port++) {
+ for (int i = 0; i < 2; i++) {
+ if (_simulatedClickStartTime[port][i] != 0) {
+ Uint32 currentTime = SDL_GetTicks();
+ if (currentTime - _simulatedClickStartTime[port][i] >= SIMULATED_CLICK_DURATION) {
+ int simulatedButton;
+ if (i == 0) {
+ simulatedButton = SDL_BUTTON_LEFT;
+ } else {
+ simulatedButton = SDL_BUTTON_RIGHT;
+ }
+ SDL_Event ev;
+ ev.type = SDL_MOUSEBUTTONUP;
+ ev.button.button = simulatedButton;
+ ev.button.x = _mouseX;
+ ev.button.y = _mouseY;
+ SDL_PushEvent(&ev);
+
+ _simulatedClickStartTime[port][i] = 0;
+ }
+ }
+ }
+ }
+}
diff --git a/backends/events/sdl/finger-sdl-events.h b/backends/events/sdl/finger-sdl-events.h
new file mode 100644
index 00000000000..b5f452521bf
--- /dev/null
+++ b/backends/events/sdl/finger-sdl-events.h
@@ -0,0 +1,81 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if !defined(DISABLE_DEFAULT_EVENTMANAGER)
+#define BACKEND_EVENTS_FINGER_H
+
+#include "backends/events/sdl/sdl-events.h"
+
+/**
+ * SDL Events manager for the touchscreen.
+ */
+class FingerSdlEventSource : public SdlEventSource {
+public:
+ FingerSdlEventSource();
+ bool pollEvent(Common::Event &event) override;
+protected:
+ void preprocessEvents(SDL_Event *event) override;
+ virtual bool isTouchpadMode(int port) = 0;
+ virtual bool isPortActive(int port) = 0;
+ virtual Common::Point getTouchscreenSize() = 0;
+ virtual void convertTouchXYToGameXY(float touchX, float touchY, int *gameX, int *gameY);
+
+private:
+ enum {
+ MAX_NUM_FINGERS = 3, // number of fingers to track per panel
+ MAX_NUM_PORTS = 5, // maximum number of supported ports
+ MAX_TAP_TIME = 250, // taps longer than this will not result in mouse click events
+ MAX_TAP_MOTION_DISTANCE = 10, // max distance finger motion in Vita screen pixels to be considered a tap
+ SIMULATED_CLICK_DURATION = 50, // time in ms how long simulated mouse clicks should be
+ FINGER_SUBPIXEL_MULTIPLIER = 16 // multiplier for sub-pixel resolution
+ };
+
+ typedef struct {
+ int id; // -1: no touch
+ uint32 timeLastDown;
+ int lastX; // last known screen coordinates
+ int lastY; // last known screen coordinates
+ float lastDownX; // SDL touch coordinates when last pressed down
+ float lastDownY; // SDL touch coordinates when last pressed down
+ } Touch;
+
+ Touch _finger[MAX_NUM_PORTS][MAX_NUM_FINGERS]; // keep track of finger status
+
+ typedef enum DraggingType {
+ DRAG_NONE = 0,
+ DRAG_TWO_FINGER,
+ DRAG_THREE_FINGER,
+ } DraggingType;
+
+ DraggingType _multiFingerDragging[MAX_NUM_PORTS]; // keep track whether we are currently drag-and-dropping
+
+ unsigned int _simulatedClickStartTime[MAX_NUM_PORTS][2]; // initiation time of last simulated left or right click (zero if no click)
+
+ int _hiresDX; // keep track of slow, sub-pixel, finger motion across multiple frames
+ int _hiresDY;
+
+ void preprocessFingerDown(SDL_Event *event);
+ void preprocessFingerUp(SDL_Event *event);
+ void preprocessFingerMotion(SDL_Event *event);
+ void finishSimulatedMouseClicks(void);
+};
+
+#endif /* BACKEND_EVENTS_FINGER_H */
diff --git a/backends/events/switchsdl/switchsdl-events.cpp b/backends/events/switchsdl/switchsdl-events.cpp
index bbfe8db180b..e1f0e6543de 100644
--- a/backends/events/switchsdl/switchsdl-events.cpp
+++ b/backends/events/switchsdl/switchsdl-events.cpp
@@ -35,354 +35,24 @@
#include "common/events.h"
#include "common/config-manager.h"
-SwitchEventSource::SwitchEventSource() {
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- _finger[i].id = -1;
- _finger[i].timeLastDown = 0;
- _finger[i].lastX = 0;
- _finger[i].lastY = 0;
- _finger[i].lastDownX = 0;
- _finger[i].lastDownY = 0;
- }
- _multiFingerDragging = DRAG_NONE;
+SwitchEventSource::SwitchEventSource() : FingerSdlEventSource() {}
- for (int i = 0; i < 2; i++) {
- _simulatedClickStartTime[i] = 0;
- }
+Common::Point SwitchEventSource::getTouchscreenSize() {
+ return Common::Point(1280, 720);
}
bool SwitchEventSource::pollEvent(Common::Event &event) {
((DefaultTimerManager *) g_system->getTimerManager())->handler();
- finishSimulatedMouseClicks();
- return SdlEventSource::pollEvent(event);
+ return FingerSdlEventSource::pollEvent(event);
}
-void SwitchEventSource::preprocessEvents(SDL_Event *event) {
- // Supported touch gestures:
- // left mouse click: single finger short tap
- // right mouse click: second finger short tap while first finger is still down
- // pointer motion: single finger drag
- if (event->type == SDL_FINGERDOWN || event->type == SDL_FINGERUP || event->type == SDL_FINGERMOTION) {
- // touchpad_mouse_mode off: use direct touch control of pointer
- // touchpad_mouse_mode on: use indirect touch control
- // where the finger can be somewhere else than the pointer and still move it
- switch (event->type) {
- case SDL_FINGERDOWN:
- //debug(0, "down[%li]: %i %i", event->tfinger.fingerId, (int) event->tfinger.x, (int) event->tfinger.y);
- preprocessFingerDown(event);
- break;
- case SDL_FINGERUP:
- //debug(0, "up[%li]: %i %i", event->tfinger.fingerId, (int) event->tfinger.x, (int) event->tfinger.y);
- preprocessFingerUp(event);
- break;
- case SDL_FINGERMOTION:
- //debug(0, "mov[%li]: %i %i", event->tfinger.fingerId, (int) event->tfinger.x, (int) event->tfinger.y);
- preprocessFingerMotion(event);
- break;
- }
- }
+bool SwitchEventSource::isTouchpadMode(int port) {
+ return ConfMan.getBool("touchpad_mouse_mode");
}
-void SwitchEventSource::preprocessFingerDown(SDL_Event *event) {
- // id (for multitouch)
- SDL_FingerID id = event->tfinger.fingerId;
-
- int x = _mouseX;
- int y = _mouseY;
-
- if (!ConfMan.getBool("touchpad_mouse_mode")) {
- convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
- }
-
- // make sure each finger is not reported down multiple times
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[i].id == id) {
- _finger[i].id = -1;
- }
- }
-
- // we need the timestamps to decide later if the user performed a short tap (click)
- // or a long tap (drag)
- // we also need the last coordinates for each finger to keep track of dragging
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[i].id == -1) {
- _finger[i].id = id;
- _finger[i].timeLastDown = event->tfinger.timestamp;
- _finger[i].lastDownX = event->tfinger.x;
- _finger[i].lastDownY = event->tfinger.y;
- _finger[i].lastX = x;
- _finger[i].lastY = y;
- break;
- }
- }
-}
-
-void SwitchEventSource::preprocessFingerUp(SDL_Event *event) {
- // id (for multitouch)
- SDL_FingerID id = event->tfinger.fingerId;
-
- // find out how many fingers were down before this event
- int numFingersDown = 0;
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[i].id >= 0) {
- numFingersDown++;
- }
- }
-
- int x = _mouseX;
- int y = _mouseY;
-
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[i].id == id) {
- _finger[i].id = -1;
- if (!_multiFingerDragging) {
- if ((event->tfinger.timestamp - _finger[i].timeLastDown) <= MAX_TAP_TIME) {
- // short (<MAX_TAP_TIME ms) tap is interpreted as right/left mouse click depending on # fingers already down
- // but only if the finger hasn't moved since it was pressed down by more than MAX_TAP_MOTION_DISTANCE pixels
- float xrel = ((event->tfinger.x * (float) TOUCHSCREEN_WIDTH) - (_finger[i].lastDownX * (float) TOUCHSCREEN_WIDTH));
- float yrel = ((event->tfinger.y * (float) TOUCHSCREEN_HEIGHT) - (_finger[i].lastDownY * (float) TOUCHSCREEN_HEIGHT));
- float maxRSquared = (float) (MAX_TAP_MOTION_DISTANCE * MAX_TAP_MOTION_DISTANCE);
- if ((xrel * xrel + yrel * yrel) < maxRSquared) {
- if (numFingersDown == 2 || numFingersDown == 1) {
- uint8 simulatedButton = 0;
- if (numFingersDown == 2) {
- simulatedButton = SDL_BUTTON_RIGHT;
- // need to raise the button later
- _simulatedClickStartTime[1] = event->tfinger.timestamp;
- } else if (numFingersDown == 1) {
- simulatedButton = SDL_BUTTON_LEFT;
- // need to raise the button later
- _simulatedClickStartTime[0] = event->tfinger.timestamp;
- if (!ConfMan.getBool("touchpad_mouse_mode")) {
- convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
- }
- }
-
- event->type = SDL_MOUSEBUTTONDOWN;
- event->button.button = simulatedButton;
- event->button.x = x;
- event->button.y = y;
- }
- }
- }
- } else if (numFingersDown == 1) {
- // when dragging, and the last finger is lifted, the drag is over
- if (!ConfMan.getBool("touchpad_mouse_mode")) {
- convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
- }
- uint8 simulatedButton = 0;
- if (_multiFingerDragging == DRAG_THREE_FINGER)
- simulatedButton = SDL_BUTTON_RIGHT;
- else {
- simulatedButton = SDL_BUTTON_LEFT;
- }
- event->type = SDL_MOUSEBUTTONUP;
- event->button.button = simulatedButton;
- event->button.x = x;
- event->button.y = y;
- _multiFingerDragging = DRAG_NONE;
- }
- }
- }
-}
-
-void SwitchEventSource::preprocessFingerMotion(SDL_Event *event) {
- // id (for multitouch)
- SDL_FingerID id = event->tfinger.fingerId;
-
- // find out how many fingers were down before this event
- int numFingersDown = 0;
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[i].id >= 0) {
- numFingersDown++;
- }
- }
-
- if (numFingersDown >= 1) {
- int x = _mouseX;
- int y = _mouseY;
- int xMax = _graphicsManager->getWindowWidth() - 1;
- int yMax = _graphicsManager->getWindowHeight() - 1;
-
- if (!ConfMan.getBool("touchpad_mouse_mode")) {
- convertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
- } else {
- // for relative mode, use the pointer speed setting
- float speedFactor = 1.0;
-
- switch (ConfMan.getInt("kbdmouse_speed")) {
- case 0:
- speedFactor = 0.25;
- break;
- case 1:
- speedFactor = 0.5;
- break;
- case 2:
- speedFactor = 0.75;
- break;
- case 3:
- speedFactor = 1.0;
- break;
- case 4:
- speedFactor = 1.25;
- break;
- case 5:
- speedFactor = 1.5;
- break;
- case 6:
- speedFactor = 1.75;
- break;
- case 7:
- speedFactor = 2.0;
- break;
- default:
- speedFactor = 1.0;
- }
-
- // convert touch events to relative mouse pointer events
- // Whenever an SDL_event involving the mouse is processed,
- // _mouseX/Y are truncated from subpixel precision to regular pixel precision.
- // Therefore, there's no need here to deal with subpixel precision in _mouseX/Y.
- x = (_mouseX + (event->tfinger.dx * 1.25 * speedFactor * xMax));
- y = (_mouseY + (event->tfinger.dy * 1.25 * speedFactor * yMax));
- }
-
- x = CLIP(x, 0, xMax);
- y = CLIP(y, 0, yMax);
-
- // update the current finger's coordinates so we can track it later
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[i].id == id) {
- _finger[i].lastX = x;
- _finger[i].lastY = y;
- }
- }
-
- // If we are starting a multi-finger drag, start holding down the mouse button
- if (numFingersDown >= 2) {
- if (!_multiFingerDragging) {
- // only start a multi-finger drag if at least two fingers have been down long enough
- int numFingersDownLong = 0;
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[i].id >= 0) {
- if (event->tfinger.timestamp - _finger[i].timeLastDown > MAX_TAP_TIME) {
- numFingersDownLong++;
- }
- }
- }
- if (numFingersDownLong >= 2) {
- // starting drag, so push mouse down at current location
- // or location of "oldest" finger depending on mode
- int mouseDownX = _mouseX;
- int mouseDownY = _mouseY;
- if (!ConfMan.getBool("touchpad_mouse_mode")) {
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[i].id == id) {
- uint32 earliestTime = _finger[i].timeLastDown;
- for (int j = 0; j < MAX_NUM_FINGERS; j++) {
- if (_finger[j].id >= 0 && (i != j) ) {
- if (_finger[j].timeLastDown < earliestTime) {
- mouseDownX = _finger[j].lastX;
- mouseDownY = _finger[j].lastY;
- earliestTime = _finger[j].timeLastDown;
- }
- }
- }
- break;
- }
- }
- }
- uint8 simulatedButton = 0;
- if (numFingersDownLong == 2) {
- simulatedButton = SDL_BUTTON_LEFT;
- _multiFingerDragging = DRAG_TWO_FINGER;
- } else {
- simulatedButton = SDL_BUTTON_RIGHT;
- _multiFingerDragging = DRAG_THREE_FINGER;
- }
- SDL_Event ev;
- ev.type = SDL_MOUSEBUTTONDOWN;
- ev.button.button = simulatedButton;
- ev.button.x = mouseDownX;
- ev.button.y = mouseDownY;
- SDL_PushEvent(&ev);
- }
- }
- }
-
- //check if this is the "oldest" finger down (or the only finger down), otherwise it will not affect mouse motion
- bool updatePointer = true;
- if (numFingersDown > 1) {
- for (int i = 0; i < MAX_NUM_FINGERS; i++) {
- if (_finger[i].id == id) {
- for (int j = 0; j < MAX_NUM_FINGERS; j++) {
- if (_finger[j].id >= 0 && (i != j) ) {
- if (_finger[j].timeLastDown < _finger[i].timeLastDown) {
- updatePointer = false;
- }
- }
- }
- }
- }
- }
- if (updatePointer) {
- event->type = SDL_MOUSEMOTION;
- event->motion.x = x;
- event->motion.y = y;
- }
- }
-}
-
-void SwitchEventSource::convertTouchXYToGameXY(float touchX, float touchY, int *gameX, int *gameY) {
- int screenH = _graphicsManager->getWindowHeight();
- int screenW = _graphicsManager->getWindowWidth();
-
- const int dispW = TOUCHSCREEN_WIDTH;
- const int dispH = TOUCHSCREEN_HEIGHT;
-
- int x, y, w, h;
- float sx, sy;
- float ratio = (float)screenW / (float)screenH;
-
- h = dispH;
- w = h * ratio;
-
- x = (dispW - w) / 2;
- y = (dispH - h) / 2;
-
- sy = (float)h / (float)screenH;
- sx = (float)w / (float)screenW;
-
- // Find touch coordinates in terms of screen pixels
- float dispTouchX = (touchX * (float)dispW);
- float dispTouchY = (touchY * (float)dispH);
-
- *gameX = CLIP((int)((dispTouchX - x) / sx), 0, screenW);
- *gameY = CLIP((int)((dispTouchY - y) / sy), 0, screenH);
+bool SwitchEventSource::isPortActive(int port) {
+ return true;
}
-void SwitchEventSource::finishSimulatedMouseClicks() {
- for (int i = 0; i < 2; i++) {
- if (_simulatedClickStartTime[i] != 0) {
- uint32 currentTime = SDL_GetTicks();
- if (currentTime - _simulatedClickStartTime[i] >= SIMULATED_CLICK_DURATION) {
- int simulatedButton;
- if (i == 0) {
- simulatedButton = SDL_BUTTON_LEFT;
- } else {
- simulatedButton = SDL_BUTTON_RIGHT;
- }
- SDL_Event ev;
- ev.type = SDL_MOUSEBUTTONUP;
- ev.button.button = simulatedButton;
- ev.button.x = _mouseX;
- ev.button.y = _mouseY;
- SDL_PushEvent(&ev);
-
- _simulatedClickStartTime[i] = 0;
- }
- }
- }
-}
#endif
diff --git a/backends/events/switchsdl/switchsdl-events.h b/backends/events/switchsdl/switchsdl-events.h
index 9f3f77bf24f..10f6d50bac4 100644
--- a/backends/events/switchsdl/switchsdl-events.h
+++ b/backends/events/switchsdl/switchsdl-events.h
@@ -23,55 +23,20 @@
#define BACKEND_EVENTS_SWITCH_H
#include "backends/events/sdl/sdl-events.h"
-
-#define TOUCHSCREEN_WIDTH 1280
-#define TOUCHSCREEN_HEIGHT 720
+#include "backends/events/sdl/finger-sdl-events.h"
/**
* SDL Events manager for the SWITCH.
*/
-class SwitchEventSource : public SdlEventSource {
+class SwitchEventSource : public FingerSdlEventSource {
public:
SwitchEventSource();
- bool pollEvent(Common::Event &event) override;
-protected:
- void preprocessEvents(SDL_Event *event) override;
-private:
-
- enum {
- MAX_NUM_FINGERS = 3, // number of fingers to track per panel
- MAX_TAP_TIME = 250, // taps longer than this will not result in mouse click events
- MAX_TAP_MOTION_DISTANCE = 10, // max distance finger motion in Vita screen pixels to be considered a tap
- SIMULATED_CLICK_DURATION = 50, // time in ms how long simulated mouse clicks should be
- MULTIPLIER = 16 // multiplier for sub-pixel resolution
- };
-
- typedef struct {
- int id; // -1: no touch
- uint32 timeLastDown;
- int lastX; // last known screen coordinates
- int lastY; // last known screen coordinates
- float lastDownX; // SDL touch coordinates when last pressed down
- float lastDownY; // SDL touch coordinates when last pressed down
- } Touch;
-
- Touch _finger[MAX_NUM_FINGERS]; // keep track of finger status
- typedef enum DraggingType {
- DRAG_NONE = 0,
- DRAG_TWO_FINGER,
- DRAG_THREE_FINGER,
- } DraggingType;
-
- DraggingType _multiFingerDragging; // keep track whether we are currently drag-and-dropping
-
- unsigned int _simulatedClickStartTime[2]; // initiation time of last simulated left or right click (zero if no click)
-
- void preprocessFingerDown(SDL_Event *event);
- void preprocessFingerUp(SDL_Event *event);
- void preprocessFingerMotion(SDL_Event *event);
- void convertTouchXYToGameXY(float touchX, float touchY, int *gameX, int *gameY);
- void finishSimulatedMouseClicks(void);
+protected:
+ bool pollEvent(Common::Event &event) override;
+ bool isPortActive(int port) override;
+ bool isTouchpadMode(int port) override;
+ Common::Point getTouchscreenSize() override;
};
#endif /* BACKEND_EVENTS_SWITCH_H */
diff --git a/backends/module.mk b/backends/module.mk
index 8cb79e3601e..ac9afaecdf4 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -463,7 +463,8 @@ MODULE_OBJS += \
fs/posix-drives/posix-drives-fs.o \
fs/posix-drives/posix-drives-fs-factory.o \
plugins/psp2/psp2-provider.o \
- events/psp2sdl/psp2sdl-events.o
+ events/psp2sdl/psp2sdl-events.o \
+ events/sdl/finger-sdl-events.o
endif
ifeq ($(BACKEND),samsungtv)
@@ -481,7 +482,8 @@ endif
ifeq ($(BACKEND),switch)
MODULE_OBJS += \
- events/switchsdl/switchsdl-events.o
+ events/switchsdl/switchsdl-events.o \
+ events/sdl/finger-sdl-events.o
endif
ifdef ENABLE_EVENTRECORDER
More information about the Scummvm-git-logs
mailing list