mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2024-12-16 22:23:07 +00:00
Remove mouse throttling code
This should be managed inside moonlight-common-c instead.
This commit is contained in:
parent
332d4433c4
commit
e1c4a488ed
4 changed files with 61 additions and 191 deletions
|
@ -9,17 +9,12 @@
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
|
||||||
#define MOUSE_POLLING_INTERVAL 5
|
|
||||||
|
|
||||||
SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer* computer, int streamWidth, int streamHeight)
|
SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer* computer, int streamWidth, int streamHeight)
|
||||||
: m_MultiController(prefs.multiController),
|
: m_MultiController(prefs.multiController),
|
||||||
m_GamepadMouse(prefs.gamepadMouse),
|
m_GamepadMouse(prefs.gamepadMouse),
|
||||||
m_SwapMouseButtons(prefs.swapMouseButtons),
|
m_SwapMouseButtons(prefs.swapMouseButtons),
|
||||||
m_ReverseScrollDirection(prefs.reverseScrollDirection),
|
m_ReverseScrollDirection(prefs.reverseScrollDirection),
|
||||||
m_SwapFaceButtons(prefs.swapFaceButtons),
|
m_SwapFaceButtons(prefs.swapFaceButtons),
|
||||||
m_BatchMouseMotion(computer->isNvidiaServerSoftware),
|
|
||||||
m_MouseMoveTimer(0),
|
|
||||||
m_MousePositionLock(0),
|
|
||||||
m_MouseWasInVideoRegion(false),
|
m_MouseWasInVideoRegion(false),
|
||||||
m_PendingMouseButtonsAllUpOnVideoRegionLeave(false),
|
m_PendingMouseButtonsAllUpOnVideoRegionLeave(false),
|
||||||
m_PointerRegionLockActive(false),
|
m_PointerRegionLockActive(false),
|
||||||
|
@ -188,25 +183,6 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer* comput
|
||||||
SDL_zero(m_LastTouchDownEvent);
|
SDL_zero(m_LastTouchDownEvent);
|
||||||
SDL_zero(m_LastTouchUpEvent);
|
SDL_zero(m_LastTouchUpEvent);
|
||||||
SDL_zero(m_TouchDownEvent);
|
SDL_zero(m_TouchDownEvent);
|
||||||
SDL_zero(m_MousePositionReport);
|
|
||||||
|
|
||||||
SDL_AtomicSet(&m_MouseDeltaX, 0);
|
|
||||||
SDL_AtomicSet(&m_MouseDeltaY, 0);
|
|
||||||
SDL_AtomicSet(&m_MousePositionUpdated, 0);
|
|
||||||
|
|
||||||
if (m_BatchMouseMotion) {
|
|
||||||
Uint32 pollingInterval = QString(qgetenv("MOUSE_POLLING_INTERVAL")).toUInt();
|
|
||||||
if (pollingInterval == 0) {
|
|
||||||
pollingInterval = MOUSE_POLLING_INTERVAL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Using custom mouse polling interval: %u ms",
|
|
||||||
pollingInterval);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_MouseMoveTimer = SDL_AddTimer(pollingInterval, SdlInputHandler::mouseMoveTimerCallback, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SdlInputHandler::~SdlInputHandler()
|
SdlInputHandler::~SdlInputHandler()
|
||||||
|
@ -226,7 +202,6 @@ SdlInputHandler::~SdlInputHandler()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_RemoveTimer(m_MouseMoveTimer);
|
|
||||||
SDL_RemoveTimer(m_LongPressTimer);
|
SDL_RemoveTimer(m_LongPressTimer);
|
||||||
SDL_RemoveTimer(m_LeftButtonReleaseTimer);
|
SDL_RemoveTimer(m_LeftButtonReleaseTimer);
|
||||||
SDL_RemoveTimer(m_RightButtonReleaseTimer);
|
SDL_RemoveTimer(m_RightButtonReleaseTimer);
|
||||||
|
@ -405,7 +380,14 @@ void SdlInputHandler::setCaptureActive(bool active)
|
||||||
mouseY -= windowY;
|
mouseY -= windowY;
|
||||||
|
|
||||||
if (isMouseInVideoRegion(mouseX, mouseY)) {
|
if (isMouseInVideoRegion(mouseX, mouseY)) {
|
||||||
updateMousePositionReport(mouseX, mouseY);
|
// Synthesize a mouse event to synchronize the cursor
|
||||||
|
SDL_MouseMotionEvent motionEvent = {};
|
||||||
|
motionEvent.type = SDL_MOUSEMOTION;
|
||||||
|
motionEvent.timestamp = SDL_GetTicks();
|
||||||
|
motionEvent.windowID = SDL_GetWindowID(m_Window);
|
||||||
|
motionEvent.x = mouseX;
|
||||||
|
motionEvent.y = mouseY;
|
||||||
|
handleMouseMotionEvent(&motionEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,6 @@
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
#define SDL_CODE_HIDE_CURSOR 1
|
|
||||||
#define SDL_CODE_SHOW_CURSOR 2
|
|
||||||
#define SDL_CODE_UNCAPTURE_MOUSE 3
|
|
||||||
|
|
||||||
struct GamepadState {
|
struct GamepadState {
|
||||||
SDL_GameController* controller;
|
SDL_GameController* controller;
|
||||||
SDL_JoystickID jsId;
|
SDL_JoystickID jsId;
|
||||||
|
@ -87,10 +83,6 @@ public:
|
||||||
|
|
||||||
bool isMouseInVideoRegion(int mouseX, int mouseY, int windowWidth = -1, int windowHeight = -1);
|
bool isMouseInVideoRegion(int mouseX, int mouseY, int windowWidth = -1, int windowHeight = -1);
|
||||||
|
|
||||||
void updateMousePositionReport(int mouseX, int mouseY);
|
|
||||||
|
|
||||||
void flushMousePositionUpdate();
|
|
||||||
|
|
||||||
void updateKeyboardGrabState();
|
void updateKeyboardGrabState();
|
||||||
|
|
||||||
void updatePointerRegionLock();
|
void updatePointerRegionLock();
|
||||||
|
@ -126,9 +118,6 @@ private:
|
||||||
static
|
static
|
||||||
Uint32 longPressTimerCallback(Uint32 interval, void* param);
|
Uint32 longPressTimerCallback(Uint32 interval, void* param);
|
||||||
|
|
||||||
static
|
|
||||||
Uint32 mouseMoveTimerCallback(Uint32 interval, void* param);
|
|
||||||
|
|
||||||
static
|
static
|
||||||
Uint32 mouseEmulationTimerCallback(Uint32 interval, void* param);
|
Uint32 mouseEmulationTimerCallback(Uint32 interval, void* param);
|
||||||
|
|
||||||
|
@ -147,17 +136,7 @@ private:
|
||||||
bool m_SwapMouseButtons;
|
bool m_SwapMouseButtons;
|
||||||
bool m_ReverseScrollDirection;
|
bool m_ReverseScrollDirection;
|
||||||
bool m_SwapFaceButtons;
|
bool m_SwapFaceButtons;
|
||||||
bool m_BatchMouseMotion;
|
|
||||||
SDL_TimerID m_MouseMoveTimer;
|
|
||||||
SDL_atomic_t m_MouseDeltaX;
|
|
||||||
SDL_atomic_t m_MouseDeltaY;
|
|
||||||
|
|
||||||
SDL_SpinLock m_MousePositionLock;
|
|
||||||
struct {
|
|
||||||
int x, y;
|
|
||||||
int windowWidth, windowHeight;
|
|
||||||
} m_MousePositionReport;
|
|
||||||
SDL_atomic_t m_MousePositionUpdated;
|
|
||||||
bool m_MouseWasInVideoRegion;
|
bool m_MouseWasInVideoRegion;
|
||||||
bool m_PendingMouseButtonsAllUpOnVideoRegionLeave;
|
bool m_PendingMouseButtonsAllUpOnVideoRegionLeave;
|
||||||
bool m_PointerRegionLockActive;
|
bool m_PointerRegionLockActive;
|
||||||
|
|
|
@ -62,114 +62,12 @@ void SdlInputHandler::handleMouseButtonEvent(SDL_MouseButtonEvent* event)
|
||||||
button = BUTTON_RIGHT;
|
button = BUTTON_RIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure any pending mouse position update has been sent before we send
|
|
||||||
// our button event. This ensures that the cursor is in the correct location
|
|
||||||
// when the button event is issued.
|
|
||||||
//
|
|
||||||
// On platforms like macOS, the mouse doesn't track when the window isn't
|
|
||||||
// focused. When we gain focus via mouse click, we immediately get a mouse
|
|
||||||
// move event and a mouse button event. If we don't flush here, the button
|
|
||||||
// will probably arrive before the mouse timer issues the position update.
|
|
||||||
flushMousePositionUpdate();
|
|
||||||
|
|
||||||
LiSendMouseButtonEvent(event->state == SDL_PRESSED ?
|
LiSendMouseButtonEvent(event->state == SDL_PRESSED ?
|
||||||
BUTTON_ACTION_PRESS :
|
BUTTON_ACTION_PRESS :
|
||||||
BUTTON_ACTION_RELEASE,
|
BUTTON_ACTION_RELEASE,
|
||||||
button);
|
button);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdlInputHandler::updateMousePositionReport(int mouseX, int mouseY)
|
|
||||||
{
|
|
||||||
int windowWidth, windowHeight;
|
|
||||||
|
|
||||||
// Call SDL_GetWindowSize() before entering the spinlock
|
|
||||||
SDL_GetWindowSize(m_Window, &windowWidth, &windowHeight);
|
|
||||||
|
|
||||||
SDL_AtomicLock(&m_MousePositionLock);
|
|
||||||
m_MousePositionReport.x = mouseX;
|
|
||||||
m_MousePositionReport.y = mouseY;
|
|
||||||
m_MousePositionReport.windowWidth = windowWidth;
|
|
||||||
m_MousePositionReport.windowHeight = windowHeight;
|
|
||||||
SDL_AtomicUnlock(&m_MousePositionLock);
|
|
||||||
SDL_AtomicSet(&m_MousePositionUpdated, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SdlInputHandler::flushMousePositionUpdate()
|
|
||||||
{
|
|
||||||
bool hasNewPosition = SDL_AtomicSet(&m_MousePositionUpdated, 0) != 0;
|
|
||||||
if (hasNewPosition) {
|
|
||||||
// If the lock is held now, the main thread is trying to update
|
|
||||||
// the mouse position. We'll pick up the new position next time.
|
|
||||||
if (SDL_AtomicTryLock(&m_MousePositionLock)) {
|
|
||||||
SDL_Rect src, dst;
|
|
||||||
bool mouseInVideoRegion;
|
|
||||||
|
|
||||||
src.x = src.y = 0;
|
|
||||||
src.w = m_StreamWidth;
|
|
||||||
src.h = m_StreamHeight;
|
|
||||||
|
|
||||||
dst.x = dst.y = 0;
|
|
||||||
dst.w = m_MousePositionReport.windowWidth;
|
|
||||||
dst.h = m_MousePositionReport.windowHeight;
|
|
||||||
|
|
||||||
// Use the stream and window sizes to determine the video region
|
|
||||||
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
|
|
||||||
|
|
||||||
mouseInVideoRegion = isMouseInVideoRegion(m_MousePositionReport.x,
|
|
||||||
m_MousePositionReport.y,
|
|
||||||
m_MousePositionReport.windowWidth,
|
|
||||||
m_MousePositionReport.windowHeight);
|
|
||||||
|
|
||||||
// Clamp motion to the video region
|
|
||||||
short x = qMin(qMax(m_MousePositionReport.x - dst.x, 0), dst.w);
|
|
||||||
short y = qMin(qMax(m_MousePositionReport.y - dst.y, 0), dst.h);
|
|
||||||
|
|
||||||
// Release the spinlock to unblock the main thread
|
|
||||||
SDL_AtomicUnlock(&m_MousePositionLock);
|
|
||||||
|
|
||||||
// Send the mouse position update if one of the following is true:
|
|
||||||
// a) it is in the video region now
|
|
||||||
// b) it just left the video region (to ensure the mouse is clamped to the video boundary)
|
|
||||||
// c) a mouse button is still down from before the cursor left the video region (to allow smooth dragging)
|
|
||||||
Uint32 buttonState = SDL_GetMouseState(nullptr, nullptr);
|
|
||||||
if (buttonState == 0) {
|
|
||||||
if (m_PendingMouseButtonsAllUpOnVideoRegionLeave) {
|
|
||||||
// Tell the main thread to stop capturing the mouse now
|
|
||||||
SDL_Event event;
|
|
||||||
event.type = SDL_USEREVENT;
|
|
||||||
event.user.code = SDL_CODE_UNCAPTURE_MOUSE;
|
|
||||||
SDL_PushEvent(&event);
|
|
||||||
|
|
||||||
m_PendingMouseButtonsAllUpOnVideoRegionLeave = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mouseInVideoRegion || m_MouseWasInVideoRegion || m_PendingMouseButtonsAllUpOnVideoRegionLeave) {
|
|
||||||
LiSendMousePositionEvent(x, y, dst.w, dst.h);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust the cursor visibility if applicable
|
|
||||||
if (mouseInVideoRegion ^ m_MouseWasInVideoRegion) {
|
|
||||||
// We must push an event for the main thread to process, because it's not safe
|
|
||||||
// to directly can SDL_ShowCursor() on the arbitrary thread on which this timer
|
|
||||||
// executes.
|
|
||||||
SDL_Event event;
|
|
||||||
event.type = SDL_USEREVENT;
|
|
||||||
event.user.code = (mouseInVideoRegion && m_MouseCursorCapturedVisibilityState == SDL_DISABLE) ?
|
|
||||||
SDL_CODE_HIDE_CURSOR : SDL_CODE_SHOW_CURSOR;
|
|
||||||
SDL_PushEvent(&event);
|
|
||||||
|
|
||||||
if (!mouseInVideoRegion && buttonState != 0) {
|
|
||||||
// If we still have a button pressed on leave, wait for that to come up
|
|
||||||
// before we stop sending mouse position events.
|
|
||||||
m_PendingMouseButtonsAllUpOnVideoRegionLeave = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_MouseWasInVideoRegion = mouseInVideoRegion;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event)
|
void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event)
|
||||||
{
|
{
|
||||||
if (!isCaptureActive()) {
|
if (!isCaptureActive()) {
|
||||||
|
@ -181,26 +79,63 @@ void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_BatchMouseMotion) {
|
if (m_AbsoluteMouseMode) {
|
||||||
// Batch until the next mouse polling window or we'll get awful
|
int windowWidth, windowHeight;
|
||||||
// input lag everything except GFE 3.14 and 3.15.
|
SDL_GetWindowSize(m_Window, &windowWidth, &windowHeight);
|
||||||
if (m_AbsoluteMouseMode) {
|
|
||||||
updateMousePositionReport(event->x, event->y);
|
SDL_Rect src, dst;
|
||||||
|
bool mouseInVideoRegion;
|
||||||
|
|
||||||
|
src.x = src.y = 0;
|
||||||
|
src.w = m_StreamWidth;
|
||||||
|
src.h = m_StreamHeight;
|
||||||
|
|
||||||
|
dst.x = dst.y = 0;
|
||||||
|
dst.w = windowWidth;
|
||||||
|
dst.h = windowHeight;
|
||||||
|
|
||||||
|
// Use the stream and window sizes to determine the video region
|
||||||
|
StreamUtils::scaleSourceToDestinationSurface(&src, &dst);
|
||||||
|
|
||||||
|
mouseInVideoRegion = isMouseInVideoRegion(event->x,
|
||||||
|
event->y,
|
||||||
|
windowWidth,
|
||||||
|
windowHeight);
|
||||||
|
|
||||||
|
// Clamp motion to the video region
|
||||||
|
short x = qMin(qMax(event->x - dst.x, 0), dst.w);
|
||||||
|
short y = qMin(qMax(event->y - dst.y, 0), dst.h);
|
||||||
|
|
||||||
|
// Send the mouse position update if one of the following is true:
|
||||||
|
// a) it is in the video region now
|
||||||
|
// b) it just left the video region (to ensure the mouse is clamped to the video boundary)
|
||||||
|
// c) a mouse button is still down from before the cursor left the video region (to allow smooth dragging)
|
||||||
|
Uint32 buttonState = SDL_GetMouseState(nullptr, nullptr);
|
||||||
|
if (buttonState == 0) {
|
||||||
|
if (m_PendingMouseButtonsAllUpOnVideoRegionLeave) {
|
||||||
|
// Stop capturing the mouse now
|
||||||
|
SDL_CaptureMouse(SDL_FALSE);
|
||||||
|
m_PendingMouseButtonsAllUpOnVideoRegionLeave = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
if (mouseInVideoRegion || m_MouseWasInVideoRegion || m_PendingMouseButtonsAllUpOnVideoRegionLeave) {
|
||||||
SDL_AtomicAdd(&m_MouseDeltaX, event->xrel);
|
LiSendMousePositionEvent(x, y, dst.w, dst.h);
|
||||||
SDL_AtomicAdd(&m_MouseDeltaY, event->yrel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adjust the cursor visibility if applicable
|
||||||
|
if (mouseInVideoRegion ^ m_MouseWasInVideoRegion) {
|
||||||
|
SDL_ShowCursor((mouseInVideoRegion && m_MouseCursorCapturedVisibilityState == SDL_DISABLE) ? SDL_DISABLE : SDL_ENABLE);
|
||||||
|
if (!mouseInVideoRegion && buttonState != 0) {
|
||||||
|
// If we still have a button pressed on leave, wait for that to come up
|
||||||
|
// before we stop sending mouse position events.
|
||||||
|
m_PendingMouseButtonsAllUpOnVideoRegionLeave = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_MouseWasInVideoRegion = mouseInVideoRegion;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// On Sunshine, we can send input immediately
|
LiSendMouseMoveEvent(event->xrel, event->yrel);
|
||||||
if (m_AbsoluteMouseMode) {
|
|
||||||
updateMousePositionReport(event->x, event->y);
|
|
||||||
flushMousePositionUpdate();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LiSendMouseMoveEvent(event->xrel, event->yrel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,23 +243,6 @@ bool SdlInputHandler::isMouseInVideoRegion(int mouseX, int mouseY, int windowWid
|
||||||
(mouseY >= dst.y && mouseY <= dst.y + dst.h);
|
(mouseY >= dst.y && mouseY <= dst.y + dst.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint32 SdlInputHandler::mouseMoveTimerCallback(Uint32 interval, void *param)
|
|
||||||
{
|
|
||||||
auto me = reinterpret_cast<SdlInputHandler*>(param);
|
|
||||||
|
|
||||||
short deltaX = (short)SDL_AtomicSet(&me->m_MouseDeltaX, 0);
|
|
||||||
short deltaY = (short)SDL_AtomicSet(&me->m_MouseDeltaY, 0);
|
|
||||||
|
|
||||||
if (deltaX != 0 || deltaY != 0) {
|
|
||||||
LiSendMouseMoveEvent(deltaX, deltaY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send mouse position updates if applicable
|
|
||||||
me->flushMousePositionUpdate();
|
|
||||||
|
|
||||||
return interval;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SdlInputHandler::updatePointerRegionLock()
|
void SdlInputHandler::updatePointerRegionLock()
|
||||||
{
|
{
|
||||||
// Pointer region lock is irrelevant in relative mouse mode
|
// Pointer region lock is irrelevant in relative mouse mode
|
||||||
|
|
|
@ -1636,15 +1636,6 @@ void Session::execInternal()
|
||||||
m_VideoDecoder->renderFrameOnMainThread();
|
m_VideoDecoder->renderFrameOnMainThread();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SDL_CODE_HIDE_CURSOR:
|
|
||||||
SDL_ShowCursor(SDL_DISABLE);
|
|
||||||
break;
|
|
||||||
case SDL_CODE_SHOW_CURSOR:
|
|
||||||
SDL_ShowCursor(SDL_ENABLE);
|
|
||||||
break;
|
|
||||||
case SDL_CODE_UNCAPTURE_MOUSE:
|
|
||||||
SDL_CaptureMouse(SDL_FALSE);
|
|
||||||
break;
|
|
||||||
case SDL_CODE_FLUSH_WINDOW_EVENT_BARRIER:
|
case SDL_CODE_FLUSH_WINDOW_EVENT_BARRIER:
|
||||||
m_FlushingWindowEventsRef--;
|
m_FlushingWindowEventsRef--;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue