diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index bd65269eb8..3dd4b5ca01 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -127,10 +127,19 @@ static void AssertCancelCallback(const char *message, void *userdata) { // Handles control rotation due to internal screen rotation. void EmuScreen::UpdatePSPButtons(uint32_t bitsToSet, uint32_t bitsToClear) { + if (!isOnTop_) { + // Auto-release inputs + bitsToSet = 0; + } __CtrlUpdateButtons(bitsToSet, bitsToClear); } void EmuScreen::SetPSPAnalog(int iInternalScreenRotation, int stick, float x, float y) { + if (!isOnTop_) { + x = 0.0f; + y = 0.0f; + } + switch (iInternalScreenRotation) { case ROTATION_LOCKED_HORIZONTAL: // Standard rotation. No change. @@ -539,10 +548,11 @@ void EmuScreen::focusChanged(ScreenFocusChange focusChange) { switch (focusChange) { case ScreenFocusChange::FOCUS_LOST_TOP: g_Config.TimeTracker().Stop(gameID); - g_controlMapper.ReleaseAll(); + isOnTop_ = false; break; case ScreenFocusChange::FOCUS_BECAME_TOP: g_Config.TimeTracker().Start(gameID); + isOnTop_ = true; break; } } @@ -739,37 +749,13 @@ static void ShowFpsLimitNotice() { } void EmuScreen::OnVKey(VirtKey virtualKeyCode, bool down) { + if (!isOnTop_) + return; + auto sc = GetI18NCategory(I18NCat::SCREEN); auto mc = GetI18NCategory(I18NCat::MAPPABLECONTROLS); switch (virtualKeyCode) { - case VIRTKEY_TOGGLE_DEBUGGER: - if (down) { - g_Config.bShowImDebugger = !g_Config.bShowImDebugger; - } - break; - case VIRTKEY_TOGGLE_TILT: - if (down) { - g_Config.bTiltInputEnabled = !g_Config.bTiltInputEnabled; - if (!g_Config.bTiltInputEnabled) { - // Reset whatever got tilted. - switch (g_Config.iTiltInputType) { - case TILT_ANALOG: - __CtrlSetAnalogXY(0, 0, 0); - break; - case TILT_ACTION_BUTTON: - __CtrlUpdateButtons(0, CTRL_CROSS | CTRL_CIRCLE | CTRL_SQUARE | CTRL_TRIANGLE); - break; - case TILT_DPAD: - __CtrlUpdateButtons(0, CTRL_UP | CTRL_DOWN | CTRL_LEFT | CTRL_RIGHT); - break; - case TILT_TRIGGER_BUTTONS: - __CtrlUpdateButtons(0, CTRL_LTRIGGER | CTRL_RTRIGGER); - break; - } - } - } - break; case VIRTKEY_FASTFORWARD: if (down && !NetworkWarnUserIfOnlineAndCantSpeed() && !bootPending_) { /* @@ -826,15 +812,6 @@ void EmuScreen::OnVKey(VirtKey virtualKeyCode, bool down) { } break; - case VIRTKEY_PAUSE: - if (down) { - // Note: We don't check NetworkWarnUserIfOnlineAndCantSpeed, because we can keep - // running in the background of the menu. - pauseTrigger_ = true; - g_controlMapper.ForceReleaseVKey(virtualKeyCode); - } - break; - case VIRTKEY_RESET_EMULATION: if (down) { System_PostUIMessage(UIMessage::REQUEST_GAME_RESET); @@ -913,6 +890,35 @@ void EmuScreen::ProcessVKey(VirtKey virtKey) { auto sc = GetI18NCategory(I18NCat::SCREEN); switch (virtKey) { + case VIRTKEY_PAUSE: + // Note: We don't check NetworkWarnUserIfOnlineAndCantSpeed, because we can keep + // running in the background of the menu. + pauseTrigger_ = true; + break; + + case VIRTKEY_TOGGLE_DEBUGGER: + g_Config.bShowImDebugger = !g_Config.bShowImDebugger; + break; + case VIRTKEY_TOGGLE_TILT: + g_Config.bTiltInputEnabled = !g_Config.bTiltInputEnabled; + if (!g_Config.bTiltInputEnabled) { + // Reset whatever got tilted. + switch (g_Config.iTiltInputType) { + case TILT_ANALOG: + __CtrlSetAnalogXY(0, 0, 0); + break; + case TILT_ACTION_BUTTON: + __CtrlUpdateButtons(0, CTRL_CROSS | CTRL_CIRCLE | CTRL_SQUARE | CTRL_TRIANGLE); + break; + case TILT_DPAD: + __CtrlUpdateButtons(0, CTRL_UP | CTRL_DOWN | CTRL_LEFT | CTRL_RIGHT); + break; + case TILT_TRIGGER_BUTTONS: + __CtrlUpdateButtons(0, CTRL_LTRIGGER | CTRL_RTRIGGER); + break; + } + } + break; case VIRTKEY_OPENCHAT: if (g_Config.bEnableNetworkChat && !g_Config.bShowImDebugger) { UI::EventParams e{}; @@ -1081,6 +1087,9 @@ void EmuScreen::ProcessVKey(VirtKey virtKey) { } void EmuScreen::OnVKeyAnalog(VirtKey virtualKeyCode, float value) { + if (!isOnTop_) + return; + if (virtualKeyCode != VIRTKEY_SPEED_ANALOG) { return; } diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 140057d712..09803941b7 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -166,6 +166,8 @@ private: bool autoLoadFailed_ = false; // to prevent repeat reloads bool readyToFinishBoot_ = false; bool skipBufferEffects_ = false; // cached state, fetched once per frame. + + bool isOnTop_ = true; }; bool MustRunBehind(); diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 3c19b77913..df50233257 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -352,30 +352,32 @@ GamePauseScreen::GamePauseScreen(const Path &filename, bool bootPending) SetExtraAssertInfo(assertStr.c_str()); saveStatePrefix_ = SaveState::GetGamePrefix(g_paramSFO); SaveState::Rescan(saveStatePrefix_); + g_controlMapper.AddListener(this); + createdTime_ = time_now_d(); } GamePauseScreen::~GamePauseScreen() { + g_controlMapper.RemoveListener(this); __DisplaySetWasPaused(); } -bool GamePauseScreen::key(const KeyInput &key) { - bool handled = UIDialogScreen::key(key); +bool GamePauseScreen::UnsyncKey(const KeyInput &key) { + int retval = UIScreen::UnsyncKey(key); + bool pauseTrigger = false; + return retval || g_controlMapper.Key(key, &pauseTrigger); +} - if (!handled && (key.flags & KeyInputFlags::DOWN)) { - // Special case to be able to unpause with a bound pause key. - // Normally we can't bind keys used in the UI. - InputMapping mapping(key.deviceId, key.keyCode); - std::vector pspButtons; - KeyMap::InputMappingToPspButton(mapping, &pspButtons); - for (auto button : pspButtons) { - if (button == VIRTKEY_PAUSE) { - TriggerFinish(DR_CANCEL); - return true; - } - } - return false; +void GamePauseScreen::UnsyncAxis(const AxisInput *axes, size_t count) { + UIScreen::UnsyncAxis(axes, count); + g_controlMapper.Axis(axes, count); +} + +void GamePauseScreen::OnVKey(VirtKey virtualKeyCode, bool down) { + // Simple de-bounce using createdTime_, just to be safe. + if (down && virtualKeyCode == VIRTKEY_PAUSE && time_now_d() > createdTime_ + 0.1) { + finishNextFrame_ = true; + finishNextFrameResult_ = DR_BACK; } - return handled; } void GamePauseScreen::CreateSavestateControls(UI::LinearLayout *leftColumnItems) { diff --git a/UI/PauseScreen.h b/UI/PauseScreen.h index 8cad4a9997..60adc70b56 100644 --- a/UI/PauseScreen.h +++ b/UI/PauseScreen.h @@ -23,17 +23,17 @@ #include "Common/File/Path.h" #include "Common/UI/UIScreen.h" #include "Common/UI/ViewGroup.h" +#include "Core/ControlMapper.h" #include "UI/BaseScreens.h" #include "UI/Screen.h" #include "UI/GameInfoCache.h" -class GamePauseScreen : public UIBaseDialogScreen { +class GamePauseScreen : public UIBaseDialogScreen, protected ControlListener { public: GamePauseScreen(const Path &filename, bool bootPending); ~GamePauseScreen(); void dialogFinished(const Screen *dialog, DialogResult dr) override; - bool key(const KeyInput &key) override; const char *tag() const override { return "GamePause"; } @@ -42,6 +42,12 @@ protected: void update() override; UI::Margins RootMargins() const override; + // For processing of certain mapped keys. + bool UnsyncKey(const KeyInput &key) override; + void UnsyncAxis(const AxisInput *axes, size_t count) override; + + void OnVKey(VirtKey virtualKeyCode, bool down); + private: void CreateSavestateControls(UI::LinearLayout *viewGroup); @@ -77,6 +83,7 @@ private: bool bootPending_ = false; std::string saveStatePrefix_; + double createdTime_ = 0.0; }; std::string GetConfirmExitMessage();