diff --git a/src/util/input_manager.cpp b/src/util/input_manager.cpp index 46a0fd59f..e5ed89b8e 100644 --- a/src/util/input_manager.cpp +++ b/src/util/input_manager.cpp @@ -1394,6 +1394,11 @@ void InputManager::UpdateHostMouseMode() Host::SetMouseMode(wanted_relative_mouse_mode, wanted_hide_host_mouse_cursor); } +bool InputManager::IsRelativeMouseModeActive() +{ + return s_relative_mouse_mode_active; +} + bool InputManager::IsUsingRawInput() { #if defined(_WIN32) @@ -1409,6 +1414,11 @@ void InputManager::SetDisplayWindowSize(float width, float height) s_window_size[1] = height; } +std::pair InputManager::GetDisplayWindowSize() +{ + return std::make_pair(s_window_size[0], s_window_size[1]); +} + void InputManager::SetDefaultSourceConfig(SettingsInterface& si) { si.ClearSection("InputSources"); diff --git a/src/util/input_manager.h b/src/util/input_manager.h index f1617c279..7d595c2b0 100644 --- a/src/util/input_manager.h +++ b/src/util/input_manager.h @@ -350,6 +350,7 @@ void UpdatePointerRelativeDelta(u32 index, InputPointerAxis axis, float d, bool /// Updates host mouse mode (relative/cursor hiding). void UpdateRelativeMouseMode(); void UpdateHostMouseMode(); +bool IsRelativeMouseModeActive(); /// Sets the state of the specified macro button. void SetMacroButtonState(u32 pad, u32 index, bool state); @@ -359,6 +360,7 @@ bool IsUsingRawInput(); /// Updates InputManager's view of the window size, used for clamping raw input coordinates. void SetDisplayWindowSize(float width, float height); +std::pair GetDisplayWindowSize(); /// Restores default configuration. void SetDefaultSourceConfig(SettingsInterface& si); diff --git a/src/util/sdl_input_source.cpp b/src/util/sdl_input_source.cpp index f0468eeaa..2b0444764 100644 --- a/src/util/sdl_input_source.cpp +++ b/src/util/sdl_input_source.cpp @@ -239,6 +239,7 @@ void SDLInputSource::LoadSettings(const SettingsInterface& si) m_controller_enhanced_mode = si.GetBoolValue("InputSources", "SDLControllerEnhancedMode", false); m_controller_ps5_player_led = si.GetBoolValue("InputSources", "SDLPS5PlayerLED", false); + m_controller_touchpad_as_pointer = si.GetBoolValue("InputSources", "SDLTouchpadAsPointer", false); m_sdl_hints = si.GetKeyValueList("SDLHints"); #ifdef __APPLE__ @@ -588,6 +589,9 @@ bool SDLInputSource::IsHandledInputEvent(const SDL_Event* ev) case SDL_CONTROLLERAXISMOTION: case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONUP: + case SDL_CONTROLLERTOUCHPADDOWN: + case SDL_CONTROLLERTOUCHPADUP: + case SDL_CONTROLLERTOUCHPADMOTION: case SDL_JOYAXISMOTION: case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: @@ -647,6 +651,11 @@ bool SDLInputSource::ProcessSDLEvent(const SDL_Event* event) case SDL_CONTROLLERBUTTONUP: return HandleControllerButtonEvent(&event->cbutton); + case SDL_CONTROLLERTOUCHPADDOWN: + case SDL_CONTROLLERTOUCHPADUP: + case SDL_CONTROLLERTOUCHPADMOTION: + return HandleControllerTouchpadEvent(&event->ctouchpad); + case SDL_JOYAXISMOTION: return HandleJoystickAxisEvent(&event->jaxis); @@ -755,6 +764,8 @@ bool SDLInputSource::OpenDevice(int index, bool is_gamecontroller) cd.haptic_left_right_effect = -1; cd.game_controller = gcontroller; cd.joystick = joystick; + cd.last_touch_x = 0.0f; + cd.last_touch_y = 0.0f; if (gcontroller) { @@ -896,6 +907,58 @@ bool SDLInputSource::HandleControllerButtonEvent(const SDL_ControllerButtonEvent return true; } +bool SDLInputSource::HandleControllerTouchpadEvent(const SDL_ControllerTouchpadEvent* ev) +{ + // More than one touchpad? + if (ev->touchpad != 0 || !m_controller_touchpad_as_pointer) + return false; + + auto it = GetControllerDataForJoystickId(ev->which); + if (it == m_controllers.end()) + return false; + + // Limited by InputManager pointers. + const u32 pointer_index = static_cast(it->player_id); + if (pointer_index >= InputManager::MAX_POINTER_DEVICES) + return false; + + // Only looking at the first finger for motion for now. + if (ev->finger == 0) + { + // If down event, reset the position. + if (ev->type == SDL_CONTROLLERTOUCHPADDOWN) + { + it->last_touch_x = ev->x; + it->last_touch_y = ev->y; + } + + const auto& [win_width, win_height] = InputManager::GetDisplayWindowSize(); + const float rel_x = (ev->x - std::exchange(it->last_touch_x, ev->x)) * win_width; + const float rel_y = (ev->y - std::exchange(it->last_touch_y, ev->y)) * win_height; + if (!InputManager::IsRelativeMouseModeActive()) + { + const auto& [current_x, current_y] = InputManager::GetPointerAbsolutePosition(pointer_index); + InputManager::UpdatePointerAbsolutePosition(pointer_index, current_x + rel_x, current_y + rel_y); + } + else + { + if (rel_x != 0.0f) + InputManager::UpdatePointerRelativeDelta(pointer_index, InputPointerAxis::X, rel_x); + if (rel_y != 0.0f) + InputManager::UpdatePointerRelativeDelta(pointer_index, InputPointerAxis::Y, rel_y); + } + } + + // If down/up event, fire the clicked handler. + if (ev->type == SDL_CONTROLLERTOUCHPADDOWN || ev->type == SDL_CONTROLLERTOUCHPADUP) + { + const InputBindingKey key(InputManager::MakePointerButtonKey(pointer_index, static_cast(ev->finger))); + InputManager::InvokeEvents(key, (ev->type == SDL_CONTROLLERTOUCHPADUP) ? 0.0f : ev->pressure); + } + + return true; +} + bool SDLInputSource::HandleJoystickAxisEvent(const SDL_JoyAxisEvent* ev) { auto it = GetControllerDataForJoystickId(ev->which); diff --git a/src/util/sdl_input_source.h b/src/util/sdl_input_source.h index 9bd38f8ec..6b35bc54d 100644 --- a/src/util/sdl_input_source.h +++ b/src/util/sdl_input_source.h @@ -62,6 +62,8 @@ private: int haptic_left_right_effect; int joystick_id; int player_id; + float last_touch_x; + float last_touch_y; bool use_game_controller_rumble; // Used to disable Joystick controls that are used in GameController inputs so we don't get double events @@ -87,6 +89,7 @@ private: bool CloseDevice(int joystick_index); bool HandleControllerAxisEvent(const SDL_ControllerAxisEvent* ev); bool HandleControllerButtonEvent(const SDL_ControllerButtonEvent* ev); + bool HandleControllerTouchpadEvent(const SDL_ControllerTouchpadEvent* ev); bool HandleJoystickAxisEvent(const SDL_JoyAxisEvent* ev); bool HandleJoystickButtonEvent(const SDL_JoyButtonEvent* ev); bool HandleJoystickHatEvent(const SDL_JoyHatEvent* ev); @@ -100,6 +103,7 @@ private: bool m_sdl_subsystem_initialized = false; bool m_controller_enhanced_mode = false; bool m_controller_ps5_player_led = false; + bool m_controller_touchpad_as_pointer = false; #ifdef __APPLE__ bool m_enable_iokit_driver = false;