summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/citra/CMakeLists.txt2
-rw-r--r--src/citra/config.cpp25
-rw-r--r--src/citra/emu_window/emu_window_sdl2.cpp21
-rw-r--r--src/citra/emu_window/emu_window_sdl2.h6
-rw-r--r--src/citra_qt/CMakeLists.txt2
-rw-r--r--src/citra_qt/bootmanager.cpp25
-rw-r--r--src/citra_qt/bootmanager.h6
-rw-r--r--src/citra_qt/config.cpp35
-rw-r--r--src/citra_qt/config.h3
-rw-r--r--src/citra_qt/configure_input.cpp9
-rw-r--r--src/core/frontend/emu_window.h2
-rw-r--r--src/input_common/CMakeLists.txt15
-rw-r--r--src/input_common/keyboard.cpp82
-rw-r--r--src/input_common/keyboard.h45
-rw-r--r--src/input_common/main.cpp35
-rw-r--r--src/input_common/main.h25
17 files changed, 254 insertions, 85 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1e1245160..a45439481 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,6 +5,7 @@ add_subdirectory(common)
5add_subdirectory(core) 5add_subdirectory(core)
6add_subdirectory(video_core) 6add_subdirectory(video_core)
7add_subdirectory(audio_core) 7add_subdirectory(audio_core)
8add_subdirectory(input_common)
8add_subdirectory(tests) 9add_subdirectory(tests)
9if (ENABLE_SDL2) 10if (ENABLE_SDL2)
10 add_subdirectory(citra) 11 add_subdirectory(citra)
diff --git a/src/citra/CMakeLists.txt b/src/citra/CMakeLists.txt
index ecb5d2dfe..47231ba71 100644
--- a/src/citra/CMakeLists.txt
+++ b/src/citra/CMakeLists.txt
@@ -18,7 +18,7 @@ create_directory_groups(${SRCS} ${HEADERS})
18include_directories(${SDL2_INCLUDE_DIR}) 18include_directories(${SDL2_INCLUDE_DIR})
19 19
20add_executable(citra ${SRCS} ${HEADERS}) 20add_executable(citra ${SRCS} ${HEADERS})
21target_link_libraries(citra core video_core audio_core common) 21target_link_libraries(citra core video_core audio_core common input_common)
22target_link_libraries(citra ${SDL2_LIBRARY} ${OPENGL_gl_LIBRARY} inih glad) 22target_link_libraries(citra ${SDL2_LIBRARY} ${OPENGL_gl_LIBRARY} inih glad)
23if (MSVC) 23if (MSVC)
24 target_link_libraries(citra getopt) 24 target_link_libraries(citra getopt)
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index fac1c9a0e..818824596 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -10,6 +10,7 @@
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "config.h" 11#include "config.h"
12#include "core/settings.h" 12#include "core/settings.h"
13#include "input_common/main.h"
13 14
14Config::Config() { 15Config::Config() {
15 // TODO: Don't hardcode the path; let the frontend decide where to put the config files. 16 // TODO: Don't hardcode the path; let the frontend decide where to put the config files.
@@ -37,25 +38,21 @@ bool Config::LoadINI(const std::string& default_contents, bool retry) {
37 return true; 38 return true;
38} 39}
39 40
40static const std::array<int, Settings::NativeInput::NUM_INPUTS> defaults = { 41static const std::array<int, Settings::NativeButton::NumButtons> default_buttons = {
41 // directly mapped keys 42 SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_T,
42 SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_Q, SDL_SCANCODE_W, 43 SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, SDL_SCANCODE_Q, SDL_SCANCODE_W,
43 SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_B, SDL_SCANCODE_T, 44 SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B,
44 SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, SDL_SCANCODE_I, SDL_SCANCODE_K, SDL_SCANCODE_J,
45 SDL_SCANCODE_L,
46
47 // indirectly mapped keys
48 SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_D,
49}; 45};
50 46
51void Config::ReadValues() { 47void Config::ReadValues() {
52 // Controls 48 // Controls
53 for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { 49 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
54 Settings::values.input_mappings[Settings::NativeInput::All[i]] = 50 std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
55 sdl2_config->GetInteger("Controls", Settings::NativeInput::Mapping[i], defaults[i]); 51 Settings::values.buttons[i] =
52 sdl2_config->Get("Controls", Settings::NativeButton::mapping[i], default_param);
53 if (Settings::values.buttons[i].empty())
54 Settings::values.buttons[i] = default_param;
56 } 55 }
57 Settings::values.pad_circle_modifier_scale =
58 (float)sdl2_config->GetReal("Controls", "pad_circle_modifier_scale", 0.5);
59 56
60 // Core 57 // Core
61 Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true); 58 Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true);
diff --git a/src/citra/emu_window/emu_window_sdl2.cpp b/src/citra/emu_window/emu_window_sdl2.cpp
index 00d00905a..6bc0b0d00 100644
--- a/src/citra/emu_window/emu_window_sdl2.cpp
+++ b/src/citra/emu_window/emu_window_sdl2.cpp
@@ -12,9 +12,9 @@
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "common/scm_rev.h" 13#include "common/scm_rev.h"
14#include "common/string_util.h" 14#include "common/string_util.h"
15#include "core/frontend/key_map.h"
16#include "core/hle/service/hid/hid.h"
17#include "core/settings.h" 15#include "core/settings.h"
16#include "input_common/keyboard.h"
17#include "input_common/main.h"
18#include "video_core/video_core.h" 18#include "video_core/video_core.h"
19 19
20void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { 20void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
@@ -40,9 +40,9 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
40 40
41void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { 41void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {
42 if (state == SDL_PRESSED) { 42 if (state == SDL_PRESSED) {
43 KeyMap::PressKey(*this, {key, keyboard_id}); 43 InputCommon::GetKeyboard()->PressKey(key);
44 } else if (state == SDL_RELEASED) { 44 } else if (state == SDL_RELEASED) {
45 KeyMap::ReleaseKey(*this, {key, keyboard_id}); 45 InputCommon::GetKeyboard()->ReleaseKey(key);
46 } 46 }
47} 47}
48 48
@@ -57,9 +57,8 @@ void EmuWindow_SDL2::OnResize() {
57} 57}
58 58
59EmuWindow_SDL2::EmuWindow_SDL2() { 59EmuWindow_SDL2::EmuWindow_SDL2() {
60 keyboard_id = KeyMap::NewDeviceId(); 60 InputCommon::Init();
61 61
62 ReloadSetKeymaps();
63 motion_emu = std::make_unique<Motion::MotionEmu>(*this); 62 motion_emu = std::make_unique<Motion::MotionEmu>(*this);
64 63
65 SDL_SetMainReady(); 64 SDL_SetMainReady();
@@ -117,6 +116,7 @@ EmuWindow_SDL2::~EmuWindow_SDL2() {
117 SDL_GL_DeleteContext(gl_context); 116 SDL_GL_DeleteContext(gl_context);
118 SDL_Quit(); 117 SDL_Quit();
119 motion_emu = nullptr; 118 motion_emu = nullptr;
119 InputCommon::Shutdown();
120} 120}
121 121
122void EmuWindow_SDL2::SwapBuffers() { 122void EmuWindow_SDL2::SwapBuffers() {
@@ -169,15 +169,6 @@ void EmuWindow_SDL2::DoneCurrent() {
169 SDL_GL_MakeCurrent(render_window, nullptr); 169 SDL_GL_MakeCurrent(render_window, nullptr);
170} 170}
171 171
172void EmuWindow_SDL2::ReloadSetKeymaps() {
173 KeyMap::ClearKeyMapping(keyboard_id);
174 for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
175 KeyMap::SetKeyMapping(
176 {Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id},
177 KeyMap::mapping_targets[i]);
178 }
179}
180
181void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest( 172void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(
182 const std::pair<unsigned, unsigned>& minimal_size) { 173 const std::pair<unsigned, unsigned>& minimal_size) {
183 174
diff --git a/src/citra/emu_window/emu_window_sdl2.h b/src/citra/emu_window/emu_window_sdl2.h
index b1cbf16d7..1ce2991f7 100644
--- a/src/citra/emu_window/emu_window_sdl2.h
+++ b/src/citra/emu_window/emu_window_sdl2.h
@@ -31,9 +31,6 @@ public:
31 /// Whether the window is still open, and a close request hasn't yet been sent 31 /// Whether the window is still open, and a close request hasn't yet been sent
32 bool IsOpen() const; 32 bool IsOpen() const;
33 33
34 /// Load keymap from configuration
35 void ReloadSetKeymaps() override;
36
37private: 34private:
38 /// Called by PollEvents when a key is pressed or released. 35 /// Called by PollEvents when a key is pressed or released.
39 void OnKeyEvent(int key, u8 state); 36 void OnKeyEvent(int key, u8 state);
@@ -61,9 +58,6 @@ private:
61 /// The OpenGL context associated with the window 58 /// The OpenGL context associated with the window
62 SDL_GLContext gl_context; 59 SDL_GLContext gl_context;
63 60
64 /// Device id of keyboard for use with KeyMap
65 int keyboard_id;
66
67 /// Motion sensors emulation 61 /// Motion sensors emulation
68 std::unique_ptr<Motion::MotionEmu> motion_emu; 62 std::unique_ptr<Motion::MotionEmu> motion_emu;
69}; 63};
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt
index 15a6ccf9a..2b1c59a92 100644
--- a/src/citra_qt/CMakeLists.txt
+++ b/src/citra_qt/CMakeLists.txt
@@ -97,7 +97,7 @@ if (APPLE)
97else() 97else()
98 add_executable(citra-qt ${SRCS} ${HEADERS} ${UI_HDRS}) 98 add_executable(citra-qt ${SRCS} ${HEADERS} ${UI_HDRS})
99endif() 99endif()
100target_link_libraries(citra-qt core video_core audio_core common) 100target_link_libraries(citra-qt core video_core audio_core common input_common)
101target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS}) 101target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS})
102target_link_libraries(citra-qt ${PLATFORM_LIBRARIES} Threads::Threads) 102target_link_libraries(citra-qt ${PLATFORM_LIBRARIES} Threads::Threads)
103 103
diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index 69d18cf0c..66c883d9a 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -13,7 +13,8 @@
13#include "common/scm_rev.h" 13#include "common/scm_rev.h"
14#include "common/string_util.h" 14#include "common/string_util.h"
15#include "core/core.h" 15#include "core/core.h"
16#include "core/frontend/key_map.h" 16#include "input_common/keyboard.h"
17#include "input_common/main.h"
17#include "video_core/debug_utils/debug_utils.h" 18#include "video_core/debug_utils/debug_utils.h"
18#include "video_core/video_core.h" 19#include "video_core/video_core.h"
19 20
@@ -99,14 +100,17 @@ private:
99}; 100};
100 101
101GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) 102GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread)
102 : QWidget(parent), child(nullptr), keyboard_id(0), emu_thread(emu_thread) { 103 : QWidget(parent), child(nullptr), emu_thread(emu_thread) {
103 104
104 std::string window_title = Common::StringFromFormat("Citra %s| %s-%s", Common::g_build_name, 105 std::string window_title = Common::StringFromFormat("Citra %s| %s-%s", Common::g_build_name,
105 Common::g_scm_branch, Common::g_scm_desc); 106 Common::g_scm_branch, Common::g_scm_desc);
106 setWindowTitle(QString::fromStdString(window_title)); 107 setWindowTitle(QString::fromStdString(window_title));
107 108
108 keyboard_id = KeyMap::NewDeviceId(); 109 InputCommon::Init();
109 ReloadSetKeymaps(); 110}
111
112GRenderWindow::~GRenderWindow() {
113 InputCommon::Shutdown();
110} 114}
111 115
112void GRenderWindow::moveContext() { 116void GRenderWindow::moveContext() {
@@ -197,11 +201,11 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
197} 201}
198 202
199void GRenderWindow::keyPressEvent(QKeyEvent* event) { 203void GRenderWindow::keyPressEvent(QKeyEvent* event) {
200 KeyMap::PressKey(*this, {event->key(), keyboard_id}); 204 InputCommon::GetKeyboard()->PressKey(event->key());
201} 205}
202 206
203void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { 207void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
204 KeyMap::ReleaseKey(*this, {event->key(), keyboard_id}); 208 InputCommon::GetKeyboard()->ReleaseKey(event->key());
205} 209}
206 210
207void GRenderWindow::mousePressEvent(QMouseEvent* event) { 211void GRenderWindow::mousePressEvent(QMouseEvent* event) {
@@ -230,14 +234,7 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
230 motion_emu->EndTilt(); 234 motion_emu->EndTilt();
231} 235}
232 236
233void GRenderWindow::ReloadSetKeymaps() { 237void GRenderWindow::ReloadSetKeymaps() {}
234 KeyMap::ClearKeyMapping(keyboard_id);
235 for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
236 KeyMap::SetKeyMapping(
237 {Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id},
238 KeyMap::mapping_targets[i]);
239 }
240}
241 238
242void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) { 239void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) {
243 NotifyClientAreaSizeChanged(std::make_pair(width, height)); 240 NotifyClientAreaSizeChanged(std::make_pair(width, height));
diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h
index 7dac1c480..923a5b456 100644
--- a/src/citra_qt/bootmanager.h
+++ b/src/citra_qt/bootmanager.h
@@ -104,6 +104,7 @@ class GRenderWindow : public QWidget, public EmuWindow {
104 104
105public: 105public:
106 GRenderWindow(QWidget* parent, EmuThread* emu_thread); 106 GRenderWindow(QWidget* parent, EmuThread* emu_thread);
107 ~GRenderWindow();
107 108
108 // EmuWindow implementation 109 // EmuWindow implementation
109 void SwapBuffers() override; 110 void SwapBuffers() override;
@@ -127,7 +128,7 @@ public:
127 void mouseMoveEvent(QMouseEvent* event) override; 128 void mouseMoveEvent(QMouseEvent* event) override;
128 void mouseReleaseEvent(QMouseEvent* event) override; 129 void mouseReleaseEvent(QMouseEvent* event) override;
129 130
130 void ReloadSetKeymaps() override; 131 void ReloadSetKeymaps();
131 132
132 void OnClientAreaResized(unsigned width, unsigned height); 133 void OnClientAreaResized(unsigned width, unsigned height);
133 134
@@ -152,9 +153,6 @@ private:
152 153
153 QByteArray geometry; 154 QByteArray geometry;
154 155
155 /// Device id of keyboard for use with KeyMap
156 int keyboard_id;
157
158 EmuThread* emu_thread; 156 EmuThread* emu_thread;
159 157
160 /// Motion sensors emulation 158 /// Motion sensors emulation
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index 5fe57dfa2..5855c7105 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -6,6 +6,7 @@
6#include "citra_qt/config.h" 6#include "citra_qt/config.h"
7#include "citra_qt/ui_settings.h" 7#include "citra_qt/ui_settings.h"
8#include "common/file_util.h" 8#include "common/file_util.h"
9#include "input_common/main.h"
9 10
10Config::Config() { 11Config::Config() {
11 // TODO: Don't hardcode the path; let the frontend decide where to put the config files. 12 // TODO: Don't hardcode the path; let the frontend decide where to put the config files.
@@ -16,25 +17,23 @@ Config::Config() {
16 Reload(); 17 Reload();
17} 18}
18 19
19const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> Config::defaults = { 20const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = {
20 // directly mapped keys 21 Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_T, Qt::Key_G, Qt::Key_F, Qt::Key_H,
21 Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_Q, Qt::Key_W, Qt::Key_1, Qt::Key_2, 22 Qt::Key_Q, Qt::Key_W, Qt::Key_M, Qt::Key_N, Qt::Key_1, Qt::Key_2, Qt::Key_B,
22 Qt::Key_M, Qt::Key_N, Qt::Key_B, Qt::Key_T, Qt::Key_G, Qt::Key_F, Qt::Key_H, Qt::Key_I,
23 Qt::Key_K, Qt::Key_J, Qt::Key_L,
24
25 // indirectly mapped keys
26 Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, Qt::Key_D,
27}; 23};
28 24
29void Config::ReadValues() { 25void Config::ReadValues() {
30 qt_config->beginGroup("Controls"); 26 qt_config->beginGroup("Controls");
31 for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { 27 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
32 Settings::values.input_mappings[Settings::NativeInput::All[i]] = 28 std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
33 qt_config->value(QString::fromStdString(Settings::NativeInput::Mapping[i]), defaults[i]) 29 Settings::values.buttons[i] =
34 .toInt(); 30 qt_config
31 ->value(Settings::NativeButton::mapping[i], QString::fromStdString(default_param))
32 .toString()
33 .toStdString();
34 if (Settings::values.buttons[i].empty())
35 Settings::values.buttons[i] = default_param;
35 } 36 }
36 Settings::values.pad_circle_modifier_scale =
37 qt_config->value("pad_circle_modifier_scale", 0.5).toFloat();
38 qt_config->endGroup(); 37 qt_config->endGroup();
39 38
40 qt_config->beginGroup("Core"); 39 qt_config->beginGroup("Core");
@@ -155,12 +154,10 @@ void Config::ReadValues() {
155 154
156void Config::SaveValues() { 155void Config::SaveValues() {
157 qt_config->beginGroup("Controls"); 156 qt_config->beginGroup("Controls");
158 for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { 157 for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
159 qt_config->setValue(QString::fromStdString(Settings::NativeInput::Mapping[i]), 158 qt_config->setValue(QString::fromStdString(Settings::NativeButton::mapping[i]),
160 Settings::values.input_mappings[Settings::NativeInput::All[i]]); 159 QString::fromStdString(Settings::values.buttons[i]));
161 } 160 }
162 qt_config->setValue("pad_circle_modifier_scale",
163 (double)Settings::values.pad_circle_modifier_scale);
164 qt_config->endGroup(); 161 qt_config->endGroup();
165 162
166 qt_config->beginGroup("Core"); 163 qt_config->beginGroup("Core");
diff --git a/src/citra_qt/config.h b/src/citra_qt/config.h
index 79c901804..d7bf99442 100644
--- a/src/citra_qt/config.h
+++ b/src/citra_qt/config.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include <string> 8#include <string>
8#include <QVariant> 9#include <QVariant>
9#include "core/settings.h" 10#include "core/settings.h"
@@ -23,5 +24,5 @@ public:
23 24
24 void Reload(); 25 void Reload();
25 void Save(); 26 void Save();
26 static const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> defaults; 27 static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
27}; 28};
diff --git a/src/citra_qt/configure_input.cpp b/src/citra_qt/configure_input.cpp
index c29652f32..8846a68b2 100644
--- a/src/citra_qt/configure_input.cpp
+++ b/src/citra_qt/configure_input.cpp
@@ -92,14 +92,7 @@ void ConfigureInput::loadConfiguration() {
92 updateButtonLabels(); 92 updateButtonLabels();
93} 93}
94 94
95void ConfigureInput::restoreDefaults() { 95void ConfigureInput::restoreDefaults() {}
96 for (const auto& input_id : Settings::NativeInput::All) {
97 const size_t index = static_cast<size_t>(input_id);
98 key_map[input_id] = static_cast<Qt::Key>(Config::defaults[index].toInt());
99 }
100 updateButtonLabels();
101 applyConfiguration();
102}
103 96
104void ConfigureInput::updateButtonLabels() { 97void ConfigureInput::updateButtonLabels() {
105 for (const auto& input_id : Settings::NativeInput::All) { 98 for (const auto& input_id : Settings::NativeInput::All) {
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h
index 1ba64c92b..de9b64953 100644
--- a/src/core/frontend/emu_window.h
+++ b/src/core/frontend/emu_window.h
@@ -52,8 +52,6 @@ public:
52 /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread 52 /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
53 virtual void DoneCurrent() = 0; 53 virtual void DoneCurrent() = 0;
54 54
55 virtual void ReloadSetKeymaps() = 0;
56
57 /** 55 /**
58 * Signals a button press action to the HID module. 56 * Signals a button press action to the HID module.
59 * @param pad_state indicates which button to press 57 * @param pad_state indicates which button to press
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
new file mode 100644
index 000000000..ac1ad45a9
--- /dev/null
+++ b/src/input_common/CMakeLists.txt
@@ -0,0 +1,15 @@
1set(SRCS
2 keyboard.cpp
3 main.cpp
4 )
5
6set(HEADERS
7 keyboard.h
8 main.h
9 )
10
11create_directory_groups(${SRCS} ${HEADERS})
12
13add_library(input_common STATIC ${SRCS} ${HEADERS})
14target_link_libraries(input_common common core)
15
diff --git a/src/input_common/keyboard.cpp b/src/input_common/keyboard.cpp
new file mode 100644
index 000000000..a8fc01f2e
--- /dev/null
+++ b/src/input_common/keyboard.cpp
@@ -0,0 +1,82 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <atomic>
6#include <list>
7#include <mutex>
8#include "input_common/keyboard.h"
9
10namespace InputCommon {
11
12class KeyButton final : public Input::ButtonDevice {
13public:
14 explicit KeyButton(std::shared_ptr<KeyButtonList> key_button_list_)
15 : key_button_list(key_button_list_) {}
16
17 ~KeyButton();
18
19 bool GetStatus() const override {
20 return status.load();
21 }
22
23 friend class KeyButtonList;
24
25private:
26 std::shared_ptr<KeyButtonList> key_button_list;
27 std::atomic<bool> status{false};
28};
29
30struct KeyButtonPair {
31 int key_code;
32 KeyButton* key_button;
33};
34
35class KeyButtonList {
36public:
37 void AddKeyButton(int key_code, KeyButton* key_button) {
38 std::lock_guard<std::mutex> guard(mutex);
39 list.push_back(KeyButtonPair{key_code, key_button});
40 }
41
42 void RemoveKeyButton(const KeyButton* key_button) {
43 std::lock_guard<std::mutex> guard(mutex);
44 list.remove_if(
45 [key_button](const KeyButtonPair& pair) { return pair.key_button == key_button; });
46 }
47
48 void ChangeKeyStatus(int key_code, bool pressed) {
49 std::lock_guard<std::mutex> guard(mutex);
50 for (const KeyButtonPair& pair : list) {
51 if (pair.key_code == key_code)
52 pair.key_button->status.store(pressed);
53 }
54 }
55
56private:
57 std::mutex mutex;
58 std::list<KeyButtonPair> list;
59};
60
61Keyboard::Keyboard() : key_button_list{std::make_shared<KeyButtonList>()} {}
62
63KeyButton::~KeyButton() {
64 key_button_list->RemoveKeyButton(this);
65}
66
67std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage& params) {
68 int key_code = params.Get("code", 0);
69 std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list);
70 key_button_list->AddKeyButton(key_code, button.get());
71 return std::move(button);
72}
73
74void Keyboard::PressKey(int key_code) {
75 key_button_list->ChangeKeyStatus(key_code, true);
76}
77
78void Keyboard::ReleaseKey(int key_code) {
79 key_button_list->ChangeKeyStatus(key_code, false);
80}
81
82} // namespace InputCommon
diff --git a/src/input_common/keyboard.h b/src/input_common/keyboard.h
new file mode 100644
index 000000000..76359aa30
--- /dev/null
+++ b/src/input_common/keyboard.h
@@ -0,0 +1,45 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include "core/frontend/input.h"
9
10namespace InputCommon {
11
12class KeyButtonList;
13
14/**
15 * A button device factory representing a keyboard. It receives keyboard events and forward them
16 * to all button devices it created.
17 */
18class Keyboard final : public Input::Factory<Input::ButtonDevice> {
19public:
20 Keyboard();
21
22 /**
23 * Creates a button device from a keyboard key
24 * @param params contains parameters for creating the device:
25 * - "code": the code of the key to bind with the button
26 */
27 std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override;
28
29 /**
30 * Sets the status of all buttons bound with the key to pressed
31 * @param key_code the code of the key to press
32 */
33 void PressKey(int key_code);
34
35 /**
36 * Sets the status of all buttons bound with the key to released
37 * @param key_code the code of the key to release
38 */
39 void ReleaseKey(int key_code);
40
41private:
42 std::shared_ptr<KeyButtonList> key_button_list;
43};
44
45} // namespace InputCommon
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
new file mode 100644
index 000000000..ff25220b4
--- /dev/null
+++ b/src/input_common/main.cpp
@@ -0,0 +1,35 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <memory>
6#include "common/param_package.h"
7#include "input_common/keyboard.h"
8#include "input_common/main.h"
9
10namespace InputCommon {
11
12static std::shared_ptr<Keyboard> keyboard;
13
14void Init() {
15 keyboard = std::make_shared<InputCommon::Keyboard>();
16 Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
17}
18
19void Shutdown() {
20 Input::UnregisterFactory<Input::ButtonDevice>("keyboard");
21 keyboard.reset();
22}
23
24Keyboard* GetKeyboard() {
25 return keyboard.get();
26}
27
28std::string GenerateKeyboardParam(int key_code) {
29 Common::ParamPackage param{
30 {"engine", "keyboard"}, {"code", std::to_string(key_code)},
31 };
32 return param.Serialize();
33}
34
35} // namespace InputCommon
diff --git a/src/input_common/main.h b/src/input_common/main.h
new file mode 100644
index 000000000..a490dd829
--- /dev/null
+++ b/src/input_common/main.h
@@ -0,0 +1,25 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <string>
8
9namespace InputCommon {
10
11/// Initializes and registers all built-in input device factories.
12void Init();
13
14/// Unresisters all build-in input device factories and shut them down.
15void Shutdown();
16
17class Keyboard;
18
19/// Gets the keyboard button device factory.
20Keyboard* GetKeyboard();
21
22/// Generates a serialized param package for creating a keyboard button device
23std::string GenerateKeyboardParam(int key_code);
24
25} // namespace InputCommon