diff --git a/src/frontend-common/common_host_interface.cpp b/src/frontend-common/common_host_interface.cpp index 28b60a74d..71dd12c20 100644 --- a/src/frontend-common/common_host_interface.cpp +++ b/src/frontend-common/common_host_interface.cpp @@ -2866,6 +2866,12 @@ std::unique_ptr CommonHostInterface::OpenPackageFile(const char* pat return FileSystem::OpenFile(full_path.c_str(), real_flags); } +bool CommonHostInterface::SetControllerNavigationButtonState(FrontendCommon::ControllerNavigationButton button, + bool pressed) +{ + return false; +} + #ifdef WITH_DISCORD_PRESENCE void CommonHostInterface::SetDiscordPresenceEnabled(bool enabled) diff --git a/src/frontend-common/common_host_interface.h b/src/frontend-common/common_host_interface.h index 5d70d3f6b..9dd43c1b1 100644 --- a/src/frontend-common/common_host_interface.h +++ b/src/frontend-common/common_host_interface.h @@ -19,7 +19,21 @@ class ControllerInterface; namespace FrontendCommon { class SaveStateSelectorUI; -} + +enum class ControllerNavigationButton : u32 +{ + Activate, // A on XBox Controller, Cross on PS Controller + Cancel, // B on XBox Controller, Circle on PS Controller + LeftShoulder, // LB on XBox Controller, L1 on PS Controller + RightShoulder, // RB on XBox Controller, R1 on PS Controller + DPadLeft, + DPadRight, + DPadUp, + DPadDown, + Count +}; + +} // namespace FrontendCommon class CommonHostInterface : public HostInterface { @@ -234,6 +248,10 @@ public: /// This is the APK for Android builds, or the program directory for standalone builds. virtual std::unique_ptr OpenPackageFile(const char* path, u32 flags) override; + /// Controller navigation, used by fullscreen mode. Returns true if the UI consumed the event, and it should not + /// execute the normal handler. + bool SetControllerNavigationButtonState(FrontendCommon::ControllerNavigationButton button, bool pressed); + /// Toggles fast forward state. bool IsFastForwardEnabled() const { return m_fast_forward_enabled; } void SetFastForwardEnabled(bool enabled); diff --git a/src/frontend-common/sdl_controller_interface.cpp b/src/frontend-common/sdl_controller_interface.cpp index fea1f3581..5686f2ca0 100644 --- a/src/frontend-common/sdl_controller_interface.cpp +++ b/src/frontend-common/sdl_controller_interface.cpp @@ -673,10 +673,37 @@ bool SDLControllerInterface::HandleControllerButtonEvent(const SDL_ControllerBut if (it == m_controllers.end()) return false; + static constexpr std::array + nav_button_mapping = {{ + FrontendCommon::ControllerNavigationButton::Activate, // SDL_CONTROLLER_BUTTON_A + FrontendCommon::ControllerNavigationButton::Cancel, // SDL_CONTROLLER_BUTTON_B + FrontendCommon::ControllerNavigationButton::Count, // SDL_CONTROLLER_BUTTON_X + FrontendCommon::ControllerNavigationButton::Count, // SDL_CONTROLLER_BUTTON_Y + FrontendCommon::ControllerNavigationButton::Count, // SDL_CONTROLLER_BUTTON_BACK + FrontendCommon::ControllerNavigationButton::Count, // SDL_CONTROLLER_BUTTON_GUIDE + FrontendCommon::ControllerNavigationButton::Count, // SDL_CONTROLLER_BUTTON_START + FrontendCommon::ControllerNavigationButton::Count, // SDL_CONTROLLER_BUTTON_LEFTSTICK + FrontendCommon::ControllerNavigationButton::Count, // SDL_CONTROLLER_BUTTON_RIGHTSTICK + FrontendCommon::ControllerNavigationButton::LeftShoulder, // SDL_CONTROLLER_BUTTON_LEFTSHOULDER + FrontendCommon::ControllerNavigationButton::RightShoulder, // SDL_CONTROLLER_BUTTON_RIGHTSHOULDER + FrontendCommon::ControllerNavigationButton::DPadUp, // SDL_CONTROLLER_BUTTON_DPAD_UP + FrontendCommon::ControllerNavigationButton::DPadDown, // SDL_CONTROLLER_BUTTON_DPAD_DOWN + FrontendCommon::ControllerNavigationButton::DPadLeft, // SDL_CONTROLLER_BUTTON_DPAD_LEFT + FrontendCommon::ControllerNavigationButton::DPadRight, // SDL_CONTROLLER_BUTTON_DPAD_RIGHT + }}; + const bool pressed = (ev->state == SDL_PRESSED); if (DoEventHook(Hook::Type::Button, it->player_id, ev->button, pressed ? 1.0f : 0.0f)) return true; + if (ev->button < nav_button_mapping.size() && + nav_button_mapping[ev->button] != FrontendCommon::ControllerNavigationButton::Count && + m_host_interface->SetControllerNavigationButtonState(nav_button_mapping[ev->button], pressed)) + { + // UI consumed the event + return true; + } + const ButtonCallback& cb = it->button_mapping[ev->button]; if (cb) {