From e895ab7d6f06274c9ae4efdc8cf545d37a756e6a Mon Sep 17 00:00:00 2001 From: german Date: Fri, 1 Jan 2021 20:37:29 -0600 Subject: Implements touch, pan, pinch and rotation gestures --- src/core/hle/service/hid/controllers/gesture.h | 92 +++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 8 deletions(-) (limited to 'src/core/hle/service/hid/controllers/gesture.h') diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index f650b8338..60ecc7822 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h @@ -5,8 +5,10 @@ #pragma once #include +#include "common/bit_field.h" #include "common/common_types.h" #include "common/swap.h" +#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/controller_base.h" namespace Service::HID { @@ -28,29 +30,64 @@ public: void OnLoadInputDevices() override; private: - struct Locations { + static constexpr size_t MAX_FINGERS = 16; + static constexpr size_t MAX_POINTS = 4; + + enum class TouchType : u32 { + Idle, // Nothing touching the screen + Complete, // Unknown. End of touch? + Cancel, // Never triggered + Touch, // Pressing without movement + Press, // Never triggered + Tap, // Fast press then release + Pan, // All points moving together across the screen + Swipe, // Fast press movement and release of a single point + Pinch, // All points moving away/closer to the midpoint + Rotate, // All points rotating from the midpoint + }; + + enum class Direction : u32 { + None, + Left, + Up, + Right, + Down, + }; + + struct Attribute { + union { + u32_le raw{}; + + BitField<0, 1, u32> is_new_touch; + BitField<1, 1, u32> is_double_tap; + }; + }; + static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size"); + + struct Points { s32_le x; s32_le y; }; + static_assert(sizeof(Points) == 8, "Points is an invalid size"); struct GestureState { s64_le sampling_number; s64_le sampling_number2; s64_le detection_count; - s32_le type; - s32_le dir; + TouchType type; + Direction dir; s32_le x; s32_le y; s32_le delta_x; s32_le delta_y; f32 vel_x; f32 vel_y; - s32_le attributes; - f32 scale; - f32 rotation; - s32_le location_count; - std::array locations; + Attribute attributes; + u32 scale; + u32 rotation_angle; + s32_le point_count; + std::array points; }; static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size"); @@ -58,6 +95,45 @@ private: CommonHeader header; std::array gesture_states; }; + static_assert(sizeof(SharedMemory) == 0x708, "SharedMemory is an invalid size"); + + struct Finger { + f32 x{}; + f32 y{}; + bool pressed{}; + }; + + struct GestureProperties { + std::array points{}; + std::size_t active_points{}; + Points mid_point{}; + s64_le detection_count{}; + u64_le delta_time{}; + float average_distance{}; + float angle{}; + }; + + // Returns an unused finger id, if there is no fingers avaliable MAX_FINGERS will be returned + std::optional GetUnusedFingerID() const; + + /** If the touch is new it tries to assing a new finger id, if there is no fingers avaliable no + * changes will be made. Updates the coordinates if the finger id it's already set. If the touch + * ends delays the output by one frame to set the end_touch flag before finally freeing the + * finger id */ + size_t UpdateTouchInputEvent(const std::tuple& touch_input, + size_t finger_id); + + // Returns the average distance, angle and middle point of the active fingers + GestureProperties GetGestureProperties(); + SharedMemory shared_memory{}; + std::unique_ptr touch_mouse_device; + std::unique_ptr touch_udp_device; + std::unique_ptr touch_btn_device; + std::array mouse_finger_id; + std::array keyboard_finger_id; + std::array udp_finger_id; + std::array fingers; + GestureProperties last_gesture; }; } // namespace Service::HID -- cgit v1.2.3