summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hid/emulated_console.cpp15
-rw-r--r--src/core/hid/input_converter.cpp4
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.cpp6
-rw-r--r--src/input_common/drivers/touch_screen.cpp89
-rw-r--r--src/input_common/drivers/touch_screen.h52
-rw-r--r--src/yuzu/bootmanager.cpp58
-rw-r--r--src/yuzu/bootmanager.h6
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp2
8 files changed, 140 insertions, 92 deletions
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index fd220ccb5..aac45907d 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -27,12 +27,19 @@ void EmulatedConsole::SetTouchParams() {
27 // We can't use mouse as touch if native mouse is enabled 27 // We can't use mouse as touch if native mouse is enabled
28 touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"}; 28 touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"};
29 } 29 }
30 touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0"}; 30
31 touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1"}; 31 touch_params[index++] =
32 Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0,touch_id:0"};
33 touch_params[index++] =
34 Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1,touch_id:1"};
35 touch_params[index++] =
36 Common::ParamPackage{"engine:touch,axis_x:4,axis_y:5,button:2,touch_id:2"};
37 touch_params[index++] =
38 Common::ParamPackage{"engine:touch,axis_x:6,axis_y:7,button:3,touch_id:3"};
32 touch_params[index++] = 39 touch_params[index++] =
33 Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536"}; 40 Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536,touch_id:0"};
34 touch_params[index++] = 41 touch_params[index++] =
35 Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072"}; 42 Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072,touch_id:1"};
36 43
37 const auto button_index = 44 const auto button_index =
38 static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue()); 45 static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index 3c26260f3..18d9f042d 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <algorithm>
4#include <random> 5#include <random>
5 6
6#include "common/input.h" 7#include "common/input.h"
@@ -196,6 +197,9 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus&
196 x = std::clamp(x, 0.0f, 1.0f); 197 x = std::clamp(x, 0.0f, 1.0f);
197 y = std::clamp(y, 0.0f, 1.0f); 198 y = std::clamp(y, 0.0f, 1.0f);
198 199
200 // Limit id to maximum number of fingers
201 status.id = std::clamp(status.id, 0, 16);
202
199 if (status.pressed.inverted) { 203 if (status.pressed.inverted) {
200 status.pressed.value = !status.pressed.value; 204 status.pressed.value = !status.pressed.value;
201 } 205 }
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index 108ce5a41..1da8d3eb0 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -44,7 +44,6 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
44 for (std::size_t id = 0; id < MAX_FINGERS; id++) { 44 for (std::size_t id = 0; id < MAX_FINGERS; id++) {
45 const auto& current_touch = touch_status[id]; 45 const auto& current_touch = touch_status[id];
46 auto& finger = fingers[id]; 46 auto& finger = fingers[id];
47 finger.position = current_touch.position;
48 finger.id = current_touch.id; 47 finger.id = current_touch.id;
49 48
50 if (finger.attribute.start_touch) { 49 if (finger.attribute.start_touch) {
@@ -61,13 +60,18 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
61 if (!finger.pressed && current_touch.pressed) { 60 if (!finger.pressed && current_touch.pressed) {
62 finger.attribute.start_touch.Assign(1); 61 finger.attribute.start_touch.Assign(1);
63 finger.pressed = true; 62 finger.pressed = true;
63 finger.position = current_touch.position;
64 continue; 64 continue;
65 } 65 }
66 66
67 if (finger.pressed && !current_touch.pressed) { 67 if (finger.pressed && !current_touch.pressed) {
68 finger.attribute.raw = 0; 68 finger.attribute.raw = 0;
69 finger.attribute.end_touch.Assign(1); 69 finger.attribute.end_touch.Assign(1);
70 continue;
70 } 71 }
72
73 // Only update position if touch is not on a special frame
74 finger.position = current_touch.position;
71 } 75 }
72 76
73 std::array<Core::HID::TouchFinger, MAX_FINGERS> active_fingers; 77 std::array<Core::HID::TouchFinger, MAX_FINGERS> active_fingers;
diff --git a/src/input_common/drivers/touch_screen.cpp b/src/input_common/drivers/touch_screen.cpp
index 8acbe4584..1753e0893 100644
--- a/src/input_common/drivers/touch_screen.cpp
+++ b/src/input_common/drivers/touch_screen.cpp
@@ -14,38 +14,93 @@ constexpr PadIdentifier identifier = {
14 14
15TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) { 15TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
16 PreSetController(identifier); 16 PreSetController(identifier);
17 ReleaseAllTouch();
17} 18}
18 19
19void TouchScreen::TouchMoved(float x, float y, std::size_t finger) { 20void TouchScreen::TouchMoved(float x, float y, std::size_t finger_id) {
20 if (finger >= 16) { 21 const auto index = GetIndexFromFingerId(finger_id);
22 if (!index) {
23 // Touch doesn't exist handle it as a new one
24 TouchPressed(x, y, finger_id);
21 return; 25 return;
22 } 26 }
23 TouchPressed(x, y, finger); 27 const auto i = index.value();
28 fingers[i].is_active = true;
29 SetButton(identifier, static_cast<int>(i), true);
30 SetAxis(identifier, static_cast<int>(i * 2), x);
31 SetAxis(identifier, static_cast<int>(i * 2 + 1), y);
24} 32}
25 33
26void TouchScreen::TouchPressed(float x, float y, std::size_t finger) { 34void TouchScreen::TouchPressed(float x, float y, std::size_t finger_id) {
27 if (finger >= 16) { 35 if (GetIndexFromFingerId(finger_id)) {
36 // Touch already exist. Just update the data
37 TouchMoved(x, y, finger_id);
28 return; 38 return;
29 } 39 }
30 SetButton(identifier, static_cast<int>(finger), true); 40 const auto index = GetNextFreeIndex();
31 SetAxis(identifier, static_cast<int>(finger * 2), x); 41 if (!index) {
32 SetAxis(identifier, static_cast<int>(finger * 2 + 1), y); 42 // No free entries. Ignore input
43 return;
44 }
45 const auto i = index.value();
46 fingers[i].is_enabled = true;
47 fingers[i].finger_id = finger_id;
48 TouchMoved(x, y, finger_id);
33} 49}
34 50
35void TouchScreen::TouchReleased(std::size_t finger) { 51void TouchScreen::TouchReleased(std::size_t finger_id) {
36 if (finger >= 16) { 52 const auto index = GetIndexFromFingerId(finger_id);
53 if (!index) {
37 return; 54 return;
38 } 55 }
39 SetButton(identifier, static_cast<int>(finger), false); 56 const auto i = index.value();
40 SetAxis(identifier, static_cast<int>(finger * 2), 0.0f); 57 fingers[i].is_enabled = false;
41 SetAxis(identifier, static_cast<int>(finger * 2 + 1), 0.0f); 58 SetButton(identifier, static_cast<int>(i), false);
59 SetAxis(identifier, static_cast<int>(i * 2), 0.0f);
60 SetAxis(identifier, static_cast<int>(i * 2 + 1), 0.0f);
61}
62
63std::optional<std::size_t> TouchScreen::GetIndexFromFingerId(std::size_t finger_id) const {
64 for (std::size_t index = 0; index < MAX_FINGER_COUNT; ++index) {
65 const auto& finger = fingers[index];
66 if (!finger.is_enabled) {
67 continue;
68 }
69 if (finger.finger_id == finger_id) {
70 return index;
71 }
72 }
73 return std::nullopt;
74}
75
76std::optional<std::size_t> TouchScreen::GetNextFreeIndex() const {
77 for (std::size_t index = 0; index < MAX_FINGER_COUNT; ++index) {
78 if (!fingers[index].is_enabled) {
79 return index;
80 }
81 }
82 return std::nullopt;
83}
84
85void TouchScreen::ClearActiveFlag() {
86 for (auto& finger : fingers) {
87 finger.is_active = false;
88 }
89}
90
91void TouchScreen::ReleaseInactiveTouch() {
92 for (const auto& finger : fingers) {
93 if (!finger.is_active) {
94 TouchReleased(finger.finger_id);
95 }
96 }
42} 97}
43 98
44void TouchScreen::ReleaseAllTouch() { 99void TouchScreen::ReleaseAllTouch() {
45 for (int index = 0; index < 16; ++index) { 100 for (const auto& finger : fingers) {
46 SetButton(identifier, index, false); 101 if (finger.is_enabled) {
47 SetAxis(identifier, index * 2, 0.0f); 102 TouchReleased(finger.finger_id);
48 SetAxis(identifier, index * 2 + 1, 0.0f); 103 }
49 } 104 }
50} 105}
51 106
diff --git a/src/input_common/drivers/touch_screen.h b/src/input_common/drivers/touch_screen.h
index 193478ead..f46036ffd 100644
--- a/src/input_common/drivers/touch_screen.h
+++ b/src/input_common/drivers/touch_screen.h
@@ -3,41 +3,65 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <optional>
7
6#include "input_common/input_engine.h" 8#include "input_common/input_engine.h"
7 9
8namespace InputCommon { 10namespace InputCommon {
9 11
10/** 12/**
11 * A button device factory representing a keyboard. It receives keyboard events and forward them 13 * A touch device factory representing a touch screen. It receives touch events and forward them
12 * to all button devices it created. 14 * to all touch devices it created.
13 */ 15 */
14class TouchScreen final : public InputEngine { 16class TouchScreen final : public InputEngine {
15public: 17public:
16 explicit TouchScreen(std::string input_engine_); 18 explicit TouchScreen(std::string input_engine_);
17 19
18 /** 20 /**
19 * Signals that mouse has moved. 21 * Signals that touch has moved and marks this touch point as active
20 * @param x the x-coordinate of the cursor 22 * @param x new horizontal position
21 * @param y the y-coordinate of the cursor 23 * @param y new vertical position
22 * @param center_x the x-coordinate of the middle of the screen 24 * @param finger_id of the touch point to be updated
23 * @param center_y the y-coordinate of the middle of the screen
24 */ 25 */
25 void TouchMoved(float x, float y, std::size_t finger); 26 void TouchMoved(float x, float y, std::size_t finger_id);
26 27
27 /** 28 /**
28 * Sets the status of all buttons bound with the key to pressed 29 * Signals and creates a new touch point with this finger id
29 * @param key_code the code of the key to press 30 * @param x starting horizontal position
31 * @param y starting vertical position
32 * @param finger_id to be assigned to the new touch point
30 */ 33 */
31 void TouchPressed(float x, float y, std::size_t finger); 34 void TouchPressed(float x, float y, std::size_t finger_id);
32 35
33 /** 36 /**
34 * Sets the status of all buttons bound with the key to released 37 * Signals and resets the touch point related to the this finger id
35 * @param key_code the code of the key to release 38 * @param finger_id to be released
36 */ 39 */
37 void TouchReleased(std::size_t finger); 40 void TouchReleased(std::size_t finger_id);
41
42 /// Resets the active flag for each touch point
43 void ClearActiveFlag();
44
45 /// Releases all touch that haven't been marked as active
46 void ReleaseInactiveTouch();
38 47
39 /// Resets all inputs to their initial value 48 /// Resets all inputs to their initial value
40 void ReleaseAllTouch(); 49 void ReleaseAllTouch();
50
51private:
52 static constexpr std::size_t MAX_FINGER_COUNT = 16;
53
54 struct TouchStatus {
55 std::size_t finger_id{};
56 bool is_enabled{};
57 bool is_active{};
58 };
59
60 std::optional<std::size_t> GetIndexFromFingerId(std::size_t finger_id) const;
61
62 std::optional<std::size_t> GetNextFreeIndex() const;
63
64 std::array<TouchStatus, MAX_FINGER_COUNT> fingers{};
41}; 65};
42 66
43} // namespace InputCommon 67} // namespace InputCommon
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index a1b819ae0..8f0a6bbb8 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -772,65 +772,25 @@ void GRenderWindow::wheelEvent(QWheelEvent* event) {
772void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) { 772void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) {
773 QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints(); 773 QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints();
774 for (const auto& touch_point : touch_points) { 774 for (const auto& touch_point : touch_points) {
775 if (!TouchUpdate(touch_point)) { 775 const auto [x, y] = ScaleTouch(touch_point.pos());
776 TouchStart(touch_point); 776 const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
777 } 777 input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, touch_point.id());
778 } 778 }
779} 779}
780 780
781void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) { 781void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) {
782 QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints(); 782 QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints();
783 input_subsystem->GetTouchScreen()->ClearActiveFlag();
783 for (const auto& touch_point : touch_points) { 784 for (const auto& touch_point : touch_points) {
784 if (!TouchUpdate(touch_point)) { 785 const auto [x, y] = ScaleTouch(touch_point.pos());
785 TouchStart(touch_point); 786 const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
786 } 787 input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, touch_point.id());
787 }
788 // Release all inactive points
789 for (std::size_t id = 0; id < touch_ids.size(); ++id) {
790 if (!TouchExist(touch_ids[id], touch_points)) {
791 touch_ids[id] = 0;
792 input_subsystem->GetTouchScreen()->TouchReleased(id);
793 }
794 } 788 }
789 input_subsystem->GetTouchScreen()->ReleaseInactiveTouch();
795} 790}
796 791
797void GRenderWindow::TouchEndEvent() { 792void GRenderWindow::TouchEndEvent() {
798 for (std::size_t id = 0; id < touch_ids.size(); ++id) { 793 input_subsystem->GetTouchScreen()->ReleaseAllTouch();
799 if (touch_ids[id] != 0) {
800 touch_ids[id] = 0;
801 input_subsystem->GetTouchScreen()->TouchReleased(id);
802 }
803 }
804}
805
806void GRenderWindow::TouchStart(const QTouchEvent::TouchPoint& touch_point) {
807 for (std::size_t id = 0; id < touch_ids.size(); ++id) {
808 if (touch_ids[id] == 0) {
809 touch_ids[id] = touch_point.id() + 1;
810 const auto [x, y] = ScaleTouch(touch_point.pos());
811 const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
812 input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id);
813 }
814 }
815}
816
817bool GRenderWindow::TouchUpdate(const QTouchEvent::TouchPoint& touch_point) {
818 for (std::size_t id = 0; id < touch_ids.size(); ++id) {
819 if (touch_ids[id] == static_cast<std::size_t>(touch_point.id() + 1)) {
820 const auto [x, y] = ScaleTouch(touch_point.pos());
821 const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
822 input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id);
823 return true;
824 }
825 }
826 return false;
827}
828
829bool GRenderWindow::TouchExist(std::size_t id,
830 const QList<QTouchEvent::TouchPoint>& touch_points) const {
831 return std::any_of(touch_points.begin(), touch_points.end(), [id](const auto& point) {
832 return id == static_cast<std::size_t>(point.id() + 1);
833 });
834} 794}
835 795
836bool GRenderWindow::event(QEvent* event) { 796bool GRenderWindow::event(QEvent* event) {
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 4b0ce0293..841816564 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -217,10 +217,6 @@ private:
217 void TouchUpdateEvent(const QTouchEvent* event); 217 void TouchUpdateEvent(const QTouchEvent* event);
218 void TouchEndEvent(); 218 void TouchEndEvent();
219 219
220 void TouchStart(const QTouchEvent::TouchPoint& touch_point);
221 bool TouchUpdate(const QTouchEvent::TouchPoint& touch_point);
222 bool TouchExist(std::size_t id, const QList<QTouchEvent::TouchPoint>& touch_points) const;
223
224 void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override; 220 void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override;
225 221
226 bool InitializeOpenGL(); 222 bool InitializeOpenGL();
@@ -246,8 +242,6 @@ private:
246 bool first_frame = false; 242 bool first_frame = false;
247 InputCommon::TasInput::TasState last_tas_state; 243 InputCommon::TasInput::TasState last_tas_state;
248 244
249 std::array<std::size_t, 16> touch_ids{};
250
251 Core::System& system; 245 Core::System& system;
252 246
253protected: 247protected:
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index ae2e62dc5..71c413e64 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -93,7 +93,7 @@ void EmuWindow_SDL2::OnFingerMotion(float x, float y, std::size_t id) {
93} 93}
94 94
95void EmuWindow_SDL2::OnFingerUp() { 95void EmuWindow_SDL2::OnFingerUp() {
96 input_subsystem->GetTouchScreen()->TouchReleased(0); 96 input_subsystem->GetTouchScreen()->ReleaseAllTouch();
97} 97}
98 98
99void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { 99void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {