#pragma once #include "settings/streamingpreferences.h" #include "backend/computermanager.h" #include struct GamepadState { SDL_GameController* controller; SDL_JoystickID jsId; short index; #if !SDL_VERSION_ATLEAST(2, 0, 9) SDL_Haptic* haptic; int hapticMethod; int hapticEffectId; #endif SDL_TimerID mouseEmulationTimer; uint32_t lastStartDownTime; #if SDL_VERSION_ATLEAST(2, 0, 14) uint8_t gyroReportPeriodMs; float lastGyroEventData[SDL_arraysize(SDL_ControllerSensorEvent::data)]; uint32_t lastGyroEventTime; uint8_t accelReportPeriodMs; float lastAccelEventData[SDL_arraysize(SDL_ControllerSensorEvent::data)]; uint32_t lastAccelEventTime; #endif int buttons; short lsX, lsY; short rsX, rsY; unsigned char lt, rt; }; // activeGamepadMask is a short, so we're bounded by the number of mask bits #define MAX_GAMEPADS 16 #define MAX_FINGERS 2 #define GAMEPAD_HAPTIC_METHOD_NONE 0 #define GAMEPAD_HAPTIC_METHOD_LEFTRIGHT 1 #define GAMEPAD_HAPTIC_METHOD_SIMPLERUMBLE 2 #define GAMEPAD_HAPTIC_SIMPLE_HIFREQ_MOTOR_WEIGHT 0.33 #define GAMEPAD_HAPTIC_SIMPLE_LOWFREQ_MOTOR_WEIGHT 0.8 class SdlInputHandler { public: explicit SdlInputHandler(StreamingPreferences& prefs, int streamWidth, int streamHeight); ~SdlInputHandler(); void setWindow(SDL_Window* window); void handleKeyEvent(SDL_KeyboardEvent* event); void handleMouseButtonEvent(SDL_MouseButtonEvent* event); void handleMouseMotionEvent(SDL_MouseMotionEvent* event); void handleMouseWheelEvent(SDL_MouseWheelEvent* event); void handleControllerAxisEvent(SDL_ControllerAxisEvent* event); void handleControllerButtonEvent(SDL_ControllerButtonEvent* event); void handleControllerDeviceEvent(SDL_ControllerDeviceEvent* event); #if SDL_VERSION_ATLEAST(2, 0, 14) void handleControllerSensorEvent(SDL_ControllerSensorEvent* event); void handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent* event); #endif #if SDL_VERSION_ATLEAST(2, 24, 0) void handleJoystickBatteryEvent(SDL_JoyBatteryEvent* event); #endif void handleJoystickArrivalEvent(SDL_JoyDeviceEvent* event); void sendText(QString& string); void rumble(uint16_t controllerNumber, uint16_t lowFreqMotor, uint16_t highFreqMotor); void rumbleTriggers(uint16_t controllerNumber, uint16_t leftTrigger, uint16_t rightTrigger); void setMotionEventState(uint16_t controllerNumber, uint8_t motionType, uint16_t reportRateHz); void setControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g, uint8_t b); void handleTouchFingerEvent(SDL_TouchFingerEvent* event); int getAttachedGamepadMask(); void raiseAllKeys(); void notifyMouseLeave(); void notifyFocusLost(); bool isCaptureActive(); bool isSystemKeyCaptureActive(); void setCaptureActive(bool active); bool isMouseInVideoRegion(int mouseX, int mouseY, int windowWidth = -1, int windowHeight = -1); void updateKeyboardGrabState(); void updatePointerRegionLock(); static QString getUnmappedGamepads(); private: enum KeyCombo { KeyComboQuit, KeyComboUngrabInput, KeyComboToggleFullScreen, KeyComboToggleStatsOverlay, KeyComboToggleMouseMode, KeyComboToggleCursorHide, KeyComboToggleMinimize, KeyComboPasteText, KeyComboTogglePointerRegionLock, KeyComboMax }; GamepadState* findStateForGamepad(SDL_JoystickID id); void sendGamepadState(GamepadState* state); void sendGamepadBatteryState(GamepadState* state, SDL_JoystickPowerLevel level); void handleAbsoluteFingerEvent(SDL_TouchFingerEvent* event); void emulateAbsoluteFingerEvent(SDL_TouchFingerEvent* event); void disableTouchFeedback(); void handleRelativeFingerEvent(SDL_TouchFingerEvent* event); void performSpecialKeyCombo(KeyCombo combo); static Uint32 longPressTimerCallback(Uint32 interval, void* param); static Uint32 mouseEmulationTimerCallback(Uint32 interval, void* param); static Uint32 releaseLeftButtonTimerCallback(Uint32 interval, void* param); static Uint32 releaseRightButtonTimerCallback(Uint32 interval, void* param); static Uint32 dragTimerCallback(Uint32 interval, void* param); SDL_Window* m_Window; bool m_MultiController; bool m_GamepadMouse; bool m_SwapMouseButtons; bool m_ReverseScrollDirection; bool m_SwapFaceButtons; bool m_MouseWasInVideoRegion; bool m_PendingMouseButtonsAllUpOnVideoRegionLeave; bool m_PointerRegionLockActive; bool m_PointerRegionLockToggledByUser; int m_GamepadMask; GamepadState m_GamepadState[MAX_GAMEPADS]; QSet m_KeysDown; bool m_FakeCaptureActive; QString m_OldIgnoreDevices; QString m_OldIgnoreDevicesExcept; QStringList m_IgnoreDeviceGuids; StreamingPreferences::CaptureSysKeysMode m_CaptureSystemKeysMode; int m_MouseCursorCapturedVisibilityState; struct { KeyCombo keyCombo; SDL_Keycode keyCode; SDL_Scancode scanCode; bool enabled; } m_SpecialKeyCombos[KeyComboMax]; SDL_TouchFingerEvent m_LastTouchDownEvent; SDL_TouchFingerEvent m_LastTouchUpEvent; SDL_TimerID m_LongPressTimer; int m_StreamWidth; int m_StreamHeight; bool m_AbsoluteMouseMode; bool m_AbsoluteTouchMode; bool m_DisabledTouchFeedback; SDL_TouchFingerEvent m_TouchDownEvent[MAX_FINGERS]; SDL_TimerID m_LeftButtonReleaseTimer; SDL_TimerID m_RightButtonReleaseTimer; SDL_TimerID m_DragTimer; char m_DragButton; int m_NumFingersDown; static const int k_ButtonMap[]; };