Finish mouse emulation support with overlay and bugfixes

This commit is contained in:
Cameron Gutman
2019-05-19 13:10:42 -07:00
parent fc8d5d5799
commit 674220087f
3 changed files with 59 additions and 24 deletions
+34 -24
View File
@@ -5,6 +5,7 @@
#include "path.h" #include "path.h"
#include <QtGlobal> #include <QtGlobal>
#include <QtMath>
#include <QDir> #include <QDir>
#define VK_0 0x30 #define VK_0 0x30
@@ -35,10 +36,10 @@
#define MOUSE_EMULATION_POLLING_INTERVAL 50 #define MOUSE_EMULATION_POLLING_INTERVAL 50
// Determines how fast the mouse will move each interval // Determines how fast the mouse will move each interval
#define MOUSE_EMULATION_MOTION_MULTIPLIER 6 #define MOUSE_EMULATION_MOTION_MULTIPLIER 4
// Determines the maximum motion amount before allowing movement // Determines the maximum motion amount before allowing movement
#define MOUSE_EMULATION_DEADZONE 3 #define MOUSE_EMULATION_DEADZONE 2
const int SdlInputHandler::k_ButtonMap[] = { const int SdlInputHandler::k_ButtonMap[] = {
A_FLAG, B_FLAG, X_FLAG, Y_FLAG, A_FLAG, B_FLAG, X_FLAG, Y_FLAG,
@@ -127,7 +128,10 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, NvComputer*, int s
SdlInputHandler::~SdlInputHandler() SdlInputHandler::~SdlInputHandler()
{ {
for (int i = 0; i < MAX_GAMEPADS; i++) { for (int i = 0; i < MAX_GAMEPADS; i++) {
SDL_RemoveTimer(m_GamepadState[i].mouseEmulationTimer); if (m_GamepadState[i].mouseEmulationTimer != 0) {
Session::get()->notifyMouseEmulationMode(false);
SDL_RemoveTimer(m_GamepadState[i].mouseEmulationTimer);
}
if (m_GamepadState[i].haptic != nullptr) { if (m_GamepadState[i].haptic != nullptr) {
SDL_HapticClose(m_GamepadState[i].haptic); SDL_HapticClose(m_GamepadState[i].haptic);
} }
@@ -691,13 +695,9 @@ Uint32 SdlInputHandler::mouseEmulationTimerCallback(Uint32 interval, void *param
float deltaX; float deltaX;
float deltaY; float deltaY;
// Produce a base vector for mouse movement // Produce a base vector for mouse movement with increased speed as we deviate further from center
deltaX = rawX / 32766.0f * MOUSE_EMULATION_MOTION_MULTIPLIER; deltaX = qPow(rawX / 32766.0f * MOUSE_EMULATION_MOTION_MULTIPLIER, 3);
deltaY = rawY / 32766.0f * MOUSE_EMULATION_MOTION_MULTIPLIER; deltaY = qPow(rawY / 32766.0f * MOUSE_EMULATION_MOTION_MULTIPLIER, 3);
// Move faster as the stick moves further from center
deltaX *= qAbs(deltaX);
deltaY *= qAbs(deltaY);
// Enforce deadzones // Enforce deadzones
deltaX = qAbs(deltaX) > MOUSE_EMULATION_DEADZONE ? deltaX - MOUSE_EMULATION_DEADZONE : 0; deltaX = qAbs(deltaX) > MOUSE_EMULATION_DEADZONE ? deltaX - MOUSE_EMULATION_DEADZONE : 0;
@@ -768,7 +768,10 @@ void SdlInputHandler::handleControllerAxisEvent(SDL_ControllerAxisEvent* event)
SDL_PeepEvents(&nextEvent, 1, SDL_GETEVENT, SDL_CONTROLLERAXISMOTION, SDL_CONTROLLERAXISMOTION); SDL_PeepEvents(&nextEvent, 1, SDL_GETEVENT, SDL_CONTROLLERAXISMOTION, SDL_CONTROLLERAXISMOTION);
} }
sendGamepadState(state); // Only send the gamepad state to the host if it's not in mouse emulation mode
if (state->mouseEmulationTimer == 0) {
sendGamepadState(state);
}
} }
void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* event) void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* event)
@@ -779,6 +782,8 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve
} }
if (event->state == SDL_PRESSED) { if (event->state == SDL_PRESSED) {
state->buttons |= k_ButtonMap[event->button];
if (event->button == SDL_CONTROLLER_BUTTON_START) { if (event->button == SDL_CONTROLLER_BUTTON_START) {
state->lastStartDownTime = SDL_GetTicks(); state->lastStartDownTime = SDL_GetTicks();
} }
@@ -804,23 +809,30 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve
else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) { else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) {
LiSendScrollEvent(-1); LiSendScrollEvent(-1);
} }
return;
} }
} }
else { else {
state->buttons &= ~k_ButtonMap[event->button];
if (event->button == SDL_CONTROLLER_BUTTON_START) { if (event->button == SDL_CONTROLLER_BUTTON_START) {
if (SDL_GetTicks() - state->lastStartDownTime > MOUSE_EMULATION_LONG_PRESS_TIME) { if (SDL_GetTicks() - state->lastStartDownTime > MOUSE_EMULATION_LONG_PRESS_TIME) {
if (state->mouseEmulationTimer != 0) { if (state->mouseEmulationTimer != 0) {
SDL_RemoveTimer(state->mouseEmulationTimer); SDL_RemoveTimer(state->mouseEmulationTimer);
state->mouseEmulationTimer = 0; state->mouseEmulationTimer = 0;
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Mouse emulation deactivated"); "Mouse emulation deactivated");
Session::get()->notifyMouseEmulationMode(false);
} }
else { else {
// Send the start button up event to the host, since we won't do it below
sendGamepadState(state);
state->mouseEmulationTimer = SDL_AddTimer(MOUSE_EMULATION_POLLING_INTERVAL, SdlInputHandler::mouseEmulationTimerCallback, state); state->mouseEmulationTimer = SDL_AddTimer(MOUSE_EMULATION_POLLING_INTERVAL, SdlInputHandler::mouseEmulationTimerCallback, state);
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Mouse emulation active"); "Mouse emulation active");
Session::get()->notifyMouseEmulationMode(true);
} }
} }
} }
@@ -840,18 +852,9 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve
else if (event->button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) { else if (event->button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) {
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X2); LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X2);
} }
return;
} }
} }
if (event->state == SDL_PRESSED) {
state->buttons |= k_ButtonMap[event->button];
}
else {
state->buttons &= ~k_ButtonMap[event->button];
}
// Handle Start+Select+L1+R1 as a gamepad quit combo // Handle Start+Select+L1+R1 as a gamepad quit combo
if (state->buttons == (PLAY_FLAG | BACK_FLAG | LB_FLAG | RB_FLAG)) { if (state->buttons == (PLAY_FLAG | BACK_FLAG | LB_FLAG | RB_FLAG)) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
@@ -869,7 +872,10 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve
return; return;
} }
sendGamepadState(state); // Only send the gamepad state to the host if it's not in mouse emulation mode
if (state->mouseEmulationTimer == 0) {
sendGamepadState(state);
}
} }
void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* event) void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* event)
@@ -974,7 +980,11 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
else if (event->type == SDL_CONTROLLERDEVICEREMOVED) { else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
state = findStateForGamepad(event->which); state = findStateForGamepad(event->which);
if (state != NULL) { if (state != NULL) {
SDL_RemoveTimer(state->mouseEmulationTimer); if (state->mouseEmulationTimer != 0) {
Session::get()->notifyMouseEmulationMode(false);
SDL_RemoveTimer(state->mouseEmulationTimer);
}
SDL_GameControllerClose(state->controller); SDL_GameControllerClose(state->controller);
if (state->haptic != nullptr) { if (state->haptic != nullptr) {
SDL_HapticClose(state->haptic); SDL_HapticClose(state->haptic);
+22
View File
@@ -130,6 +130,11 @@ void Session::clConnectionStatusUpdate(int connectionStatus)
return; return;
} }
if (s_ActiveSession->m_MouseEmulationRefCount > 0) {
// Don't display the overlay if mouse emulation is already using it
return;
}
switch (connectionStatus) switch (connectionStatus)
{ {
case CONN_STATUS_POOR: case CONN_STATUS_POOR:
@@ -307,6 +312,7 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere
m_UnexpectedTermination(true), // Failure prior to streaming is unexpected m_UnexpectedTermination(true), // Failure prior to streaming is unexpected
m_InputHandler(nullptr), m_InputHandler(nullptr),
m_InputHandlerLock(0), m_InputHandlerLock(0),
m_MouseEmulationRefCount(0),
m_OpusDecoder(nullptr), m_OpusDecoder(nullptr),
m_AudioRenderer(nullptr), m_AudioRenderer(nullptr),
m_AudioSampleCount(0), m_AudioSampleCount(0),
@@ -825,6 +831,22 @@ void Session::toggleFullscreen()
} }
} }
void Session::notifyMouseEmulationMode(bool enabled)
{
m_MouseEmulationRefCount += enabled ? 1 : -1;
SDL_assert(m_MouseEmulationRefCount >= 0);
// We re-use the status update overlay for mouse mode notification
if (m_MouseEmulationRefCount > 0) {
strcpy(m_OverlayManager.getOverlayText(Overlay::OverlayStatusUpdate), "Gamepad mouse mode active\nLong press Start to deactivate");
m_OverlayManager.setOverlayTextUpdated(Overlay::OverlayStatusUpdate);
m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, true);
}
else {
m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, false);
}
}
void Session::exec(int displayOriginX, int displayOriginY) void Session::exec(int displayOriginX, int displayOriginY)
{ {
m_DisplayOriginX = displayOriginX; m_DisplayOriginX = displayOriginX;
+3
View File
@@ -77,6 +77,8 @@ private:
void toggleFullscreen(); void toggleFullscreen();
void notifyMouseEmulationMode(bool enabled);
void updateOptimalWindowDisplayMode(); void updateOptimalWindowDisplayMode();
static static
@@ -141,6 +143,7 @@ private:
bool m_UnexpectedTermination; bool m_UnexpectedTermination;
SdlInputHandler* m_InputHandler; SdlInputHandler* m_InputHandler;
SDL_SpinLock m_InputHandlerLock; SDL_SpinLock m_InputHandlerLock;
int m_MouseEmulationRefCount;
int m_ActiveVideoFormat; int m_ActiveVideoFormat;
int m_ActiveVideoWidth; int m_ActiveVideoWidth;