mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-04 21:05:06 +01:00
Fix HID touch points not being removed from screen
Tapping anything in titles that supported touch (such as Puyo Puyo Tetris or Sonic Mania) wouldn't work due to the first touch point never being removed from the screen, it is supposed to be removed after a 3 frame delay from the touch ending. This commit introduces a mechanism to "time-out" touch points which counts down during the shared memory updates and removes them from the screen after a specified timeout duration.
This commit is contained in:
parent
70ad4498a2
commit
94fdd6aa43
@ -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<TouchScreenPoint> 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<u32>(host.attribute);
|
||||
if (guest.attribute.end)
|
||||
pointTimeout[i] = TouchPointTimeout;
|
||||
|
||||
guest.index = static_cast<u32>(host.id);
|
||||
guest.positionX = static_cast<u32>(host.x);
|
||||
guest.positionY = static_cast<u32>(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;
|
||||
|
||||
|
@ -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<uint8_t, 16> 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:
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user