mirror of
https://github.com/moonlight-stream/moonlight-qt
synced 2025-01-09 17:58:43 +00:00
Implement gyro/accel and touchpad input using Sunshine extension
This commit is contained in:
parent
b945c8c2dc
commit
9af58af5e4
4 changed files with 125 additions and 0 deletions
|
@ -312,6 +312,58 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve
|
|||
}
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
|
||||
void SdlInputHandler::handleControllerSensorEvent(SDL_ControllerSensorEvent* event)
|
||||
{
|
||||
GamepadState* state = findStateForGamepad(event->which);
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->sensor) {
|
||||
case SDL_SENSOR_ACCEL:
|
||||
if (state->accelReportPeriodMs && SDL_TICKS_PASSED(event->timestamp, state->lastAccelEventTime + state->accelReportPeriodMs)) {
|
||||
LiSendControllerMotionEvent((uint8_t)state->index, LI_MOTION_TYPE_ACCEL, event->data[0], event->data[1], event->data[2]);
|
||||
state->lastAccelEventTime = event->timestamp;
|
||||
}
|
||||
break;
|
||||
case SDL_SENSOR_GYRO:
|
||||
if (state->gyroReportPeriodMs && SDL_TICKS_PASSED(event->timestamp, state->lastGyroEventTime + state->gyroReportPeriodMs)) {
|
||||
LiSendControllerMotionEvent((uint8_t)state->index, LI_MOTION_TYPE_GYRO, event->data[0], event->data[1], event->data[2]);
|
||||
state->lastGyroEventTime = event->timestamp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SdlInputHandler::handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent* event)
|
||||
{
|
||||
GamepadState* state = findStateForGamepad(event->which);
|
||||
if (state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t eventType;
|
||||
switch (event->type) {
|
||||
case SDL_CONTROLLERTOUCHPADDOWN:
|
||||
eventType = LI_TOUCH_EVENT_DOWN;
|
||||
break;
|
||||
case SDL_CONTROLLERTOUCHPADUP:
|
||||
eventType = LI_TOUCH_EVENT_UP;
|
||||
break;
|
||||
case SDL_CONTROLLERTOUCHPADMOTION:
|
||||
eventType = LI_TOUCH_EVENT_MOVE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
LiSendControllerTouchEvent((uint8_t)state->index, eventType, event->finger, event->x, event->y, event->pressure);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* event)
|
||||
{
|
||||
GamepadState* state;
|
||||
|
@ -580,6 +632,32 @@ void SdlInputHandler::rumbleTriggers(uint16_t controllerNumber, uint16_t leftTri
|
|||
#endif
|
||||
}
|
||||
|
||||
void SdlInputHandler::setMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz)
|
||||
{
|
||||
// Make sure the controller number is within our supported count
|
||||
if (controllerNumber >= MAX_GAMEPADS) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
if (m_GamepadState[controllerNumber].controller != nullptr) {
|
||||
uint8_t reportPeriodMs = reportRateHz ? (1000 / reportRateHz) : 0;
|
||||
|
||||
switch (motionType) {
|
||||
case LI_MOTION_TYPE_ACCEL:
|
||||
m_GamepadState[controllerNumber].accelReportPeriodMs = reportPeriodMs;
|
||||
SDL_GameControllerSetSensorEnabled(m_GamepadState[controllerNumber].controller, SDL_SENSOR_ACCEL, reportRateHz ? SDL_TRUE : SDL_FALSE);
|
||||
break;
|
||||
|
||||
case LI_MOTION_TYPE_GYRO:
|
||||
m_GamepadState[controllerNumber].gyroReportPeriodMs = reportPeriodMs;
|
||||
SDL_GameControllerSetSensorEnabled(m_GamepadState[controllerNumber].controller, SDL_SENSOR_GYRO, reportRateHz ? SDL_TRUE : SDL_FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
QString SdlInputHandler::getUnmappedGamepads()
|
||||
{
|
||||
QString ret;
|
||||
|
|
|
@ -19,6 +19,12 @@ struct GamepadState {
|
|||
SDL_TimerID mouseEmulationTimer;
|
||||
uint32_t lastStartDownTime;
|
||||
|
||||
uint8_t gyroReportPeriodMs;
|
||||
uint32_t lastGyroEventTime;
|
||||
|
||||
uint8_t accelReportPeriodMs;
|
||||
uint32_t lastAccelEventTime;
|
||||
|
||||
int buttons;
|
||||
short lsX, lsY;
|
||||
short rsX, rsY;
|
||||
|
@ -58,6 +64,12 @@ public:
|
|||
|
||||
void handleControllerDeviceEvent(SDL_ControllerDeviceEvent* event);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
void handleControllerSensorEvent(SDL_ControllerSensorEvent* event);
|
||||
|
||||
void handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent* event);
|
||||
#endif
|
||||
|
||||
void handleJoystickArrivalEvent(SDL_JoyDeviceEvent* event);
|
||||
|
||||
void sendText(QString& string);
|
||||
|
@ -66,6 +78,8 @@ public:
|
|||
|
||||
void rumbleTriggers(uint16_t controllerNumber, uint16_t leftTrigger, uint16_t rightTrigger);
|
||||
|
||||
void setMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz);
|
||||
|
||||
void handleTouchFingerEvent(SDL_TouchFingerEvent* event);
|
||||
|
||||
int getAttachedGamepadMask();
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#define SDL_CODE_FLUSH_WINDOW_EVENT_BARRIER 100
|
||||
#define SDL_CODE_GAMECONTROLLER_RUMBLE 101
|
||||
#define SDL_CODE_GAMECONTROLLER_RUMBLE_TRIGGERS 102
|
||||
#define SDL_CODE_GAMECONTROLLER_SET_MOTION_EVENT_STATE 103
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
|
@ -64,6 +65,7 @@ CONNECTION_LISTENER_CALLBACKS Session::k_ConnCallbacks = {
|
|||
Session::clConnectionStatusUpdate,
|
||||
Session::clSetHdrMode,
|
||||
Session::clRumbleTriggers,
|
||||
Session::clSetMotionEventState,
|
||||
};
|
||||
|
||||
Session* Session::s_ActiveSession;
|
||||
|
@ -228,6 +230,19 @@ void Session::clRumbleTriggers(uint16_t controllerNumber, uint16_t leftTrigger,
|
|||
SDL_PushEvent(&rumbleEvent);
|
||||
}
|
||||
|
||||
void Session::clSetMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz)
|
||||
{
|
||||
// We push an event for the main thread to handle in order to properly synchronize
|
||||
// with the removal of game controllers that could result in our game controller
|
||||
// going away during this callback.
|
||||
SDL_Event setMotionEventStateEvent = {};
|
||||
setMotionEventStateEvent.type = SDL_USEREVENT;
|
||||
setMotionEventStateEvent.user.code = SDL_CODE_GAMECONTROLLER_SET_MOTION_EVENT_STATE;
|
||||
setMotionEventStateEvent.user.data1 = (void*)(uintptr_t)controllerNumber;
|
||||
setMotionEventStateEvent.user.data2 = (void*)(uintptr_t)((motionType << 16) | reportRateHz);
|
||||
SDL_PushEvent(&setMotionEventStateEvent);
|
||||
}
|
||||
|
||||
bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
|
||||
SDL_Window* window, int videoFormat, int width, int height,
|
||||
int frameRate, bool enableVsync, bool enableFramePacing, bool testOnly, IVideoDecoder*& chosenDecoder)
|
||||
|
@ -1659,6 +1674,11 @@ void Session::execInternal()
|
|||
(uint16_t)((uintptr_t)event.user.data2 >> 16),
|
||||
(uint16_t)((uintptr_t)event.user.data2 & 0xFFFF));
|
||||
break;
|
||||
case SDL_CODE_GAMECONTROLLER_SET_MOTION_EVENT_STATE:
|
||||
m_InputHandler->setMotionEventState((uint16_t)(uintptr_t)event.user.data1,
|
||||
(uint8_t)((uintptr_t)event.user.data2 >> 16),
|
||||
(uint16_t)((uintptr_t)event.user.data2 & 0xFFFF));
|
||||
break;
|
||||
default:
|
||||
SDL_assert(false);
|
||||
}
|
||||
|
@ -1845,6 +1865,16 @@ void Session::execInternal()
|
|||
presence.runCallbacks();
|
||||
m_InputHandler->handleControllerButtonEvent(&event.cbutton);
|
||||
break;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
case SDL_CONTROLLERSENSORUPDATE:
|
||||
m_InputHandler->handleControllerSensorEvent(&event.csensor);
|
||||
break;
|
||||
case SDL_CONTROLLERTOUCHPADDOWN:
|
||||
case SDL_CONTROLLERTOUCHPADUP:
|
||||
case SDL_CONTROLLERTOUCHPADMOTION:
|
||||
m_InputHandler->handleControllerTouchpadEvent(&event.ctouchpad);
|
||||
break;
|
||||
#endif
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
m_InputHandler->handleControllerDeviceEvent(&event.cdevice);
|
||||
|
|
|
@ -127,6 +127,9 @@ private:
|
|||
static
|
||||
void clRumbleTriggers(uint16_t controllerNumber, uint16_t leftTrigger, uint16_t rightTrigger);
|
||||
|
||||
static
|
||||
void clSetMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz);
|
||||
|
||||
static
|
||||
int arInit(int audioConfiguration,
|
||||
const POPUS_MULTISTREAM_CONFIGURATION opusConfig,
|
||||
|
|
Loading…
Reference in a new issue