@@ -21,5 +21,6 @@
#include <src/platform/linux/qemu/frame_store.h>
#include <src/platform/linux/qemu/input.h>
#include <src/platform/linux/qemu/session.h>
#include <src/platform/virtualhid_input.h>
using namespace std::literals;
@@ -309,6 +310,35 @@
}
// @tag requirements: [REQ-INP-002]
TEST_F(QemuInputTest, RelativeMouseOnAnAbsoluteGuestIgnoresMouseSetReportsOfOlderPositions) {
connect_input();
auto session = qemu::shared_session(bus->address());
ASSERT_TRUE(session);
auto store = std::make_shared<qemu::frame_store_t>();
auto registration = session->register_listener(0, store);
ASSERT_TRUE(registration);
ASSERT_TRUE(fake->wait_for_listener(0));
qemu::set_capture_console(session, 0, store);
ASSERT_TRUE(input->wait_for_console(5s));
// the guest moves its hardware cursor for every SetAbsPosition, but QEMU's MouseSet reports lag behind
input->abs_mouse(port_640x400, 100.0f, 100.0f);
input->move_mouse(10, 0);
input->move_mouse(10, 0);
ASSERT_TRUE(fake->mouse_set(0, 110, 100, true)); // the report for the first move arrives
input->move_mouse(10, 0);
ASSERT_TRUE(fake->mouse_set(0, 120, 100, true));
input->move_mouse(10, 0);
EXPECT_EQ(calls(), (std::vector<std::string> {"abs 100 100", "abs 110 100", "abs 120 100", "abs 130 100", "abs 140 100"}));
// once our own motion stopped, the guest's position counts again (it may have moved the pointer)
ASSERT_TRUE(fake->mouse_set(0, 300, 200, true));
std::this_thread::sleep_for(150ms);
input->move_mouse(5, 5);
EXPECT_EQ(calls(), (std::vector<std::string> {"abs 100 100", "abs 110 100", "abs 120 100", "abs 130 100", "abs 140 100", "abs 305 205"}));
}
// @tag requirements: [REQ-INP-002]
TEST_F(QemuInputTest, AbsoluteMouseBecomesRelativeMotionFromTheGuestPointer) {
connect_input();
set_absolute(false);
@@ -525,6 +555,17 @@
EXPECT_EQ(qemu::input_count(), 1u);
auto client = platf::allocate_client_input_context(platform_input);
ASSERT_TRUE(client);
// only gamepads use libvirtualhid: no idle keyboard, mouse, touchscreen or pen tablet on the host
const auto &host = platf::virtualhid::get_input_context(platform_input);
EXPECT_FALSE(host.host_pointer_devices);
EXPECT_EQ(host.keyboard, nullptr);
EXPECT_EQ(host.mouse, nullptr);
EXPECT_EQ(platf::virtualhid::get_client_context(client.get()).touch, nullptr);
EXPECT_EQ(platf::virtualhid::get_client_context(client.get()).pen, nullptr);
platf::virtualhid::get_input_context(platform_input).refresh_keyboard();
platf::virtualhid::get_input_context(platform_input).refresh_mouse();
EXPECT_EQ(host.keyboard, nullptr);
EXPECT_EQ(host.mouse, nullptr);
ASSERT_TRUE(qemu_test::wait_until([&]() {
platf::keyboard_update(platform_input, vk_a, false, 0);
@@ -553,12 +594,44 @@
auto other = platf::input();
ASSERT_TRUE(other);
EXPECT_EQ(qemu::input_count(), 0u) << "no QEMU input unless capture = qemu";
EXPECT_TRUE(platf::virtualhid::get_input_context(other).host_pointer_devices) << "libvirtualhid keeps every device";
auto other_client = platf::allocate_client_input_context(other);
ASSERT_TRUE(other_client);
// every event goes to libvirtualhid, none to the VM, and stopping the stream leaves the VM alone
fake->clear_input_calls(0);
platf::keyboard_update(other, vk_a, false, 0);
platf::keyboard_update(other, vk_a, true, 0);
platf::button_mouse(other, BUTTON_LEFT, false);
platf::button_mouse(other, BUTTON_LEFT, true);
platf::abs_mouse(other, port_640x400, 5.0f, 6.0f);
platf::move_mouse(other, 1, 1);
platf::scroll(other, -120);
platf::hscroll(other, 120);
platf::unicode(other, "x", 1);
platf::touch_update(other_client.get(), port_640x400, touch_event(LI_TOUCH_EVENT_DOWN, 1, 0.5f, 0.5f));
platf::pen_update(other_client.get(), port_640x400, {LI_TOUCH_EVENT_HOVER, LI_TOOL_TYPE_PEN, 0, LI_TILT_UNKNOWN, LI_ROT_UNKNOWN, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f});
platf::streaming_will_stop();
std::this_thread::sleep_for(300ms);
EXPECT_TRUE(fake->input_calls(0).empty());
EXPECT_TRUE(fake->input_calls(1).empty());
}
// @tag requirements: [REQ-INP-003]
TEST_F(QemuInputTest, AdvertisesPenAndTouchWithQemuCapture) {
config::input.native_pen_touch = true;
EXPECT_TRUE(platf::get_capabilities() & platf::platform_caps::pen_touch);
config::input.native_pen_touch = false;
EXPECT_FALSE(platf::get_capabilities() & platf::platform_caps::pen_touch);
}
// @tag requirements: [REQ-INP-003, REQ-CMP-001]
TEST_F(QemuInputTest, PenAndTouchFollowLibvirtualhidWithOtherCaptures) {
config::video.capture = "x11";
const auto runtime = platf::virtualhid::create_runtime();
const bool host_devices = runtime && (runtime->capabilities().supports_touchscreen || runtime->capabilities().supports_pen_tablet);
config::input.native_pen_touch = true;
EXPECT_EQ((bool) (platf::get_capabilities() & platf::platform_caps::pen_touch), host_devices) << "as in a build without the QEMU backend";
config::input.native_pen_touch = false;
EXPECT_FALSE(platf::get_capabilities() & platf::platform_caps::pen_touch);
}