mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-06-28 09:59:32 -06:00
ControllerInterface/Win32: Prevent devcies from losing their "id" on a hotplug event.
This commit is contained in:
@ -3,9 +3,11 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "InputCommon/ControllerInterface/DInput/DInput.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
#include "InputCommon/ControllerInterface/DInput/DInputJoystick.h"
|
||||
#include "InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h"
|
||||
|
||||
@ -40,25 +42,32 @@ std::string GetDeviceName(const LPDIRECTINPUTDEVICE8 device)
|
||||
{
|
||||
result = StripSpaces(UTF16ToUTF8(str.wsz));
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(PAD, "GetProperty(DIPROP_PRODUCTNAME) failed.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PopulateDevices(HWND hwnd)
|
||||
{
|
||||
g_controller_interface.RemoveDevice([](const auto* dev) { return dev->GetSource() == "DInput"; });
|
||||
// Remove unplugged devices.
|
||||
g_controller_interface.RemoveDevice(
|
||||
[](const auto* dev) { return dev->GetSource() == DINPUT_SOURCE_NAME && !dev->IsValid(); });
|
||||
|
||||
IDirectInput8* idi8;
|
||||
if (FAILED(DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8,
|
||||
(LPVOID*)&idi8, nullptr)))
|
||||
{
|
||||
ERROR_LOG(PAD, "DirectInput8Create failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
InitKeyboardMouse(idi8, hwnd);
|
||||
InitKeyboardMouse(idi8);
|
||||
InitJoystick(idi8, hwnd);
|
||||
|
||||
idi8->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace DInput
|
||||
} // namespace ciface
|
||||
|
@ -4,8 +4,9 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
@ -17,7 +18,19 @@ namespace ciface
|
||||
{
|
||||
namespace DInput
|
||||
{
|
||||
#define DATA_BUFFER_SIZE 32
|
||||
constexpr DWORD DATA_BUFFER_SIZE = 32;
|
||||
|
||||
struct GUIDComparator
|
||||
{
|
||||
bool operator()(const GUID& left, const GUID& right) const
|
||||
{
|
||||
static_assert(std::is_trivially_copyable_v<GUID>);
|
||||
|
||||
return memcmp(&left, &right, sizeof(left)) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
static std::set<GUID, GUIDComparator> s_guids_in_use;
|
||||
|
||||
void InitJoystick(IDirectInput8* const idi8, HWND hwnd)
|
||||
{
|
||||
@ -28,12 +41,18 @@ void InitJoystick(IDirectInput8* const idi8, HWND hwnd)
|
||||
std::unordered_set<DWORD> xinput_guids = GetXInputGUIDS();
|
||||
for (DIDEVICEINSTANCE& joystick : joysticks)
|
||||
{
|
||||
// skip XInput Devices
|
||||
// Skip XInput Devices
|
||||
if (xinput_guids.count(joystick.guidProduct.Data1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip devices we are already using.
|
||||
if (s_guids_in_use.count(joystick.guidInstance))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LPDIRECTINPUTDEVICE8 js_device;
|
||||
if (SUCCEEDED(idi8->CreateDevice(joystick.guidInstance, &js_device, nullptr)))
|
||||
{
|
||||
@ -55,7 +74,9 @@ void InitJoystick(IDirectInput8* const idi8, HWND hwnd)
|
||||
}
|
||||
}
|
||||
|
||||
s_guids_in_use.insert(joystick.guidInstance);
|
||||
auto js = std::make_shared<Joystick>(js_device);
|
||||
|
||||
// only add if it has some inputs/outputs
|
||||
if (js->Inputs().size() || js->Outputs().size())
|
||||
g_controller_interface.AddDevice(std::move(js));
|
||||
@ -161,6 +182,17 @@ Joystick::Joystick(/*const LPCDIDEVICEINSTANCE lpddi, */ const LPDIRECTINPUTDEVI
|
||||
|
||||
Joystick::~Joystick()
|
||||
{
|
||||
DIDEVICEINSTANCE info = {};
|
||||
info.dwSize = sizeof(info);
|
||||
if (SUCCEEDED(m_device->GetDeviceInfo(&info)))
|
||||
{
|
||||
s_guids_in_use.erase(info.guidInstance);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(PAD, "DInputJoystick: GetDeviceInfo failed.");
|
||||
}
|
||||
|
||||
DeInitForceFeedback();
|
||||
|
||||
m_device->Unacquire();
|
||||
@ -177,7 +209,10 @@ std::string Joystick::GetSource() const
|
||||
return DINPUT_SOURCE_NAME;
|
||||
}
|
||||
|
||||
// update IO
|
||||
bool Joystick::IsValid() const
|
||||
{
|
||||
return SUCCEEDED(m_device->Acquire());
|
||||
}
|
||||
|
||||
void Joystick::UpdateInput()
|
||||
{
|
||||
|
@ -68,6 +68,8 @@ public:
|
||||
std::string GetName() const override;
|
||||
std::string GetSource() const override;
|
||||
|
||||
bool IsValid() const final override;
|
||||
|
||||
private:
|
||||
const LPDIRECTINPUTDEVICE8 m_device;
|
||||
|
||||
@ -75,5 +77,5 @@ private:
|
||||
|
||||
bool m_buffered;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace DInput
|
||||
} // namespace ciface
|
||||
|
@ -29,12 +29,13 @@ static const struct
|
||||
#include "InputCommon/ControllerInterface/DInput/NamedKeys.h" // NOLINT
|
||||
};
|
||||
|
||||
// lil silly
|
||||
static HWND m_hwnd;
|
||||
// Prevent duplicate keyboard/mouse devices.
|
||||
static bool s_keyboard_mouse_exists = false;
|
||||
|
||||
void InitKeyboardMouse(IDirectInput8* const idi8, HWND _hwnd)
|
||||
void InitKeyboardMouse(IDirectInput8* const idi8)
|
||||
{
|
||||
m_hwnd = _hwnd;
|
||||
if (s_keyboard_mouse_exists)
|
||||
return;
|
||||
|
||||
// mouse and keyboard are a combined device, to allow shift+click and stuff
|
||||
// if that's dumb, I will make a VirtualDevice class that just uses ranges of inputs/outputs from
|
||||
@ -63,6 +64,8 @@ void InitKeyboardMouse(IDirectInput8* const idi8, HWND _hwnd)
|
||||
|
||||
KeyboardMouse::~KeyboardMouse()
|
||||
{
|
||||
s_keyboard_mouse_exists = false;
|
||||
|
||||
// kb
|
||||
m_kb_device->Unacquire();
|
||||
m_kb_device->Release();
|
||||
@ -75,6 +78,8 @@ KeyboardMouse::KeyboardMouse(const LPDIRECTINPUTDEVICE8 kb_device,
|
||||
const LPDIRECTINPUTDEVICE8 mo_device)
|
||||
: m_kb_device(kb_device), m_mo_device(mo_device)
|
||||
{
|
||||
s_keyboard_mouse_exists = true;
|
||||
|
||||
m_kb_device->Acquire();
|
||||
m_mo_device->Acquire();
|
||||
|
||||
@ -237,5 +242,5 @@ ControlState KeyboardMouse::Cursor::GetState() const
|
||||
{
|
||||
return std::max(0.0, ControlState(m_axis) / (m_positive ? 1.0 : -1.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace DInput
|
||||
} // namespace ciface
|
||||
|
@ -13,7 +13,7 @@ namespace ciface
|
||||
{
|
||||
namespace DInput
|
||||
{
|
||||
void InitKeyboardMouse(IDirectInput8* const idi8, HWND _hwnd);
|
||||
void InitKeyboardMouse(IDirectInput8* const idi8);
|
||||
|
||||
class KeyboardMouse : public Core::Device
|
||||
{
|
||||
@ -98,5 +98,5 @@ private:
|
||||
DWORD m_last_update;
|
||||
State m_state_in;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace DInput
|
||||
} // namespace ciface
|
||||
|
Reference in New Issue
Block a user