summaryrefslogtreecommitdiff
path: root/src/input_common
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common')
-rw-r--r--src/input_common/drivers/sdl_driver.cpp23
-rw-r--r--src/input_common/drivers/sdl_driver.h12
-rw-r--r--src/input_common/drivers/touch_screen.cpp89
-rw-r--r--src/input_common/drivers/touch_screen.h52
4 files changed, 143 insertions, 33 deletions
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index a5c63e74a..1a14ef10b 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -434,6 +434,7 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en
434 using namespace std::chrono_literals; 434 using namespace std::chrono_literals;
435 while (initialized) { 435 while (initialized) {
436 SDL_PumpEvents(); 436 SDL_PumpEvents();
437 SendVibrations();
437 std::this_thread::sleep_for(1ms); 438 std::this_thread::sleep_for(1ms);
438 } 439 }
439 }); 440 });
@@ -531,13 +532,31 @@ Common::Input::VibrationError SDLDriver::SetRumble(
531 .type = Common::Input::VibrationAmplificationType::Exponential, 532 .type = Common::Input::VibrationAmplificationType::Exponential,
532 }; 533 };
533 534
534 if (!joystick->RumblePlay(new_vibration)) { 535 if (vibration.type == Common::Input::VibrationAmplificationType::Test) {
535 return Common::Input::VibrationError::Unknown; 536 if (!joystick->RumblePlay(new_vibration)) {
537 return Common::Input::VibrationError::Unknown;
538 }
539 return Common::Input::VibrationError::None;
536 } 540 }
537 541
542 vibration_queue.Push(VibrationRequest{
543 .identifier = identifier,
544 .vibration = new_vibration,
545 });
546
538 return Common::Input::VibrationError::None; 547 return Common::Input::VibrationError::None;
539} 548}
540 549
550void SDLDriver::SendVibrations() {
551 while (!vibration_queue.Empty()) {
552 VibrationRequest request;
553 vibration_queue.Pop(request);
554 const auto joystick = GetSDLJoystickByGUID(request.identifier.guid.RawString(),
555 static_cast<int>(request.identifier.port));
556 joystick->RumblePlay(request.vibration);
557 }
558}
559
541Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid, 560Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid,
542 s32 axis, float value) const { 561 s32 axis, float value) const {
543 Common::ParamPackage params{}; 562 Common::ParamPackage params{};
diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h
index dcd0d1e64..c82632506 100644
--- a/src/input_common/drivers/sdl_driver.h
+++ b/src/input_common/drivers/sdl_driver.h
@@ -12,6 +12,7 @@
12#include <SDL.h> 12#include <SDL.h>
13 13
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "common/threadsafe_queue.h"
15#include "input_common/input_engine.h" 16#include "input_common/input_engine.h"
16 17
17union SDL_Event; 18union SDL_Event;
@@ -64,12 +65,20 @@ public:
64 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; 65 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
65 66
66private: 67private:
68 struct VibrationRequest {
69 PadIdentifier identifier;
70 Common::Input::VibrationStatus vibration;
71 };
72
67 void InitJoystick(int joystick_index); 73 void InitJoystick(int joystick_index);
68 void CloseJoystick(SDL_Joystick* sdl_joystick); 74 void CloseJoystick(SDL_Joystick* sdl_joystick);
69 75
70 /// Needs to be called before SDL_QuitSubSystem. 76 /// Needs to be called before SDL_QuitSubSystem.
71 void CloseJoysticks(); 77 void CloseJoysticks();
72 78
79 /// Takes all vibrations from the queue and sends the command to the controller
80 void SendVibrations();
81
73 Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, 82 Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis,
74 float value = 0.1f) const; 83 float value = 0.1f) const;
75 Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, 84 Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid,
@@ -107,6 +116,9 @@ private:
107 /// Returns true if the button is on the left joycon 116 /// Returns true if the button is on the left joycon
108 bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const; 117 bool IsButtonOnLeftSide(Settings::NativeButton::Values button) const;
109 118
119 /// Queue of vibration request to controllers
120 Common::SPSCQueue<VibrationRequest> vibration_queue;
121
110 /// Map of GUID of a list of corresponding virtual Joysticks 122 /// Map of GUID of a list of corresponding virtual Joysticks
111 std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map; 123 std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map;
112 std::mutex joystick_map_mutex; 124 std::mutex joystick_map_mutex;
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