Use mouse capture for Win32 instead of our global mouse state hack

This commit is contained in:
Cameron Gutman 2021-02-07 12:38:57 -06:00
commit 36dc0f3e3c
4 changed files with 16 additions and 33 deletions

View file

@ -30,7 +30,6 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s
m_StreamHeight(streamHeight),
m_AbsoluteMouseMode(prefs.absoluteMouseMode),
m_AbsoluteTouchMode(prefs.absoluteTouchMode),
m_PendingMouseLeaveButtonUp(0),
m_LeftButtonReleaseTimer(0),
m_RightButtonReleaseTimer(0),
m_DragTimer(0),
@ -270,13 +269,14 @@ void SdlInputHandler::notifyMouseLeave()
{
#ifdef Q_OS_WIN32
// SDL on Windows doesn't send the mouse button up until the mouse re-enters the window
// after leaving it. This breaks some of the Aero snap gestures, so we'll fake it here.
// after leaving it. This breaks some of the Aero snap gestures, so we'll capture it to
// allow us to receive the mouse button up events later.
if (m_AbsoluteMouseMode && isCaptureActive()) {
// NB: Not using SDL_GetGlobalMouseState() because we want our state not the system's
Uint32 mouseState = SDL_GetMouseState(nullptr, nullptr);
for (Uint32 button = SDL_BUTTON_LEFT; button <= SDL_BUTTON_X2; button++) {
if (mouseState & SDL_BUTTON(button)) {
m_PendingMouseLeaveButtonUp = button;
SDL_CaptureMouse(SDL_TRUE);
break;
}
}

View file

@ -7,6 +7,7 @@
#define SDL_CODE_HIDE_CURSOR 1
#define SDL_CODE_SHOW_CURSOR 2
#define SDL_CODE_UNCAPTURE_MOUSE 3
struct GamepadState {
SDL_GameController* controller;
@ -175,7 +176,6 @@ private:
int m_StreamHeight;
bool m_AbsoluteMouseMode;
bool m_AbsoluteTouchMode;
Uint32 m_PendingMouseLeaveButtonUp;
SDL_TouchFingerEvent m_TouchDownEvent[MAX_FINGERS];
SDL_TimerID m_LeftButtonReleaseTimer;

View file

@ -133,7 +133,15 @@ void SdlInputHandler::flushMousePositionUpdate()
// 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) {
m_PendingMouseButtonsAllUpOnVideoRegionLeave = false;
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);
@ -251,33 +259,5 @@ Uint32 SdlInputHandler::mouseMoveTimerCallback(Uint32 interval, void *param)
// Send mouse position updates if applicable
me->flushMousePositionUpdate();
#ifdef Q_OS_WIN32
// See comment in SdlInputHandler::notifyMouseLeave()
if (me->m_AbsoluteMouseMode && me->m_PendingMouseLeaveButtonUp != 0 && me->isCaptureActive()) {
int mouseX, mouseY;
int windowX, windowY;
Uint32 mouseState = SDL_GetGlobalMouseState(&mouseX, &mouseY);
SDL_GetWindowPosition(me->m_Window, &windowX, &windowY);
// If the button is now up, send the synthetic mouse up event
if ((mouseState & SDL_BUTTON(me->m_PendingMouseLeaveButtonUp)) == 0) {
SDL_Event event;
event.button.type = SDL_MOUSEBUTTONUP;
event.button.timestamp = SDL_GetTicks();
event.button.windowID = SDL_GetWindowID(me->m_Window);
event.button.which = 0;
event.button.button = me->m_PendingMouseLeaveButtonUp;
event.button.state = SDL_RELEASED;
event.button.clicks = 1;
event.button.x = mouseX - windowX;
event.button.y = mouseY - windowY;
SDL_PushEvent(&event);
me->m_PendingMouseLeaveButtonUp = 0;
}
}
#endif
return interval;
}

View file

@ -1321,6 +1321,9 @@ void Session::exec(int displayOriginX, int displayOriginY)
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:
m_FlushingWindowEventsRef--;
break;