mirror of
https://github.com/flyinghead/flycast.git
synced 2026-11-07 09:16:10 -10:00
input: rebase absolute mouse motion after relative input (#2528)
[ci skip]
This commit is contained in:
1 parent
59ed35a7ea
commit
b4c38d652e
3 files changed
+144
No files matched your search
@@ -146,6 +146,10 @@ void SetRelativeMousePosition(float xrel, float yrel, u32 mouseId)
|
||||
{
|
||||
if (mouseId >= std::size(mo_x_delta))
|
||||
return;
|
||||
// Relative motion has a different coordinate space. Rebase the next absolute
|
||||
// position instead of replaying movement since the last absolute event.
|
||||
mo_x_prev[mouseId] = -1;
|
||||
mo_y_prev[mouseId] = -1;
|
||||
int width = mo_width;
|
||||
int height = mo_height;
|
||||
if (config::Rotate90)
|
||||
|
||||
@@ -27,6 +27,7 @@ target_sources(${PROJECT_NAME} PRIVATE
|
||||
src/input/ButtonComboTest.cpp
|
||||
src/input/GamepadInputHandlingTest.cpp
|
||||
src/input/MultiBindMappingTest.cpp
|
||||
src/input/MouseTest.cpp
|
||||
src/input/InputDefTest.cpp
|
||||
src/input/InputMappingConfigFileTest.cpp
|
||||
src/input/InputSetTest.cpp
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "cfg/option.h"
|
||||
#include "input/mouse.h"
|
||||
|
||||
class MouseTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
int sensitivity;
|
||||
int stretching;
|
||||
bool rotate;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
sensitivity = config::MouseSensitivity;
|
||||
stretching = config::ScreenStretching;
|
||||
rotate = config::Rotate90;
|
||||
config::MouseSensitivity = 100;
|
||||
config::ScreenStretching = 100;
|
||||
config::Rotate90 = false;
|
||||
// Initialize the window dimensions used by relative input.
|
||||
SetMousePosition(0, 0, 640, 480);
|
||||
resetMouseState();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
resetMouseState();
|
||||
config::MouseSensitivity = sensitivity;
|
||||
config::ScreenStretching = stretching;
|
||||
config::Rotate90 = rotate;
|
||||
}
|
||||
|
||||
static void resetMouseState()
|
||||
{
|
||||
for (unsigned port = 0; port < 4; port++)
|
||||
{
|
||||
mo_x_abs[port] = mo_y_abs[port] = 0;
|
||||
mo_x_prev[port] = mo_y_prev[port] = -1;
|
||||
mo_x_delta[port] = mo_y_delta[port] = mo_wheel_delta[port] = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(MouseTest, AbsoluteMotionUsesWindowScaleAndSensitivity)
|
||||
{
|
||||
config::MouseSensitivity = 125;
|
||||
SetMousePosition(200, 160, 1280, 960);
|
||||
EXPECT_EQ(mo_x_abs[0], 100);
|
||||
EXPECT_EQ(mo_y_abs[0], 80);
|
||||
EXPECT_FLOAT_EQ(mo_x_delta[0], 0);
|
||||
EXPECT_FLOAT_EQ(mo_y_delta[0], 0);
|
||||
|
||||
SetMousePosition(206, 156, 1280, 960);
|
||||
SetMousePosition(202, 158, 1280, 960);
|
||||
EXPECT_EQ(mo_x_abs[0], 101);
|
||||
EXPECT_EQ(mo_y_abs[0], 79);
|
||||
EXPECT_FLOAT_EQ(mo_x_delta[0], 1.25f);
|
||||
EXPECT_FLOAT_EQ(mo_y_delta[0], -1.25f);
|
||||
}
|
||||
|
||||
TEST_F(MouseTest, RelativeMotionAccumulatesAndUpdatesAbsolutePosition)
|
||||
{
|
||||
SetMousePosition(100, 100, 640, 480);
|
||||
config::MouseSensitivity = 50;
|
||||
SetRelativeMousePosition(8, -4);
|
||||
SetRelativeMousePosition(-2, 6);
|
||||
EXPECT_FLOAT_EQ(mo_x_delta[0], 3);
|
||||
EXPECT_FLOAT_EQ(mo_y_delta[0], 1);
|
||||
EXPECT_EQ(mo_x_abs[0], 103);
|
||||
EXPECT_EQ(mo_y_abs[0], 101);
|
||||
}
|
||||
|
||||
TEST_F(MouseTest, ReturningToAbsoluteInputDoesNotReplayConsumedMotion)
|
||||
{
|
||||
SetMousePosition(100, 100, 640, 480);
|
||||
SetRelativeMousePosition(100, 40);
|
||||
// The guest has already consumed the captured movement.
|
||||
mo_x_delta[0] = mo_y_delta[0] = 0;
|
||||
|
||||
SetMousePosition(200, 140, 640, 480);
|
||||
EXPECT_FLOAT_EQ(mo_x_delta[0], 0);
|
||||
EXPECT_FLOAT_EQ(mo_y_delta[0], 0);
|
||||
SetMousePosition(201, 138, 640, 480);
|
||||
EXPECT_FLOAT_EQ(mo_x_delta[0], 1);
|
||||
EXPECT_FLOAT_EQ(mo_y_delta[0], -2);
|
||||
}
|
||||
|
||||
TEST_F(MouseTest, ReturningToAbsoluteInputPreservesPendingFractions)
|
||||
{
|
||||
SetMousePosition(100, 100, 640, 480);
|
||||
config::MouseSensitivity = 25;
|
||||
SetRelativeMousePosition(1, -3);
|
||||
mo_wheel_delta[0] = 0.5f;
|
||||
|
||||
// A restored host position need not match the emulated absolute position.
|
||||
SetMousePosition(300, 200, 640, 480);
|
||||
EXPECT_EQ(mo_x_abs[0], 300);
|
||||
EXPECT_EQ(mo_y_abs[0], 200);
|
||||
EXPECT_FLOAT_EQ(mo_x_delta[0], 0.25f);
|
||||
EXPECT_FLOAT_EQ(mo_y_delta[0], -0.75f);
|
||||
SetMousePosition(302, 204, 640, 480);
|
||||
EXPECT_FLOAT_EQ(mo_x_delta[0], 0.75f);
|
||||
EXPECT_FLOAT_EQ(mo_y_delta[0], 0.25f);
|
||||
EXPECT_FLOAT_EQ(mo_wheel_delta[0], 0.5f);
|
||||
}
|
||||
|
||||
TEST_F(MouseTest, ChangingInputModeOnlyRebasesItsOwnPort)
|
||||
{
|
||||
SetMousePosition(100, 100, 640, 480, 0);
|
||||
SetMousePosition(200, 200, 640, 480, 1);
|
||||
SetRelativeMousePosition(20, -10, 0);
|
||||
SetMousePosition(203, 204, 640, 480, 1);
|
||||
SetMousePosition(120, 90, 640, 480, 0);
|
||||
|
||||
EXPECT_FLOAT_EQ(mo_x_delta[0], 20);
|
||||
EXPECT_FLOAT_EQ(mo_y_delta[0], -10);
|
||||
EXPECT_FLOAT_EQ(mo_x_delta[1], 3);
|
||||
EXPECT_FLOAT_EQ(mo_y_delta[1], 4);
|
||||
}
|
||||
|
||||
TEST_F(MouseTest, ReturningToAbsoluteInputPreservesRotation)
|
||||
{
|
||||
config::Rotate90 = true;
|
||||
SetMousePosition(100, 200, 480, 640);
|
||||
SetRelativeMousePosition(8, 4);
|
||||
EXPECT_FLOAT_EQ(mo_x_delta[0], -4);
|
||||
EXPECT_FLOAT_EQ(mo_y_delta[0], 8);
|
||||
EXPECT_EQ(mo_x_abs[0], 435);
|
||||
EXPECT_EQ(mo_y_abs[0], 108);
|
||||
mo_x_delta[0] = mo_y_delta[0] = 0;
|
||||
|
||||
SetMousePosition(108, 204, 480, 640);
|
||||
EXPECT_FLOAT_EQ(mo_x_delta[0], 0);
|
||||
EXPECT_FLOAT_EQ(mo_y_delta[0], 0);
|
||||
SetMousePosition(110, 207, 480, 640);
|
||||
EXPECT_FLOAT_EQ(mo_x_delta[0], -3);
|
||||
EXPECT_FLOAT_EQ(mo_y_delta[0], 2);
|
||||
}
|
||||
Reference in new issue
Block a user