Skip to content

Commit

Permalink
fix: mouse absolute position tracks client window size
Browse files Browse the repository at this point in the history
  • Loading branch information
ABeltramo committed Jan 12, 2025
1 parent afcee03 commit ed4d059
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 18 deletions.
23 changes: 16 additions & 7 deletions src/moonlight-server/control/input_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,8 @@ static inline float deg2rad(float degree) {
void mouse_move_rel(const MOUSE_MOVE_REL_PACKET &pkt, events::StreamSession &session) {
if (session.mouse->has_value()) {
auto pointer_acceleration = session.client_settings->mouse_acceleration;
short delta_x = boost::endian::big_to_native(pkt.delta_x) * pointer_acceleration;
short delta_y = boost::endian::big_to_native(pkt.delta_y) * pointer_acceleration;
auto delta_x = static_cast<float>(boost::endian::big_to_native(pkt.delta_x)) * pointer_acceleration;
auto delta_y = static_cast<float>(boost::endian::big_to_native(pkt.delta_y)) * pointer_acceleration;
std::visit([delta_x, delta_y](auto &mouse) { mouse.move(delta_x, delta_y); }, session.mouse->value());
} else {
logs::log(logs::warning, "Received MOUSE_MOVE_REL_PACKET but no mouse device is present");
Expand All @@ -248,11 +248,20 @@ void mouse_move_rel(const MOUSE_MOVE_REL_PACKET &pkt, events::StreamSession &ses
void mouse_move_abs(const MOUSE_MOVE_ABS_PACKET &pkt, events::StreamSession &session) {
if (session.mouse->has_value()) {
auto pointer_acceleration = session.client_settings->mouse_acceleration;
float x = boost::endian::big_to_native(pkt.x) * pointer_acceleration;
float y = boost::endian::big_to_native(pkt.y) * pointer_acceleration;
float width = boost::endian::big_to_native(pkt.width);
float height = boost::endian::big_to_native(pkt.height);
std::visit([x, y, width, height](auto &mouse) { mouse.move_abs(x, y, width, height); }, session.mouse->value());
float x = boost::endian::big_to_native(pkt.x);
float y = boost::endian::big_to_native(pkt.y);
float window_width = boost::endian::big_to_native(pkt.width);
float window_height = boost::endian::big_to_native(pkt.height);

auto absolute_x = (x / window_width) * static_cast<float>(session.display_mode.width) * pointer_acceleration;
auto absolute_y = (y / window_height) * static_cast<float>(session.display_mode.height) * pointer_acceleration;

std::visit([absolute_x,
absolute_y,
screen_width = session.display_mode.width,
screen_height = session.display_mode.height](
auto &mouse) { mouse.move_abs(absolute_x, absolute_y, screen_width, screen_height); },
session.mouse->value());
} else {
logs::log(logs::warning, "Received MOUSE_MOVE_ABS_PACKET but no mouse device is present");
}
Expand Down
24 changes: 13 additions & 11 deletions tests/platforms/linux/inputtino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ TEST_CASE("uinput - mouse", "[UINPUT]") {
libevdev_ptr mouse_rel_dev(libevdev_new(), ::libevdev_free);
libevdev_ptr mouse_abs_dev(libevdev_new(), ::libevdev_free);
auto mouse = std::make_shared<std::optional<events::MouseTypes>>(std::move(*Mouse::create()));
auto session = events::StreamSession{.mouse = mouse};
auto session = events::StreamSession{.display_mode = {.width = 1920, .height = 1080}, .mouse = mouse};

link_devnode(mouse_rel_dev.get(), std::get<state::input::Mouse>(mouse->value()).get_nodes()[0]);
link_devnode(mouse_abs_dev.get(), std::get<state::input::Mouse>(mouse->value()).get_nodes()[1]);
Expand All @@ -207,28 +207,30 @@ TEST_CASE("uinput - mouse", "[UINPUT]") {
REQUIRE(events.size() == 2);
REQUIRE_THAT(libevdev_event_type_get_name(events[0]->type), Equals("EV_REL"));
REQUIRE_THAT(libevdev_event_code_get_name(events[0]->type, events[0]->code), Equals("REL_X"));
REQUIRE(10 == mv_packet.delta_x);
REQUIRE(events[0]->value > 0);

REQUIRE_THAT(libevdev_event_type_get_name(events[1]->type), Equals("EV_REL"));
REQUIRE_THAT(libevdev_event_code_get_name(events[1]->type, events[1]->code), Equals("REL_Y"));
REQUIRE(20 == mv_packet.delta_y);
REQUIRE(events[1]->value > 0);
}

SECTION("Mouse move absolute") {
auto mv_packet = pkts::MOUSE_MOVE_ABS_PACKET{.x = boost::endian::native_to_big((short)10),
.y = boost::endian::native_to_big((short)20),
.width = boost::endian::native_to_big((short)1920),
.height = boost::endian::native_to_big((short)1080)};
auto mv_packet = pkts::MOUSE_MOVE_ABS_PACKET{.x = boost::endian::native_to_big((short)100),
.y = boost::endian::native_to_big((short)200),
.width = boost::endian::native_to_big((short)1280),
.height = boost::endian::native_to_big((short)720)};
mv_packet.type = pkts::MOUSE_MOVE_ABS;

control::handle_input(session, {}, &mv_packet);
events = fetch_events_debug(mouse_abs_dev);
REQUIRE(events.size() == 2);
REQUIRE_THAT(libevdev_event_type_get_name(events[0]->type), Equals("EV_ABS"));
REQUIRE_THAT(libevdev_event_code_get_name(events[0]->type, events[0]->code), Equals("ABS_X"));
REQUIRE(events[0]->value > 0);

REQUIRE_THAT(libevdev_event_type_get_name(events[1]->type), Equals("EV_ABS"));
REQUIRE_THAT(libevdev_event_code_get_name(events[1]->type, events[1]->code), Equals("ABS_Y"));
REQUIRE(events[1]->value > 0);
}

SECTION("Mouse press button") {
Expand Down Expand Up @@ -295,8 +297,8 @@ TEST_CASE("uinput - mouse", "[UINPUT]") {
TEST_CASE("uinput - joypad", "[UINPUT]") {
SECTION("OLD Moonlight: create joypad on first packet arrival") {
events::App app = {};
auto session =
events::StreamSession{.event_bus = std::make_shared<events::EventBusType>(), .app = std::make_shared<events::App>(app)};
auto session = events::StreamSession{.event_bus = std::make_shared<events::EventBusType>(),
.app = std::make_shared<events::App>(app)};
short controller_number = 1;
auto c_pkt =
pkts::CONTROLLER_MULTI_PACKET{.controller_number = controller_number, .button_flags = pkts::RIGHT_STICK};
Expand All @@ -311,8 +313,8 @@ TEST_CASE("uinput - joypad", "[UINPUT]") {

SECTION("NEW Moonlight: create joypad with CONTROLLER_ARRIVAL") {
events::App app = {};
auto session =
events::StreamSession{.event_bus = std::make_shared<events::EventBusType>(), .app = std::make_shared<events::App>(app)};
auto session = events::StreamSession{.event_bus = std::make_shared<events::EventBusType>(),
.app = std::make_shared<events::App>(app)};
uint8_t controller_number = 1;
auto c_pkt = pkts::CONTROLLER_ARRIVAL_PACKET{.controller_number = controller_number,
.controller_type = pkts::XBOX,
Expand Down

0 comments on commit ed4d059

Please sign in to comment.