mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-22 23:18:01 +03:00
Add touch gestures
This adds gestures that allow touch device users to emulate the following mouse/keyboard actions: - Right-click: touch outside the game's viewport - Ctrl key: one-finger touch and hold (for one second) - Mouse wheel: Swipe up / down with two fingers
This commit is contained in:
+70
-2
@@ -151,6 +151,13 @@ static SDL_GameController *controllers[MAX_CONTROLLERS];
|
||||
static SDL_MouseButtonEvent deferred_synthetic_mouse_event;
|
||||
#define SYNTHETIC_MOUSE_EVENT_DELAY 50
|
||||
|
||||
static uint32_t long_touch_start_timestamp;
|
||||
static SDL_FRect long_touch_finger_rect;
|
||||
#define LONG_TOUCH_DURATION 1000
|
||||
|
||||
static float scroll_gesture_y;
|
||||
#define SCROLL_GESTURE_SENSITIVITY 0.02f // 2% of screen height
|
||||
|
||||
static enum sact_keycode sdl_to_sact_button(int button)
|
||||
{
|
||||
switch (button) {
|
||||
@@ -230,6 +237,21 @@ static void mouse_event(SDL_MouseButtonEvent *e)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void synthetic_mouse_event(SDL_MouseButtonEvent *e)
|
||||
{
|
||||
if (e->state == SDL_PRESSED) {
|
||||
// Touch outside the viewport is treated as right-click.
|
||||
SDL_Point p = { .x = e->x, .y = e->y };
|
||||
if (SDL_PointInRect(&p, &sdl.viewport))
|
||||
key_state[VK_LBUTTON] = true;
|
||||
else
|
||||
key_state[VK_RBUTTON] = true;
|
||||
} else {
|
||||
key_state[VK_LBUTTON] = false;
|
||||
key_state[VK_RBUTTON] = false;
|
||||
}
|
||||
}
|
||||
|
||||
#define JOYAXIS_DEADZONE 13500
|
||||
|
||||
enum joyaxis_axis {
|
||||
@@ -485,9 +507,14 @@ void handle_events(void)
|
||||
{
|
||||
// Flush the deferred mouse button event if it's older than 50ms.
|
||||
if (deferred_synthetic_mouse_event.timestamp && deferred_synthetic_mouse_event.timestamp + SYNTHETIC_MOUSE_EVENT_DELAY < SDL_GetTicks()) {
|
||||
mouse_event(&deferred_synthetic_mouse_event);
|
||||
synthetic_mouse_event(&deferred_synthetic_mouse_event);
|
||||
deferred_synthetic_mouse_event.timestamp = 0;
|
||||
}
|
||||
// Long touch emulates pressing the Ctrl key.
|
||||
if (long_touch_start_timestamp && long_touch_start_timestamp + LONG_TOUCH_DURATION < SDL_GetTicks()) {
|
||||
key_state[VK_LBUTTON] = false;
|
||||
key_state[VK_CONTROL] = true;
|
||||
}
|
||||
|
||||
SDL_Event e;
|
||||
while (SDL_PollEvent(&e)) {
|
||||
@@ -530,7 +557,7 @@ void handle_events(void)
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (e.button.which == SDL_TOUCH_MOUSEID) {
|
||||
if (deferred_synthetic_mouse_event.timestamp)
|
||||
mouse_event(&deferred_synthetic_mouse_event);
|
||||
synthetic_mouse_event(&deferred_synthetic_mouse_event);
|
||||
deferred_synthetic_mouse_event = e.button;
|
||||
} else {
|
||||
mouse_event(&e.button);
|
||||
@@ -539,6 +566,47 @@ void handle_events(void)
|
||||
case SDL_MOUSEWHEEL:
|
||||
wheel_dir = e.wheel.y;
|
||||
break;
|
||||
case SDL_FINGERDOWN:
|
||||
if (SDL_GetNumTouchFingers(e.tfinger.touchId) >= 2) {
|
||||
// The user is about to start a multi-touch gesture.
|
||||
key_state[VK_LBUTTON] = false;
|
||||
key_state[VK_RBUTTON] = false;
|
||||
deferred_synthetic_mouse_event.timestamp = 0;
|
||||
long_touch_start_timestamp = 0;
|
||||
scroll_gesture_y = -1.0f;
|
||||
break;
|
||||
}
|
||||
long_touch_start_timestamp = e.tfinger.timestamp;
|
||||
// Movement within this rect (1% of the screen size from the touch
|
||||
// start position) will be ignored.
|
||||
long_touch_finger_rect = (SDL_FRect) {
|
||||
.x = e.tfinger.x - 0.01,
|
||||
.y = e.tfinger.y - 0.01,
|
||||
.w = 0.02,
|
||||
.h = 0.02
|
||||
};
|
||||
break;
|
||||
case SDL_FINGERMOTION:
|
||||
if (SDL_PointInFRect(&(SDL_FPoint){ e.tfinger.x, e.tfinger.y }, &long_touch_finger_rect))
|
||||
break;
|
||||
// Cancel the timer only if Ctrl emulation has not already started.
|
||||
if (!key_state[VK_CONTROL])
|
||||
long_touch_start_timestamp = 0;
|
||||
break;
|
||||
case SDL_FINGERUP:
|
||||
long_touch_start_timestamp = 0;
|
||||
key_state[VK_CONTROL] = false;
|
||||
break;
|
||||
case SDL_MULTIGESTURE:
|
||||
if (e.mgesture.numFingers == 2) {
|
||||
if (scroll_gesture_y < 0.0f)
|
||||
scroll_gesture_y = e.mgesture.y;
|
||||
float dy = scroll_gesture_y - e.mgesture.y;
|
||||
if (dy * dy > SCROLL_GESTURE_SENSITIVITY * SCROLL_GESTURE_SENSITIVITY) {
|
||||
wheel_dir = dy < 0 ? 1 : -1; // Swipe up to scroll down.
|
||||
scroll_gesture_y = e.mgesture.y;
|
||||
}
|
||||
}
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
if (e.cdevice.which < MAX_CONTROLLERS)
|
||||
controllers[e.cdevice.which] = SDL_GameControllerOpen(e.cdevice.which);
|
||||
|
||||
Reference in New Issue
Block a user