diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/frontend/emu_window.cpp | 8 | ||||
| -rw-r--r-- | src/core/frontend/input.h | 7 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/touchscreen.cpp | 114 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/touchscreen.h | 16 |
4 files changed, 84 insertions, 61 deletions
diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index 8c1193894..589842917 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp | |||
| @@ -30,12 +30,14 @@ private: | |||
| 30 | class Device : public Input::TouchDevice { | 30 | class Device : public Input::TouchDevice { |
| 31 | public: | 31 | public: |
| 32 | explicit Device(std::weak_ptr<TouchState>&& touch_state) : touch_state(touch_state) {} | 32 | explicit Device(std::weak_ptr<TouchState>&& touch_state) : touch_state(touch_state) {} |
| 33 | std::tuple<float, float, bool> GetStatus() const override { | 33 | Input::TouchStatus GetStatus() const override { |
| 34 | Input::TouchStatus touch_status = {}; | ||
| 34 | if (auto state = touch_state.lock()) { | 35 | if (auto state = touch_state.lock()) { |
| 35 | std::lock_guard guard{state->mutex}; | 36 | std::lock_guard guard{state->mutex}; |
| 36 | return std::make_tuple(state->touch_x, state->touch_y, state->touch_pressed); | 37 | touch_status[0] = |
| 38 | std::make_tuple(state->touch_x, state->touch_y, state->touch_pressed); | ||
| 37 | } | 39 | } |
| 38 | return std::make_tuple(0.0f, 0.0f, false); | 40 | return touch_status; |
| 39 | } | 41 | } |
| 40 | 42 | ||
| 41 | private: | 43 | private: |
diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h index de51a754e..f014dfea3 100644 --- a/src/core/frontend/input.h +++ b/src/core/frontend/input.h | |||
| @@ -163,10 +163,11 @@ using MotionStatus = std::tuple<Common::Vec3<float>, Common::Vec3<float>, Common | |||
| 163 | using MotionDevice = InputDevice<MotionStatus>; | 163 | using MotionDevice = InputDevice<MotionStatus>; |
| 164 | 164 | ||
| 165 | /** | 165 | /** |
| 166 | * A touch status is an object that returns a tuple of two floats and a bool. The floats are | 166 | * A touch status is an object that returns an array of 16 tuple elements of two floats and a bool. |
| 167 | * x and y coordinates in the range 0.0 - 1.0, and the bool indicates whether it is pressed. | 167 | * The floats are x and y coordinates in the range 0.0 - 1.0, and the bool indicates whether it is |
| 168 | * pressed. | ||
| 168 | */ | 169 | */ |
| 169 | using TouchStatus = std::tuple<float, float, bool>; | 170 | using TouchStatus = std::array<std::tuple<float, float, bool>, 16>; |
| 170 | 171 | ||
| 171 | /** | 172 | /** |
| 172 | * A touch device is an input device that returns a touch status object | 173 | * A touch device is an input device that returns a touch status object |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index 13f75b48a..dc0d2c712 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 5 | #include <cstring> | 6 | #include <cstring> |
| 6 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 7 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| @@ -16,7 +17,13 @@ constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; | |||
| 16 | Controller_Touchscreen::Controller_Touchscreen(Core::System& system) : ControllerBase(system) {} | 17 | Controller_Touchscreen::Controller_Touchscreen(Core::System& system) : ControllerBase(system) {} |
| 17 | Controller_Touchscreen::~Controller_Touchscreen() = default; | 18 | Controller_Touchscreen::~Controller_Touchscreen() = default; |
| 18 | 19 | ||
| 19 | void Controller_Touchscreen::OnInit() {} | 20 | void Controller_Touchscreen::OnInit() { |
| 21 | for (size_t id = 0; id < MAX_FINGERS; id++) { | ||
| 22 | mouse_finger_id[id] = MAX_FINGERS; | ||
| 23 | keyboard_finger_id[id] = MAX_FINGERS; | ||
| 24 | udp_finger_id[id] = MAX_FINGERS; | ||
| 25 | } | ||
| 26 | } | ||
| 20 | 27 | ||
| 21 | void Controller_Touchscreen::OnRelease() {} | 28 | void Controller_Touchscreen::OnRelease() {} |
| 22 | 29 | ||
| @@ -40,32 +47,35 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin | |||
| 40 | cur_entry.sampling_number = last_entry.sampling_number + 1; | 47 | cur_entry.sampling_number = last_entry.sampling_number + 1; |
| 41 | cur_entry.sampling_number2 = cur_entry.sampling_number; | 48 | cur_entry.sampling_number2 = cur_entry.sampling_number; |
| 42 | 49 | ||
| 43 | updateTouchInputEvent(touch_mouse_device->GetStatus(), mouse_finger_id); | 50 | const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); |
| 44 | updateTouchInputEvent(touch_btn_device->GetStatus(), keyboard_finger_id); | 51 | const Input::TouchStatus& keyboard_status = touch_btn_device->GetStatus(); |
| 45 | updateTouchInputEvent(touch_udp_device->GetStatus(), udp_finger_id); | 52 | const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); |
| 46 | 53 | for (size_t id = 0; id < mouse_status.size(); id++) { | |
| 47 | std::array<Finger, 16> sorted_fingers; | 54 | mouse_finger_id[id] = UpdateTouchInputEvent(mouse_status[id], mouse_finger_id[id]); |
| 48 | size_t active_fingers = 0; | 55 | keyboard_finger_id[id] = UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]); |
| 49 | for (Finger finger : fingers) { | 56 | udp_finger_id[id] = UpdateTouchInputEvent(udp_status[id], udp_finger_id[id]); |
| 50 | if (finger.pressed) { | ||
| 51 | sorted_fingers[active_fingers++] = finger; | ||
| 52 | } | ||
| 53 | } | 57 | } |
| 54 | 58 | ||
| 59 | std::array<Finger, 16> active_fingers; | ||
| 60 | const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), | ||
| 61 | [](const auto& finger) { return finger.pressed; }); | ||
| 62 | const auto active_fingers_count = | ||
| 63 | static_cast<size_t>(std::distance(active_fingers.begin(), end_iter)); | ||
| 64 | |||
| 55 | const u64 tick = core_timing.GetCPUTicks(); | 65 | const u64 tick = core_timing.GetCPUTicks(); |
| 56 | cur_entry.entry_count = static_cast<s32_le>(active_fingers); | 66 | cur_entry.entry_count = static_cast<s32_le>(active_fingers_count); |
| 57 | for (size_t id = 0; id < MAX_FINGERS; id++) { | 67 | for (size_t id = 0; id < MAX_FINGERS; id++) { |
| 58 | auto& touch_entry = cur_entry.states[id]; | 68 | auto& touch_entry = cur_entry.states[id]; |
| 59 | if (id < active_fingers) { | 69 | if (id < active_fingers_count) { |
| 60 | touch_entry.x = static_cast<u16>(sorted_fingers[id].x * Layout::ScreenUndocked::Width); | 70 | touch_entry.x = static_cast<u16>(active_fingers[id].x * Layout::ScreenUndocked::Width); |
| 61 | touch_entry.y = static_cast<u16>(sorted_fingers[id].y * Layout::ScreenUndocked::Height); | 71 | touch_entry.y = static_cast<u16>(active_fingers[id].y * Layout::ScreenUndocked::Height); |
| 62 | touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; | 72 | touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; |
| 63 | touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; | 73 | touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; |
| 64 | touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; | 74 | touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; |
| 65 | touch_entry.delta_time = tick - sorted_fingers[id].last_touch; | 75 | touch_entry.delta_time = tick - active_fingers[id].last_touch; |
| 66 | sorted_fingers[id].last_touch = tick; | 76 | active_fingers[id].last_touch = tick; |
| 67 | touch_entry.finger = sorted_fingers[id].id; | 77 | touch_entry.finger = active_fingers[id].id; |
| 68 | touch_entry.attribute.raw = sorted_fingers[id].attribute.raw; | 78 | touch_entry.attribute.raw = active_fingers[id].attribute.raw; |
| 69 | } else { | 79 | } else { |
| 70 | // Clear touch entry | 80 | // Clear touch entry |
| 71 | touch_entry.attribute.raw = 0; | 81 | touch_entry.attribute.raw = 0; |
| @@ -91,44 +101,50 @@ void Controller_Touchscreen::OnLoadInputDevices() { | |||
| 91 | } | 101 | } |
| 92 | } | 102 | } |
| 93 | 103 | ||
| 94 | void Controller_Touchscreen::updateTouchInputEvent( | 104 | std::optional<size_t> Controller_Touchscreen::GetUnusedFingerID() const { |
| 95 | const std::tuple<float, float, bool>& touch_input, size_t& finger_id) { | 105 | size_t first_free_id = 0; |
| 96 | bool pressed = false; | 106 | while (first_free_id < MAX_FINGERS) { |
| 97 | float x, y; | 107 | if (!fingers[first_free_id].pressed) { |
| 98 | std::tie(x, y, pressed) = touch_input; | 108 | return first_free_id; |
| 109 | } else { | ||
| 110 | first_free_id++; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | return std::nullopt; | ||
| 114 | } | ||
| 115 | |||
| 116 | size_t Controller_Touchscreen::UpdateTouchInputEvent( | ||
| 117 | const std::tuple<float, float, bool>& touch_input, size_t finger_id) { | ||
| 118 | const auto& [x, y, pressed] = touch_input; | ||
| 99 | if (pressed) { | 119 | if (pressed) { |
| 100 | if (finger_id == -1) { | 120 | Attributes attribute = {}; |
| 101 | int first_free_id = 0; | 121 | if (finger_id == MAX_FINGERS) { |
| 102 | int found = false; | 122 | const auto first_free_id = GetUnusedFingerID(); |
| 103 | while (!found && first_free_id < MAX_FINGERS) { | 123 | if (!first_free_id) { |
| 104 | if (!fingers[first_free_id].pressed) { | 124 | // Invalid finger id do nothing |
| 105 | found = true; | 125 | return MAX_FINGERS; |
| 106 | } else { | ||
| 107 | first_free_id++; | ||
| 108 | } | ||
| 109 | } | 126 | } |
| 110 | if (found) { | 127 | finger_id = first_free_id.value(); |
| 111 | finger_id = first_free_id; | 128 | fingers[finger_id].pressed = true; |
| 112 | fingers[finger_id].x = x; | 129 | fingers[finger_id].id = static_cast<u32_le>(finger_id); |
| 113 | fingers[finger_id].y = y; | 130 | attribute.start_touch.Assign(1); |
| 114 | fingers[finger_id].pressed = true; | ||
| 115 | fingers[finger_id].id = static_cast<u32_le>(finger_id); | ||
| 116 | fingers[finger_id].attribute.start_touch.Assign(1); | ||
| 117 | } | ||
| 118 | } else { | ||
| 119 | fingers[finger_id].x = x; | ||
| 120 | fingers[finger_id].y = y; | ||
| 121 | fingers[finger_id].attribute.raw = 0; | ||
| 122 | } | 131 | } |
| 123 | } else if (finger_id != -1) { | 132 | fingers[finger_id].x = x; |
| 133 | fingers[finger_id].y = y; | ||
| 134 | fingers[finger_id].attribute = attribute; | ||
| 135 | return finger_id; | ||
| 136 | } | ||
| 137 | |||
| 138 | if (finger_id != MAX_FINGERS) { | ||
| 124 | if (!fingers[finger_id].attribute.end_touch) { | 139 | if (!fingers[finger_id].attribute.end_touch) { |
| 125 | fingers[finger_id].attribute.end_touch.Assign(1); | 140 | fingers[finger_id].attribute.end_touch.Assign(1); |
| 126 | fingers[finger_id].attribute.start_touch.Assign(0); | 141 | fingers[finger_id].attribute.start_touch.Assign(0); |
| 127 | } else { | 142 | return finger_id; |
| 128 | fingers[finger_id].pressed = false; | ||
| 129 | finger_id = -1; | ||
| 130 | } | 143 | } |
| 144 | fingers[finger_id].pressed = false; | ||
| 131 | } | 145 | } |
| 146 | |||
| 147 | return MAX_FINGERS; | ||
| 132 | } | 148 | } |
| 133 | 149 | ||
| 134 | } // namespace Service::HID | 150 | } // namespace Service::HID |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index 03f399344..e39ab89ee 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h | |||
| @@ -30,13 +30,17 @@ public: | |||
| 30 | void OnLoadInputDevices() override; | 30 | void OnLoadInputDevices() override; |
| 31 | 31 | ||
| 32 | private: | 32 | private: |
| 33 | static constexpr size_t MAX_FINGERS = 16; | ||
| 34 | |||
| 35 | // Returns an unused finger id, if there is no fingers available std::nullopt will be returned | ||
| 36 | std::optional<size_t> GetUnusedFingerID() const; | ||
| 37 | |||
| 33 | // If the touch is new it tries to assing a new finger id, if there is no fingers avaliable no | 38 | // If the touch is new it tries to assing a new finger id, if there is no fingers avaliable no |
| 34 | // changes will be made. Updates the coordinates if the finger id it's already set. If the touch | 39 | // changes will be made. Updates the coordinates if the finger id it's already set. If the touch |
| 35 | // ends delays the output by one frame to set the end_touch flag before finally freeing the | 40 | // ends delays the output by one frame to set the end_touch flag before finally freeing the |
| 36 | // finger id | 41 | // finger id |
| 37 | void updateTouchInputEvent(const std::tuple<float, float, bool>& touch_input, | 42 | size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input, |
| 38 | size_t& finger_id); | 43 | size_t finger_id); |
| 39 | static const size_t MAX_FINGERS = 16; | ||
| 40 | 44 | ||
| 41 | struct Attributes { | 45 | struct Attributes { |
| 42 | union { | 46 | union { |
| @@ -88,9 +92,9 @@ private: | |||
| 88 | std::unique_ptr<Input::TouchDevice> touch_mouse_device; | 92 | std::unique_ptr<Input::TouchDevice> touch_mouse_device; |
| 89 | std::unique_ptr<Input::TouchDevice> touch_udp_device; | 93 | std::unique_ptr<Input::TouchDevice> touch_udp_device; |
| 90 | std::unique_ptr<Input::TouchDevice> touch_btn_device; | 94 | std::unique_ptr<Input::TouchDevice> touch_btn_device; |
| 91 | size_t mouse_finger_id{-1}; | 95 | std::array<size_t, MAX_FINGERS> mouse_finger_id; |
| 92 | size_t keyboard_finger_id{-1}; | 96 | std::array<size_t, MAX_FINGERS> keyboard_finger_id; |
| 93 | size_t udp_finger_id{-1}; | 97 | std::array<size_t, MAX_FINGERS> udp_finger_id; |
| 94 | std::array<Finger, MAX_FINGERS> fingers; | 98 | std::array<Finger, MAX_FINGERS> fingers; |
| 95 | }; | 99 | }; |
| 96 | } // namespace Service::HID | 100 | } // namespace Service::HID |