diff --git a/Common/UI/Screen.cpp b/Common/UI/Screen.cpp index e263ebfc59..d71336c77a 100644 --- a/Common/UI/Screen.cpp +++ b/Common/UI/Screen.cpp @@ -13,6 +13,15 @@ #include "Core/KeyMap.h" +void Screen::focusChanged(ScreenFocusChange change) { + char *eventName = ""; + switch (change) { + case ScreenFocusChange::FOCUS_LOST_TOP: eventName = "FOCUS_LOST_TOP"; break; + case ScreenFocusChange::FOCUS_BECAME_TOP: eventName = "FOCUS_BECAME_TOP"; break; + } + DEBUG_LOG(SYSTEM, "Screen %s got %s", this->tag(), eventName); +} + ScreenManager::~ScreenManager() { shutdown(); } @@ -68,14 +77,17 @@ void ScreenManager::switchToNext() { Layer temp = {nullptr, 0}; if (!stack_.empty()) { temp = stack_.back(); + temp.screen->focusChanged(ScreenFocusChange::FOCUS_LOST_TOP); stack_.pop_back(); } stack_.push_back(nextStack_.front()); + nextStack_.front().screen->focusChanged(ScreenFocusChange::FOCUS_BECAME_TOP); if (temp.screen) { delete temp.screen; } UI::SetFocusedView(nullptr); + // When will this ever happen? Should handle focus here too? for (size_t i = 1; i < nextStack_.size(); ++i) { stack_.push_back(nextStack_[i]); } @@ -264,17 +276,30 @@ void ScreenManager::push(Screen *screen, int layerFlags) { touch(input); Layer layer = {screen, layerFlags}; - if (nextStack_.empty()) + + if (!stack_.empty()) { + stack_.back().screen->focusChanged(ScreenFocusChange::FOCUS_LOST_TOP); + } + + if (nextStack_.empty()) { + layer.screen->focusChanged(ScreenFocusChange::FOCUS_BECAME_TOP); stack_.push_back(layer); - else + } else { nextStack_.push_back(layer); + } } void ScreenManager::pop() { std::lock_guard guard(inputLock_); - if (stack_.size()) { + if (!stack_.empty()) { + stack_.back().screen->focusChanged(ScreenFocusChange::FOCUS_LOST_TOP); + delete stack_.back().screen; stack_.pop_back(); + + if (!stack_.empty()) { + stack_.back().screen->focusChanged(ScreenFocusChange::FOCUS_LOST_TOP); + } } else { ERROR_LOG(SYSTEM, "Can't pop when stack empty"); } @@ -318,12 +343,19 @@ void ScreenManager::processFinishDialog() { std::lock_guard guard(inputLock_); // Another dialog may have been pushed before the render, so search for it. Screen *caller = dialogParent(dialogFinished_); + bool erased = false; for (size_t i = 0; i < stack_.size(); ++i) { if (stack_[i].screen == dialogFinished_) { + stack_[i].screen->focusChanged(ScreenFocusChange::FOCUS_LOST_TOP); stack_.erase(stack_.begin() + i); + erased = true; } } + if (erased && !stack_.empty()) { + stack_.back().screen->focusChanged(ScreenFocusChange::FOCUS_BECAME_TOP); + } + if (!caller) { ERROR_LOG(SYSTEM, "ERROR: no top screen when finishing dialog"); } else if (caller != topScreen()) { diff --git a/Common/UI/Screen.h b/Common/UI/Screen.h index 4bd77b7ad1..829c2b90ad 100644 --- a/Common/UI/Screen.h +++ b/Common/UI/Screen.h @@ -42,6 +42,11 @@ namespace Draw { class DrawContext; } +enum class ScreenFocusChange { + FOCUS_LOST_TOP, // Another screen was pushed on top + FOCUS_BECAME_TOP, // Became the top screen again +}; + class Screen { public: Screen() : screenManager_(nullptr) { } @@ -60,6 +65,8 @@ public: virtual void deviceLost() {} virtual void deviceRestored() {} + virtual void focusChanged(ScreenFocusChange change); + // Return value of UnsyncTouch is only used to let the overlay screen block touches. virtual bool UnsyncTouch(const TouchInput &touch) = 0; // Return value of UnsyncKey is used to not block certain system keys like volume when unhandled, on Android.