mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-09 23:59:27 +01:00
Merge pull request #11363 from TheConfuZzledDude/xinput2-scroll-axis
InputCommon/XInput2: Added an axis output for the scroll wheel
This commit is contained in:
commit
f13f54e3db
@ -49,6 +49,13 @@
|
|||||||
// more responsive. This might be useful as a user-customizable option.
|
// more responsive. This might be useful as a user-customizable option.
|
||||||
#define MOUSE_AXIS_SMOOTHING 1.5f
|
#define MOUSE_AXIS_SMOOTHING 1.5f
|
||||||
|
|
||||||
|
// The scroll axis value should decay a lot faster than the mouse axes since
|
||||||
|
// it should ideally register each click of the scroll wheel. Decreasing this
|
||||||
|
// value makes it more likely that a scroll wheel input is registered, but less
|
||||||
|
// likely to differentiate between different inputs, while increasing it will
|
||||||
|
// more cleanly separate each scroll wheel click, but risks dropping some inputs
|
||||||
|
#define SCROLL_AXIS_DECAY 1.1f
|
||||||
|
|
||||||
namespace ciface::XInput2
|
namespace ciface::XInput2
|
||||||
{
|
{
|
||||||
// This function will add zero or more KeyboardMouse objects to devices.
|
// This function will add zero or more KeyboardMouse objects to devices.
|
||||||
@ -74,6 +81,7 @@ void PopulateDevices(void* const hwnd)
|
|||||||
|
|
||||||
XIDeviceInfo* all_masters;
|
XIDeviceInfo* all_masters;
|
||||||
XIDeviceInfo* current_master;
|
XIDeviceInfo* current_master;
|
||||||
|
double scroll_increment = 1.0f;
|
||||||
int num_masters;
|
int num_masters;
|
||||||
|
|
||||||
all_masters = XIQueryDevice(dpy, XIAllMasterDevices, &num_masters);
|
all_masters = XIQueryDevice(dpy, XIAllMasterDevices, &num_masters);
|
||||||
@ -81,12 +89,26 @@ void PopulateDevices(void* const hwnd)
|
|||||||
for (int i = 0; i < num_masters; i++)
|
for (int i = 0; i < num_masters; i++)
|
||||||
{
|
{
|
||||||
current_master = &all_masters[i];
|
current_master = &all_masters[i];
|
||||||
|
|
||||||
if (current_master->use == XIMasterPointer)
|
if (current_master->use == XIMasterPointer)
|
||||||
{
|
{
|
||||||
|
// We need to query the master for the scroll wheel's increment, since the increment used
|
||||||
|
// varies depending on what input driver is being used. For example, xf86-libinput uses 120.0.
|
||||||
|
for (int j = 0; j < current_master->num_classes; j++)
|
||||||
|
{
|
||||||
|
if (current_master->classes[j]->type == XIScrollClass)
|
||||||
|
{
|
||||||
|
XIScrollClassInfo* scroll_event =
|
||||||
|
reinterpret_cast<XIScrollClassInfo*>(current_master->classes[j]);
|
||||||
|
scroll_increment = scroll_event->increment;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Since current_master is a master pointer, its attachment must
|
// Since current_master is a master pointer, its attachment must
|
||||||
// be a master keyboard.
|
// be a master keyboard.
|
||||||
g_controller_interface.AddDevice(std::make_shared<KeyboardMouse>(
|
g_controller_interface.AddDevice(
|
||||||
(Window)hwnd, xi_opcode, current_master->deviceid, current_master->attachment));
|
std::make_shared<KeyboardMouse>((Window)hwnd, xi_opcode, current_master->deviceid,
|
||||||
|
current_master->attachment, scroll_increment));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,8 +150,10 @@ void KeyboardMouse::SelectEventsForDevice(XIEventMask* mask, int deviceid)
|
|||||||
XIFreeDeviceInfo(all_slaves);
|
XIFreeDeviceInfo(all_slaves);
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyboardMouse::KeyboardMouse(Window window, int opcode, int pointer, int keyboard)
|
KeyboardMouse::KeyboardMouse(Window window, int opcode, int pointer, int keyboard,
|
||||||
: m_window(window), xi_opcode(opcode), pointer_deviceid(pointer), keyboard_deviceid(keyboard)
|
double scroll_increment)
|
||||||
|
: m_window(window), xi_opcode(opcode), pointer_deviceid(pointer), keyboard_deviceid(keyboard),
|
||||||
|
scroll_increment(scroll_increment)
|
||||||
{
|
{
|
||||||
// The cool thing about each KeyboardMouse object having its own Display
|
// The cool thing about each KeyboardMouse object having its own Display
|
||||||
// is that each one gets its own separate copy of the X11 event stream,
|
// is that each one gets its own separate copy of the X11 event stream,
|
||||||
@ -195,14 +219,21 @@ KeyboardMouse::KeyboardMouse(Window window, int opcode, int pointer, int keyboar
|
|||||||
for (int i = 0; i != 4; ++i)
|
for (int i = 0; i != 4; ++i)
|
||||||
AddInput(new Cursor(!!(i & 2), !!(i & 1), (i & 2) ? &m_state.cursor.y : &m_state.cursor.x));
|
AddInput(new Cursor(!!(i & 2), !!(i & 1), (i & 2) ? &m_state.cursor.y : &m_state.cursor.x));
|
||||||
|
|
||||||
// Mouse Axis, X-/+ and Y-/+
|
// Mouse Axis, X-/+, Y-/+ and Z-/+
|
||||||
for (int i = 0; i != 4; ++i)
|
AddInput(new Axis(0, false, &m_state.axis.x));
|
||||||
AddInput(new Axis(!!(i & 2), !!(i & 1), (i & 2) ? &m_state.axis.y : &m_state.axis.x));
|
AddInput(new Axis(0, true, &m_state.axis.x));
|
||||||
|
AddInput(new Axis(1, false, &m_state.axis.y));
|
||||||
|
AddInput(new Axis(1, true, &m_state.axis.y));
|
||||||
|
AddInput(new Axis(2, false, &m_state.axis.z));
|
||||||
|
AddInput(new Axis(2, true, &m_state.axis.z));
|
||||||
|
|
||||||
// Relative Mouse, X-/+ and Y-/+
|
// Relative Mouse, X-/+, Y-/+ and Z-/+
|
||||||
for (int i = 0; i != 4; ++i)
|
AddInput(new RelativeMouse(0, false, &m_state.relative_mouse.x));
|
||||||
AddInput(new RelativeMouse(!!(i & 2), !!(i & 1),
|
AddInput(new RelativeMouse(0, true, &m_state.relative_mouse.x));
|
||||||
(i & 2) ? &m_state.relative_mouse.y : &m_state.relative_mouse.x));
|
AddInput(new RelativeMouse(1, false, &m_state.relative_mouse.y));
|
||||||
|
AddInput(new RelativeMouse(1, true, &m_state.relative_mouse.y));
|
||||||
|
AddInput(new RelativeMouse(2, false, &m_state.relative_mouse.z));
|
||||||
|
AddInput(new RelativeMouse(2, true, &m_state.relative_mouse.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyboardMouse::~KeyboardMouse()
|
KeyboardMouse::~KeyboardMouse()
|
||||||
@ -256,7 +287,7 @@ void KeyboardMouse::UpdateInput()
|
|||||||
XFlush(m_display);
|
XFlush(m_display);
|
||||||
|
|
||||||
// for the axis controls
|
// for the axis controls
|
||||||
float delta_x = 0.0f, delta_y = 0.0f;
|
float delta_x = 0.0f, delta_y = 0.0f, delta_z = 0.0f;
|
||||||
double delta_delta;
|
double delta_delta;
|
||||||
bool mouse_moved = false;
|
bool mouse_moved = false;
|
||||||
|
|
||||||
@ -293,26 +324,39 @@ void KeyboardMouse::UpdateInput()
|
|||||||
m_state.keyboard[dev_event->detail / 8] &= ~(1 << (dev_event->detail % 8));
|
m_state.keyboard[dev_event->detail / 8] &= ~(1 << (dev_event->detail % 8));
|
||||||
break;
|
break;
|
||||||
case XI_RawMotion:
|
case XI_RawMotion:
|
||||||
|
{
|
||||||
mouse_moved = true;
|
mouse_moved = true;
|
||||||
|
|
||||||
// always safe because there is always at least one byte in
|
float values[4] = {};
|
||||||
// raw_event->valuators.mask, and if a bit is set in the mask,
|
size_t value_idx = 0;
|
||||||
// then the value in raw_values is also available.
|
|
||||||
if (XIMaskIsSet(raw_event->valuators.mask, 0))
|
// We only care about the first 4 axes, which should always be available at minimum
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
delta_delta = raw_event->raw_values[0];
|
if (XIMaskIsSet(raw_event->valuators.mask, i))
|
||||||
// test for inf and nan
|
{
|
||||||
if (delta_delta == delta_delta && 1 + delta_delta != delta_delta)
|
values[i] = raw_event->raw_values[value_idx++];
|
||||||
delta_x += delta_delta;
|
}
|
||||||
}
|
|
||||||
if (XIMaskIsSet(raw_event->valuators.mask, 1))
|
|
||||||
{
|
|
||||||
delta_delta = raw_event->raw_values[1];
|
|
||||||
// test for inf and nan
|
|
||||||
if (delta_delta == delta_delta && 1 + delta_delta != delta_delta)
|
|
||||||
delta_y += delta_delta;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delta_delta = values[0];
|
||||||
|
// test for inf and nan
|
||||||
|
if (delta_delta == delta_delta && 1 + delta_delta != delta_delta)
|
||||||
|
delta_x += delta_delta;
|
||||||
|
|
||||||
|
delta_delta = values[1];
|
||||||
|
// test for inf and nan
|
||||||
|
if (delta_delta == delta_delta && 1 + delta_delta != delta_delta)
|
||||||
|
delta_y += delta_delta;
|
||||||
|
|
||||||
|
// Scroll wheel input gets scaled to be similar to the mouse axes
|
||||||
|
delta_delta = values[3] * 8.0 / scroll_increment;
|
||||||
|
// test for inf and nan
|
||||||
|
if (delta_delta == delta_delta && 1 + delta_delta != delta_delta)
|
||||||
|
delta_z += delta_delta;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case XI_FocusOut:
|
case XI_FocusOut:
|
||||||
// Clear keyboard state on FocusOut as we will not be receiving KeyRelease events.
|
// Clear keyboard state on FocusOut as we will not be receiving KeyRelease events.
|
||||||
m_state.keyboard.fill(0);
|
m_state.keyboard.fill(0);
|
||||||
@ -324,6 +368,7 @@ void KeyboardMouse::UpdateInput()
|
|||||||
|
|
||||||
m_state.relative_mouse.x = delta_x;
|
m_state.relative_mouse.x = delta_x;
|
||||||
m_state.relative_mouse.y = delta_y;
|
m_state.relative_mouse.y = delta_y;
|
||||||
|
m_state.relative_mouse.z = delta_z;
|
||||||
|
|
||||||
// apply axis smoothing
|
// apply axis smoothing
|
||||||
m_state.axis.x *= MOUSE_AXIS_SMOOTHING;
|
m_state.axis.x *= MOUSE_AXIS_SMOOTHING;
|
||||||
@ -332,6 +377,8 @@ void KeyboardMouse::UpdateInput()
|
|||||||
m_state.axis.y *= MOUSE_AXIS_SMOOTHING;
|
m_state.axis.y *= MOUSE_AXIS_SMOOTHING;
|
||||||
m_state.axis.y += delta_y;
|
m_state.axis.y += delta_y;
|
||||||
m_state.axis.y /= MOUSE_AXIS_SMOOTHING + 1.0f;
|
m_state.axis.y /= MOUSE_AXIS_SMOOTHING + 1.0f;
|
||||||
|
m_state.axis.z += delta_z;
|
||||||
|
m_state.axis.z /= SCROLL_AXIS_DECAY;
|
||||||
|
|
||||||
// Get the absolute position of the mouse pointer
|
// Get the absolute position of the mouse pointer
|
||||||
const bool should_center_mouse =
|
const bool should_center_mouse =
|
||||||
|
@ -28,8 +28,8 @@ private:
|
|||||||
std::array<char, 32> keyboard;
|
std::array<char, 32> keyboard;
|
||||||
unsigned int buttons;
|
unsigned int buttons;
|
||||||
Common::Vec2 cursor;
|
Common::Vec2 cursor;
|
||||||
Common::Vec2 axis;
|
Common::Vec3 axis;
|
||||||
Common::Vec2 relative_mouse;
|
Common::Vec3 relative_mouse;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Key : public Input
|
class Key : public Input
|
||||||
@ -113,7 +113,8 @@ private:
|
|||||||
public:
|
public:
|
||||||
void UpdateInput() override;
|
void UpdateInput() override;
|
||||||
|
|
||||||
KeyboardMouse(Window window, int opcode, int pointer_deviceid, int keyboard_deviceid);
|
KeyboardMouse(Window window, int opcode, int pointer_deviceid, int keyboard_deviceid,
|
||||||
|
double scroll_increment);
|
||||||
~KeyboardMouse();
|
~KeyboardMouse();
|
||||||
|
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
@ -126,6 +127,7 @@ private:
|
|||||||
const int xi_opcode;
|
const int xi_opcode;
|
||||||
const int pointer_deviceid;
|
const int pointer_deviceid;
|
||||||
const int keyboard_deviceid;
|
const int keyboard_deviceid;
|
||||||
|
const double scroll_increment;
|
||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
} // namespace ciface::XInput2
|
} // namespace ciface::XInput2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user