Merge pull request #1964 from ergo720/mouse_input
Re-enable Mouse Support
This commit is contained in:
commit
abb50d6f99
|
@ -52,6 +52,6 @@ typedef enum class _IPC_UPDATE_KERNEL {
|
||||||
, CONFIG_INPUT_SYNC
|
, CONFIG_INPUT_SYNC
|
||||||
} IPC_UPDATE_KERNEL;
|
} IPC_UPDATE_KERNEL;
|
||||||
|
|
||||||
void ipc_send_kernel_update(IPC_UPDATE_KERNEL command, const unsigned int value, const unsigned int hwnd);
|
void ipc_send_kernel_update(IPC_UPDATE_KERNEL command, const int value, const unsigned int hwnd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -62,8 +62,9 @@ uint16_t g_LibVersion_DSOUND = 0;
|
||||||
// * 5: (ergo720), added new input gui settings and revision to core
|
// * 5: (ergo720), added new input gui settings and revision to core
|
||||||
// * 6: (RadWolfie), added loader executable member to core, only for clean up loader expertimental setting
|
// * 6: (RadWolfie), added loader executable member to core, only for clean up loader expertimental setting
|
||||||
// * 7: (RadWolfie), fix allowAdminPrivilege not align with other boolean members
|
// * 7: (RadWolfie), fix allowAdminPrivilege not align with other boolean members
|
||||||
|
// * 8: (ergo720), added general input settings
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
const unsigned int settings_version = 7;
|
const unsigned int settings_version = 8;
|
||||||
|
|
||||||
Settings* g_Settings = nullptr;
|
Settings* g_Settings = nullptr;
|
||||||
|
|
||||||
|
@ -125,15 +126,21 @@ static struct {
|
||||||
const char* adapter_name = "adapter_name";
|
const char* adapter_name = "adapter_name";
|
||||||
} sect_network_keys;
|
} sect_network_keys;
|
||||||
|
|
||||||
|
static const char *section_input_general = "input-general";
|
||||||
|
static struct {
|
||||||
|
const char *mo_axis_range = "MouseAxisRange";
|
||||||
|
const char *mo_wheel_range = "MouseWheelRange";
|
||||||
|
} sect_input_general;
|
||||||
|
|
||||||
static const char* section_controller_dinput = "controller-dinput";
|
static const char* section_controller_dinput = "controller-dinput";
|
||||||
static const char* section_controller_port = "controller-port";
|
static const char* section_controller_port = "controller-port";
|
||||||
|
|
||||||
static const char* section_input = "input-port-";
|
static const char* section_input_port = "input-port-";
|
||||||
static struct {
|
static struct {
|
||||||
const char* type = "Type";
|
const char* type = "Type";
|
||||||
const char* device = "DeviceName";
|
const char* device = "DeviceName";
|
||||||
const char* config = "ProfileName";
|
const char* config = "ProfileName";
|
||||||
} sect_input;
|
} sect_input_port;
|
||||||
|
|
||||||
static const char* section_input_profiles = "input-profile-";
|
static const char* section_input_profiles = "input-profile-";
|
||||||
static struct {
|
static struct {
|
||||||
|
@ -366,6 +373,10 @@ bool Settings::LoadConfig()
|
||||||
|
|
||||||
// ==== Core End ============
|
// ==== Core End ============
|
||||||
|
|
||||||
|
// Delete/update legacy configs from previous revisions
|
||||||
|
RemoveLegacyConfigs(m_core.Revision);
|
||||||
|
m_core.Revision = settings_version;
|
||||||
|
|
||||||
// ==== Hack Begin ==========
|
// ==== Hack Begin ==========
|
||||||
|
|
||||||
m_hacks.DisablePixelShaders = m_si.GetBoolValue(section_hack, sect_hack_keys.DisablePixelShaders, /*Default=*/false);
|
m_hacks.DisablePixelShaders = m_si.GetBoolValue(section_hack, sect_hack_keys.DisablePixelShaders, /*Default=*/false);
|
||||||
|
@ -435,21 +446,28 @@ bool Settings::LoadConfig()
|
||||||
|
|
||||||
// ==== Network End =========
|
// ==== Network End =========
|
||||||
|
|
||||||
// ==== Input Begin ====
|
// ==== Input General Begin ====
|
||||||
|
|
||||||
|
m_input_general.MoAxisRange = m_si.GetLongValue(section_input_general, sect_input_general.mo_axis_range, MO_AXIS_DEFAULT_RANGE);
|
||||||
|
m_input_general.MoWheelRange = m_si.GetLongValue(section_input_general, sect_input_general.mo_wheel_range, MO_WHEEL_DEFAULT_RANGE);
|
||||||
|
|
||||||
|
// ==== Input General End ==============
|
||||||
|
|
||||||
|
// ==== Input Port Begin ====
|
||||||
|
|
||||||
for (int port_num = 0; port_num < 4; port_num++) {
|
for (int port_num = 0; port_num < 4; port_num++) {
|
||||||
std::string current_section = std::string(section_input) + std::to_string(port_num);
|
std::string current_section = std::string(section_input_port) + std::to_string(port_num);
|
||||||
int ret = m_si.GetLongValue(current_section.c_str(), sect_input.type, -2);
|
int ret = m_si.GetLongValue(current_section.c_str(), sect_input_port.type, -2);
|
||||||
if (ret == -2) {
|
if (ret == -2) {
|
||||||
m_input[port_num].Type = to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID);
|
m_input_port[port_num].Type = to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
m_input[port_num].Type = ret;
|
m_input_port[port_num].Type = ret;
|
||||||
m_input[port_num].DeviceName = m_si.GetValue(current_section.c_str(), sect_input.device);
|
m_input_port[port_num].DeviceName = m_si.GetValue(current_section.c_str(), sect_input_port.device);
|
||||||
m_input[port_num].ProfileName = TrimQuoteFromString(m_si.GetValue(current_section.c_str(), sect_input.config));
|
m_input_port[port_num].ProfileName = TrimQuoteFromString(m_si.GetValue(current_section.c_str(), sect_input_port.config));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==== Input End ==============
|
// ==== Input Port End ==============
|
||||||
|
|
||||||
// ==== Input Profile Begin ====
|
// ==== Input Profile Begin ====
|
||||||
std::array<std::vector<std::string>, to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX)> control_names;
|
std::array<std::vector<std::string>, to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX)> control_names;
|
||||||
|
@ -488,10 +506,6 @@ bool Settings::LoadConfig()
|
||||||
|
|
||||||
// ==== Input Profile End ======
|
// ==== Input Profile End ======
|
||||||
|
|
||||||
// Delete legacy configs from previous revisions
|
|
||||||
RemoveLegacyConfigs(m_core.Revision);
|
|
||||||
m_core.Revision = settings_version;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,18 +596,25 @@ bool Settings::Save(std::string file_path)
|
||||||
|
|
||||||
// ==== Network End =========
|
// ==== Network End =========
|
||||||
|
|
||||||
// ==== Input Begin ====
|
// ==== Input General Begin =======
|
||||||
|
|
||||||
|
m_si.SetLongValue(section_input_general, sect_input_general.mo_axis_range, m_input_general.MoAxisRange, nullptr, false, true);
|
||||||
|
m_si.SetLongValue(section_input_general, sect_input_general.mo_wheel_range, m_input_general.MoWheelRange, nullptr, false, true);
|
||||||
|
|
||||||
|
// ==== Input General End =========
|
||||||
|
|
||||||
|
// ==== Input Port Begin ====
|
||||||
|
|
||||||
for (int port_num = 0; port_num < 4; port_num++) {
|
for (int port_num = 0; port_num < 4; port_num++) {
|
||||||
std::string current_section = std::string(section_input) + std::to_string(port_num);
|
std::string current_section = std::string(section_input_port) + std::to_string(port_num);
|
||||||
std::string quoted_prf_str = m_input[port_num].ProfileName.insert(0, "\"");
|
std::string quoted_prf_str = m_input_port[port_num].ProfileName.insert(0, "\"");
|
||||||
quoted_prf_str += "\"";
|
quoted_prf_str += "\"";
|
||||||
m_si.SetLongValue(current_section.c_str(), sect_input.type, m_input[port_num].Type, nullptr, false, true);
|
m_si.SetLongValue(current_section.c_str(), sect_input_port.type, m_input_port[port_num].Type, nullptr, false, true);
|
||||||
m_si.SetValue(current_section.c_str(), sect_input.device, m_input[port_num].DeviceName.c_str(), nullptr, true);
|
m_si.SetValue(current_section.c_str(), sect_input_port.device, m_input_port[port_num].DeviceName.c_str(), nullptr, true);
|
||||||
m_si.SetValue(current_section.c_str(), sect_input.config, quoted_prf_str.c_str(), nullptr, true);
|
m_si.SetValue(current_section.c_str(), sect_input_port.config, quoted_prf_str.c_str(), nullptr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==== Input End ==============
|
// ==== Input Port End ==============
|
||||||
|
|
||||||
// ==== Input Profile Begin ====
|
// ==== Input Profile Begin ====
|
||||||
|
|
||||||
|
@ -693,19 +714,19 @@ void Settings::SyncToEmulator()
|
||||||
|
|
||||||
// register input settings
|
// register input settings
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
g_EmuShared->SetInputDevTypeSettings(&m_input[i].Type, i);
|
g_EmuShared->SetInputDevTypeSettings(&m_input_port[i].Type, i);
|
||||||
if (m_input[i].Type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
|
if (m_input_port[i].Type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
|
||||||
g_EmuShared->SetInputDevNameSettings(m_input[i].DeviceName.c_str(), i);
|
g_EmuShared->SetInputDevNameSettings(m_input_port[i].DeviceName.c_str(), i);
|
||||||
auto it = std::find_if(m_input_profiles[m_input[i].Type].begin(),
|
auto it = std::find_if(m_input_profiles[m_input_port[i].Type].begin(),
|
||||||
m_input_profiles[m_input[i].Type].end(), [this, i](const auto& profile) {
|
m_input_profiles[m_input_port[i].Type].end(), [this, i](const auto& profile) {
|
||||||
if (profile.ProfileName == m_input[i].ProfileName) {
|
if (profile.ProfileName == m_input_port[i].ProfileName) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
if (it != m_input_profiles[m_input[i].Type].end()) {
|
if (it != m_input_profiles[m_input_port[i].Type].end()) {
|
||||||
char controls_name[XBOX_CTRL_NUM_BUTTONS][30];
|
char controls_name[XBOX_CTRL_NUM_BUTTONS][30];
|
||||||
for (int index = 0; index < dev_num_buttons[m_input[i].Type]; index++) {
|
for (int index = 0; index < dev_num_buttons[m_input_port[i].Type]; index++) {
|
||||||
strncpy(controls_name[index], it->ControlList[index].c_str(), 30);
|
strncpy(controls_name[index], it->ControlList[index].c_str(), 30);
|
||||||
}
|
}
|
||||||
g_EmuShared->SetInputBindingsSettings(controls_name, XBOX_CTRL_NUM_BUTTONS, i);
|
g_EmuShared->SetInputBindingsSettings(controls_name, XBOX_CTRL_NUM_BUTTONS, i);
|
||||||
|
@ -713,6 +734,9 @@ void Settings::SyncToEmulator()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_EmuShared->SetInputMoAxisSettings(m_input_general.MoAxisRange);
|
||||||
|
g_EmuShared->SetInputMoWheelSettings(m_input_general.MoWheelRange);
|
||||||
|
|
||||||
// register Hacks settings
|
// register Hacks settings
|
||||||
g_EmuShared->SetHackSettings(&m_hacks);
|
g_EmuShared->SetHackSettings(&m_hacks);
|
||||||
|
|
||||||
|
@ -893,4 +917,38 @@ void Settings::RemoveLegacyConfigs(unsigned int CurrentRevision)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CurrentRevision < 8) {
|
||||||
|
const std::string kb_str = "Keyboard";
|
||||||
|
|
||||||
|
for (unsigned port_num = 0; port_num < 4; ++port_num) {
|
||||||
|
std::string current_section = std::string(section_input_port) + std::to_string(port_num);
|
||||||
|
std::string device_name = m_si.GetValue(current_section.c_str(), sect_input_port.device, "");
|
||||||
|
|
||||||
|
// NOTE: with C++20, this can be simplified by simply calling device_name.ends_with()
|
||||||
|
if (device_name.length() >= kb_str.length()) {
|
||||||
|
if (device_name.compare(device_name.length() - kb_str.length(), kb_str.length(), kb_str) == 0) {
|
||||||
|
device_name += "Mouse";
|
||||||
|
m_si.SetValue(current_section.c_str(), sect_input_port.device, device_name.c_str(), nullptr, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned index = 0; ; ++index) {
|
||||||
|
std::string current_section = std::string(section_input_profiles) + std::to_string(index);
|
||||||
|
if (m_si.GetSectionSize(current_section.c_str()) == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string device_name = m_si.GetValue(current_section.c_str(), sect_input_profiles.device, "");
|
||||||
|
|
||||||
|
// NOTE: with C++20, this can be simplified by simply calling device_name.ends_with()
|
||||||
|
if (device_name.length() >= kb_str.length()) {
|
||||||
|
if (device_name.compare(device_name.length() - kb_str.length(), kb_str.length(), kb_str) == 0) {
|
||||||
|
device_name += "Mouse";
|
||||||
|
m_si.SetValue(current_section.c_str(), sect_input_profiles.device, device_name.c_str(), nullptr, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,12 +134,18 @@ public:
|
||||||
} m_audio;
|
} m_audio;
|
||||||
static_assert(sizeof(s_audio) == 0x4C, assert_check_shared_memory(s_audio));
|
static_assert(sizeof(s_audio) == 0x4C, assert_check_shared_memory(s_audio));
|
||||||
|
|
||||||
struct s_input {
|
struct s_input_general {
|
||||||
|
long MoAxisRange;
|
||||||
|
long MoWheelRange;
|
||||||
|
};
|
||||||
|
s_input_general m_input_general;
|
||||||
|
|
||||||
|
struct s_input_port {
|
||||||
int Type;
|
int Type;
|
||||||
std::string DeviceName;
|
std::string DeviceName;
|
||||||
std::string ProfileName;
|
std::string ProfileName;
|
||||||
};
|
};
|
||||||
std::array<s_input, 4> m_input;
|
std::array<s_input_port, 4> m_input_port;
|
||||||
|
|
||||||
struct s_input_profiles {
|
struct s_input_profiles {
|
||||||
int Type;
|
int Type;
|
||||||
|
|
|
@ -51,8 +51,6 @@ namespace DInput
|
||||||
#include "DInputKeyboardCodes.h"
|
#include "DInputKeyboardCodes.h"
|
||||||
};
|
};
|
||||||
|
|
||||||
bool bKbMoEnumerated = false;
|
|
||||||
|
|
||||||
void InitKeyboardMouse(IDirectInput8* idi8)
|
void InitKeyboardMouse(IDirectInput8* idi8)
|
||||||
{
|
{
|
||||||
// From Dolphin: "mouse and keyboard are a combined device, to allow shift+click and stuff
|
// From Dolphin: "mouse and keyboard are a combined device, to allow shift+click and stuff
|
||||||
|
@ -60,26 +58,27 @@ namespace DInput
|
||||||
// other devices so there can be a separated Keyboard and mouse, as well as combined KeyboardMouse"
|
// other devices so there can be a separated Keyboard and mouse, as well as combined KeyboardMouse"
|
||||||
|
|
||||||
LPDIRECTINPUTDEVICE8 kb_device = nullptr;
|
LPDIRECTINPUTDEVICE8 kb_device = nullptr;
|
||||||
//LPDIRECTINPUTDEVICE8 mo_device = nullptr;
|
LPDIRECTINPUTDEVICE8 mo_device = nullptr;
|
||||||
|
|
||||||
if (SUCCEEDED(idi8->CreateDevice(GUID_SysKeyboard, &kb_device, nullptr)) &&
|
if (SUCCEEDED(idi8->CreateDevice(GUID_SysKeyboard, &kb_device, nullptr)) &&
|
||||||
SUCCEEDED(kb_device->SetDataFormat(&c_dfDIKeyboard)) &&
|
SUCCEEDED(kb_device->SetDataFormat(&c_dfDIKeyboard)) &&
|
||||||
SUCCEEDED(kb_device->SetCooperativeLevel(nullptr, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) //&&
|
SUCCEEDED(kb_device->SetCooperativeLevel(nullptr, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)) &&
|
||||||
//SUCCEEDED(idi8->CreateDevice(GUID_SysMouse, &mo_device, nullptr)) &&
|
SUCCEEDED(idi8->CreateDevice(GUID_SysMouse, &mo_device, nullptr)) &&
|
||||||
//SUCCEEDED(mo_device->SetDataFormat(&c_dfDIMouse2)) &&
|
SUCCEEDED(mo_device->SetDataFormat(&c_dfDIMouse2)) &&
|
||||||
//SUCCEEDED(mo_device->SetCooperativeLevel(nullptr, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))
|
SUCCEEDED(mo_device->SetCooperativeLevel(nullptr, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))
|
||||||
{
|
{
|
||||||
g_InputDeviceManager.AddDevice(std::make_shared<KeyboardMouse>(kb_device));
|
g_InputDeviceManager.AddDevice(std::make_shared<KeyboardMouse>(kb_device, mo_device));
|
||||||
bKbMoEnumerated = true;
|
bKbMoEnumerated = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kb_device)
|
if (kb_device) {
|
||||||
kb_device->Release();
|
kb_device->Release();
|
||||||
#if 0
|
}
|
||||||
if (mo_device)
|
|
||||||
|
if (mo_device) {
|
||||||
mo_device->Release();
|
mo_device->Release();
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopulateDevices()
|
void PopulateDevices()
|
||||||
|
@ -104,36 +103,40 @@ namespace DInput
|
||||||
PopulateDevices();
|
PopulateDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyboardMouse::KeyboardMouse(const LPDIRECTINPUTDEVICE8 kb_device)
|
KeyboardMouse::KeyboardMouse(const LPDIRECTINPUTDEVICE8 kb_device, const LPDIRECTINPUTDEVICE8 mo_device)
|
||||||
: m_kb_device(kb_device)//, m_mo_device(mo_device)
|
: m_kb_device(kb_device), m_mo_device(mo_device)
|
||||||
{
|
{
|
||||||
m_kb_device->Acquire();
|
m_kb_device->Acquire();
|
||||||
//m_mo_device->Acquire();
|
m_mo_device->Acquire();
|
||||||
|
|
||||||
memset(&m_state_in, 0, sizeof(m_state_in));
|
std::memset(&m_state_in, 0, sizeof(m_state_in));
|
||||||
|
|
||||||
// KEYBOARD
|
// KEYBOARD
|
||||||
// add keys
|
// add keys
|
||||||
for (uint8_t i = 0; i < sizeof(named_keys) / sizeof(*named_keys); ++i) {
|
for (uint8_t i = 0; i < sizeof(named_keys) / sizeof(*named_keys); ++i) {
|
||||||
AddInput(new Key(i, m_state_in.keyboard[named_keys[i].code]));
|
AddInput(new Key(i, m_state_in.keyboard[named_keys[i].code]));
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
// MOUSE
|
// MOUSE
|
||||||
// get caps
|
// get caps
|
||||||
DIDEVCAPS mouse_caps;
|
DIDEVCAPS mouse_caps;
|
||||||
memset(&mouse_caps, 0, sizeof(mouse_caps));
|
std::memset(&mouse_caps, 0, sizeof(mouse_caps));
|
||||||
mouse_caps.dwSize = sizeof(mouse_caps);
|
mouse_caps.dwSize = sizeof(mouse_caps);
|
||||||
m_mo_device->GetCapabilities(&mouse_caps);
|
m_mo_device->GetCapabilities(&mouse_caps);
|
||||||
|
|
||||||
// mouse buttons
|
// mouse buttons
|
||||||
for (unsigned char i = 0; i < mouse_caps.dwButtons; ++i) {
|
for (unsigned char i = 0; i < mouse_caps.dwButtons; ++i) {
|
||||||
AddInput(new Button(i, m_state_in.mouse.rgbButtons[i]));
|
AddInput(new Button(i, m_state_in.mouse.rgbButtons[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// cursor, with a hax for-loop
|
// mouse axes
|
||||||
for (unsigned int i = 0; i < 4; ++i) {
|
for (unsigned int i = 0; i < mouse_caps.dwAxes; ++i) {
|
||||||
AddInput(new Cursor(!!(i & 2), (&m_state_in.cursor.x)[i / 2], !!(i & 1)));
|
const LONG &ax = (&m_state_in.mouse.lX)[i];
|
||||||
|
|
||||||
|
// each axis gets a negative and a positive input instance associated with it
|
||||||
|
AddInput(new Axis(i, ax, (2 == i) ? mo_wheel_range_neg : mo_axis_range_neg));
|
||||||
|
AddInput(new Axis(i, ax, (2 == i) ? mo_wheel_range_pos : mo_axis_range_pos));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyboardMouse::~KeyboardMouse()
|
KeyboardMouse::~KeyboardMouse()
|
||||||
|
@ -141,85 +144,50 @@ namespace DInput
|
||||||
// kb
|
// kb
|
||||||
m_kb_device->Unacquire();
|
m_kb_device->Unacquire();
|
||||||
m_kb_device->Release();
|
m_kb_device->Release();
|
||||||
#if 0
|
|
||||||
// mouse
|
// mouse
|
||||||
m_mo_device->Unacquire();
|
m_mo_device->Unacquire();
|
||||||
m_mo_device->Release();
|
m_mo_device->Release();
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetMousePos(ControlState* const x, ControlState* const y)
|
|
||||||
{
|
|
||||||
POINT point = { 1, 1 };
|
|
||||||
GetCursorPos(&point);
|
|
||||||
// Get the cursor position relative to the upper left corner of the current window
|
|
||||||
HWND hwnd = WindowFromPoint(point);
|
|
||||||
DWORD processId;
|
|
||||||
GetWindowThreadProcessId(hwnd, &processId);
|
|
||||||
if (processId == GetCurrentProcessId())
|
|
||||||
{
|
|
||||||
ScreenToClient(hwnd, &point);
|
|
||||||
|
|
||||||
// Get the size of the current window.
|
|
||||||
RECT rect;
|
|
||||||
GetClientRect(hwnd, &rect);
|
|
||||||
// Width and height is the size of the rendering window
|
|
||||||
unsigned int win_width = rect.right - rect.left;
|
|
||||||
unsigned int win_height = rect.bottom - rect.top;
|
|
||||||
|
|
||||||
// Return the mouse position as a range from -1 to 1
|
|
||||||
*x = (ControlState)point.x / (ControlState)win_width * 2 - 1;
|
|
||||||
*y = (ControlState)point.y / (ControlState)win_height * 2 - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*x = (ControlState)0;
|
|
||||||
*y = (ControlState)0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardMouse::UpdateInput()
|
bool KeyboardMouse::UpdateInput()
|
||||||
{
|
{
|
||||||
// Update keyboard and mouse button states
|
if (mo_leave_wnd) {
|
||||||
|
std::memset(&m_state_in, 0, sizeof(m_state_in));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DIMOUSESTATE2 tmp_mouse;
|
||||||
|
|
||||||
HRESULT kb_hr = m_kb_device->GetDeviceState(sizeof(m_state_in.keyboard), &m_state_in.keyboard);
|
HRESULT kb_hr = m_kb_device->GetDeviceState(sizeof(m_state_in.keyboard), &m_state_in.keyboard);
|
||||||
//HRESULT mo_hr = m_mo_device->GetDeviceState(sizeof(m_state_in.mouse), &m_state_in.mouse);
|
HRESULT mo_hr = m_mo_device->GetDeviceState(sizeof(tmp_mouse), &tmp_mouse);
|
||||||
|
|
||||||
if (DIERR_INPUTLOST == kb_hr || DIERR_NOTACQUIRED == kb_hr) {
|
if (DIERR_INPUTLOST == kb_hr || DIERR_NOTACQUIRED == kb_hr) {
|
||||||
m_kb_device->Acquire();
|
m_kb_device->Acquire();
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
if (DIERR_INPUTLOST == mo_hr || DIERR_NOTACQUIRED == mo_hr) {
|
if (DIERR_INPUTLOST == mo_hr || DIERR_NOTACQUIRED == mo_hr) {
|
||||||
m_mo_device->Acquire();
|
m_mo_device->Acquire();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (SUCCEEDED(kb_hr)) //&& SUCCEEDED(mo_hr))
|
if (SUCCEEDED(kb_hr) && SUCCEEDED(mo_hr))
|
||||||
{
|
{
|
||||||
#if 0
|
// NOTE: the /= 2 will cause the mouse input to naturally decay to zero if the mouse did not change its position
|
||||||
ControlState temp_x, temp_y;
|
for (unsigned int i = 0; i < 3; ++i) {
|
||||||
|
((&m_state_in.mouse.lX)[i] += (&tmp_mouse.lX)[i]) /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
// Update absolute mouse position
|
std::memcpy(m_state_in.mouse.rgbButtons, tmp_mouse.rgbButtons, sizeof(m_state_in.mouse.rgbButtons));
|
||||||
GetMousePos(&m_state_in.cursor.x, &m_state_in.cursor.y);
|
|
||||||
|
|
||||||
// Save current absolute mouse position
|
|
||||||
temp_x = m_state_in.cursor.x;
|
|
||||||
temp_y = m_state_in.cursor.y;
|
|
||||||
|
|
||||||
// Update relative mouse motion
|
|
||||||
m_state_in.cursor.x -= m_state_in.cursor.last_x;
|
|
||||||
m_state_in.cursor.y -= m_state_in.cursor.last_y;
|
|
||||||
|
|
||||||
// Update previous absolute mouse position
|
|
||||||
m_state_in.cursor.last_x = temp_x;
|
|
||||||
m_state_in.cursor.last_y = temp_y;
|
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KeyboardMouse::GetDeviceName() const
|
std::string KeyboardMouse::GetDeviceName() const
|
||||||
{
|
{
|
||||||
return "Keyboard";
|
return "KeyboardMouse";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KeyboardMouse::GetAPI() const
|
std::string KeyboardMouse::GetAPI() const
|
||||||
|
@ -237,11 +205,11 @@ namespace DInput
|
||||||
return std::string("Click ") + char('0' + m_index);
|
return std::string("Click ") + char('0' + m_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string KeyboardMouse::Cursor::GetName() const
|
std::string KeyboardMouse::Axis::GetName() const
|
||||||
{
|
{
|
||||||
static char tmpstr[] = "Cursor ..";
|
static char tmpstr[] = "Axis ..";
|
||||||
tmpstr[7] = (char)('X' + m_index);
|
tmpstr[5] = (char)('X' + m_index);
|
||||||
tmpstr[8] = (m_positive ? '+' : '-');
|
tmpstr[6] = (m_range < 0 ? '-' : '+');
|
||||||
return tmpstr;
|
return tmpstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,8 +223,8 @@ namespace DInput
|
||||||
return (m_button != 0);
|
return (m_button != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ControlState KeyboardMouse::Cursor::GetState() const
|
ControlState KeyboardMouse::Axis::GetState() const
|
||||||
{
|
{
|
||||||
return std::max(0.0, ControlState(m_axis) / (m_positive ? 1.0 : -1.0));
|
return std::clamp(ControlState(m_axis) / m_range, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,14 +34,19 @@
|
||||||
|
|
||||||
namespace DInput
|
namespace DInput
|
||||||
{
|
{
|
||||||
extern bool bKbMoEnumerated;
|
inline bool bKbMoEnumerated = false;
|
||||||
|
inline bool mo_leave_wnd = false;
|
||||||
|
inline LONG mo_axis_range_pos = 0;
|
||||||
|
inline LONG mo_axis_range_neg = 0;
|
||||||
|
inline LONG mo_wheel_range_pos = 0;
|
||||||
|
inline LONG mo_wheel_range_neg = 0;
|
||||||
void GetDeviceChanges();
|
void GetDeviceChanges();
|
||||||
void PopulateDevices();
|
void PopulateDevices();
|
||||||
|
|
||||||
class KeyboardMouse : public InputDevice
|
class KeyboardMouse : public InputDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
KeyboardMouse(const LPDIRECTINPUTDEVICE8 kb_device);
|
KeyboardMouse(const LPDIRECTINPUTDEVICE8 kb_device, const LPDIRECTINPUTDEVICE8 mo_device);
|
||||||
~KeyboardMouse();
|
~KeyboardMouse();
|
||||||
std::string GetDeviceName() const override;
|
std::string GetDeviceName() const override;
|
||||||
std::string GetAPI() const override;
|
std::string GetAPI() const override;
|
||||||
|
@ -73,33 +78,27 @@ namespace DInput
|
||||||
const uint8_t m_index;
|
const uint8_t m_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Cursor : public Input
|
class Axis : public Input
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Cursor(uint8_t index, const ControlState& axis, const bool positive)
|
Axis(uint8_t index, const LONG &axis, const LONG &range) : m_axis(axis), m_range(range), m_index(index) {}
|
||||||
: m_axis(axis), m_index(index), m_positive(positive) {}
|
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
bool IsDetectable() override { return true; }
|
|
||||||
ControlState GetState() const override;
|
ControlState GetState() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ControlState& m_axis;
|
const LONG &m_axis;
|
||||||
|
const LONG &m_range;
|
||||||
const uint8_t m_index;
|
const uint8_t m_index;
|
||||||
const bool m_positive;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
BYTE keyboard[256];
|
BYTE keyboard[256];
|
||||||
DIMOUSESTATE2 mouse;
|
DIMOUSESTATE2 mouse;
|
||||||
struct
|
|
||||||
{
|
|
||||||
ControlState x, y, last_x, last_y;
|
|
||||||
} cursor;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const LPDIRECTINPUTDEVICE8 m_kb_device;
|
const LPDIRECTINPUTDEVICE8 m_kb_device;
|
||||||
//const LPDIRECTINPUTDEVICE8 m_mo_device;
|
const LPDIRECTINPUTDEVICE8 m_mo_device;
|
||||||
State m_state_in;
|
State m_state_in;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,8 @@
|
||||||
#define DIRECTION_IN 0
|
#define DIRECTION_IN 0
|
||||||
#define DIRECTION_OUT 1
|
#define DIRECTION_OUT 1
|
||||||
|
|
||||||
|
#define MO_AXIS_DEFAULT_RANGE 10l
|
||||||
|
#define MO_WHEEL_DEFAULT_RANGE 80l
|
||||||
|
|
||||||
typedef double ControlState;
|
typedef double ControlState;
|
||||||
|
|
||||||
|
@ -65,6 +67,10 @@ typedef enum class _XBOX_INPUT_DEVICE : int {
|
||||||
}
|
}
|
||||||
XBOX_INPUT_DEVICE;
|
XBOX_INPUT_DEVICE;
|
||||||
|
|
||||||
|
// Flags that indicate that WM_MOUSELEAVE and WM_MOUSEMOVE respectively are being tracked in the rendering window procedure
|
||||||
|
inline bool g_bIsTrackingMoLeave = false;
|
||||||
|
inline bool g_bIsTrackingMoMove = false;
|
||||||
|
|
||||||
// Lookup array used to translate a gui port to an xbox usb port and vice versa
|
// Lookup array used to translate a gui port to an xbox usb port and vice versa
|
||||||
extern int Gui2XboxPortArray[4];
|
extern int Gui2XboxPortArray[4];
|
||||||
|
|
||||||
|
@ -87,7 +93,6 @@ public:
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ControlState GetState() const = 0;
|
virtual ControlState GetState() const = 0;
|
||||||
virtual bool IsDetectable() { return true; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Output : public IoControl
|
class Output : public IoControl
|
||||||
|
@ -144,31 +149,6 @@ public:
|
||||||
m_Bindings[XButton] = Control;
|
m_Bindings[XButton] = Control;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
class FullAnalogSurface : public Input
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FullAnalogSurface(Input* Low, Input* High) : m_Low(*Low), m_High(*High) {}
|
|
||||||
ControlState GetState() const override
|
|
||||||
{
|
|
||||||
return (1 + m_High.GetState() - m_Low.GetState()) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetName() const override { return m_Low.GetName() + *m_High.GetName().rbegin(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Input& m_Low;
|
|
||||||
Input& m_High;
|
|
||||||
};
|
|
||||||
|
|
||||||
void AddAnalogInputs(Input* Low, Input* High)
|
|
||||||
{
|
|
||||||
AddInput(Low);
|
|
||||||
AddInput(High);
|
|
||||||
AddInput(new FullAnalogSurface(Low, High));
|
|
||||||
AddInput(new FullAnalogSurface(High, Low));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// arbitrary ID assigned by to the device
|
// arbitrary ID assigned by to the device
|
||||||
int m_ID;
|
int m_ID;
|
||||||
|
|
|
@ -78,9 +78,9 @@ void InputDeviceManager::Initialize(bool is_gui)
|
||||||
std::unique_lock<std::mutex> lck(m_Mtx);
|
std::unique_lock<std::mutex> lck(m_Mtx);
|
||||||
m_bPendingShutdown = false;
|
m_bPendingShutdown = false;
|
||||||
|
|
||||||
m_PollingThread = std::thread([this]() {
|
m_PollingThread = std::thread([this, is_gui]() {
|
||||||
XInput::Init(m_Mtx);
|
XInput::Init(m_Mtx);
|
||||||
Sdl::Init(m_Mtx, m_Cv);
|
Sdl::Init(m_Mtx, m_Cv, is_gui);
|
||||||
});
|
});
|
||||||
|
|
||||||
m_Cv.wait(lck, []() {
|
m_Cv.wait(lck, []() {
|
||||||
|
@ -93,6 +93,7 @@ void InputDeviceManager::Initialize(bool is_gui)
|
||||||
CxbxKrnlCleanup("Failed to initialize input subsystem! Consult debug log for more information");
|
CxbxKrnlCleanup("Failed to initialize input subsystem! Consult debug log for more information");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateOpt(is_gui);
|
||||||
RefreshDevices();
|
RefreshDevices();
|
||||||
|
|
||||||
if (!is_gui) {
|
if (!is_gui) {
|
||||||
|
@ -519,3 +520,22 @@ std::shared_ptr<InputDevice> InputDeviceManager::FindDevice(int usb_port, int du
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InputDeviceManager::UpdateOpt(bool is_gui)
|
||||||
|
{
|
||||||
|
if (!is_gui) {
|
||||||
|
long axis_range, wheel_range;
|
||||||
|
g_EmuShared->GetInputMoAxisSettings(&axis_range);
|
||||||
|
g_EmuShared->GetInputMoWheelSettings(&wheel_range);
|
||||||
|
DInput::mo_axis_range_pos = axis_range;
|
||||||
|
DInput::mo_wheel_range_pos = wheel_range;
|
||||||
|
DInput::mo_axis_range_neg = -(axis_range);
|
||||||
|
DInput::mo_wheel_range_neg = -(wheel_range);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DInput::mo_axis_range_pos = g_Settings->m_input_general.MoAxisRange;
|
||||||
|
DInput::mo_wheel_range_pos = g_Settings->m_input_general.MoWheelRange;
|
||||||
|
DInput::mo_axis_range_neg = -(g_Settings->m_input_general.MoAxisRange);
|
||||||
|
DInput::mo_wheel_range_neg = -(g_Settings->m_input_general.MoWheelRange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -82,6 +82,8 @@ public:
|
||||||
std::shared_ptr<InputDevice> FindDevice(int usb_port, int dummy) const;
|
std::shared_ptr<InputDevice> FindDevice(int usb_port, int dummy) const;
|
||||||
// attach/detach guest devices to the emulated machine
|
// attach/detach guest devices to the emulated machine
|
||||||
void UpdateDevices(int port, bool ack);
|
void UpdateDevices(int port, bool ack);
|
||||||
|
// update input options
|
||||||
|
void UpdateOpt(bool is_gui);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
#define OUTPUT_TIMEOUT 3000
|
#define OUTPUT_TIMEOUT 3000
|
||||||
|
|
||||||
|
|
||||||
constexpr ControlState INPUT_DETECT_THRESHOLD = 0.55; // arbitrary number, using what Dolphin uses
|
constexpr ControlState INPUT_DETECT_THRESHOLD = 0.35; // NOTE: this should probably be made user configurable
|
||||||
InputWindow* g_InputWindow = nullptr;
|
InputWindow* g_InputWindow = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ InputDevice::Input* InputWindow::DetectInput(InputDevice* const Device, int ms)
|
||||||
Device->UpdateInput();
|
Device->UpdateInput();
|
||||||
std::vector<bool>::iterator state = initial_states.begin();
|
std::vector<bool>::iterator state = initial_states.begin();
|
||||||
for (; i != e && s == e; i++, state++) {
|
for (; i != e && s == e; i++, state++) {
|
||||||
if ((*i)->IsDetectable() && (*i)->GetState() > INPUT_DETECT_THRESHOLD) {
|
if ((*i)->GetState() > INPUT_DETECT_THRESHOLD) {
|
||||||
if (*state == false) {
|
if (*state == false) {
|
||||||
// input was not initially pressed or it was but released afterwards
|
// input was not initially pressed or it was but released afterwards
|
||||||
s = i;
|
s = i;
|
||||||
|
@ -337,8 +337,8 @@ void InputWindow::LoadProfile(const std::string& name)
|
||||||
for (int index = 0; index < m_max_num_buttons; index++) {
|
for (int index = 0; index < m_max_num_buttons; index++) {
|
||||||
m_DeviceConfig->FindButtonByIndex(index)->UpdateText(profile->ControlList[index].c_str());
|
m_DeviceConfig->FindButtonByIndex(index)->UpdateText(profile->ControlList[index].c_str());
|
||||||
}
|
}
|
||||||
g_Settings->m_input[m_port_num].DeviceName = profile->DeviceName;
|
g_Settings->m_input_port[m_port_num].DeviceName = profile->DeviceName;
|
||||||
g_Settings->m_input[m_port_num].ProfileName = profile->ProfileName;
|
g_Settings->m_input_port[m_port_num].ProfileName = profile->ProfileName;
|
||||||
m_bHasChanges = false;
|
m_bHasChanges = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,8 +364,8 @@ bool InputWindow::SaveProfile(const std::string& name)
|
||||||
}
|
}
|
||||||
SendMessage(m_hwnd_profile_list, CB_SETCURSEL, SendMessage(m_hwnd_profile_list, CB_ADDSTRING, 0,
|
SendMessage(m_hwnd_profile_list, CB_SETCURSEL, SendMessage(m_hwnd_profile_list, CB_ADDSTRING, 0,
|
||||||
reinterpret_cast<LPARAM>(profile.ProfileName.c_str())), 0);
|
reinterpret_cast<LPARAM>(profile.ProfileName.c_str())), 0);
|
||||||
g_Settings->m_input[m_port_num].DeviceName = profile.DeviceName;
|
g_Settings->m_input_port[m_port_num].DeviceName = profile.DeviceName;
|
||||||
g_Settings->m_input[m_port_num].ProfileName = profile.ProfileName;
|
g_Settings->m_input_port[m_port_num].ProfileName = profile.ProfileName;
|
||||||
g_Settings->m_input_profiles[m_dev_type].push_back(std::move(profile));
|
g_Settings->m_input_profiles[m_dev_type].push_back(std::move(profile));
|
||||||
m_bHasChanges = false;
|
m_bHasChanges = false;
|
||||||
return true;
|
return true;
|
||||||
|
@ -379,16 +379,16 @@ void InputWindow::DeleteProfile(const std::string& name)
|
||||||
}
|
}
|
||||||
SendMessage(m_hwnd_profile_list, CB_DELETESTRING, SendMessage(m_hwnd_profile_list, CB_FINDSTRINGEXACT, 1,
|
SendMessage(m_hwnd_profile_list, CB_DELETESTRING, SendMessage(m_hwnd_profile_list, CB_FINDSTRINGEXACT, 1,
|
||||||
reinterpret_cast<LPARAM>(profile->ProfileName.c_str())), 0);
|
reinterpret_cast<LPARAM>(profile->ProfileName.c_str())), 0);
|
||||||
if (profile->ProfileName == g_Settings->m_input[m_port_num].ProfileName) {
|
if (profile->ProfileName == g_Settings->m_input_port[m_port_num].ProfileName) {
|
||||||
SendMessage(m_hwnd_profile_list, CB_SETCURSEL, -1, 0);
|
SendMessage(m_hwnd_profile_list, CB_SETCURSEL, -1, 0);
|
||||||
UpdateCurrentDevice();
|
UpdateCurrentDevice();
|
||||||
ClearBindings();
|
ClearBindings();
|
||||||
g_Settings->m_input[m_port_num].DeviceName = "";
|
g_Settings->m_input_port[m_port_num].DeviceName = "";
|
||||||
g_Settings->m_input[m_port_num].ProfileName = "";
|
g_Settings->m_input_port[m_port_num].ProfileName = "";
|
||||||
m_bHasChanges = false;
|
m_bHasChanges = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LoadProfile(g_Settings->m_input[m_port_num].ProfileName);
|
LoadProfile(g_Settings->m_input_port[m_port_num].ProfileName);
|
||||||
}
|
}
|
||||||
g_Settings->m_input_profiles[m_dev_type].erase(profile);
|
g_Settings->m_input_profiles[m_dev_type].erase(profile);
|
||||||
}
|
}
|
||||||
|
@ -411,7 +411,7 @@ void InputWindow::LoadDefaultProfile()
|
||||||
SendMessage(m_hwnd_profile_list, CB_ADDSTRING, 0,
|
SendMessage(m_hwnd_profile_list, CB_ADDSTRING, 0,
|
||||||
reinterpret_cast<LPARAM>(g_Settings->m_input_profiles[m_dev_type][index].ProfileName.c_str()));
|
reinterpret_cast<LPARAM>(g_Settings->m_input_profiles[m_dev_type][index].ProfileName.c_str()));
|
||||||
}
|
}
|
||||||
LoadProfile(g_Settings->m_input[m_port_num].ProfileName);
|
LoadProfile(g_Settings->m_input_port[m_port_num].ProfileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputWindow::UpdateCurrentDevice()
|
void InputWindow::UpdateCurrentDevice()
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace Sdl
|
||||||
int SdlInitStatus = SDL_NOT_INIT;
|
int SdlInitStatus = SDL_NOT_INIT;
|
||||||
bool SdlPopulateOK = false;
|
bool SdlPopulateOK = false;
|
||||||
|
|
||||||
void Init(std::mutex& Mtx, std::condition_variable& Cv)
|
void Init(std::mutex& Mtx, std::condition_variable& Cv, bool is_gui)
|
||||||
{
|
{
|
||||||
SDL_Event Event;
|
SDL_Event Event;
|
||||||
uint32_t CustomEvent_t;
|
uint32_t CustomEvent_t;
|
||||||
|
@ -155,9 +155,15 @@ namespace Sdl
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (Event.type == UpdateInputEvent_t) {
|
else if (Event.type == UpdateInputEvent_t) {
|
||||||
XInput::GetDeviceChanges();
|
if ((*static_cast<int *>(Event.user.data1)) == PORT_INVALID) {
|
||||||
DInput::GetDeviceChanges();
|
g_InputDeviceManager.UpdateOpt(is_gui);
|
||||||
g_InputDeviceManager.UpdateDevices(*static_cast<int*>(Event.user.data1), false);
|
}
|
||||||
|
else {
|
||||||
|
XInput::GetDeviceChanges();
|
||||||
|
DInput::GetDeviceChanges();
|
||||||
|
g_InputDeviceManager.UpdateDevices(*static_cast<int *>(Event.user.data1), false);
|
||||||
|
}
|
||||||
|
|
||||||
delete Event.user.data1;
|
delete Event.user.data1;
|
||||||
Event.user.data1 = nullptr;
|
Event.user.data1 = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +301,8 @@ namespace Sdl
|
||||||
// get axes
|
// get axes
|
||||||
for (i = 0; i != NumAxes; ++i) {
|
for (i = 0; i != NumAxes; ++i) {
|
||||||
// each axis gets a negative and a positive input instance associated with it
|
// each axis gets a negative and a positive input instance associated with it
|
||||||
AddAnalogInputs(new Axis(i, m_Joystick, -32768), new Axis(i, m_Joystick, 32767));
|
AddInput(new Axis(i, m_Joystick, -32768));
|
||||||
|
AddInput(new Axis(i, m_Joystick, 32767));
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to get supported ff effects
|
// try to get supported ff effects
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace Sdl
|
||||||
extern bool SdlPopulateOK;
|
extern bool SdlPopulateOK;
|
||||||
|
|
||||||
// initialize SDL
|
// initialize SDL
|
||||||
void Init(std::mutex& Mtx, std::condition_variable& Cv);
|
void Init(std::mutex& Mtx, std::condition_variable& Cv, bool is_gui);
|
||||||
// shutdown SDL
|
// shutdown SDL
|
||||||
void DeInit(std::thread& Thr);
|
void DeInit(std::thread& Thr);
|
||||||
// open the sdl joystick with the specified index
|
// open the sdl joystick with the specified index
|
||||||
|
|
|
@ -152,9 +152,9 @@ EmuShared::EmuShared()
|
||||||
m_bDebugging = false;
|
m_bDebugging = false;
|
||||||
m_bEmulating_status = false;
|
m_bEmulating_status = false;
|
||||||
m_bFirstLaunch = false;
|
m_bFirstLaunch = false;
|
||||||
|
m_bClipCursor = false;
|
||||||
|
|
||||||
// Reserve space (default to 0)
|
// Reserve space (default to 0)
|
||||||
m_bReserved2 = false;
|
|
||||||
m_bReserved3 = false;
|
m_bReserved3 = false;
|
||||||
m_bReserved4 = false;
|
m_bReserved4 = false;
|
||||||
m_Reserved5 = 0;
|
m_Reserved5 = 0;
|
||||||
|
|
|
@ -149,6 +149,14 @@ class EmuShared : public Mutex
|
||||||
Unlock();
|
Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ******************************************************************
|
||||||
|
// * Input option Accessors
|
||||||
|
// ******************************************************************
|
||||||
|
void GetInputMoAxisSettings(long *axis) { Lock(); *axis = m_MoAxisRange; Unlock(); }
|
||||||
|
void SetInputMoAxisSettings(const long axis) { Lock(); m_MoAxisRange = axis; Unlock(); }
|
||||||
|
void GetInputMoWheelSettings(long *wheel) { Lock(); *wheel = m_MoWheelRange; Unlock(); }
|
||||||
|
void SetInputMoWheelSettings(const long wheel) { Lock(); m_MoWheelRange = wheel; Unlock(); }
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * LLE Flags Accessors
|
// * LLE Flags Accessors
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -236,6 +244,12 @@ class EmuShared : public Mutex
|
||||||
void GetStorageLocation(char *path) { Lock(); strncpy(path, m_core.szStorageLocation, MAX_PATH); Unlock(); }
|
void GetStorageLocation(char *path) { Lock(); strncpy(path, m_core.szStorageLocation, MAX_PATH); Unlock(); }
|
||||||
void SetStorageLocation(const char *path) { Lock(); strncpy(m_core.szStorageLocation, path, MAX_PATH); Unlock(); }
|
void SetStorageLocation(const char *path) { Lock(); strncpy(m_core.szStorageLocation, path, MAX_PATH); Unlock(); }
|
||||||
|
|
||||||
|
// ******************************************************************
|
||||||
|
// * ClipCursor flag Accessors
|
||||||
|
// ******************************************************************
|
||||||
|
void GetClipCursorFlag(bool *value) { Lock(); *value = m_bClipCursor; Unlock(); }
|
||||||
|
void SetClipCursorFlag(const bool *value) { Lock(); m_bClipCursor = *value; Unlock(); }
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * Reset specific variables to default for kernel mode.
|
// * Reset specific variables to default for kernel mode.
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -284,14 +298,16 @@ class EmuShared : public Mutex
|
||||||
int m_Reserved7[4];
|
int m_Reserved7[4];
|
||||||
#endif
|
#endif
|
||||||
bool m_bFirstLaunch;
|
bool m_bFirstLaunch;
|
||||||
bool m_bReserved2;
|
bool m_bClipCursor;
|
||||||
bool m_bReserved3;
|
bool m_bReserved3;
|
||||||
bool m_bReserved4;
|
bool m_bReserved4;
|
||||||
unsigned int m_dwKrnlProcID; // Only used for kernel mode level.
|
unsigned int m_dwKrnlProcID; // Only used for kernel mode level.
|
||||||
int m_DeviceType[4];
|
int m_DeviceType[4];
|
||||||
char m_DeviceControlNames[4][XBOX_CTRL_NUM_BUTTONS][30]; // macro should be num of buttons of dev with highest num buttons
|
char m_DeviceControlNames[4][XBOX_CTRL_NUM_BUTTONS][30]; // macro should be num of buttons of dev with highest num buttons
|
||||||
char m_DeviceName[4][50];
|
char m_DeviceName[4][50];
|
||||||
int m_Reserved99[28]; // Reserve space
|
long m_MoAxisRange;
|
||||||
|
long m_MoWheelRange;
|
||||||
|
int m_Reserved99[26]; // Reserve space
|
||||||
|
|
||||||
// Settings class in memory should not be tampered by third-party.
|
// Settings class in memory should not be tampered by third-party.
|
||||||
// Third-party program should only be allow to edit settings.ini file.
|
// Third-party program should only be allow to edit settings.ini file.
|
||||||
|
|
|
@ -76,7 +76,7 @@ void ipc_send_gui_update(IPC_UPDATE_GUI command, const unsigned int value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ipc_send_kernel_update(IPC_UPDATE_KERNEL command, const unsigned int value, const unsigned int hwnd)
|
void ipc_send_kernel_update(IPC_UPDATE_KERNEL command, const int value, const unsigned int hwnd)
|
||||||
{
|
{
|
||||||
// Don't send if GUI process didn't create kernel process.
|
// Don't send if GUI process didn't create kernel process.
|
||||||
if (hwnd == NULL) {
|
if (hwnd == NULL) {
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include "WalkIndexBuffer.h"
|
#include "WalkIndexBuffer.h"
|
||||||
#include "core\kernel\common\strings.hpp" // For uem_str
|
#include "core\kernel\common\strings.hpp" // For uem_str
|
||||||
#include "common\input\SdlJoystick.h"
|
#include "common\input\SdlJoystick.h"
|
||||||
|
#include "common\input\DInputKeyboardMouse.h"
|
||||||
#include "common/util/strConverter.hpp" // for utf8_to_utf16
|
#include "common/util/strConverter.hpp" // for utf8_to_utf16
|
||||||
#include "VertexShaderSource.h"
|
#include "VertexShaderSource.h"
|
||||||
|
|
||||||
|
@ -81,6 +82,7 @@ using namespace std::literals::chrono_literals;
|
||||||
|
|
||||||
// Global(s)
|
// Global(s)
|
||||||
HWND g_hEmuWindow = NULL; // rendering window
|
HWND g_hEmuWindow = NULL; // rendering window
|
||||||
|
bool g_bClipCursor = false; // indicates that the mouse cursor should be confined inside the rendering window
|
||||||
IDirect3DDevice *g_pD3DDevice = nullptr; // Direct3D Device
|
IDirect3DDevice *g_pD3DDevice = nullptr; // Direct3D Device
|
||||||
|
|
||||||
// Static Variable(s)
|
// Static Variable(s)
|
||||||
|
@ -675,6 +677,18 @@ void DrawUEM(HWND hWnd)
|
||||||
EndPaint(hWnd, &ps);
|
EndPaint(hWnd, &ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CxbxClipCursor(HWND hWnd)
|
||||||
|
{
|
||||||
|
RECT wnd_rect;
|
||||||
|
GetWindowRect(hWnd, &wnd_rect);
|
||||||
|
ClipCursor(&wnd_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CxbxReleaseCursor()
|
||||||
|
{
|
||||||
|
ClipCursor(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
inline DWORD GetXboxCommonResourceType(const xbox::DWORD XboxResource_Common)
|
inline DWORD GetXboxCommonResourceType(const xbox::DWORD XboxResource_Common)
|
||||||
{
|
{
|
||||||
DWORD dwCommonType = XboxResource_Common & X_D3DCOMMON_TYPE_MASK;
|
DWORD dwCommonType = XboxResource_Common & X_D3DCOMMON_TYPE_MASK;
|
||||||
|
@ -1844,6 +1858,7 @@ static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar
|
||||||
{
|
{
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
{
|
{
|
||||||
|
CxbxReleaseCursor();
|
||||||
DeleteObject(g_hBgBrush);
|
DeleteObject(g_hBgBrush);
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
return D3D_OK; // = 0
|
return D3D_OK; // = 0
|
||||||
|
@ -1928,6 +1943,18 @@ static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar
|
||||||
{
|
{
|
||||||
VertexBufferConverter.PrintStats();
|
VertexBufferConverter.PrintStats();
|
||||||
}
|
}
|
||||||
|
else if (wParam == VK_F3)
|
||||||
|
{
|
||||||
|
g_bClipCursor = !g_bClipCursor;
|
||||||
|
g_EmuShared->SetClipCursorFlag(&g_bClipCursor);
|
||||||
|
|
||||||
|
if (g_bClipCursor) {
|
||||||
|
CxbxClipCursor(hWnd);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CxbxReleaseCursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (wParam == VK_F6)
|
else if (wParam == VK_F6)
|
||||||
{
|
{
|
||||||
// For some unknown reason, F6 isn't handled in WndMain::WndProc
|
// For some unknown reason, F6 isn't handled in WndMain::WndProc
|
||||||
|
@ -1990,10 +2017,55 @@ static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_bClipCursor) {
|
||||||
|
CxbxClipCursor(hWnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_MOVE:
|
||||||
|
{
|
||||||
|
if (g_bClipCursor) {
|
||||||
|
CxbxClipCursor(hWnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_MOUSELEAVE:
|
||||||
|
{
|
||||||
|
DInput::mo_leave_wnd = true;
|
||||||
|
g_bIsTrackingMoLeave = false;
|
||||||
|
g_bIsTrackingMoMove = true;
|
||||||
|
ShowCursor(TRUE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
{
|
||||||
|
if (g_bClipCursor) {
|
||||||
|
CxbxClipCursor(hWnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_bIsTrackingMoLeave) {
|
||||||
|
TRACKMOUSEEVENT tme;
|
||||||
|
tme.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||||
|
tme.hwndTrack = hWnd;
|
||||||
|
tme.dwFlags = TME_LEAVE;
|
||||||
|
TrackMouseEvent(&tme);
|
||||||
|
g_bIsTrackingMoLeave = true;
|
||||||
|
ShowCursor(FALSE);
|
||||||
|
|
||||||
|
if (g_bIsTrackingMoMove) {
|
||||||
|
DInput::mo_leave_wnd = false;
|
||||||
|
g_bIsTrackingMoMove = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
|
CxbxReleaseCursor();
|
||||||
DestroyWindow(hWnd);
|
DestroyWindow(hWnd);
|
||||||
CxbxKrnlShutDown();
|
CxbxKrnlShutDown();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -681,6 +681,9 @@ void CxbxKrnlEmulate(unsigned int reserved_systems, blocks_reserved_t blocks_res
|
||||||
//g_EmuShared->SetIsReady(true);
|
//g_EmuShared->SetIsReady(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize ClipCursor flag from EmuShared */
|
||||||
|
g_EmuShared->GetClipCursorFlag(&g_bClipCursor);
|
||||||
|
|
||||||
/* Initialize popup message management from kernel side. */
|
/* Initialize popup message management from kernel side. */
|
||||||
log_init_popup_msg();
|
log_init_popup_msg();
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,7 @@ bool CxbxIsElevated();
|
||||||
extern uint32_t CxbxKrnl_KernelThunkTable[379];
|
extern uint32_t CxbxKrnl_KernelThunkTable[379];
|
||||||
|
|
||||||
extern bool g_bIsWine;
|
extern bool g_bIsWine;
|
||||||
|
extern bool g_bClipCursor;
|
||||||
extern bool g_CxbxPrintUEM;
|
extern bool g_CxbxPrintUEM;
|
||||||
extern ULONG g_CxbxFatalErrorCode;
|
extern ULONG g_CxbxFatalErrorCode;
|
||||||
|
|
||||||
|
|
|
@ -37,35 +37,45 @@
|
||||||
|
|
||||||
// Windows dialog procedure for the input menu
|
// Windows dialog procedure for the input menu
|
||||||
static INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
static INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
// Window procedure of the subclass
|
||||||
|
LRESULT CALLBACK WindowsCtrlSubProcNumericFilter(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
|
||||||
HWND g_ChildWnd = NULL;
|
HWND g_ChildWnd = NULL;
|
||||||
|
static bool g_bHasOptChanges = false;
|
||||||
|
|
||||||
|
|
||||||
void SyncInputSettings(int port_num, int dev_type)
|
void SyncInputSettings(int port_num, int dev_type, bool is_opt)
|
||||||
{
|
{
|
||||||
if (g_ChildWnd) {
|
if (g_ChildWnd) {
|
||||||
// Sync updated input to kernel process to use run-time settings.
|
if (!is_opt) {
|
||||||
g_EmuShared->SetInputDevTypeSettings(&g_Settings->m_input[port_num].Type, port_num);
|
// Sync updated input to kernel process to use run-time settings.
|
||||||
|
g_EmuShared->SetInputDevTypeSettings(&g_Settings->m_input_port[port_num].Type, port_num);
|
||||||
|
|
||||||
if (dev_type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
|
if (dev_type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
|
||||||
std::string dev_name = g_Settings->m_input[port_num].DeviceName;
|
std::string dev_name = g_Settings->m_input_port[port_num].DeviceName;
|
||||||
std::string profile_name = g_Settings->m_input[port_num].ProfileName;
|
std::string profile_name = g_Settings->m_input_port[port_num].ProfileName;
|
||||||
|
|
||||||
g_EmuShared->SetInputDevNameSettings(dev_name.c_str(), port_num);
|
g_EmuShared->SetInputDevNameSettings(dev_name.c_str(), port_num);
|
||||||
auto it = std::find_if(g_Settings->m_input_profiles[dev_type].begin(),
|
auto it = std::find_if(g_Settings->m_input_profiles[dev_type].begin(),
|
||||||
g_Settings->m_input_profiles[dev_type].end(), [&profile_name](const auto& profile) {
|
g_Settings->m_input_profiles[dev_type].end(), [&profile_name](const auto &profile) {
|
||||||
if (profile.ProfileName == profile_name) {
|
if (profile.ProfileName == profile_name) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
if (it != g_Settings->m_input_profiles[dev_type].end()) {
|
||||||
|
char controls_name[XBOX_CTRL_NUM_BUTTONS][30];
|
||||||
|
for (int index = 0; index < dev_num_buttons[dev_type]; index++) {
|
||||||
|
strncpy(controls_name[index], it->ControlList[index].c_str(), 30);
|
||||||
}
|
}
|
||||||
return false;
|
g_EmuShared->SetInputBindingsSettings(controls_name, XBOX_CTRL_NUM_BUTTONS, port_num);
|
||||||
});
|
|
||||||
if (it != g_Settings->m_input_profiles[dev_type].end()) {
|
|
||||||
char controls_name[XBOX_CTRL_NUM_BUTTONS][30];
|
|
||||||
for (int index = 0; index < dev_num_buttons[dev_type]; index++) {
|
|
||||||
strncpy(controls_name[index], it->ControlList[index].c_str(), 30);
|
|
||||||
}
|
}
|
||||||
g_EmuShared->SetInputBindingsSettings(controls_name, XBOX_CTRL_NUM_BUTTONS, port_num);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
g_EmuShared->SetInputMoAxisSettings(g_Settings->m_input_general.MoAxisRange);
|
||||||
|
g_EmuShared->SetInputMoWheelSettings(g_Settings->m_input_general.MoWheelRange);
|
||||||
|
port_num = PORT_INVALID;
|
||||||
|
}
|
||||||
#if 0 // lle usb
|
#if 0 // lle usb
|
||||||
ipc_send_kernel_update(IPC_UPDATE_KERNEL::CONFIG_INPUT_SYNC, PORT_DEC(Gui2XboxPortArray[port_num]),
|
ipc_send_kernel_update(IPC_UPDATE_KERNEL::CONFIG_INPUT_SYNC, PORT_DEC(Gui2XboxPortArray[port_num]),
|
||||||
reinterpret_cast<std::uintptr_t>(g_ChildWnd));
|
reinterpret_cast<std::uintptr_t>(g_ChildWnd));
|
||||||
|
@ -75,6 +85,15 @@ void SyncInputSettings(int port_num, int dev_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateInputOpt(HWND hwnd)
|
||||||
|
{
|
||||||
|
char buffer[30];
|
||||||
|
SendMessage(GetDlgItem(hwnd, IDC_MOUSE_RANGE), WM_GETTEXT, 30, reinterpret_cast<LPARAM>(buffer));
|
||||||
|
g_Settings->m_input_general.MoAxisRange = std::stol(buffer);
|
||||||
|
SendMessage(GetDlgItem(hwnd, IDC_WHEEL_RANGE), WM_GETTEXT, 30, reinterpret_cast<LPARAM>(buffer));
|
||||||
|
g_Settings->m_input_general.MoWheelRange = std::stol(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
void ShowInputConfig(HWND hwnd, HWND ChildWnd)
|
void ShowInputConfig(HWND hwnd, HWND ChildWnd)
|
||||||
{
|
{
|
||||||
g_InputDeviceManager.Initialize(true);
|
g_InputDeviceManager.Initialize(true);
|
||||||
|
@ -90,20 +109,18 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
|
||||||
{
|
{
|
||||||
case WM_INITDIALOG:
|
case WM_INITDIALOG:
|
||||||
{
|
{
|
||||||
HWND hHandle;
|
|
||||||
|
|
||||||
// Set window icon
|
// Set window icon
|
||||||
SetClassLong(hWndDlg, GCL_HICON, (LONG)LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_CXBX)));
|
SetClassLong(hWndDlg, GCL_HICON, (LONG)LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_CXBX)));
|
||||||
|
|
||||||
for (int i = 0, j = 0; i != 4; i++) {
|
for (int i = 0, j = 0; i != 4; i++) {
|
||||||
hHandle = GetDlgItem(hWndDlg, IDC_DEVICE_PORT1 + i);
|
HWND hHandle = GetDlgItem(hWndDlg, IDC_DEVICE_PORT1 + i);
|
||||||
for (auto str : { "None", "MS Controller Duke", "MS Controller S" }) {
|
for (auto str : { "None", "MS Controller Duke", "MS Controller S" }) {
|
||||||
LRESULT index = SendMessage(hHandle, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(str));
|
LRESULT index = SendMessage(hHandle, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(str));
|
||||||
SendMessage(hHandle, CB_SETITEMDATA, index,
|
SendMessage(hHandle, CB_SETITEMDATA, index,
|
||||||
to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) + j);
|
to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) + j);
|
||||||
if (g_Settings->m_input[i].Type == to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) + j) {
|
if (g_Settings->m_input_port[i].Type == to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) + j) {
|
||||||
SendMessage(hHandle, CB_SETCURSEL, index, 0);
|
SendMessage(hHandle, CB_SETCURSEL, index, 0);
|
||||||
if (g_Settings->m_input[i].Type == to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
|
if (g_Settings->m_input_port[i].Type == to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
|
||||||
EnableWindow(GetDlgItem(hWndDlg, IDC_CONFIGURE_PORT1 + i), FALSE);
|
EnableWindow(GetDlgItem(hWndDlg, IDC_CONFIGURE_PORT1 + i), FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,11 +128,28 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
|
||||||
}
|
}
|
||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto i : { IDC_MOUSE_RANGE, IDC_WHEEL_RANGE }) {
|
||||||
|
HWND hEditControlArray = GetDlgItem(hWndDlg, i);
|
||||||
|
SetWindowSubclass(hEditControlArray, WindowsCtrlSubProcNumericFilter, i, 0);
|
||||||
|
SendMessage(hEditControlArray, EM_SETLIMITTEXT, 6, 0);
|
||||||
|
SendMessage(hEditControlArray, WM_SETTEXT, 0, reinterpret_cast<LPARAM>((i == IDC_MOUSE_RANGE) ?
|
||||||
|
std::to_string(g_Settings->m_input_general.MoAxisRange).c_str() :
|
||||||
|
std::to_string(g_Settings->m_input_general.MoWheelRange).c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset option changes flag
|
||||||
|
g_bHasOptChanges = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
{
|
{
|
||||||
|
if (g_bHasOptChanges) {
|
||||||
|
UpdateInputOpt(hWndDlg);
|
||||||
|
SyncInputSettings(0, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
g_InputDeviceManager.Shutdown();
|
g_InputDeviceManager.Shutdown();
|
||||||
g_ChildWnd = NULL;
|
g_ChildWnd = NULL;
|
||||||
EndDialog(hWndDlg, wParam);
|
EndDialog(hWndDlg, wParam);
|
||||||
|
@ -140,6 +174,11 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
|
||||||
assert(port != -1);
|
assert(port != -1);
|
||||||
HWND hHandle = GetDlgItem(hWndDlg, IDC_DEVICE_PORT1 + port);
|
HWND hHandle = GetDlgItem(hWndDlg, IDC_DEVICE_PORT1 + port);
|
||||||
int DeviceType = SendMessage(hHandle, CB_GETITEMDATA, SendMessage(hHandle, CB_GETCURSEL, 0, 0), 0);
|
int DeviceType = SendMessage(hHandle, CB_GETITEMDATA, SendMessage(hHandle, CB_GETCURSEL, 0, 0), 0);
|
||||||
|
if (g_bHasOptChanges) {
|
||||||
|
UpdateInputOpt(hWndDlg);
|
||||||
|
g_InputDeviceManager.UpdateOpt(true);
|
||||||
|
}
|
||||||
|
|
||||||
switch (DeviceType)
|
switch (DeviceType)
|
||||||
{
|
{
|
||||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE):
|
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE):
|
||||||
|
@ -156,7 +195,7 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
|
||||||
DeviceType < to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX));
|
DeviceType < to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX));
|
||||||
|
|
||||||
// Also inform the kernel process if it exists
|
// Also inform the kernel process if it exists
|
||||||
SyncInputSettings(port, DeviceType);
|
SyncInputSettings(port, DeviceType, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -183,16 +222,66 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
|
||||||
EnableWindow(GetDlgItem(hWndDlg, IDC_CONFIGURE_PORT1 + port), TRUE);
|
EnableWindow(GetDlgItem(hWndDlg, IDC_CONFIGURE_PORT1 + port), TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Settings->m_input[port].Type = dev_type;
|
g_Settings->m_input_port[port].Type = dev_type;
|
||||||
|
|
||||||
// Also inform the kernel process if it exists
|
// Also inform the kernel process if it exists
|
||||||
SyncInputSettings(port, dev_type);
|
SyncInputSettings(port, dev_type, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IDC_MOUSE_RANGE:
|
||||||
|
case IDC_WHEEL_RANGE:
|
||||||
|
{
|
||||||
|
if (HIWORD(wParam) == EN_CHANGE) {
|
||||||
|
g_bHasOptChanges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK WindowsCtrlSubProcNumericFilter(HWND hWnd, UINT uMsg, WPARAM wParam,
|
||||||
|
LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
|
||||||
|
{
|
||||||
|
switch (uMsg)
|
||||||
|
{
|
||||||
|
// Remove the window subclass when this window is destroyed
|
||||||
|
case WM_NCDESTROY:
|
||||||
|
RemoveWindowSubclass(hWnd, WindowsCtrlSubProcNumericFilter, uIdSubclass);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Override the default system behaviour and process WM_CHAR ourselves
|
||||||
|
case WM_GETDLGCODE:
|
||||||
|
if (lParam) {
|
||||||
|
LPMSG lpmsg = reinterpret_cast<LPMSG>(lParam);
|
||||||
|
if (lpmsg->message == WM_CHAR) {
|
||||||
|
return DLGC_WANTCHARS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_CHAR:
|
||||||
|
{
|
||||||
|
// Make sure we only allow decimal numbers and some special keys to delete characters
|
||||||
|
if (!((wParam >= '0' && wParam <= '9')
|
||||||
|
|| wParam == VK_CANCEL
|
||||||
|
|| wParam == VK_CLEAR
|
||||||
|
|| wParam == VK_DELETE
|
||||||
|
|| wParam == VK_BACK))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Don't allow pasting operations, they can be used to bypass the filtering done in WM_CHAR
|
||||||
|
case WM_PASTE:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,10 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
GUIDELINES DESIGNINFO
|
GUIDELINES DESIGNINFO
|
||||||
BEGIN
|
BEGIN
|
||||||
|
IDD_INPUT_CFG, DIALOG
|
||||||
|
BEGIN
|
||||||
|
END
|
||||||
|
|
||||||
IDD_VIRTUAL_SBC_FEEDBACK, DIALOG
|
IDD_VIRTUAL_SBC_FEEDBACK, DIALOG
|
||||||
BEGIN
|
BEGIN
|
||||||
LEFTMARGIN, 7
|
LEFTMARGIN, 7
|
||||||
|
@ -83,7 +87,7 @@ END
|
||||||
// Dialog
|
// Dialog
|
||||||
//
|
//
|
||||||
|
|
||||||
IDD_INPUT_CFG DIALOGEX 0, 0, 243, 124
|
IDD_INPUT_CFG DIALOGEX 0, 0, 243, 175
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
CAPTION "Cxbx-Reloaded : Input Configuration"
|
CAPTION "Cxbx-Reloaded : Input Configuration"
|
||||||
FONT 8, "Verdana", 0, 0, 0x1
|
FONT 8, "Verdana", 0, 0, 0x1
|
||||||
|
@ -101,6 +105,11 @@ BEGIN
|
||||||
LTEXT "Port 2",IDC_STATIC,23,48,20,10
|
LTEXT "Port 2",IDC_STATIC,23,48,20,10
|
||||||
LTEXT "Port 3",IDC_STATIC,23,69,20,10
|
LTEXT "Port 3",IDC_STATIC,23,69,20,10
|
||||||
LTEXT "Port 4",IDC_STATIC,23,90,20,10
|
LTEXT "Port 4",IDC_STATIC,23,90,20,10
|
||||||
|
GROUPBOX "Options",IDC_INPUT_OPTIONS,13,119,217,49,WS_GROUP,WS_EX_CLIENTEDGE
|
||||||
|
EDITTEXT IDC_MOUSE_RANGE,95,129,121,14
|
||||||
|
EDITTEXT IDC_WHEEL_RANGE,95,147,121,14
|
||||||
|
LTEXT "Mouse axis range",IDC_STATIC,23,129,69,14,SS_CENTERIMAGE
|
||||||
|
LTEXT "Mouse wheel range",IDC_STATIC,23,146,68,14,SS_CENTERIMAGE
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_XID_DUKE_CFG DIALOGEX 0, 0, 528, 280
|
IDD_XID_DUKE_CFG DIALOGEX 0, 0, 528, 280
|
||||||
|
@ -531,6 +540,11 @@ BEGIN
|
||||||
0
|
0
|
||||||
END
|
END
|
||||||
|
|
||||||
|
IDD_INPUT_CFG AFX_DIALOG_LAYOUT
|
||||||
|
BEGIN
|
||||||
|
0
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -679,7 +693,7 @@ BEGIN
|
||||||
END
|
END
|
||||||
MENUITEM "Use Loader Executable", ID_USELOADEREXEC,MFT_STRING,MFS_ENABLED
|
MENUITEM "Use Loader Executable", ID_USELOADEREXEC,MFT_STRING,MFS_ENABLED
|
||||||
MENUITEM "Ignore Invalid Xbe Signature", ID_SETTINGS_IGNOREINVALIDXBESIG,MFT_STRING,MFS_ENABLED
|
MENUITEM "Ignore Invalid Xbe Signature", ID_SETTINGS_IGNOREINVALIDXBESIG,MFT_STRING,MFS_ENABLED
|
||||||
MENUITEM "Ignore Invalid Xbe Sections", ID_SETTINGS_IGNOREINVALIDXBESEC, MFT_STRING, MFS_ENABLED
|
MENUITEM "Ignore Invalid Xbe Sections", ID_SETTINGS_IGNOREINVALIDXBESEC,MFT_STRING,MFS_ENABLED
|
||||||
MENUITEM "Allow Admin Privilege", ID_SETTINGS_ALLOWADMINPRIVILEGE,MFT_STRING,MFS_ENABLED
|
MENUITEM "Allow Admin Privilege", ID_SETTINGS_ALLOWADMINPRIVILEGE,MFT_STRING,MFS_ENABLED
|
||||||
MENUITEM "", -1, MFT_SEPARATOR
|
MENUITEM "", -1, MFT_SEPARATOR
|
||||||
MENUITEM "Reset To Defaults", ID_SETTINGS_INITIALIZE,MFT_STRING,MFS_ENABLED
|
MENUITEM "Reset To Defaults", ID_SETTINGS_INITIALIZE,MFT_STRING,MFS_ENABLED
|
||||||
|
|
|
@ -304,6 +304,9 @@
|
||||||
#define IDC_RUMBLE_TEST 1302
|
#define IDC_RUMBLE_TEST 1302
|
||||||
#define IDC_NETWORK_ADAPTER 1303
|
#define IDC_NETWORK_ADAPTER 1303
|
||||||
#define IDC_LOG_POPUP_TESTCASE 1304
|
#define IDC_LOG_POPUP_TESTCASE 1304
|
||||||
|
#define IDC_INPUT_OPTIONS 1305
|
||||||
|
#define IDC_MOUSE_RANGE 1306
|
||||||
|
#define IDC_WHEEL_RANGE 1307
|
||||||
#define ID_FILE_EXIT 40005
|
#define ID_FILE_EXIT 40005
|
||||||
#define ID_HELP_ABOUT 40008
|
#define ID_HELP_ABOUT 40008
|
||||||
#define ID_EMULATION_START 40009
|
#define ID_EMULATION_START 40009
|
||||||
|
@ -374,7 +377,7 @@
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 136
|
#define _APS_NEXT_RESOURCE_VALUE 136
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40117
|
#define _APS_NEXT_COMMAND_VALUE 40117
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1305
|
#define _APS_NEXT_CONTROL_VALUE 1308
|
||||||
#define _APS_NEXT_SYMED_VALUE 109
|
#define _APS_NEXT_SYMED_VALUE 109
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue