Skip to content

Commit

Permalink
Add a screen focus-tracking mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Nov 26, 2023
1 parent 31c85ae commit b1bc6ca
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
38 changes: 35 additions & 3 deletions Common/UI/Screen.cpp
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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]);
}
Expand Down Expand Up @@ -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<std::recursive_mutex> 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");
}
Expand Down Expand Up @@ -318,12 +343,19 @@ void ScreenManager::processFinishDialog() {
std::lock_guard<std::recursive_mutex> 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()) {
Expand Down
7 changes: 7 additions & 0 deletions Common/UI/Screen.h
Expand Up @@ -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) { }
Expand All @@ -60,6 +65,8 @@ class Screen {
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.
Expand Down

0 comments on commit b1bc6ca

Please sign in to comment.