diff options
| author | 2021-01-02 22:04:50 -0600 | |
|---|---|---|
| committer | 2021-01-15 09:05:17 -0600 | |
| commit | 8495e1bd8373fed993975e40c360c87409455e9e (patch) | |
| tree | fffff1304673212280dc0e927b69efa3ca4fc8b3 /src | |
| parent | Allow to return up to 16 touch inputs per engine (diff) | |
| download | yuzu-8495e1bd8373fed993975e40c360c87409455e9e.tar.gz yuzu-8495e1bd8373fed993975e40c360c87409455e9e.tar.xz yuzu-8495e1bd8373fed993975e40c360c87409455e9e.zip | |
Add mutitouch support for touch screens
Diffstat (limited to '')
| -rw-r--r-- | src/core/frontend/emu_window.cpp | 42 | ||||
| -rw-r--r-- | src/core/frontend/emu_window.h | 12 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/touchscreen.cpp | 30 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/touchscreen.h | 14 | ||||
| -rw-r--r-- | src/input_common/touch_from_button.cpp | 4 | ||||
| -rw-r--r-- | src/input_common/udp/client.cpp | 19 | ||||
| -rw-r--r-- | src/input_common/udp/client.h | 8 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.cpp | 73 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.h | 8 | ||||
| -rw-r--r-- | src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 12 |
10 files changed, 137 insertions, 85 deletions
diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index 589842917..af6c1633a 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp | |||
| @@ -21,21 +21,17 @@ public: | |||
| 21 | 21 | ||
| 22 | std::mutex mutex; | 22 | std::mutex mutex; |
| 23 | 23 | ||
| 24 | bool touch_pressed = false; ///< True if touchpad area is currently pressed, otherwise false | 24 | Input::TouchStatus status; |
| 25 | |||
| 26 | float touch_x = 0.0f; ///< Touchpad X-position | ||
| 27 | float touch_y = 0.0f; ///< Touchpad Y-position | ||
| 28 | 25 | ||
| 29 | private: | 26 | private: |
| 30 | class Device : public Input::TouchDevice { | 27 | class Device : public Input::TouchDevice { |
| 31 | public: | 28 | public: |
| 32 | explicit Device(std::weak_ptr<TouchState>&& touch_state) : touch_state(touch_state) {} | 29 | explicit Device(std::weak_ptr<TouchState>&& touch_state) : touch_state(touch_state) {} |
| 33 | Input::TouchStatus GetStatus() const override { | 30 | Input::TouchStatus GetStatus() const override { |
| 34 | Input::TouchStatus touch_status = {}; | 31 | Input::TouchStatus touch_status{}; |
| 35 | if (auto state = touch_state.lock()) { | 32 | if (auto state = touch_state.lock()) { |
| 36 | std::lock_guard guard{state->mutex}; | 33 | std::lock_guard guard{state->mutex}; |
| 37 | touch_status[0] = | 34 | touch_status = state->status; |
| 38 | std::make_tuple(state->touch_x, state->touch_y, state->touch_pressed); | ||
| 39 | } | 35 | } |
| 40 | return touch_status; | 36 | return touch_status; |
| 41 | } | 37 | } |
| @@ -81,36 +77,44 @@ std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsi | |||
| 81 | return std::make_tuple(new_x, new_y); | 77 | return std::make_tuple(new_x, new_y); |
| 82 | } | 78 | } |
| 83 | 79 | ||
| 84 | void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { | 80 | void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y, std::size_t id) { |
| 85 | if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) | 81 | if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) { |
| 86 | return; | 82 | return; |
| 83 | } | ||
| 84 | if (id >= touch_state->status.size()) { | ||
| 85 | return; | ||
| 86 | } | ||
| 87 | 87 | ||
| 88 | std::lock_guard guard{touch_state->mutex}; | 88 | std::lock_guard guard{touch_state->mutex}; |
| 89 | touch_state->touch_x = | 89 | const float x = |
| 90 | static_cast<float>(framebuffer_x - framebuffer_layout.screen.left) / | 90 | static_cast<float>(framebuffer_x - framebuffer_layout.screen.left) / |
| 91 | static_cast<float>(framebuffer_layout.screen.right - framebuffer_layout.screen.left); | 91 | static_cast<float>(framebuffer_layout.screen.right - framebuffer_layout.screen.left); |
| 92 | touch_state->touch_y = | 92 | const float y = |
| 93 | static_cast<float>(framebuffer_y - framebuffer_layout.screen.top) / | 93 | static_cast<float>(framebuffer_y - framebuffer_layout.screen.top) / |
| 94 | static_cast<float>(framebuffer_layout.screen.bottom - framebuffer_layout.screen.top); | 94 | static_cast<float>(framebuffer_layout.screen.bottom - framebuffer_layout.screen.top); |
| 95 | 95 | ||
| 96 | touch_state->touch_pressed = true; | 96 | touch_state->status[id] = std::make_tuple(x, y, true); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | void EmuWindow::TouchReleased() { | 99 | void EmuWindow::TouchReleased(std::size_t id) { |
| 100 | if (id >= touch_state->status.size()) { | ||
| 101 | return; | ||
| 102 | } | ||
| 100 | std::lock_guard guard{touch_state->mutex}; | 103 | std::lock_guard guard{touch_state->mutex}; |
| 101 | touch_state->touch_pressed = false; | 104 | touch_state->status[id] = std::make_tuple(0.0f, 0.0f, false); |
| 102 | touch_state->touch_x = 0; | ||
| 103 | touch_state->touch_y = 0; | ||
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) { | 107 | void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y, std::size_t id) { |
| 107 | if (!touch_state->touch_pressed) | 108 | if (id >= touch_state->status.size()) { |
| 109 | return; | ||
| 110 | } | ||
| 111 | if (!std::get<2>(touch_state->status[id])) | ||
| 108 | return; | 112 | return; |
| 109 | 113 | ||
| 110 | if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) | 114 | if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) |
| 111 | std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y); | 115 | std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y); |
| 112 | 116 | ||
| 113 | TouchPressed(framebuffer_x, framebuffer_y); | 117 | TouchPressed(framebuffer_x, framebuffer_y, id); |
| 114 | } | 118 | } |
| 115 | 119 | ||
| 116 | void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) { | 120 | void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) { |
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 276d2b906..f8db42ab4 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h | |||
| @@ -117,18 +117,22 @@ public: | |||
| 117 | * Signal that a touch pressed event has occurred (e.g. mouse click pressed) | 117 | * Signal that a touch pressed event has occurred (e.g. mouse click pressed) |
| 118 | * @param framebuffer_x Framebuffer x-coordinate that was pressed | 118 | * @param framebuffer_x Framebuffer x-coordinate that was pressed |
| 119 | * @param framebuffer_y Framebuffer y-coordinate that was pressed | 119 | * @param framebuffer_y Framebuffer y-coordinate that was pressed |
| 120 | * @param id Touch event id | ||
| 120 | */ | 121 | */ |
| 121 | void TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y); | 122 | void TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y, std::size_t id); |
| 122 | 123 | ||
| 123 | /// Signal that a touch released event has occurred (e.g. mouse click released) | 124 | /** Signal that a touch released event has occurred (e.g. mouse click released) |
| 124 | void TouchReleased(); | 125 | *@param id Touch event id |
| 126 | */ | ||
| 127 | void TouchReleased(std::size_t id); | ||
| 125 | 128 | ||
| 126 | /** | 129 | /** |
| 127 | * Signal that a touch movement event has occurred (e.g. mouse was moved over the emu window) | 130 | * Signal that a touch movement event has occurred (e.g. mouse was moved over the emu window) |
| 128 | * @param framebuffer_x Framebuffer x-coordinate | 131 | * @param framebuffer_x Framebuffer x-coordinate |
| 129 | * @param framebuffer_y Framebuffer y-coordinate | 132 | * @param framebuffer_y Framebuffer y-coordinate |
| 133 | * @param id Touch event id | ||
| 130 | */ | 134 | */ |
| 131 | void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y); | 135 | void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y, std::size_t id); |
| 132 | 136 | ||
| 133 | /** | 137 | /** |
| 134 | * Returns currently active configuration. | 138 | * Returns currently active configuration. |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index dc0d2c712..cd318f25b 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp | |||
| @@ -18,7 +18,7 @@ Controller_Touchscreen::Controller_Touchscreen(Core::System& system) : Controlle | |||
| 18 | Controller_Touchscreen::~Controller_Touchscreen() = default; | 18 | Controller_Touchscreen::~Controller_Touchscreen() = default; |
| 19 | 19 | ||
| 20 | void Controller_Touchscreen::OnInit() { | 20 | void Controller_Touchscreen::OnInit() { |
| 21 | for (size_t id = 0; id < MAX_FINGERS; id++) { | 21 | for (std::size_t id = 0; id < MAX_FINGERS; ++id) { |
| 22 | mouse_finger_id[id] = MAX_FINGERS; | 22 | mouse_finger_id[id] = MAX_FINGERS; |
| 23 | keyboard_finger_id[id] = MAX_FINGERS; | 23 | keyboard_finger_id[id] = MAX_FINGERS; |
| 24 | udp_finger_id[id] = MAX_FINGERS; | 24 | udp_finger_id[id] = MAX_FINGERS; |
| @@ -48,23 +48,29 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin | |||
| 48 | cur_entry.sampling_number2 = cur_entry.sampling_number; | 48 | cur_entry.sampling_number2 = cur_entry.sampling_number; |
| 49 | 49 | ||
| 50 | const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); | 50 | const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); |
| 51 | const Input::TouchStatus& keyboard_status = touch_btn_device->GetStatus(); | ||
| 52 | const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); | 51 | const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); |
| 53 | for (size_t id = 0; id < mouse_status.size(); id++) { | 52 | for (std::size_t id = 0; id < mouse_status.size(); ++id) { |
| 54 | mouse_finger_id[id] = UpdateTouchInputEvent(mouse_status[id], mouse_finger_id[id]); | 53 | mouse_finger_id[id] = UpdateTouchInputEvent(mouse_status[id], mouse_finger_id[id]); |
| 55 | keyboard_finger_id[id] = UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]); | ||
| 56 | udp_finger_id[id] = UpdateTouchInputEvent(udp_status[id], udp_finger_id[id]); | 54 | udp_finger_id[id] = UpdateTouchInputEvent(udp_status[id], udp_finger_id[id]); |
| 57 | } | 55 | } |
| 58 | 56 | ||
| 57 | if (Settings::values.use_touch_from_button) { | ||
| 58 | const Input::TouchStatus& keyboard_status = touch_btn_device->GetStatus(); | ||
| 59 | for (std::size_t id = 0; id < mouse_status.size(); ++id) { | ||
| 60 | keyboard_finger_id[id] = | ||
| 61 | UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 59 | std::array<Finger, 16> active_fingers; | 65 | std::array<Finger, 16> active_fingers; |
| 60 | const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), | 66 | const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), |
| 61 | [](const auto& finger) { return finger.pressed; }); | 67 | [](const auto& finger) { return finger.pressed; }); |
| 62 | const auto active_fingers_count = | 68 | const auto active_fingers_count = |
| 63 | static_cast<size_t>(std::distance(active_fingers.begin(), end_iter)); | 69 | static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); |
| 64 | 70 | ||
| 65 | const u64 tick = core_timing.GetCPUTicks(); | 71 | const u64 tick = core_timing.GetCPUTicks(); |
| 66 | cur_entry.entry_count = static_cast<s32_le>(active_fingers_count); | 72 | cur_entry.entry_count = static_cast<s32_le>(active_fingers_count); |
| 67 | for (size_t id = 0; id < MAX_FINGERS; id++) { | 73 | for (std::size_t id = 0; id < MAX_FINGERS; ++id) { |
| 68 | auto& touch_entry = cur_entry.states[id]; | 74 | auto& touch_entry = cur_entry.states[id]; |
| 69 | if (id < active_fingers_count) { | 75 | if (id < active_fingers_count) { |
| 70 | touch_entry.x = static_cast<u16>(active_fingers[id].x * Layout::ScreenUndocked::Width); | 76 | touch_entry.x = static_cast<u16>(active_fingers[id].x * Layout::ScreenUndocked::Width); |
| @@ -73,7 +79,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin | |||
| 73 | touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; | 79 | touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; |
| 74 | touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; | 80 | touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; |
| 75 | touch_entry.delta_time = tick - active_fingers[id].last_touch; | 81 | touch_entry.delta_time = tick - active_fingers[id].last_touch; |
| 76 | active_fingers[id].last_touch = tick; | 82 | fingers[active_fingers[id].id].last_touch = tick; |
| 77 | touch_entry.finger = active_fingers[id].id; | 83 | touch_entry.finger = active_fingers[id].id; |
| 78 | touch_entry.attribute.raw = active_fingers[id].attribute.raw; | 84 | touch_entry.attribute.raw = active_fingers[id].attribute.raw; |
| 79 | } else { | 85 | } else { |
| @@ -101,8 +107,8 @@ void Controller_Touchscreen::OnLoadInputDevices() { | |||
| 101 | } | 107 | } |
| 102 | } | 108 | } |
| 103 | 109 | ||
| 104 | std::optional<size_t> Controller_Touchscreen::GetUnusedFingerID() const { | 110 | std::optional<std::size_t> Controller_Touchscreen::GetUnusedFingerID() const { |
| 105 | size_t first_free_id = 0; | 111 | std::size_t first_free_id = 0; |
| 106 | while (first_free_id < MAX_FINGERS) { | 112 | while (first_free_id < MAX_FINGERS) { |
| 107 | if (!fingers[first_free_id].pressed) { | 113 | if (!fingers[first_free_id].pressed) { |
| 108 | return first_free_id; | 114 | return first_free_id; |
| @@ -113,11 +119,11 @@ std::optional<size_t> Controller_Touchscreen::GetUnusedFingerID() const { | |||
| 113 | return std::nullopt; | 119 | return std::nullopt; |
| 114 | } | 120 | } |
| 115 | 121 | ||
| 116 | size_t Controller_Touchscreen::UpdateTouchInputEvent( | 122 | std::size_t Controller_Touchscreen::UpdateTouchInputEvent( |
| 117 | const std::tuple<float, float, bool>& touch_input, size_t finger_id) { | 123 | const std::tuple<float, float, bool>& touch_input, std::size_t finger_id) { |
| 118 | const auto& [x, y, pressed] = touch_input; | 124 | const auto& [x, y, pressed] = touch_input; |
| 119 | if (pressed) { | 125 | if (pressed) { |
| 120 | Attributes attribute = {}; | 126 | Attributes attribute{}; |
| 121 | if (finger_id == MAX_FINGERS) { | 127 | if (finger_id == MAX_FINGERS) { |
| 122 | const auto first_free_id = GetUnusedFingerID(); | 128 | const auto first_free_id = GetUnusedFingerID(); |
| 123 | if (!first_free_id) { | 129 | if (!first_free_id) { |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index e39ab89ee..784124e25 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h | |||
| @@ -30,17 +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; | 33 | static constexpr std::size_t MAX_FINGERS = 16; |
| 34 | 34 | ||
| 35 | // Returns an unused finger id, if there is no fingers available std::nullopt will be returned | 35 | // Returns an unused finger id, if there is no fingers available std::nullopt will be returned |
| 36 | std::optional<size_t> GetUnusedFingerID() const; | 36 | std::optional<std::size_t> GetUnusedFingerID() const; |
| 37 | 37 | ||
| 38 | // 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 |
| 39 | // 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 |
| 40 | // 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 |
| 41 | // finger id | 41 | // finger id |
| 42 | size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input, | 42 | std::size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input, |
| 43 | size_t finger_id); | 43 | std::size_t finger_id); |
| 44 | 44 | ||
| 45 | struct Attributes { | 45 | struct Attributes { |
| 46 | union { | 46 | union { |
| @@ -92,9 +92,9 @@ private: | |||
| 92 | std::unique_ptr<Input::TouchDevice> touch_mouse_device; | 92 | std::unique_ptr<Input::TouchDevice> touch_mouse_device; |
| 93 | std::unique_ptr<Input::TouchDevice> touch_udp_device; | 93 | std::unique_ptr<Input::TouchDevice> touch_udp_device; |
| 94 | std::unique_ptr<Input::TouchDevice> touch_btn_device; | 94 | std::unique_ptr<Input::TouchDevice> touch_btn_device; |
| 95 | std::array<size_t, MAX_FINGERS> mouse_finger_id; | 95 | std::array<std::size_t, MAX_FINGERS> mouse_finger_id; |
| 96 | std::array<size_t, MAX_FINGERS> keyboard_finger_id; | 96 | std::array<std::size_t, MAX_FINGERS> keyboard_finger_id; |
| 97 | std::array<size_t, MAX_FINGERS> udp_finger_id; | 97 | std::array<std::size_t, MAX_FINGERS> udp_finger_id; |
| 98 | std::array<Finger, MAX_FINGERS> fingers; | 98 | std::array<Finger, MAX_FINGERS> fingers; |
| 99 | }; | 99 | }; |
| 100 | } // namespace Service::HID | 100 | } // namespace Service::HID |
diff --git a/src/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp index 5226e70df..ffbe4f2ed 100644 --- a/src/input_common/touch_from_button.cpp +++ b/src/input_common/touch_from_button.cpp | |||
| @@ -26,8 +26,8 @@ public: | |||
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | Input::TouchStatus GetStatus() const override { | 28 | Input::TouchStatus GetStatus() const override { |
| 29 | Input::TouchStatus touch_status = {}; | 29 | Input::TouchStatus touch_status{}; |
| 30 | for (size_t id = 0; id < map.size() && id < touch_status.size(); id++) { | 30 | for (std::size_t id = 0; id < map.size() && id < touch_status.size(); ++id) { |
| 31 | const bool state = std::get<0>(map[id])->GetStatus(); | 31 | const bool state = std::get<0>(map[id])->GetStatus(); |
| 32 | if (state) { | 32 | if (state) { |
| 33 | const float x = static_cast<float>(std::get<1>(map[id])) / | 33 | const float x = static_cast<float>(std::get<1>(map[id])) / |
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index 53648cb53..5e39fdce2 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp | |||
| @@ -136,8 +136,8 @@ static void SocketLoop(Socket* socket) { | |||
| 136 | 136 | ||
| 137 | Client::Client() { | 137 | Client::Client() { |
| 138 | LOG_INFO(Input, "Udp Initialization started"); | 138 | LOG_INFO(Input, "Udp Initialization started"); |
| 139 | for (size_t id = 0; id < MAX_TOUCH_FINGERS; id++) { | 139 | for (std::size_t id = 0; id < MAX_TOUCH_FINGERS; ++id) { |
| 140 | finger_id[id] = MAX_UDP_CLIENTS * 2; | 140 | finger_id[id] = MAX_TOUCH_FINGERS; |
| 141 | } | 141 | } |
| 142 | ReloadSockets(); | 142 | ReloadSockets(); |
| 143 | } | 143 | } |
| @@ -262,7 +262,7 @@ void Client::OnPadData(Response::PadData data, std::size_t client) { | |||
| 262 | std::lock_guard guard(clients[client].status.update_mutex); | 262 | std::lock_guard guard(clients[client].status.update_mutex); |
| 263 | clients[client].status.motion_status = clients[client].motion.GetMotion(); | 263 | clients[client].status.motion_status = clients[client].motion.GetMotion(); |
| 264 | 264 | ||
| 265 | for (size_t id = 0; id < data.touch.size(); id++) { | 265 | for (std::size_t id = 0; id < data.touch.size(); ++id) { |
| 266 | UpdateTouchInput(data.touch[id], client, id); | 266 | UpdateTouchInput(data.touch[id], client, id); |
| 267 | } | 267 | } |
| 268 | 268 | ||
| @@ -314,7 +314,7 @@ void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& a | |||
| 314 | .port = clients[client].port, | 314 | .port = clients[client].port, |
| 315 | .pad_index = clients[client].pad_index, | 315 | .pad_index = clients[client].pad_index, |
| 316 | }; | 316 | }; |
| 317 | for (size_t i = 0; i < 3; ++i) { | 317 | for (std::size_t i = 0; i < 3; ++i) { |
| 318 | if (gyro[i] > 5.0f || gyro[i] < -5.0f) { | 318 | if (gyro[i] > 5.0f || gyro[i] < -5.0f) { |
| 319 | pad.motion = static_cast<PadMotion>(i); | 319 | pad.motion = static_cast<PadMotion>(i); |
| 320 | pad.motion_value = gyro[i]; | 320 | pad.motion_value = gyro[i]; |
| @@ -328,8 +328,8 @@ void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& a | |||
| 328 | } | 328 | } |
| 329 | } | 329 | } |
| 330 | 330 | ||
| 331 | std::optional<size_t> Client::GetUnusedFingerID() const { | 331 | std::optional<std::size_t> Client::GetUnusedFingerID() const { |
| 332 | size_t first_free_id = 0; | 332 | std::size_t first_free_id = 0; |
| 333 | while (first_free_id < MAX_TOUCH_FINGERS) { | 333 | while (first_free_id < MAX_TOUCH_FINGERS) { |
| 334 | if (!std::get<2>(touch_status[first_free_id])) { | 334 | if (!std::get<2>(touch_status[first_free_id])) { |
| 335 | return first_free_id; | 335 | return first_free_id; |
| @@ -340,7 +340,7 @@ std::optional<size_t> Client::GetUnusedFingerID() const { | |||
| 340 | return std::nullopt; | 340 | return std::nullopt; |
| 341 | } | 341 | } |
| 342 | 342 | ||
| 343 | void Client::UpdateTouchInput(Response::TouchPad& touch_pad, size_t client, size_t id) { | 343 | void Client::UpdateTouchInput(Response::TouchPad& touch_pad, std::size_t client, std::size_t id) { |
| 344 | // TODO: Use custom calibration per device | 344 | // TODO: Use custom calibration per device |
| 345 | const Common::ParamPackage touch_param(Settings::values.touch_device); | 345 | const Common::ParamPackage touch_param(Settings::values.touch_device); |
| 346 | const u16 min_x = static_cast<u16>(touch_param.Get("min_x", 100)); | 346 | const u16 min_x = static_cast<u16>(touch_param.Get("min_x", 100)); |
| @@ -367,10 +367,7 @@ void Client::UpdateTouchInput(Response::TouchPad& touch_pad, size_t client, size | |||
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | if (finger_id[client * 2 + id] != MAX_TOUCH_FINGERS) { | 369 | if (finger_id[client * 2 + id] != MAX_TOUCH_FINGERS) { |
| 370 | auto& [x, y, pressed] = touch_status[finger_id[client * 2 + id]]; | 370 | touch_status[finger_id[client * 2 + id]] = {}; |
| 371 | x = 0; | ||
| 372 | y = 0; | ||
| 373 | pressed = false; | ||
| 374 | finger_id[client * 2 + id] = MAX_TOUCH_FINGERS; | 371 | finger_id[client * 2 + id] = MAX_TOUCH_FINGERS; |
| 375 | } | 372 | } |
| 376 | } | 373 | } |
diff --git a/src/input_common/udp/client.h b/src/input_common/udp/client.h index 1cd251ec8..822f9c550 100644 --- a/src/input_common/udp/client.h +++ b/src/input_common/udp/client.h | |||
| @@ -28,8 +28,8 @@ class Socket; | |||
| 28 | namespace Response { | 28 | namespace Response { |
| 29 | struct PadData; | 29 | struct PadData; |
| 30 | struct PortInfo; | 30 | struct PortInfo; |
| 31 | struct Version; | ||
| 32 | struct TouchPad; | 31 | struct TouchPad; |
| 32 | struct Version; | ||
| 33 | } // namespace Response | 33 | } // namespace Response |
| 34 | 34 | ||
| 35 | enum class PadMotion { | 35 | enum class PadMotion { |
| @@ -129,10 +129,10 @@ private: | |||
| 129 | 129 | ||
| 130 | // Returns an unused finger id, if there is no fingers available std::nullopt will be | 130 | // Returns an unused finger id, if there is no fingers available std::nullopt will be |
| 131 | // returned | 131 | // returned |
| 132 | std::optional<size_t> GetUnusedFingerID() const; | 132 | std::optional<std::size_t> GetUnusedFingerID() const; |
| 133 | 133 | ||
| 134 | // Merges and updates all touch inputs into the touch_status array | 134 | // Merges and updates all touch inputs into the touch_status array |
| 135 | void UpdateTouchInput(Response::TouchPad& touch_pad, size_t client, size_t id); | 135 | void UpdateTouchInput(Response::TouchPad& touch_pad, std::size_t client, std::size_t id); |
| 136 | 136 | ||
| 137 | bool configuring = false; | 137 | bool configuring = false; |
| 138 | 138 | ||
| @@ -143,7 +143,7 @@ private: | |||
| 143 | std::array<ClientData, MAX_UDP_CLIENTS> clients{}; | 143 | std::array<ClientData, MAX_UDP_CLIENTS> clients{}; |
| 144 | Common::SPSCQueue<UDPPadStatus> pad_queue{}; | 144 | Common::SPSCQueue<UDPPadStatus> pad_queue{}; |
| 145 | Input::TouchStatus touch_status{}; | 145 | Input::TouchStatus touch_status{}; |
| 146 | std::array<size_t, MAX_TOUCH_FINGERS> finger_id{}; | 146 | std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{}; |
| 147 | }; | 147 | }; |
| 148 | 148 | ||
| 149 | /// An async job allowing configuration of the touchpad calibration. | 149 | /// An async job allowing configuration of the touchpad calibration. |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index e6c8f18af..1f91514ef 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -394,7 +394,7 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) { | |||
| 394 | input_subsystem->GetMouse()->PressButton(x, y, event->button()); | 394 | input_subsystem->GetMouse()->PressButton(x, y, event->button()); |
| 395 | 395 | ||
| 396 | if (event->button() == Qt::LeftButton) { | 396 | if (event->button() == Qt::LeftButton) { |
| 397 | this->TouchPressed(x, y); | 397 | this->TouchPressed(x, y, 0); |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | emit MouseActivity(); | 400 | emit MouseActivity(); |
| @@ -409,7 +409,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { | |||
| 409 | auto pos = event->pos(); | 409 | auto pos = event->pos(); |
| 410 | const auto [x, y] = ScaleTouch(pos); | 410 | const auto [x, y] = ScaleTouch(pos); |
| 411 | input_subsystem->GetMouse()->MouseMove(x, y); | 411 | input_subsystem->GetMouse()->MouseMove(x, y); |
| 412 | this->TouchMoved(x, y); | 412 | this->TouchMoved(x, y, 0); |
| 413 | 413 | ||
| 414 | emit MouseActivity(); | 414 | emit MouseActivity(); |
| 415 | } | 415 | } |
| @@ -423,36 +423,71 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { | |||
| 423 | input_subsystem->GetMouse()->ReleaseButton(event->button()); | 423 | input_subsystem->GetMouse()->ReleaseButton(event->button()); |
| 424 | 424 | ||
| 425 | if (event->button() == Qt::LeftButton) { | 425 | if (event->button() == Qt::LeftButton) { |
| 426 | this->TouchReleased(); | 426 | this->TouchReleased(0); |
| 427 | } | 427 | } |
| 428 | } | 428 | } |
| 429 | 429 | ||
| 430 | void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) { | 430 | void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) { |
| 431 | // TouchBegin always has exactly one touch point, so take the .first() | 431 | QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints(); |
| 432 | const auto [x, y] = ScaleTouch(event->touchPoints().first().pos()); | 432 | for (const auto& touch_point : touch_points) { |
| 433 | this->TouchPressed(x, y); | 433 | if (!TouchUpdate(touch_point)) { |
| 434 | TouchStart(touch_point); | ||
| 435 | } | ||
| 436 | } | ||
| 434 | } | 437 | } |
| 435 | 438 | ||
| 436 | void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) { | 439 | void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) { |
| 437 | QPointF pos; | 440 | QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints(); |
| 438 | int active_points = 0; | 441 | for (const auto& touch_point : touch_points) { |
| 439 | 442 | if (!TouchUpdate(touch_point)) { | |
| 440 | // average all active touch points | 443 | TouchStart(touch_point); |
| 441 | for (const auto& tp : event->touchPoints()) { | ||
| 442 | if (tp.state() & (Qt::TouchPointPressed | Qt::TouchPointMoved | Qt::TouchPointStationary)) { | ||
| 443 | active_points++; | ||
| 444 | pos += tp.pos(); | ||
| 445 | } | 444 | } |
| 446 | } | 445 | } |
| 446 | // Release all inactive points | ||
| 447 | for (std::size_t id = 0; id < touch_ids.size(); ++id) { | ||
| 448 | if (!TouchExist(touch_ids[id], touch_points)) { | ||
| 449 | touch_ids[id] = 0; | ||
| 450 | this->TouchReleased(id + 1); | ||
| 451 | } | ||
| 452 | } | ||
| 453 | } | ||
| 447 | 454 | ||
| 448 | pos /= active_points; | 455 | void GRenderWindow::TouchEndEvent() { |
| 456 | for (std::size_t id = 0; id < touch_ids.size(); ++id) { | ||
| 457 | if (touch_ids[id] != 0) { | ||
| 458 | touch_ids[id] = 0; | ||
| 459 | this->TouchReleased(id + 1); | ||
| 460 | } | ||
| 461 | } | ||
| 462 | } | ||
| 449 | 463 | ||
| 450 | const auto [x, y] = ScaleTouch(pos); | 464 | bool GRenderWindow::TouchStart(const QTouchEvent::TouchPoint& touch_point) { |
| 451 | this->TouchMoved(x, y); | 465 | for (std::size_t id = 0; id < touch_ids.size(); ++id) { |
| 466 | if (touch_ids[id] == 0) { | ||
| 467 | touch_ids[id] = touch_point.id() + 1; | ||
| 468 | const auto [x, y] = ScaleTouch(touch_point.pos()); | ||
| 469 | this->TouchPressed(x, y, id + 1); | ||
| 470 | return true; | ||
| 471 | } | ||
| 472 | } | ||
| 473 | return false; | ||
| 452 | } | 474 | } |
| 453 | 475 | ||
| 454 | void GRenderWindow::TouchEndEvent() { | 476 | bool GRenderWindow::TouchUpdate(const QTouchEvent::TouchPoint& touch_point) { |
| 455 | this->TouchReleased(); | 477 | for (std::size_t id = 0; id < touch_ids.size(); ++id) { |
| 478 | if (touch_ids[id] == touch_point.id() + 1) { | ||
| 479 | const auto [x, y] = ScaleTouch(touch_point.pos()); | ||
| 480 | this->TouchMoved(x, y, id + 1); | ||
| 481 | return true; | ||
| 482 | } | ||
| 483 | } | ||
| 484 | return false; | ||
| 485 | } | ||
| 486 | |||
| 487 | bool GRenderWindow::TouchExist(std::size_t id, | ||
| 488 | const QList<QTouchEvent::TouchPoint>& touch_points) const { | ||
| 489 | return std::any_of(touch_points.begin(), touch_points.end(), | ||
| 490 | [id](const auto& point) { return id == point.id() + 1; }); | ||
| 456 | } | 491 | } |
| 457 | 492 | ||
| 458 | bool GRenderWindow::event(QEvent* event) { | 493 | bool GRenderWindow::event(QEvent* event) { |
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 339095509..b5ec7de07 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include <QImage> | 12 | #include <QImage> |
| 13 | #include <QThread> | 13 | #include <QThread> |
| 14 | #include <QTouchEvent> | ||
| 14 | #include <QWidget> | 15 | #include <QWidget> |
| 15 | #include <QWindow> | 16 | #include <QWindow> |
| 16 | 17 | ||
| @@ -21,7 +22,6 @@ | |||
| 21 | class GRenderWindow; | 22 | class GRenderWindow; |
| 22 | class GMainWindow; | 23 | class GMainWindow; |
| 23 | class QKeyEvent; | 24 | class QKeyEvent; |
| 24 | class QTouchEvent; | ||
| 25 | class QStringList; | 25 | class QStringList; |
| 26 | 26 | ||
| 27 | namespace InputCommon { | 27 | namespace InputCommon { |
| @@ -191,6 +191,10 @@ private: | |||
| 191 | void TouchUpdateEvent(const QTouchEvent* event); | 191 | void TouchUpdateEvent(const QTouchEvent* event); |
| 192 | void TouchEndEvent(); | 192 | void TouchEndEvent(); |
| 193 | 193 | ||
| 194 | bool TouchStart(const QTouchEvent::TouchPoint& touch_point); | ||
| 195 | bool TouchUpdate(const QTouchEvent::TouchPoint& touch_point); | ||
| 196 | bool TouchExist(std::size_t id, const QList<QTouchEvent::TouchPoint>& touch_points) const; | ||
| 197 | |||
| 194 | void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override; | 198 | void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override; |
| 195 | 199 | ||
| 196 | bool InitializeOpenGL(); | 200 | bool InitializeOpenGL(); |
| @@ -215,6 +219,8 @@ private: | |||
| 215 | 219 | ||
| 216 | bool first_frame = false; | 220 | bool first_frame = false; |
| 217 | 221 | ||
| 222 | std::array<std::size_t, 16> touch_ids{}; | ||
| 223 | |||
| 218 | protected: | 224 | protected: |
| 219 | void showEvent(QShowEvent* event) override; | 225 | void showEvent(QShowEvent* event) override; |
| 220 | bool eventFilter(QObject* object, QEvent* event) override; | 226 | bool eventFilter(QObject* object, QEvent* event) override; |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index e32bed5e6..7843d5167 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | |||
| @@ -29,16 +29,16 @@ EmuWindow_SDL2::~EmuWindow_SDL2() { | |||
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { | 31 | void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { |
| 32 | TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); | 32 | TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0), 0); |
| 33 | input_subsystem->GetMouse()->MouseMove(x, y); | 33 | input_subsystem->GetMouse()->MouseMove(x, y); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { | 36 | void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { |
| 37 | if (button == SDL_BUTTON_LEFT) { | 37 | if (button == SDL_BUTTON_LEFT) { |
| 38 | if (state == SDL_PRESSED) { | 38 | if (state == SDL_PRESSED) { |
| 39 | TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); | 39 | TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0), 0); |
| 40 | } else { | 40 | } else { |
| 41 | TouchReleased(); | 41 | TouchReleased(0); |
| 42 | } | 42 | } |
| 43 | } else if (button == SDL_BUTTON_RIGHT) { | 43 | } else if (button == SDL_BUTTON_RIGHT) { |
| 44 | if (state == SDL_PRESSED) { | 44 | if (state == SDL_PRESSED) { |
| @@ -66,16 +66,16 @@ void EmuWindow_SDL2::OnFingerDown(float x, float y) { | |||
| 66 | // 3DS does | 66 | // 3DS does |
| 67 | 67 | ||
| 68 | const auto [px, py] = TouchToPixelPos(x, y); | 68 | const auto [px, py] = TouchToPixelPos(x, y); |
| 69 | TouchPressed(px, py); | 69 | TouchPressed(px, py, 0); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | void EmuWindow_SDL2::OnFingerMotion(float x, float y) { | 72 | void EmuWindow_SDL2::OnFingerMotion(float x, float y) { |
| 73 | const auto [px, py] = TouchToPixelPos(x, y); | 73 | const auto [px, py] = TouchToPixelPos(x, y); |
| 74 | TouchMoved(px, py); | 74 | TouchMoved(px, py, 0); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | void EmuWindow_SDL2::OnFingerUp() { | 77 | void EmuWindow_SDL2::OnFingerUp() { |
| 78 | TouchReleased(); | 78 | TouchReleased(0); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { | 81 | void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { |