Add HID touch attribute and index reporting

Adds missing parameter TouchAttribute and emulates correctly the touch point index. Both changes are necessary on Voez to keep track of each finger.
This commit is contained in:
Narr the Reg 2022-05-29 04:28:51 -05:00 committed by GitHub
parent 80c8fb8791
commit 7aa6a5c4ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 9 deletions

View File

@ -6,13 +6,27 @@
#include "common.h"
namespace skyline::input {
/**
* @brief Indicates if touch point has started or ended
* @url https://switchbrew.org/wiki/HID_services#TouchAttribute
*/
union TouchAttribute {
u32 raw{};
struct {
bool start : 1;
bool end : 1;
};
};
static_assert(sizeof(TouchAttribute) == 0x4);
/**
* @brief A descriptor for a single point on the touch screen
* @url https://switchbrew.org/wiki/HID_Shared_Memory#TouchScreenStateData
*/
struct TouchScreenStateData {
u64 timestamp; //!< The timestamp in samples
u32 _pad0_;
TouchAttribute attribute;
u32 index; //!< The index of this touch

View File

@ -15,21 +15,23 @@ namespace skyline::input {
}
}
void TouchManager::SetState(const span<TouchScreenPoint> &points) {
void TouchManager::SetState(span<TouchScreenPoint> touchPoints) {
if (!activated)
return;
const auto &lastEntry{section.entries[section.header.currentEntry]};
auto entryIndex{(section.header.currentEntry != constant::HidEntryCount - 1) ? section.header.currentEntry + 1 : 0};
auto &entry{section.entries[entryIndex]};
touchPoints = touchPoints.first(std::min(touchPoints.size(), entry.data.size()));
entry.globalTimestamp = lastEntry.globalTimestamp + 1;
entry.localTimestamp = lastEntry.localTimestamp + 1;
entry.touchCount = points.size();
entry.touchCount = touchPoints.size();
for (size_t i{}; i < points.size(); i++) {
const auto &host{points[i]};
for (size_t i{}; i < touchPoints.size(); i++) {
const auto &host{touchPoints[i]};
auto &guest{entry.data[i]};
guest.index = static_cast<u32>(i);
guest.attribute.raw = static_cast<u32>(host.attribute);
guest.index = static_cast<u32>(host.id);
guest.positionX = static_cast<u32>(host.x);
guest.positionY = static_cast<u32>(host.y);
guest.minorAxis = static_cast<u32>(host.minor);
@ -37,6 +39,10 @@ namespace skyline::input {
guest.angle = host.angle;
}
// Clear unused touch points
for (size_t i{touchPoints.size()}; i < entry.data.size(); i++)
entry.data[i] = {};
section.header.timestamp = util::GetTimeTicks();
section.header.entryCount = std::min(static_cast<u8>(section.header.entryCount + 1), constant::HidEntryCount);
section.header.maxEntry = section.header.entryCount;

View File

@ -13,6 +13,8 @@ namespace skyline::input {
* @note This structure corresponds to TouchScreenStateData, see that for details
*/
struct TouchScreenPoint {
jint attribute;
jint id;
jint x;
jint y;
jint minor;
@ -37,6 +39,6 @@ namespace skyline::input {
void Activate();
void SetState(const span<TouchScreenPoint> &points);
void SetState(span<TouchScreenPoint> touchPoints);
};
}

View File

@ -467,8 +467,8 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(view : View, event : MotionEvent) : Boolean {
val count = if (event.action != MotionEvent.ACTION_UP && event.action != MotionEvent.ACTION_CANCEL) event.pointerCount else 0
val points = IntArray(count * 5) // This is an array of skyline::input::TouchScreenPoint in C++ as that allows for efficient transfer of values to it
val count = event.pointerCount
val points = IntArray(count * 7) // This is an array of skyline::input::TouchScreenPoint in C++ as that allows for efficient transfer of values to it
var offset = 0
for (index in 0 until count) {
val pointer = MotionEvent.PointerCoords()
@ -477,6 +477,14 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
val x = 0f.coerceAtLeast(pointer.x * 1280 / view.width).toInt()
val y = 0f.coerceAtLeast(pointer.y * 720 / view.height).toInt()
val attribute = when (event.action) {
MotionEvent.ACTION_DOWN -> 1
MotionEvent.ACTION_UP -> 2
else -> 0
}
points[offset++] = attribute
points[offset++] = event.getPointerId(index)
points[offset++] = x
points[offset++] = y
points[offset++] = pointer.touchMinor.toInt()