mirror of
https://github.com/InstanceBrick/nightcap.git
synced 2026-10-23 08:01:53 +02:00
Scale mouse input for high-density windows
This commit is contained in:
1 parent
0b7326d8d1
commit
497cf9ea6c
3 files changed
+75
-14
No files matched your search
@@ -20,7 +20,8 @@ bool ConvertSdlEvent(SDL_Window* window, const SDL_Event& source,
|
||||
destination->payload = QuitEvent{};
|
||||
return true;
|
||||
case SDL_EVENT_WINDOW_RESIZED:
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: {
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
|
||||
case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: {
|
||||
WindowResizedEvent resized;
|
||||
if (!SDL_GetWindowSize(window, &resized.logical_width,
|
||||
&resized.logical_height) ||
|
||||
|
||||
@@ -32,6 +32,12 @@ RobloxInputDispatchResult Result(RobloxInputDispatchState state,
|
||||
return {state, kind, std::move(status)};
|
||||
}
|
||||
|
||||
float ScaleToSurfacePixels(float coordinate, int32_t logical_extent,
|
||||
int32_t pixel_extent) {
|
||||
return coordinate * static_cast<float>(pixel_extent) /
|
||||
static_cast<float>(logical_extent);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AndroidKeyMapping MapSdlKeyToAndroid(uint32_t sdl_scancode) {
|
||||
@@ -493,11 +499,19 @@ RobloxInputDispatchResult RobloxInputRouter::HandleMouseMotionLocked(
|
||||
RobloxInputEventKind::kMouseMotion,
|
||||
Unsupported("native mouse motion is unavailable"));
|
||||
}
|
||||
mouse_x_ = event.x;
|
||||
mouse_y_ = event.y;
|
||||
return NativeResultLocked(sink_.mouse_move(sink_.context, event.x, event.y,
|
||||
event.delta_x, event.delta_y),
|
||||
RobloxInputEventKind::kMouseMotion);
|
||||
mouse_x_ = ScaleToSurfacePixels(event.x, snapshot_.viewport.logical_width,
|
||||
snapshot_.viewport.pixel_width);
|
||||
mouse_y_ = ScaleToSurfacePixels(event.y, snapshot_.viewport.logical_height,
|
||||
snapshot_.viewport.pixel_height);
|
||||
const float delta_x = ScaleToSurfacePixels(
|
||||
event.delta_x, snapshot_.viewport.logical_width,
|
||||
snapshot_.viewport.pixel_width);
|
||||
const float delta_y = ScaleToSurfacePixels(
|
||||
event.delta_y, snapshot_.viewport.logical_height,
|
||||
snapshot_.viewport.pixel_height);
|
||||
return NativeResultLocked(
|
||||
sink_.mouse_move(sink_.context, mouse_x_, mouse_y_, delta_x, delta_y),
|
||||
RobloxInputEventKind::kMouseMotion);
|
||||
}
|
||||
|
||||
RobloxInputDispatchResult RobloxInputRouter::HandleMouseButtonLocked(
|
||||
@@ -513,9 +527,11 @@ RobloxInputDispatchResult RobloxInputRouter::HandleMouseButtonLocked(
|
||||
RobloxInputEventKind::kMouseButton,
|
||||
Unsupported("SDL mouse button has no Android mapping"));
|
||||
}
|
||||
mouse_x_ = event.x;
|
||||
mouse_y_ = event.y;
|
||||
Status status = sink_.mouse_button(sink_.context, event.x, event.y,
|
||||
mouse_x_ = ScaleToSurfacePixels(event.x, snapshot_.viewport.logical_width,
|
||||
snapshot_.viewport.pixel_width);
|
||||
mouse_y_ = ScaleToSurfacePixels(event.y, snapshot_.viewport.logical_height,
|
||||
snapshot_.viewport.pixel_height);
|
||||
Status status = sink_.mouse_button(sink_.context, mouse_x_, mouse_y_,
|
||||
event.pressed, android_button);
|
||||
if (status.ok()) {
|
||||
const auto active = std::find(active_mouse_buttons_.begin(),
|
||||
@@ -538,8 +554,12 @@ RobloxInputDispatchResult RobloxInputRouter::HandleMouseWheelLocked(
|
||||
RobloxInputEventKind::kMouseWheel,
|
||||
Unsupported("vertical native mouse wheel is unavailable"));
|
||||
}
|
||||
mouse_x_ = std::max(0.0f, event.mouse_x);
|
||||
mouse_y_ = std::max(0.0f, event.mouse_y);
|
||||
mouse_x_ = ScaleToSurfacePixels(
|
||||
std::max(0.0f, event.mouse_x), snapshot_.viewport.logical_width,
|
||||
snapshot_.viewport.pixel_width);
|
||||
mouse_y_ = ScaleToSurfacePixels(
|
||||
std::max(0.0f, event.mouse_y), snapshot_.viewport.logical_height,
|
||||
snapshot_.viewport.pixel_height);
|
||||
return NativeResultLocked(
|
||||
sink_.mouse_wheel(sink_.context, mouse_x_, mouse_y_, event.delta_y),
|
||||
RobloxInputEventKind::kMouseWheel);
|
||||
|
||||
@@ -204,8 +204,13 @@ TEST_F(RobloxInputRouterTest, RoutesMouseMotionButtonAndVerticalWheel) {
|
||||
.dispatched());
|
||||
|
||||
ASSERT_EQ(probe_.mouse_moves.size(), 1U);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_moves[0].delta_x, 5.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_moves[0].x, 200.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_moves[0].y, 160.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_moves[0].delta_x, 10.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_moves[0].delta_y, -6.0f);
|
||||
ASSERT_EQ(probe_.mouse_buttons.size(), 1U);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_buttons[0].x, 200.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_buttons[0].y, 160.0f);
|
||||
EXPECT_EQ(probe_.mouse_buttons[0].button, 1);
|
||||
ASSERT_EQ(probe_.mouse_wheels.size(), 1U);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_wheels[0].x, 0.0f);
|
||||
@@ -213,6 +218,41 @@ TEST_F(RobloxInputRouterTest, RoutesMouseMotionButtonAndVerticalWheel) {
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_wheels[0].delta_y, -2.0f);
|
||||
}
|
||||
|
||||
TEST_F(RobloxInputRouterTest,
|
||||
ScalesMouseCoordinatesAfterDisplayScaleChange) {
|
||||
const RobloxInputDispatchResult resize = router_.HandleEvent(
|
||||
Event(platform::WindowResizedEvent{1000, 800, 1250, 1000}));
|
||||
ASSERT_EQ(resize.state, RobloxInputDispatchState::kStateUpdated);
|
||||
|
||||
ASSERT_TRUE(router_
|
||||
.HandleEvent(Event(platform::MouseMotionEvent{
|
||||
400.0f, 240.0f, 8.0f, -4.0f, 0}))
|
||||
.dispatched());
|
||||
ASSERT_TRUE(router_
|
||||
.HandleEvent(Event(platform::MouseButtonEvent{
|
||||
true, SDL_BUTTON_LEFT, 1, 300.0f, 200.0f}))
|
||||
.dispatched());
|
||||
ASSERT_TRUE(router_
|
||||
.HandleEvent(Event(
|
||||
platform::MouseWheelEvent{0.0f, 2.0f, 600.0f, 400.0f}))
|
||||
.dispatched());
|
||||
|
||||
ASSERT_EQ(probe_.mouse_moves.size(), 1U);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_moves[0].x, 500.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_moves[0].y, 300.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_moves[0].delta_x, 10.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_moves[0].delta_y, -5.0f);
|
||||
|
||||
ASSERT_EQ(probe_.mouse_buttons.size(), 1U);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_buttons[0].x, 375.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_buttons[0].y, 250.0f);
|
||||
|
||||
ASSERT_EQ(probe_.mouse_wheels.size(), 1U);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_wheels[0].x, 750.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_wheels[0].y, 500.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_wheels[0].delta_y, 2.0f);
|
||||
}
|
||||
|
||||
TEST_F(RobloxInputRouterTest, ScalesNormalizedTouchAndKeepsStablePointerIds) {
|
||||
EXPECT_TRUE(router_
|
||||
.HandleEvent(Event(platform::TouchEvent{
|
||||
@@ -493,8 +533,8 @@ TEST_F(RobloxInputRouterTest,
|
||||
|
||||
ASSERT_TRUE(result.dispatched());
|
||||
ASSERT_EQ(probe_.mouse_buttons.size(), 1U);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_buttons[0].x, 321.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_buttons[0].y, 123.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_buttons[0].x, 642.0f);
|
||||
EXPECT_FLOAT_EQ(probe_.mouse_buttons[0].y, 246.0f);
|
||||
EXPECT_TRUE(probe_.mouse_buttons[0].pressed);
|
||||
EXPECT_EQ(probe_.mouse_buttons[0].button, 0);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user