From 2165f56aee3c1ff55142c85a00137cc22c4f1bb0 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 18 Jun 2023 16:02:21 -0500 Subject: [PATCH] Implement full multi-touch support using Sunshine protocol extension --- app/streaming/input/abstouch.cpp | 55 ++++++++++++++++++++++++++++++++ app/streaming/input/input.h | 2 ++ 2 files changed, 57 insertions(+) diff --git a/app/streaming/input/abstouch.cpp b/app/streaming/input/abstouch.cpp index e9803431..9143c4a6 100644 --- a/app/streaming/input/abstouch.cpp +++ b/app/streaming/input/abstouch.cpp @@ -28,6 +28,61 @@ Uint32 SdlInputHandler::longPressTimerCallback(Uint32, void*) } void SdlInputHandler::handleAbsoluteFingerEvent(SDL_TouchFingerEvent* event) +{ + 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; + + // Scale window-relative events to be video-relative and clamp to video region + float vidrelx = qMin(qMax((int)(event->x * windowWidth), dst.x), dst.x + dst.w) - dst.x; + float vidrely = qMin(qMax((int)(event->y * windowHeight), dst.y), dst.y + dst.h) - dst.y; + + uint8_t eventType; + switch (event->type) { + case SDL_FINGERDOWN: + eventType = LI_TOUCH_EVENT_DOWN; + break; + case SDL_FINGERMOTION: + eventType = LI_TOUCH_EVENT_MOVE; + break; + case SDL_FINGERUP: + eventType = LI_TOUCH_EVENT_UP; + break; + default: + return; + } + + uint32_t pointerId; + + // If the pointer ID is larger than we can fit, just CRC it and use that as the ID. + if ((uint64_t)event->fingerId > UINT32_MAX) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QByteArrayView bav((char*)&event->fingerId, sizeof(event->fingerId)); + pointerId = qChecksum(bav); +#else + pointerId = qChecksum((char*)&event->fingerId, sizeof(event->fingerId)); +#endif + } + else { + pointerId = (uint32_t)event->fingerId; + } + + // Try to send it as a native touch event, otherwise fall back to our touch emulation + if (LiSendTouchEvent(eventType, pointerId, vidrelx / dst.w, vidrely / dst.h, event->pressure) == LI_ERR_UNSUPPORTED) { + emulateAbsoluteFingerEvent(event); + } +} + +void SdlInputHandler::emulateAbsoluteFingerEvent(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 diff --git a/app/streaming/input/input.h b/app/streaming/input/input.h index e9e519f0..ab93a4a4 100644 --- a/app/streaming/input/input.h +++ b/app/streaming/input/input.h @@ -110,6 +110,8 @@ private: void handleAbsoluteFingerEvent(SDL_TouchFingerEvent* event); + void emulateAbsoluteFingerEvent(SDL_TouchFingerEvent* event); + void handleRelativeFingerEvent(SDL_TouchFingerEvent* event); void performSpecialKeyCombo(KeyCombo combo);