InputCommon: add Keyboard
This commit is contained in:
parent
70420272ca
commit
38e800f70d
17 changed files with 254 additions and 85 deletions
|
@ -5,6 +5,7 @@ add_subdirectory(common)
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
add_subdirectory(video_core)
|
add_subdirectory(video_core)
|
||||||
add_subdirectory(audio_core)
|
add_subdirectory(audio_core)
|
||||||
|
add_subdirectory(input_common)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
if (ENABLE_SDL2)
|
if (ENABLE_SDL2)
|
||||||
add_subdirectory(citra)
|
add_subdirectory(citra)
|
||||||
|
|
|
@ -18,7 +18,7 @@ create_directory_groups(${SRCS} ${HEADERS})
|
||||||
include_directories(${SDL2_INCLUDE_DIR})
|
include_directories(${SDL2_INCLUDE_DIR})
|
||||||
|
|
||||||
add_executable(citra ${SRCS} ${HEADERS})
|
add_executable(citra ${SRCS} ${HEADERS})
|
||||||
target_link_libraries(citra core video_core audio_core common)
|
target_link_libraries(citra core video_core audio_core common input_common)
|
||||||
target_link_libraries(citra ${SDL2_LIBRARY} ${OPENGL_gl_LIBRARY} inih glad)
|
target_link_libraries(citra ${SDL2_LIBRARY} ${OPENGL_gl_LIBRARY} inih glad)
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_link_libraries(citra getopt)
|
target_link_libraries(citra getopt)
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
#include "input_common/main.h"
|
||||||
|
|
||||||
Config::Config() {
|
Config::Config() {
|
||||||
// TODO: Don't hardcode the path; let the frontend decide where to put the config files.
|
// 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) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const std::array<int, Settings::NativeInput::NUM_INPUTS> defaults = {
|
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons = {
|
||||||
// directly mapped keys
|
SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_T,
|
||||||
SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_Q, SDL_SCANCODE_W,
|
SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, SDL_SCANCODE_Q, SDL_SCANCODE_W,
|
||||||
SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_B, SDL_SCANCODE_T,
|
SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B,
|
||||||
SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, SDL_SCANCODE_I, SDL_SCANCODE_K, SDL_SCANCODE_J,
|
|
||||||
SDL_SCANCODE_L,
|
|
||||||
|
|
||||||
// indirectly mapped keys
|
|
||||||
SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_D,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void Config::ReadValues() {
|
void Config::ReadValues() {
|
||||||
// Controls
|
// Controls
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||||
Settings::values.input_mappings[Settings::NativeInput::All[i]] =
|
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||||
sdl2_config->GetInteger("Controls", Settings::NativeInput::Mapping[i], defaults[i]);
|
Settings::values.buttons[i] =
|
||||||
|
sdl2_config->Get("Controls", Settings::NativeButton::mapping[i], default_param);
|
||||||
|
if (Settings::values.buttons[i].empty())
|
||||||
|
Settings::values.buttons[i] = default_param;
|
||||||
}
|
}
|
||||||
Settings::values.pad_circle_modifier_scale =
|
|
||||||
(float)sdl2_config->GetReal("Controls", "pad_circle_modifier_scale", 0.5);
|
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true);
|
Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true);
|
||||||
|
|
|
@ -12,9 +12,9 @@
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/scm_rev.h"
|
#include "common/scm_rev.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/frontend/key_map.h"
|
|
||||||
#include "core/hle/service/hid/hid.h"
|
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
#include "input_common/keyboard.h"
|
||||||
|
#include "input_common/main.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
|
void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
|
||||||
|
@ -40,9 +40,9 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) {
|
||||||
|
|
||||||
void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {
|
void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) {
|
||||||
if (state == SDL_PRESSED) {
|
if (state == SDL_PRESSED) {
|
||||||
KeyMap::PressKey(*this, {key, keyboard_id});
|
InputCommon::GetKeyboard()->PressKey(key);
|
||||||
} else if (state == SDL_RELEASED) {
|
} else if (state == SDL_RELEASED) {
|
||||||
KeyMap::ReleaseKey(*this, {key, keyboard_id});
|
InputCommon::GetKeyboard()->ReleaseKey(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +57,8 @@ void EmuWindow_SDL2::OnResize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
EmuWindow_SDL2::EmuWindow_SDL2() {
|
EmuWindow_SDL2::EmuWindow_SDL2() {
|
||||||
keyboard_id = KeyMap::NewDeviceId();
|
InputCommon::Init();
|
||||||
|
|
||||||
ReloadSetKeymaps();
|
|
||||||
motion_emu = std::make_unique<Motion::MotionEmu>(*this);
|
motion_emu = std::make_unique<Motion::MotionEmu>(*this);
|
||||||
|
|
||||||
SDL_SetMainReady();
|
SDL_SetMainReady();
|
||||||
|
@ -117,6 +116,7 @@ EmuWindow_SDL2::~EmuWindow_SDL2() {
|
||||||
SDL_GL_DeleteContext(gl_context);
|
SDL_GL_DeleteContext(gl_context);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
motion_emu = nullptr;
|
motion_emu = nullptr;
|
||||||
|
InputCommon::Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_SDL2::SwapBuffers() {
|
void EmuWindow_SDL2::SwapBuffers() {
|
||||||
|
@ -169,15 +169,6 @@ void EmuWindow_SDL2::DoneCurrent() {
|
||||||
SDL_GL_MakeCurrent(render_window, nullptr);
|
SDL_GL_MakeCurrent(render_window, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_SDL2::ReloadSetKeymaps() {
|
|
||||||
KeyMap::ClearKeyMapping(keyboard_id);
|
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
|
||||||
KeyMap::SetKeyMapping(
|
|
||||||
{Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id},
|
|
||||||
KeyMap::mapping_targets[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(
|
void EmuWindow_SDL2::OnMinimalClientAreaChangeRequest(
|
||||||
const std::pair<unsigned, unsigned>& minimal_size) {
|
const std::pair<unsigned, unsigned>& minimal_size) {
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,6 @@ public:
|
||||||
/// Whether the window is still open, and a close request hasn't yet been sent
|
/// Whether the window is still open, and a close request hasn't yet been sent
|
||||||
bool IsOpen() const;
|
bool IsOpen() const;
|
||||||
|
|
||||||
/// Load keymap from configuration
|
|
||||||
void ReloadSetKeymaps() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Called by PollEvents when a key is pressed or released.
|
/// Called by PollEvents when a key is pressed or released.
|
||||||
void OnKeyEvent(int key, u8 state);
|
void OnKeyEvent(int key, u8 state);
|
||||||
|
@ -61,9 +58,6 @@ private:
|
||||||
/// The OpenGL context associated with the window
|
/// The OpenGL context associated with the window
|
||||||
SDL_GLContext gl_context;
|
SDL_GLContext gl_context;
|
||||||
|
|
||||||
/// Device id of keyboard for use with KeyMap
|
|
||||||
int keyboard_id;
|
|
||||||
|
|
||||||
/// Motion sensors emulation
|
/// Motion sensors emulation
|
||||||
std::unique_ptr<Motion::MotionEmu> motion_emu;
|
std::unique_ptr<Motion::MotionEmu> motion_emu;
|
||||||
};
|
};
|
||||||
|
|
|
@ -97,7 +97,7 @@ if (APPLE)
|
||||||
else()
|
else()
|
||||||
add_executable(citra-qt ${SRCS} ${HEADERS} ${UI_HDRS})
|
add_executable(citra-qt ${SRCS} ${HEADERS} ${UI_HDRS})
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(citra-qt core video_core audio_core common)
|
target_link_libraries(citra-qt core video_core audio_core common input_common)
|
||||||
target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS})
|
target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS})
|
||||||
target_link_libraries(citra-qt ${PLATFORM_LIBRARIES} Threads::Threads)
|
target_link_libraries(citra-qt ${PLATFORM_LIBRARIES} Threads::Threads)
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
#include "common/scm_rev.h"
|
#include "common/scm_rev.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/frontend/key_map.h"
|
#include "input_common/keyboard.h"
|
||||||
|
#include "input_common/main.h"
|
||||||
#include "video_core/debug_utils/debug_utils.h"
|
#include "video_core/debug_utils/debug_utils.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
|
@ -99,14 +100,17 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread)
|
GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread)
|
||||||
: QWidget(parent), child(nullptr), keyboard_id(0), emu_thread(emu_thread) {
|
: QWidget(parent), child(nullptr), emu_thread(emu_thread) {
|
||||||
|
|
||||||
std::string window_title = Common::StringFromFormat("Citra %s| %s-%s", Common::g_build_name,
|
std::string window_title = Common::StringFromFormat("Citra %s| %s-%s", Common::g_build_name,
|
||||||
Common::g_scm_branch, Common::g_scm_desc);
|
Common::g_scm_branch, Common::g_scm_desc);
|
||||||
setWindowTitle(QString::fromStdString(window_title));
|
setWindowTitle(QString::fromStdString(window_title));
|
||||||
|
|
||||||
keyboard_id = KeyMap::NewDeviceId();
|
InputCommon::Init();
|
||||||
ReloadSetKeymaps();
|
}
|
||||||
|
|
||||||
|
GRenderWindow::~GRenderWindow() {
|
||||||
|
InputCommon::Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRenderWindow::moveContext() {
|
void GRenderWindow::moveContext() {
|
||||||
|
@ -197,11 +201,11 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRenderWindow::keyPressEvent(QKeyEvent* event) {
|
void GRenderWindow::keyPressEvent(QKeyEvent* event) {
|
||||||
KeyMap::PressKey(*this, {event->key(), keyboard_id});
|
InputCommon::GetKeyboard()->PressKey(event->key());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
|
void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
|
||||||
KeyMap::ReleaseKey(*this, {event->key(), keyboard_id});
|
InputCommon::GetKeyboard()->ReleaseKey(event->key());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRenderWindow::mousePressEvent(QMouseEvent* event) {
|
void GRenderWindow::mousePressEvent(QMouseEvent* event) {
|
||||||
|
@ -230,14 +234,7 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
motion_emu->EndTilt();
|
motion_emu->EndTilt();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GRenderWindow::ReloadSetKeymaps() {
|
void GRenderWindow::ReloadSetKeymaps() {}
|
||||||
KeyMap::ClearKeyMapping(keyboard_id);
|
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
|
||||||
KeyMap::SetKeyMapping(
|
|
||||||
{Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id},
|
|
||||||
KeyMap::mapping_targets[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) {
|
void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) {
|
||||||
NotifyClientAreaSizeChanged(std::make_pair(width, height));
|
NotifyClientAreaSizeChanged(std::make_pair(width, height));
|
||||||
|
|
|
@ -104,6 +104,7 @@ class GRenderWindow : public QWidget, public EmuWindow {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GRenderWindow(QWidget* parent, EmuThread* emu_thread);
|
GRenderWindow(QWidget* parent, EmuThread* emu_thread);
|
||||||
|
~GRenderWindow();
|
||||||
|
|
||||||
// EmuWindow implementation
|
// EmuWindow implementation
|
||||||
void SwapBuffers() override;
|
void SwapBuffers() override;
|
||||||
|
@ -127,7 +128,7 @@ public:
|
||||||
void mouseMoveEvent(QMouseEvent* event) override;
|
void mouseMoveEvent(QMouseEvent* event) override;
|
||||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||||
|
|
||||||
void ReloadSetKeymaps() override;
|
void ReloadSetKeymaps();
|
||||||
|
|
||||||
void OnClientAreaResized(unsigned width, unsigned height);
|
void OnClientAreaResized(unsigned width, unsigned height);
|
||||||
|
|
||||||
|
@ -152,9 +153,6 @@ private:
|
||||||
|
|
||||||
QByteArray geometry;
|
QByteArray geometry;
|
||||||
|
|
||||||
/// Device id of keyboard for use with KeyMap
|
|
||||||
int keyboard_id;
|
|
||||||
|
|
||||||
EmuThread* emu_thread;
|
EmuThread* emu_thread;
|
||||||
|
|
||||||
/// Motion sensors emulation
|
/// Motion sensors emulation
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "citra_qt/config.h"
|
#include "citra_qt/config.h"
|
||||||
#include "citra_qt/ui_settings.h"
|
#include "citra_qt/ui_settings.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
|
#include "input_common/main.h"
|
||||||
|
|
||||||
Config::Config() {
|
Config::Config() {
|
||||||
// TODO: Don't hardcode the path; let the frontend decide where to put the config files.
|
// TODO: Don't hardcode the path; let the frontend decide where to put the config files.
|
||||||
|
@ -16,25 +17,23 @@ Config::Config() {
|
||||||
Reload();
|
Reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> Config::defaults = {
|
const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = {
|
||||||
// directly mapped keys
|
Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_T, Qt::Key_G, Qt::Key_F, Qt::Key_H,
|
||||||
Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_Q, Qt::Key_W, Qt::Key_1, Qt::Key_2,
|
Qt::Key_Q, Qt::Key_W, Qt::Key_M, Qt::Key_N, Qt::Key_1, Qt::Key_2, Qt::Key_B,
|
||||||
Qt::Key_M, Qt::Key_N, Qt::Key_B, Qt::Key_T, Qt::Key_G, Qt::Key_F, Qt::Key_H, Qt::Key_I,
|
|
||||||
Qt::Key_K, Qt::Key_J, Qt::Key_L,
|
|
||||||
|
|
||||||
// indirectly mapped keys
|
|
||||||
Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, Qt::Key_D,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void Config::ReadValues() {
|
void Config::ReadValues() {
|
||||||
qt_config->beginGroup("Controls");
|
qt_config->beginGroup("Controls");
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||||
Settings::values.input_mappings[Settings::NativeInput::All[i]] =
|
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
|
||||||
qt_config->value(QString::fromStdString(Settings::NativeInput::Mapping[i]), defaults[i])
|
Settings::values.buttons[i] =
|
||||||
.toInt();
|
qt_config
|
||||||
|
->value(Settings::NativeButton::mapping[i], QString::fromStdString(default_param))
|
||||||
|
.toString()
|
||||||
|
.toStdString();
|
||||||
|
if (Settings::values.buttons[i].empty())
|
||||||
|
Settings::values.buttons[i] = default_param;
|
||||||
}
|
}
|
||||||
Settings::values.pad_circle_modifier_scale =
|
|
||||||
qt_config->value("pad_circle_modifier_scale", 0.5).toFloat();
|
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
|
|
||||||
qt_config->beginGroup("Core");
|
qt_config->beginGroup("Core");
|
||||||
|
@ -155,12 +154,10 @@ void Config::ReadValues() {
|
||||||
|
|
||||||
void Config::SaveValues() {
|
void Config::SaveValues() {
|
||||||
qt_config->beginGroup("Controls");
|
qt_config->beginGroup("Controls");
|
||||||
for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) {
|
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
|
||||||
qt_config->setValue(QString::fromStdString(Settings::NativeInput::Mapping[i]),
|
qt_config->setValue(QString::fromStdString(Settings::NativeButton::mapping[i]),
|
||||||
Settings::values.input_mappings[Settings::NativeInput::All[i]]);
|
QString::fromStdString(Settings::values.buttons[i]));
|
||||||
}
|
}
|
||||||
qt_config->setValue("pad_circle_modifier_scale",
|
|
||||||
(double)Settings::values.pad_circle_modifier_scale);
|
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
|
|
||||||
qt_config->beginGroup("Core");
|
qt_config->beginGroup("Core");
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
@ -23,5 +24,5 @@ public:
|
||||||
|
|
||||||
void Reload();
|
void Reload();
|
||||||
void Save();
|
void Save();
|
||||||
static const std::array<QVariant, Settings::NativeInput::NUM_INPUTS> defaults;
|
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
|
||||||
};
|
};
|
||||||
|
|
|
@ -92,14 +92,7 @@ void ConfigureInput::loadConfiguration() {
|
||||||
updateButtonLabels();
|
updateButtonLabels();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInput::restoreDefaults() {
|
void ConfigureInput::restoreDefaults() {}
|
||||||
for (const auto& input_id : Settings::NativeInput::All) {
|
|
||||||
const size_t index = static_cast<size_t>(input_id);
|
|
||||||
key_map[input_id] = static_cast<Qt::Key>(Config::defaults[index].toInt());
|
|
||||||
}
|
|
||||||
updateButtonLabels();
|
|
||||||
applyConfiguration();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureInput::updateButtonLabels() {
|
void ConfigureInput::updateButtonLabels() {
|
||||||
for (const auto& input_id : Settings::NativeInput::All) {
|
for (const auto& input_id : Settings::NativeInput::All) {
|
||||||
|
|
|
@ -52,8 +52,6 @@ public:
|
||||||
/// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
|
/// Releases (dunno if this is the "right" word) the GLFW context from the caller thread
|
||||||
virtual void DoneCurrent() = 0;
|
virtual void DoneCurrent() = 0;
|
||||||
|
|
||||||
virtual void ReloadSetKeymaps() = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals a button press action to the HID module.
|
* Signals a button press action to the HID module.
|
||||||
* @param pad_state indicates which button to press
|
* @param pad_state indicates which button to press
|
||||||
|
|
15
src/input_common/CMakeLists.txt
Normal file
15
src/input_common/CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
set(SRCS
|
||||||
|
keyboard.cpp
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(HEADERS
|
||||||
|
keyboard.h
|
||||||
|
main.h
|
||||||
|
)
|
||||||
|
|
||||||
|
create_directory_groups(${SRCS} ${HEADERS})
|
||||||
|
|
||||||
|
add_library(input_common STATIC ${SRCS} ${HEADERS})
|
||||||
|
target_link_libraries(input_common common core)
|
||||||
|
|
82
src/input_common/keyboard.cpp
Normal file
82
src/input_common/keyboard.cpp
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// Copyright 2017 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <list>
|
||||||
|
#include <mutex>
|
||||||
|
#include "input_common/keyboard.h"
|
||||||
|
|
||||||
|
namespace InputCommon {
|
||||||
|
|
||||||
|
class KeyButton final : public Input::ButtonDevice {
|
||||||
|
public:
|
||||||
|
explicit KeyButton(std::shared_ptr<KeyButtonList> key_button_list_)
|
||||||
|
: key_button_list(key_button_list_) {}
|
||||||
|
|
||||||
|
~KeyButton();
|
||||||
|
|
||||||
|
bool GetStatus() const override {
|
||||||
|
return status.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class KeyButtonList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<KeyButtonList> key_button_list;
|
||||||
|
std::atomic<bool> status{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KeyButtonPair {
|
||||||
|
int key_code;
|
||||||
|
KeyButton* key_button;
|
||||||
|
};
|
||||||
|
|
||||||
|
class KeyButtonList {
|
||||||
|
public:
|
||||||
|
void AddKeyButton(int key_code, KeyButton* key_button) {
|
||||||
|
std::lock_guard<std::mutex> guard(mutex);
|
||||||
|
list.push_back(KeyButtonPair{key_code, key_button});
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveKeyButton(const KeyButton* key_button) {
|
||||||
|
std::lock_guard<std::mutex> guard(mutex);
|
||||||
|
list.remove_if(
|
||||||
|
[key_button](const KeyButtonPair& pair) { return pair.key_button == key_button; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChangeKeyStatus(int key_code, bool pressed) {
|
||||||
|
std::lock_guard<std::mutex> guard(mutex);
|
||||||
|
for (const KeyButtonPair& pair : list) {
|
||||||
|
if (pair.key_code == key_code)
|
||||||
|
pair.key_button->status.store(pressed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex mutex;
|
||||||
|
std::list<KeyButtonPair> list;
|
||||||
|
};
|
||||||
|
|
||||||
|
Keyboard::Keyboard() : key_button_list{std::make_shared<KeyButtonList>()} {}
|
||||||
|
|
||||||
|
KeyButton::~KeyButton() {
|
||||||
|
key_button_list->RemoveKeyButton(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage& params) {
|
||||||
|
int key_code = params.Get("code", 0);
|
||||||
|
std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list);
|
||||||
|
key_button_list->AddKeyButton(key_code, button.get());
|
||||||
|
return std::move(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyboard::PressKey(int key_code) {
|
||||||
|
key_button_list->ChangeKeyStatus(key_code, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyboard::ReleaseKey(int key_code) {
|
||||||
|
key_button_list->ChangeKeyStatus(key_code, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace InputCommon
|
45
src/input_common/keyboard.h
Normal file
45
src/input_common/keyboard.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright 2017 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "core/frontend/input.h"
|
||||||
|
|
||||||
|
namespace InputCommon {
|
||||||
|
|
||||||
|
class KeyButtonList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A button device factory representing a keyboard. It receives keyboard events and forward them
|
||||||
|
* to all button devices it created.
|
||||||
|
*/
|
||||||
|
class Keyboard final : public Input::Factory<Input::ButtonDevice> {
|
||||||
|
public:
|
||||||
|
Keyboard();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a button device from a keyboard key
|
||||||
|
* @param params contains parameters for creating the device:
|
||||||
|
* - "code": the code of the key to bind with the button
|
||||||
|
*/
|
||||||
|
std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the status of all buttons bound with the key to pressed
|
||||||
|
* @param key_code the code of the key to press
|
||||||
|
*/
|
||||||
|
void PressKey(int key_code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the status of all buttons bound with the key to released
|
||||||
|
* @param key_code the code of the key to release
|
||||||
|
*/
|
||||||
|
void ReleaseKey(int key_code);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<KeyButtonList> key_button_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace InputCommon
|
35
src/input_common/main.cpp
Normal file
35
src/input_common/main.cpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2017 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "common/param_package.h"
|
||||||
|
#include "input_common/keyboard.h"
|
||||||
|
#include "input_common/main.h"
|
||||||
|
|
||||||
|
namespace InputCommon {
|
||||||
|
|
||||||
|
static std::shared_ptr<Keyboard> keyboard;
|
||||||
|
|
||||||
|
void Init() {
|
||||||
|
keyboard = std::make_shared<InputCommon::Keyboard>();
|
||||||
|
Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shutdown() {
|
||||||
|
Input::UnregisterFactory<Input::ButtonDevice>("keyboard");
|
||||||
|
keyboard.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
Keyboard* GetKeyboard() {
|
||||||
|
return keyboard.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GenerateKeyboardParam(int key_code) {
|
||||||
|
Common::ParamPackage param{
|
||||||
|
{"engine", "keyboard"}, {"code", std::to_string(key_code)},
|
||||||
|
};
|
||||||
|
return param.Serialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace InputCommon
|
25
src/input_common/main.h
Normal file
25
src/input_common/main.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2017 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace InputCommon {
|
||||||
|
|
||||||
|
/// Initializes and registers all built-in input device factories.
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
/// Unresisters all build-in input device factories and shut them down.
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
class Keyboard;
|
||||||
|
|
||||||
|
/// Gets the keyboard button device factory.
|
||||||
|
Keyboard* GetKeyboard();
|
||||||
|
|
||||||
|
/// Generates a serialized param package for creating a keyboard button device
|
||||||
|
std::string GenerateKeyboardParam(int key_code);
|
||||||
|
|
||||||
|
} // namespace InputCommon
|
Loading…
Reference in a new issue