From 37387e151f298b1b8e7948d8410a39103f9db782 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 23 Jun 2017 16:43:10 -0700 Subject: [PATCH] Batch mouse movement events to reduce input lag with high polling rate mice --- input.cpp | 12 +++++++++++- main.cpp | 7 ++++--- moonlight.hpp | 8 ++++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/input.cpp b/input.cpp index 2fc0b91..bab7617 100644 --- a/input.cpp +++ b/input.cpp @@ -51,6 +51,13 @@ static char GetModifierFlags(const pp::InputEvent& event) { return flags; } +void MoonlightInstance::ReportMouseMovement() { + if (m_MouseDeltaX != 0 || m_MouseDeltaY != 0) { + LiSendMouseMoveEvent(m_MouseDeltaX, m_MouseDeltaY); + m_MouseDeltaX = m_MouseDeltaY = 0; + } +} + bool MoonlightInstance::HandleInputEvent(const pp::InputEvent& event) { switch (event.GetType()) { case PP_INPUTEVENT_TYPE_MOUSEDOWN: { @@ -77,7 +84,10 @@ bool MoonlightInstance::HandleInputEvent(const pp::InputEvent& event) { pp::MouseInputEvent mouseEvent(event); pp::Point posDelta = mouseEvent.GetMovement(); - LiSendMouseMoveEvent(posDelta.x(), posDelta.y()); + // Wait to report mouse movement until the next input polling window + // to allow batching to occur which reduces overall input lag. + m_MouseDeltaX += posDelta.x(); + m_MouseDeltaY += posDelta.y(); return true; } diff --git a/main.cpp b/main.cpp index 8132e95..c92a6c3 100644 --- a/main.cpp +++ b/main.cpp @@ -85,18 +85,19 @@ void* MoonlightInstance::StopThreadFunc(void* context) { // We also need to stop this thread after the connection thread, because it depends // on being initialized there. - pthread_join(g_Instance->m_GamepadThread, NULL); + pthread_join(g_Instance->m_InputThread, NULL); // Stop the connection LiStopConnection(); return NULL; } -void* MoonlightInstance::GamepadThreadFunc(void* context) { +void* MoonlightInstance::InputThreadFunc(void* context) { MoonlightInstance* me = (MoonlightInstance*)context; while (me->m_Running) { me->PollGamepads(); + me->ReportMouseMovement(); // Poll every 10 ms usleep(10 * 1000); @@ -135,7 +136,7 @@ void* MoonlightInstance::ConnectionThreadFunc(void* context) { // Set running state before starting connection-specific threads me->m_Running = true; - pthread_create(&me->m_GamepadThread, NULL, MoonlightInstance::GamepadThreadFunc, me); + pthread_create(&me->m_InputThread, NULL, MoonlightInstance::InputThreadFunc, me); return NULL; } diff --git a/moonlight.hpp b/moonlight.hpp index ac85f36..95ce03c 100644 --- a/moonlight.hpp +++ b/moonlight.hpp @@ -59,6 +59,8 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock { m_MouseLocked(false), m_WaitingForAllModifiersUp(false), m_AccumulatedTicks(0), + m_MouseDeltaX(0), + m_MouseDeltaY(0), openHttpThread(this) { // This function MUST be used otherwise sockets don't work (nacl_io_init() doesn't work!) nacl_io_init_ppapi(pp_instance(), pp::Module::Get()->get_browser_interface()); @@ -85,6 +87,7 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock { void PairCallback(int32_t /*result*/, int32_t callbackId, pp::VarArray args); bool HandleInputEvent(const pp::InputEvent& event); + void ReportMouseMovement(); void PollGamepads(); @@ -105,7 +108,7 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock { static void ProfilerPrintWarning(const char* message); static void* ConnectionThreadFunc(void* context); - static void* GamepadThreadFunc(void* context); + static void* InputThreadFunc(void* context); static void* StopThreadFunc(void* context); static void ClStageStarting(int stage); @@ -151,7 +154,7 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock { bool m_Running; pthread_t m_ConnectionThread; - pthread_t m_GamepadThread; + pthread_t m_InputThread; pp::Graphics3D m_Graphics3D; pp::VideoDecoder* m_VideoDecoder; @@ -173,6 +176,7 @@ class MoonlightInstance : public pp::Instance, public pp::MouseLock { bool m_MouseLocked; bool m_WaitingForAllModifiersUp; float m_AccumulatedTicks; + int32_t m_MouseDeltaX, m_MouseDeltaY; pp::SimpleThread openHttpThread; };