2015-05-24 04:55:12 +00:00
|
|
|
// Copyright 2010 Dolphin Emulator Project
|
2021-07-05 01:22:19 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2010-04-02 02:48:24 +00:00
|
|
|
|
2014-02-17 10:18:15 +00:00
|
|
|
#include "InputCommon/ControllerInterface/DInput/DInput.h"
|
2019-03-09 15:57:37 +00:00
|
|
|
|
2021-12-12 21:50:18 +00:00
|
|
|
#include "Common/HRWrap.h"
|
2019-03-09 15:57:37 +00:00
|
|
|
#include "Common/Logging/Log.h"
|
2016-06-12 15:08:04 +00:00
|
|
|
#include "Common/StringUtil.h"
|
2010-06-21 03:12:16 +00:00
|
|
|
|
2019-03-09 15:57:37 +00:00
|
|
|
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
2014-02-17 10:18:15 +00:00
|
|
|
#include "InputCommon/ControllerInterface/DInput/DInputJoystick.h"
|
|
|
|
#include "InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h"
|
2010-06-21 03:12:16 +00:00
|
|
|
|
2010-04-02 02:48:24 +00:00
|
|
|
#pragma comment(lib, "Dinput8.lib")
|
|
|
|
#pragma comment(lib, "dxguid.lib")
|
|
|
|
|
2019-06-17 20:39:24 +00:00
|
|
|
namespace ciface::DInput
|
2010-04-02 02:48:24 +00:00
|
|
|
{
|
2021-05-15 09:20:20 +00:00
|
|
|
static IDirectInput8* s_idi8 = nullptr;
|
|
|
|
|
2010-06-21 03:12:16 +00:00
|
|
|
BOOL CALLBACK DIEnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef)
|
|
|
|
{
|
|
|
|
((std::list<DIDEVICEOBJECTINSTANCE>*)pvRef)->push_back(*lpddoi);
|
|
|
|
return DIENUM_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
|
|
|
|
{
|
|
|
|
((std::list<DIDEVICEINSTANCE>*)pvRef)->push_back(*lpddi);
|
|
|
|
return DIENUM_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string GetDeviceName(const LPDIRECTINPUTDEVICE8 device)
|
|
|
|
{
|
2013-02-28 00:01:48 +00:00
|
|
|
DIPROPSTRING str = {};
|
2010-06-21 03:12:16 +00:00
|
|
|
str.diph.dwSize = sizeof(str);
|
|
|
|
str.diph.dwHeaderSize = sizeof(str.diph);
|
|
|
|
str.diph.dwHow = DIPH_DEVICE;
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2013-02-28 00:01:48 +00:00
|
|
|
std::string result;
|
2021-12-12 21:50:18 +00:00
|
|
|
HRESULT hr = device->GetProperty(DIPROP_PRODUCTNAME, &str.diph);
|
|
|
|
if (SUCCEEDED(hr))
|
2010-06-21 03:12:16 +00:00
|
|
|
{
|
2022-07-19 22:13:26 +00:00
|
|
|
result = StripWhitespace(WStringToUTF8(str.wsz));
|
2010-06-21 03:12:16 +00:00
|
|
|
}
|
2019-03-09 15:57:37 +00:00
|
|
|
else
|
|
|
|
{
|
2021-12-12 21:50:18 +00:00
|
|
|
ERROR_LOG_FMT(CONTROLLERINTERFACE, "GetProperty(DIPROP_PRODUCTNAME) failed: {}",
|
|
|
|
Common::HRWrap(hr));
|
2019-03-09 15:57:37 +00:00
|
|
|
}
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2013-02-28 00:01:48 +00:00
|
|
|
return result;
|
2010-06-21 03:12:16 +00:00
|
|
|
}
|
|
|
|
|
2021-05-15 09:20:20 +00:00
|
|
|
// Assumes hwnd had not changed from the previous call
|
2016-10-16 20:39:05 +00:00
|
|
|
void PopulateDevices(HWND hwnd)
|
2010-04-02 02:48:24 +00:00
|
|
|
{
|
2021-12-12 21:50:18 +00:00
|
|
|
if (!s_idi8)
|
2021-05-15 09:20:20 +00:00
|
|
|
{
|
2021-12-12 21:50:18 +00:00
|
|
|
HRESULT hr = DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION,
|
|
|
|
IID_IDirectInput8, (LPVOID*)&s_idi8, nullptr);
|
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
|
|
|
ERROR_LOG_FMT(CONTROLLERINTERFACE, "DirectInput8Create failed: {}", Common::HRWrap(hr));
|
|
|
|
return;
|
|
|
|
}
|
2021-05-15 09:20:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Remove old (invalid) devices. No need to ever remove the KeyboardMouse device.
|
|
|
|
// Note that if we have 2+ DInput controllers, not fully repopulating devices
|
|
|
|
// will mean that a device with index "2" could persist while there is no device with index "0".
|
|
|
|
// This is slightly inconsistent as when we refresh all devices, they will instead reset, and
|
|
|
|
// that happens a lot (for uncontrolled reasons, like starting/stopping the emulation).
|
2019-03-09 15:57:37 +00:00
|
|
|
g_controller_interface.RemoveDevice(
|
|
|
|
[](const auto* dev) { return dev->GetSource() == DINPUT_SOURCE_NAME && !dev->IsValid(); });
|
2017-11-10 20:30:37 +00:00
|
|
|
|
2021-05-15 09:20:20 +00:00
|
|
|
InitKeyboardMouse(s_idi8, hwnd);
|
|
|
|
InitJoystick(s_idi8, hwnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ChangeWindow(HWND hwnd)
|
|
|
|
{
|
|
|
|
if (s_idi8) // Has init? Ignore if called before the first PopulateDevices()
|
2014-08-23 00:17:49 +00:00
|
|
|
{
|
2021-05-15 09:20:20 +00:00
|
|
|
// The KeyboardMouse device is marked as virtual device, so we avoid removing it.
|
|
|
|
// We need to force all the DInput joysticks to be destroyed now, or recreation would fail.
|
|
|
|
g_controller_interface.RemoveDevice(
|
|
|
|
[](const auto* dev) {
|
|
|
|
return dev->GetSource() == DINPUT_SOURCE_NAME && !dev->IsVirtualDevice();
|
|
|
|
},
|
|
|
|
true);
|
2010-04-02 02:48:24 +00:00
|
|
|
|
2021-05-15 09:20:20 +00:00
|
|
|
SetKeyboardMouseWindow(hwnd);
|
|
|
|
InitJoystick(s_idi8, hwnd);
|
|
|
|
}
|
|
|
|
}
|
2010-04-02 02:48:24 +00:00
|
|
|
|
2021-05-15 09:20:20 +00:00
|
|
|
void DeInit()
|
|
|
|
{
|
|
|
|
if (s_idi8)
|
|
|
|
{
|
|
|
|
s_idi8->Release();
|
|
|
|
s_idi8 = nullptr;
|
|
|
|
}
|
2010-04-02 02:48:24 +00:00
|
|
|
}
|
2019-06-17 20:39:24 +00:00
|
|
|
} // namespace ciface::DInput
|