mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-12-15 05:42:28 +00:00
107 lines
4 KiB
C++
107 lines
4 KiB
C++
#include "input.h"
|
|
|
|
#include <Limelight.h>
|
|
#include <SDL.h>
|
|
#include "streaming/streamutils.h"
|
|
|
|
#include <QtMath>
|
|
|
|
// How long the fingers must be stationary to start a right click
|
|
#define LONG_PRESS_ACTIVATION_DELAY 650
|
|
|
|
// How far the finger can move before it cancels a right click
|
|
#define LONG_PRESS_ACTIVATION_DELTA 0.01f
|
|
|
|
// How long the double tap deadzone stays in effect between touch up and touch down
|
|
#define DOUBLE_TAP_DEAD_ZONE_DELAY 250
|
|
|
|
// How far the finger can move before it can override the double tap deadzone
|
|
#define DOUBLE_TAP_DEAD_ZONE_DELTA 0.025f
|
|
|
|
Uint32 SdlInputHandler::longPressTimerCallback(Uint32, void*)
|
|
{
|
|
// Raise the left click and start a right click
|
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void SdlInputHandler::handleAbsoluteFingerEvent(SDL_TouchFingerEvent* event)
|
|
{
|
|
// Observations on Windows 10: x and y appear to be relative to 0,0 of the window client area.
|
|
// Although SDL documentation states they are 0.0 - 1.0 float values, they can actually be higher
|
|
// or lower than those values as touch events continue for touches started within the client area that
|
|
// leave the client area during a drag motion.
|
|
// dx and dy are deltas from the last touch event, not the first touch down.
|
|
|
|
// Ignore touch down events with more than one finger
|
|
if (event->type == SDL_FINGERDOWN && SDL_GetNumTouchFingers(event->touchId) > 1) {
|
|
return;
|
|
}
|
|
|
|
// Ignore touch move and touch up events from the non-primary finger
|
|
if (event->type != SDL_FINGERDOWN && event->fingerId != m_LastTouchDownEvent.fingerId) {
|
|
return;
|
|
}
|
|
|
|
SDL_Rect src, dst;
|
|
int windowWidth, windowHeight;
|
|
|
|
SDL_GetWindowSize(m_Window, &windowWidth, &windowHeight);
|
|
|
|
src.x = src.y = 0;
|
|
src.w = m_StreamWidth;
|
|
src.h = m_StreamHeight;
|
|
|
|
dst.x = dst.y = 0;
|
|
dst.w = windowWidth;
|
|
dst.h = windowHeight;
|
|
|
|
// Use the stream and window sizes to determine the video region
|
|
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
|
|
|
|
if (qSqrt(qPow(event->x - m_LastTouchDownEvent.x, 2) + qPow(event->y - m_LastTouchDownEvent.y, 2)) > LONG_PRESS_ACTIVATION_DELTA) {
|
|
// Moved too far since touch down. Cancel the long press timer.
|
|
SDL_RemoveTimer(m_LongPressTimer);
|
|
m_LongPressTimer = 0;
|
|
}
|
|
|
|
// Don't reposition for finger down events within the deadzone. This makes double-clicking easier.
|
|
if (event->type != SDL_FINGERDOWN ||
|
|
event->timestamp - m_LastTouchUpEvent.timestamp > DOUBLE_TAP_DEAD_ZONE_DELAY ||
|
|
qSqrt(qPow(event->x - m_LastTouchUpEvent.x, 2) + qPow(event->y - m_LastTouchUpEvent.y, 2)) > DOUBLE_TAP_DEAD_ZONE_DELTA) {
|
|
// Scale window-relative events to be video-relative and clamp to video region
|
|
short x = qMin(qMax((int)(event->x * windowWidth), dst.x), dst.x + dst.w);
|
|
short y = qMin(qMax((int)(event->y * windowHeight), dst.y), dst.y + dst.h);
|
|
|
|
// Update the cursor position relative to the video region
|
|
LiSendMousePositionEvent(x - dst.x, y - dst.y, dst.w, dst.h);
|
|
}
|
|
|
|
if (event->type == SDL_FINGERDOWN) {
|
|
m_LastTouchDownEvent = *event;
|
|
|
|
// Start/restart the long press timer
|
|
SDL_RemoveTimer(m_LongPressTimer);
|
|
m_LongPressTimer = SDL_AddTimer(LONG_PRESS_ACTIVATION_DELAY,
|
|
longPressTimerCallback,
|
|
nullptr);
|
|
|
|
// Left button down on finger down
|
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
|
}
|
|
else if (event->type == SDL_FINGERUP) {
|
|
m_LastTouchUpEvent = *event;
|
|
|
|
// Cancel the long press timer
|
|
SDL_RemoveTimer(m_LongPressTimer);
|
|
m_LongPressTimer = 0;
|
|
|
|
// Left button up on finger up
|
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
|
|
|
// Raise right button too in case we triggered a long press gesture
|
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
|
|
}
|
|
}
|