mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 13:27:45 -07:00
Merge pull request #12632 from jordan-woyak/input-backend-impls
Implement missing InputBackend classes.
This commit is contained in:
commit
e62d8ecfa8
@ -23,6 +23,7 @@
|
||||
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
|
||||
#include "InputCommon/ControllerInterface/InputBackend.h"
|
||||
#include "jni/AndroidCommon/AndroidCommon.h"
|
||||
#include "jni/AndroidCommon/IDCache.h"
|
||||
#include "jni/Input/CoreDevice.h"
|
||||
@ -444,6 +445,23 @@ std::shared_ptr<ciface::Core::Device> FindDevice(jint device_id)
|
||||
|
||||
namespace ciface::Android
|
||||
{
|
||||
class InputBackend final : public ciface::InputBackend
|
||||
{
|
||||
public:
|
||||
using ciface::InputBackend::InputBackend;
|
||||
~InputBackend();
|
||||
void PopulateDevices() override;
|
||||
|
||||
private:
|
||||
void AddDevice(JNIEnv* env, int device_id);
|
||||
void AddSensorDevice(JNIEnv* env);
|
||||
};
|
||||
|
||||
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface)
|
||||
{
|
||||
return std::make_unique<InputBackend>(controller_interface);
|
||||
}
|
||||
|
||||
class AndroidInput : public Core::Device::Input
|
||||
{
|
||||
public:
|
||||
@ -885,7 +903,7 @@ void Init()
|
||||
s_controller_interface_register_input_device_listener);
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
InputBackend::~InputBackend()
|
||||
{
|
||||
JNIEnv* env = IDCache::GetEnvForThread();
|
||||
|
||||
@ -903,7 +921,7 @@ void Shutdown()
|
||||
env->DeleteGlobalRef(s_keycodes_array);
|
||||
}
|
||||
|
||||
static void AddDevice(JNIEnv* env, int device_id)
|
||||
void InputBackend::AddDevice(JNIEnv* env, int device_id)
|
||||
{
|
||||
jobject input_device =
|
||||
env->CallStaticObjectMethod(s_input_device_class, s_input_device_get_device, device_id);
|
||||
@ -921,7 +939,7 @@ static void AddDevice(JNIEnv* env, int device_id)
|
||||
if (device->Inputs().empty() && device->Outputs().empty())
|
||||
return;
|
||||
|
||||
g_controller_interface.AddDevice(device);
|
||||
GetControllerInterface().AddDevice(device);
|
||||
|
||||
Core::DeviceQualifier qualifier;
|
||||
qualifier.FromDevice(device.get());
|
||||
@ -936,7 +954,7 @@ static void AddDevice(JNIEnv* env, int device_id)
|
||||
env->DeleteLocalRef(j_qualifier);
|
||||
}
|
||||
|
||||
static void AddSensorDevice(JNIEnv* env)
|
||||
void InputBackend::AddSensorDevice(JNIEnv* env)
|
||||
{
|
||||
// Device sensors (accelerometer, etc.) aren't associated with any Android InputDevice.
|
||||
// Create an otherwise empty Dolphin input device so that they have somewhere to live.
|
||||
@ -946,7 +964,7 @@ static void AddSensorDevice(JNIEnv* env)
|
||||
if (device->Inputs().empty() && device->Outputs().empty())
|
||||
return;
|
||||
|
||||
g_controller_interface.AddDevice(device);
|
||||
GetControllerInterface().AddDevice(device);
|
||||
|
||||
Core::DeviceQualifier qualifier;
|
||||
qualifier.FromDevice(device.get());
|
||||
@ -959,7 +977,7 @@ static void AddSensorDevice(JNIEnv* env)
|
||||
env->DeleteLocalRef(j_qualifier);
|
||||
}
|
||||
|
||||
void PopulateDevices()
|
||||
void InputBackend::PopulateDevices()
|
||||
{
|
||||
INFO_LOG_FMT(CONTROLLERINTERFACE, "Android populating devices");
|
||||
|
||||
|
@ -3,11 +3,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "InputCommon/ControllerInterface/InputBackend.h"
|
||||
|
||||
namespace ciface::Android
|
||||
{
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
void PopulateDevices();
|
||||
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface);
|
||||
|
||||
} // namespace ciface::Android
|
||||
|
@ -59,25 +59,25 @@ void ControllerInterface::Initialize(const WindowSystemInfo& wsi)
|
||||
m_populating_devices_counter = 1;
|
||||
|
||||
#ifdef CIFACE_USE_WIN32
|
||||
ciface::Win32::Init(wsi.render_window);
|
||||
m_input_backends.emplace_back(ciface::Win32::CreateInputBackend(this));
|
||||
#endif
|
||||
#ifdef CIFACE_USE_XLIB
|
||||
// nothing needed
|
||||
m_input_backends.emplace_back(ciface::XInput2::CreateInputBackend(this));
|
||||
#endif
|
||||
#ifdef CIFACE_USE_OSX
|
||||
// nothing needed for Quartz
|
||||
m_input_backends.emplace_back(ciface::Quartz::CreateInputBackend(this));
|
||||
#endif
|
||||
#ifdef CIFACE_USE_SDL
|
||||
m_input_backends.emplace_back(ciface::SDL::CreateInputBackend(this));
|
||||
#endif
|
||||
#ifdef CIFACE_USE_ANDROID
|
||||
ciface::Android::Init();
|
||||
m_input_backends.emplace_back(ciface::Android::CreateInputBackend(this));
|
||||
#endif
|
||||
#ifdef CIFACE_USE_EVDEV
|
||||
m_input_backends.emplace_back(ciface::evdev::CreateInputBackend(this));
|
||||
#endif
|
||||
#ifdef CIFACE_USE_PIPES
|
||||
// nothing needed
|
||||
m_input_backends.emplace_back(ciface::Pipes::CreateInputBackend(this));
|
||||
#endif
|
||||
#ifdef CIFACE_USE_DUALSHOCKUDPCLIENT
|
||||
m_input_backends.emplace_back(ciface::DualShockUDPClient::CreateInputBackend(this));
|
||||
@ -128,22 +128,20 @@ void ControllerInterface::RefreshDevices(RefreshReason reason)
|
||||
// or removing them as we are populating them (causing missing or duplicate devices).
|
||||
std::lock_guard lk_population(m_devices_population_mutex);
|
||||
|
||||
#if defined(CIFACE_USE_WIN32) && !defined(CIFACE_USE_XLIB) && !defined(CIFACE_USE_OSX)
|
||||
// If only the window changed, avoid removing and re-adding all devices.
|
||||
// Instead only refresh devices that require the window handle.
|
||||
if (reason == RefreshReason::WindowChangeOnly)
|
||||
{
|
||||
m_populating_devices_counter.fetch_add(1);
|
||||
|
||||
// No need to do anything else in this case.
|
||||
// Only (Win32) DInput needs the window handle to be updated.
|
||||
ciface::Win32::ChangeWindow(m_wsi.render_window);
|
||||
for (auto& backend : m_input_backends)
|
||||
backend->HandleWindowChange();
|
||||
|
||||
if (m_populating_devices_counter.fetch_sub(1) == 1)
|
||||
InvokeDevicesChangedCallbacks();
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_populating_devices_counter.fetch_add(1);
|
||||
|
||||
@ -159,26 +157,6 @@ void ControllerInterface::RefreshDevices(RefreshReason reason)
|
||||
// do it async, to not risk the emulated controllers default config loading not finding a default
|
||||
// device.
|
||||
|
||||
#ifdef CIFACE_USE_WIN32
|
||||
ciface::Win32::PopulateDevices(m_wsi.render_window);
|
||||
#endif
|
||||
#ifdef CIFACE_USE_XLIB
|
||||
if (m_wsi.type == WindowSystemType::X11)
|
||||
ciface::XInput2::PopulateDevices(m_wsi.render_window);
|
||||
#endif
|
||||
#ifdef CIFACE_USE_OSX
|
||||
if (m_wsi.type == WindowSystemType::MacOS)
|
||||
{
|
||||
ciface::Quartz::PopulateDevices(m_wsi.render_window);
|
||||
}
|
||||
#endif
|
||||
#ifdef CIFACE_USE_ANDROID
|
||||
ciface::Android::PopulateDevices();
|
||||
#endif
|
||||
#ifdef CIFACE_USE_PIPES
|
||||
ciface::Pipes::PopulateDevices();
|
||||
#endif
|
||||
|
||||
for (auto& backend : m_input_backends)
|
||||
backend->PopulateDevices();
|
||||
|
||||
@ -217,19 +195,6 @@ void ControllerInterface::Shutdown()
|
||||
// Update control references so shared_ptr<Device>s are freed up BEFORE we shutdown the backends.
|
||||
ClearDevices();
|
||||
|
||||
#ifdef CIFACE_USE_WIN32
|
||||
ciface::Win32::DeInit();
|
||||
#endif
|
||||
#ifdef CIFACE_USE_XLIB
|
||||
// nothing needed
|
||||
#endif
|
||||
#ifdef CIFACE_USE_OSX
|
||||
ciface::Quartz::DeInit();
|
||||
#endif
|
||||
#ifdef CIFACE_USE_ANDROID
|
||||
ciface::Android::Shutdown();
|
||||
#endif
|
||||
|
||||
// Empty the container of input backends to deconstruct and deinitialize them.
|
||||
m_input_backends.clear();
|
||||
|
||||
@ -423,6 +388,11 @@ ciface::InputChannel ControllerInterface::GetCurrentInputChannel()
|
||||
return tls_input_channel;
|
||||
}
|
||||
|
||||
WindowSystemInfo ControllerInterface::GetWindowSystemInfo() const
|
||||
{
|
||||
return m_wsi;
|
||||
}
|
||||
|
||||
void ControllerInterface::SetAspectRatioAdjustment(float value)
|
||||
{
|
||||
m_aspect_ratio_adjustment = value;
|
||||
|
@ -122,6 +122,8 @@ public:
|
||||
static void SetCurrentInputChannel(ciface::InputChannel);
|
||||
static ciface::InputChannel GetCurrentInputChannel();
|
||||
|
||||
WindowSystemInfo GetWindowSystemInfo() const;
|
||||
|
||||
private:
|
||||
void ClearDevices();
|
||||
|
||||
|
@ -16,6 +16,10 @@ void InputBackend::UpdateInput(std::vector<std::weak_ptr<ciface::Core::Device>>&
|
||||
{
|
||||
}
|
||||
|
||||
void InputBackend::HandleWindowChange()
|
||||
{
|
||||
}
|
||||
|
||||
ControllerInterface& InputBackend::GetControllerInterface()
|
||||
{
|
||||
return m_controller_interface;
|
||||
|
@ -28,6 +28,8 @@ public:
|
||||
// just add them to the removal list if necessary.
|
||||
virtual void UpdateInput(std::vector<std::weak_ptr<ciface::Core::Device>>& devices_to_remove);
|
||||
|
||||
virtual void HandleWindowChange();
|
||||
|
||||
ControllerInterface& GetControllerInterface();
|
||||
|
||||
private:
|
||||
|
@ -39,7 +39,19 @@ static double StringToDouble(const std::string& text)
|
||||
return result;
|
||||
}
|
||||
|
||||
void PopulateDevices()
|
||||
class InputBackend final : public ciface::InputBackend
|
||||
{
|
||||
public:
|
||||
using ciface::InputBackend::InputBackend;
|
||||
void PopulateDevices() override;
|
||||
};
|
||||
|
||||
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface)
|
||||
{
|
||||
return std::make_unique<InputBackend>(controller_interface);
|
||||
}
|
||||
|
||||
void InputBackend::PopulateDevices()
|
||||
{
|
||||
// Search the Pipes directory for files that we can open in read-only,
|
||||
// non-blocking mode. The device name is the virtual name of the file.
|
||||
|
@ -21,7 +21,7 @@ namespace ciface::Pipes
|
||||
// SET {L, R} [0, 1]
|
||||
// SET {MAIN, C} [0, 1] [0, 1]
|
||||
|
||||
void PopulateDevices();
|
||||
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface);
|
||||
|
||||
class PipeDevice : public Core::Device
|
||||
{
|
||||
|
@ -3,8 +3,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "InputCommon/ControllerInterface/InputBackend.h"
|
||||
|
||||
namespace ciface::Quartz
|
||||
{
|
||||
void PopulateDevices(void* window);
|
||||
void DeInit();
|
||||
std::string GetSourceName();
|
||||
|
||||
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface);
|
||||
} // namespace ciface::Quartz
|
||||
|
@ -7,15 +7,40 @@
|
||||
|
||||
namespace ciface::Quartz
|
||||
{
|
||||
void PopulateDevices(void* window)
|
||||
std::string GetSourceName()
|
||||
{
|
||||
if (!window)
|
||||
return "Quartz";
|
||||
}
|
||||
|
||||
class InputBackend final : public ciface::InputBackend
|
||||
{
|
||||
public:
|
||||
using ciface::InputBackend::InputBackend;
|
||||
void PopulateDevices() override;
|
||||
void HandleWindowChange() override;
|
||||
};
|
||||
|
||||
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface)
|
||||
{
|
||||
return std::make_unique<InputBackend>(controller_interface);
|
||||
}
|
||||
|
||||
void InputBackend::HandleWindowChange()
|
||||
{
|
||||
const std::string source_name = GetSourceName();
|
||||
GetControllerInterface().RemoveDevice(
|
||||
[&](const auto* dev) { return dev->GetSource() == source_name; }, true);
|
||||
|
||||
PopulateDevices();
|
||||
}
|
||||
|
||||
void InputBackend::PopulateDevices()
|
||||
{
|
||||
const WindowSystemInfo wsi = GetControllerInterface().GetWindowSystemInfo();
|
||||
if (wsi.type != WindowSystemType::MacOS)
|
||||
return;
|
||||
|
||||
g_controller_interface.AddDevice(std::make_shared<KeyboardAndMouse>(window));
|
||||
GetControllerInterface().AddDevice(std::make_shared<KeyboardAndMouse>(wsi.render_window));
|
||||
}
|
||||
|
||||
void DeInit()
|
||||
{
|
||||
}
|
||||
} // namespace ciface::Quartz
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "Core/Host.h"
|
||||
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
#include "InputCommon/ControllerInterface/Quartz/Quartz.h"
|
||||
|
||||
/// Helper class to get window position data from threads other than the main thread
|
||||
@interface DolWindowPositionObserver : NSObject
|
||||
@ -279,7 +280,7 @@ std::string KeyboardAndMouse::GetName() const
|
||||
|
||||
std::string KeyboardAndMouse::GetSource() const
|
||||
{
|
||||
return "Quartz";
|
||||
return Quartz::GetSourceName();
|
||||
}
|
||||
|
||||
ControlState KeyboardAndMouse::Cursor::GetState() const
|
||||
|
@ -20,13 +20,25 @@
|
||||
|
||||
#pragma comment(lib, "OneCoreUAP.Lib")
|
||||
|
||||
// Dolphin's render window
|
||||
static HWND s_hwnd;
|
||||
static std::mutex s_populate_mutex;
|
||||
// TODO is this really needed?
|
||||
static Common::Flag s_first_populate_devices_asked;
|
||||
static HCMNOTIFICATION s_notify_handle;
|
||||
|
||||
namespace ciface::Win32
|
||||
{
|
||||
class InputBackend final : public ciface::InputBackend
|
||||
{
|
||||
public:
|
||||
InputBackend(ControllerInterface* controller_interface);
|
||||
~InputBackend();
|
||||
|
||||
void PopulateDevices() override;
|
||||
void HandleWindowChange() override;
|
||||
HWND GetHWND();
|
||||
};
|
||||
} // namespace ciface::Win32
|
||||
|
||||
_Pre_satisfies_(EventDataSize >= sizeof(CM_NOTIFY_EVENT_DATA)) static DWORD CALLBACK
|
||||
OnDevicesChanged(_In_ HCMNOTIFICATION hNotify, _In_opt_ PVOID Context,
|
||||
_In_ CM_NOTIFY_ACTION Action,
|
||||
@ -43,8 +55,9 @@ _Pre_satisfies_(EventDataSize >= sizeof(CM_NOTIFY_EVENT_DATA)) static DWORD CALL
|
||||
std::lock_guard lk_population(s_populate_mutex);
|
||||
// TODO: we could easily use the message passed alongside this event, which tells
|
||||
// whether a device was added or removed, to avoid removing old, still connected, devices
|
||||
g_controller_interface.PlatformPopulateDevices([] {
|
||||
ciface::DInput::PopulateDevices(s_hwnd);
|
||||
g_controller_interface.PlatformPopulateDevices([&] {
|
||||
ciface::DInput::PopulateDevices(
|
||||
static_cast<ciface::Win32::InputBackend*>(Context)->GetHWND());
|
||||
ciface::XInput::PopulateDevices();
|
||||
});
|
||||
}
|
||||
@ -52,10 +65,21 @@ _Pre_satisfies_(EventDataSize >= sizeof(CM_NOTIFY_EVENT_DATA)) static DWORD CALL
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
void ciface::Win32::Init(void* hwnd)
|
||||
namespace ciface::Win32
|
||||
{
|
||||
s_hwnd = static_cast<HWND>(hwnd);
|
||||
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface)
|
||||
{
|
||||
return std::make_unique<InputBackend>(controller_interface);
|
||||
}
|
||||
|
||||
HWND InputBackend::GetHWND()
|
||||
{
|
||||
return static_cast<HWND>(GetControllerInterface().GetWindowSystemInfo().render_window);
|
||||
}
|
||||
|
||||
InputBackend::InputBackend(ControllerInterface* controller_interface)
|
||||
: ciface::InputBackend(controller_interface)
|
||||
{
|
||||
XInput::Init();
|
||||
WGInput::Init();
|
||||
|
||||
@ -63,35 +87,32 @@ void ciface::Win32::Init(void* hwnd)
|
||||
.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE,
|
||||
.u{.DeviceInterface{.ClassGuid = GUID_DEVINTERFACE_HID}}};
|
||||
const CONFIGRET cfg_rv =
|
||||
CM_Register_Notification(¬ify_filter, nullptr, OnDevicesChanged, &s_notify_handle);
|
||||
CM_Register_Notification(¬ify_filter, this, OnDevicesChanged, &s_notify_handle);
|
||||
if (cfg_rv != CR_SUCCESS)
|
||||
{
|
||||
ERROR_LOG_FMT(CONTROLLERINTERFACE, "CM_Register_Notification failed: {:x}", cfg_rv);
|
||||
}
|
||||
}
|
||||
|
||||
void ciface::Win32::PopulateDevices(void* hwnd)
|
||||
void InputBackend::PopulateDevices()
|
||||
{
|
||||
s_hwnd = static_cast<HWND>(hwnd);
|
||||
std::lock_guard lk_population(s_populate_mutex);
|
||||
s_first_populate_devices_asked.Set();
|
||||
ciface::DInput::PopulateDevices(s_hwnd);
|
||||
ciface::DInput::PopulateDevices(GetHWND());
|
||||
ciface::XInput::PopulateDevices();
|
||||
ciface::WGInput::PopulateDevices();
|
||||
}
|
||||
|
||||
void ciface::Win32::ChangeWindow(void* hwnd)
|
||||
void InputBackend::HandleWindowChange()
|
||||
{
|
||||
s_hwnd = static_cast<HWND>(hwnd);
|
||||
std::lock_guard lk_population(s_populate_mutex);
|
||||
ciface::DInput::ChangeWindow(s_hwnd);
|
||||
ciface::DInput::ChangeWindow(GetHWND());
|
||||
}
|
||||
|
||||
void ciface::Win32::DeInit()
|
||||
InputBackend::~InputBackend()
|
||||
{
|
||||
s_first_populate_devices_asked.Clear();
|
||||
DInput::DeInit();
|
||||
s_hwnd = nullptr;
|
||||
|
||||
if (s_notify_handle)
|
||||
{
|
||||
@ -106,3 +127,5 @@ void ciface::Win32::DeInit()
|
||||
XInput::DeInit();
|
||||
WGInput::DeInit();
|
||||
}
|
||||
|
||||
} // namespace ciface::Win32
|
||||
|
@ -3,10 +3,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "InputCommon/ControllerInterface/InputBackend.h"
|
||||
|
||||
namespace ciface::Win32
|
||||
{
|
||||
void Init(void* hwnd);
|
||||
void PopulateDevices(void* hwnd);
|
||||
void ChangeWindow(void* hwnd);
|
||||
void DeInit();
|
||||
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface);
|
||||
} // namespace ciface::Win32
|
||||
|
@ -66,9 +66,38 @@ constexpr int XINPUT_MAJOR = 2, XINPUT_MINOR = 1;
|
||||
|
||||
namespace ciface::XInput2
|
||||
{
|
||||
// This function will add zero or more KeyboardMouse objects to devices.
|
||||
void PopulateDevices(void* const hwnd)
|
||||
constexpr std::string_view SOURCE_NAME = "XInput2";
|
||||
|
||||
class InputBackend final : public ciface::InputBackend
|
||||
{
|
||||
public:
|
||||
using ciface::InputBackend::InputBackend;
|
||||
void PopulateDevices() override;
|
||||
void HandleWindowChange() override;
|
||||
};
|
||||
|
||||
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface)
|
||||
{
|
||||
return std::make_unique<InputBackend>(controller_interface);
|
||||
}
|
||||
|
||||
void InputBackend::HandleWindowChange()
|
||||
{
|
||||
GetControllerInterface().RemoveDevice(
|
||||
[](const auto* dev) { return dev->GetSource() == SOURCE_NAME; }, true);
|
||||
|
||||
PopulateDevices();
|
||||
}
|
||||
|
||||
// This function will add zero or more KeyboardMouse objects to devices.
|
||||
void InputBackend::PopulateDevices()
|
||||
{
|
||||
const WindowSystemInfo wsi = GetControllerInterface().GetWindowSystemInfo();
|
||||
if (wsi.type != WindowSystemType::X11)
|
||||
return;
|
||||
|
||||
const auto hwnd = wsi.render_window;
|
||||
|
||||
Display* dpy = XOpenDisplay(nullptr);
|
||||
|
||||
// xi_opcode is important; it will be used to identify XInput events by
|
||||
@ -119,7 +148,7 @@ void PopulateDevices(void* const hwnd)
|
||||
}
|
||||
// Since current_master is a master pointer, its attachment must
|
||||
// be a master keyboard.
|
||||
g_controller_interface.AddDevice(
|
||||
GetControllerInterface().AddDevice(
|
||||
std::make_shared<KeyboardMouse>((Window)hwnd, xi_opcode, current_master->deviceid,
|
||||
current_master->attachment, scroll_increment));
|
||||
}
|
||||
@ -382,7 +411,7 @@ std::string KeyboardMouse::GetName() const
|
||||
|
||||
std::string KeyboardMouse::GetSource() const
|
||||
{
|
||||
return "XInput2";
|
||||
return std::string(SOURCE_NAME);
|
||||
}
|
||||
|
||||
KeyboardMouse::Key::Key(Display* const display, KeyCode keycode, const char* keyboard)
|
||||
|
@ -16,10 +16,11 @@ extern "C" {
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Matrix.h"
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
#include "InputCommon/ControllerInterface/InputBackend.h"
|
||||
|
||||
namespace ciface::XInput2
|
||||
{
|
||||
void PopulateDevices(void* const hwnd);
|
||||
std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* controller_interface);
|
||||
|
||||
class KeyboardMouse : public Core::Device
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user