diff --git a/app/src/main/cpp/skyline/input/touch.cpp b/app/src/main/cpp/skyline/input/touch.cpp index 79bb0d43..9951b5ea 100644 --- a/app/src/main/cpp/skyline/input/touch.cpp +++ b/app/src/main/cpp/skyline/input/touch.cpp @@ -9,6 +9,7 @@ namespace skyline::input { } void TouchManager::Activate() { + std::scoped_lock lock{mutex}; if (!activated) { activated = true; SetState({}); @@ -16,13 +17,21 @@ namespace skyline::input { } void TouchManager::SetState(span touchPoints) { + std::scoped_lock lock{mutex}; + touchPoints = touchPoints.first(std::min(touchPoints.size(), screenState.data.size())); screenState.touchCount = touchPoints.size(); for (size_t i{}; i < touchPoints.size(); i++) { const auto &host{touchPoints[i]}; auto &guest{screenState.data[i]}; + + constexpr uint8_t TouchPointTimeout{3}; //!< The amount of frames an ended point is expected to be active before it is removed from the screen + guest.attribute.raw = static_cast(host.attribute); + if (guest.attribute.end) + pointTimeout[i] = TouchPointTimeout; + guest.index = static_cast(host.id); guest.positionX = static_cast(host.x); guest.positionY = static_cast(host.y); @@ -37,6 +46,30 @@ namespace skyline::input { } void TouchManager::UpdateSharedMemory() { + std::scoped_lock lock{mutex}; + + for (size_t i{}; i < screenState.data.size(); i++) { + // Remove any touch points which have ended after they are timed out + if (screenState.data[i].attribute.end) { + auto &timeout{pointTimeout[i]}; + if (timeout > 0) { + // Tick the timeout counter + timeout--; + } else { + // Erase the point from the screen + if (i != screenState.data.size() - 1) { + // Move every point after the one being removed to fill the gap + for (size_t j{i + 1}; j < screenState.data.size(); j++) { + screenState.data[j - 1] = screenState.data[j]; + pointTimeout[j - 1] = pointTimeout[j]; + } + i--; + } + screenState.touchCount--; + } + } + } + if (!activated) return; diff --git a/app/src/main/cpp/skyline/input/touch.h b/app/src/main/cpp/skyline/input/touch.h index 16ac2b0f..1605bf74 100644 --- a/app/src/main/cpp/skyline/input/touch.h +++ b/app/src/main/cpp/skyline/input/touch.h @@ -30,7 +30,10 @@ namespace skyline::input { const DeviceState &state; bool activated{}; TouchScreenSection §ion; + + std::recursive_mutex mutex; TouchScreenState screenState{}; //!< The current state of the touch screen + std::array pointTimeout; //!< A frame timeout counter for each point which has ended (according to it's attribute), when it reaches 0 the point is removed from the screen public: /**