diff --git a/ext/native/ui/ui_screen.cpp b/ext/native/ui/ui_screen.cpp index 57af678ddd..ef0e0bbce8 100644 --- a/ext/native/ui/ui_screen.cpp +++ b/ext/native/ui/ui_screen.cpp @@ -23,7 +23,7 @@ void UIScreen::DoRecreateViews() { UI::PersistMap persisted; bool persisting = root_ != nullptr; if (persisting) { - root_->PersistData(UI::PERSIST_SAVE, persisted); + root_->PersistData(UI::PERSIST_SAVE, "root", persisted); } delete root_; @@ -34,8 +34,16 @@ void UIScreen::DoRecreateViews() { } recreateViews_ = false; - if (persisting) { - root_->PersistData(UI::PERSIST_RESTORE, persisted); + if (persisting && root_ != nullptr) { + root_->PersistData(UI::PERSIST_RESTORE, "root", persisted); + + // Update layout and refocus so things scroll into view. + // This is for resizing down, when focused on something now offscreen. + UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_); + UI::View *focused = UI::GetFocusedView(); + if (focused) { + root_->SubviewFocused(focused); + } } } } diff --git a/ext/native/ui/view.cpp b/ext/native/ui/view.cpp index 4ec1c965f3..32ba78ae7f 100644 --- a/ext/native/ui/view.cpp +++ b/ext/native/ui/view.cpp @@ -164,6 +164,28 @@ std::string View::Describe() const { } +void View::PersistData(PersistStatus status, std::string anonId, PersistMap &storage) { + // Remember if this view was a focused view. + std::string tag = Tag(); + if (tag.empty()) { + tag = anonId; + } + + const std::string focusedKey = "ViewFocused::" + tag; + switch (status) { + case UI::PERSIST_SAVE: + if (HasFocus()) { + storage[focusedKey].resize(1); + } + break; + case UI::PERSIST_RESTORE: + if (storage.find(focusedKey) != storage.end()) { + SetFocus(); + } + break; + } +} + Point View::GetFocusPosition(FocusDirection dir) { // The +2/-2 is some extra fudge factor to cover for views sitting right next to each other. // Distance zero yields strange results otherwise. diff --git a/ext/native/ui/view.h b/ext/native/ui/view.h index 4b4cbb32d4..aab3761ddd 100644 --- a/ext/native/ui/view.h +++ b/ext/native/ui/view.h @@ -346,7 +346,7 @@ public: virtual std::string Describe() const; virtual void FocusChanged(int focusFlags) {} - virtual void PersistData(PersistStatus status, PersistMap &storage) {} + virtual void PersistData(PersistStatus status, std::string anonId, PersistMap &storage); void Move(Bounds bounds) { bounds_ = bounds; @@ -388,7 +388,7 @@ public: void SetEnabledPtr(bool *enabled) { enabledPtr_ = enabled; enabledMeansDisabled_ = false; } void SetDisabledPtr(bool *disabled) { enabledPtr_ = disabled; enabledMeansDisabled_ = true; } - void SetVisibility(Visibility visibility) { visibility_ = visibility; } + virtual void SetVisibility(Visibility visibility) { visibility_ = visibility; } Visibility GetVisibility() const { return visibility_; } const std::string &Tag() const { return tag_; } diff --git a/ext/native/ui/viewgroup.cpp b/ext/native/ui/viewgroup.cpp index 3140141ac1..47010c38ef 100644 --- a/ext/native/ui/viewgroup.cpp +++ b/ext/native/ui/viewgroup.cpp @@ -3,6 +3,7 @@ #include "base/functional.h" #include "base/logging.h" #include "base/mutex.h" +#include "base/stringutil.h" #include "base/timeutil.h" #include "input/keycodes.h" #include "ui/ui_context.h" @@ -75,10 +76,17 @@ void ViewGroup::Clear() { views_.clear(); } -void ViewGroup::PersistData(PersistStatus status, PersistMap &storage) { +void ViewGroup::PersistData(PersistStatus status, std::string anonId, PersistMap &storage) { lock_guard guard(modifyLock_); + + std::string tag = Tag(); + if (tag.empty()) { + tag = anonId; + } + + ITOA stringify; for (size_t i = 0; i < views_.size(); i++) { - views_[i]->PersistData(status, storage); + views_[i]->PersistData(status, tag + "/" + stringify.p((int)i), storage); } } @@ -812,12 +820,12 @@ bool ScrollView::SubviewFocused(View *view) { return true; } -void ScrollView::PersistData(PersistStatus status, PersistMap &storage) { - ViewGroup::PersistData(status, storage); +void ScrollView::PersistData(PersistStatus status, std::string anonId, PersistMap &storage) { + ViewGroup::PersistData(status, anonId, storage); - const std::string &tag = Tag(); + std::string tag = Tag(); if (tag.empty()) { - return; + tag = anonId; } PersistBuffer &buffer = storage["ScrollView::" + tag]; @@ -843,6 +851,16 @@ void ScrollView::PersistData(PersistStatus status, PersistMap &storage) { } } +void ScrollView::SetVisibility(Visibility visibility) { + ViewGroup::SetVisibility(visibility); + + if (visibility == V_GONE) { + // Since this is no longer shown, forget the scroll position. + // For example, this happens when switching tabs. + ScrollTo(0.0f); + } +} + void ScrollView::ScrollTo(float newScrollPos) { scrollTarget_ = newScrollPos; scrollToTarget_ = true; @@ -1084,12 +1102,12 @@ EventReturn TabHolder::OnTabClick(EventParams &e) { return EVENT_DONE; } -void TabHolder::PersistData(PersistStatus status, PersistMap &storage) { - ViewGroup::PersistData(status, storage); +void TabHolder::PersistData(PersistStatus status, std::string anonId, PersistMap &storage) { + ViewGroup::PersistData(status, anonId, storage); - const std::string &tag = Tag(); + std::string tag = Tag(); if (tag.empty()) { - return; + tag = anonId; } PersistBuffer &buffer = storage["TabHolder::" + tag]; diff --git a/ext/native/ui/viewgroup.h b/ext/native/ui/viewgroup.h index a178a94f55..e5cac7a176 100644 --- a/ext/native/ui/viewgroup.h +++ b/ext/native/ui/viewgroup.h @@ -64,7 +64,7 @@ public: virtual void SetBG(const Drawable &bg) { bg_ = bg; } virtual void Clear(); - void PersistData(PersistStatus status, PersistMap &storage) override; + void PersistData(PersistStatus status, std::string anonId, PersistMap &storage) override; View *GetViewByIndex(int index) { return views_[index]; } int GetNumSubviews() const { return (int)views_.size(); } void SetHasDropShadow(bool has) { hasDropShadow_ = has; } @@ -228,7 +228,7 @@ public: scrollToTarget_(false), inertia_(0), lastViewSize_(0.0f), - scrollToTopOnSizeChange_(true) {} + scrollToTopOnSizeChange_(false) {} void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) override; void Layout() override; @@ -246,8 +246,8 @@ public: // Override so that we can scroll to the active one after moving the focus. bool SubviewFocused(View *view) override; - - void PersistData(PersistStatus status, PersistMap &storage) override; + void PersistData(PersistStatus status, std::string anonId, PersistMap &storage) override; + void SetVisibility(Visibility visibility) override; // Quick hack to prevent scrolling to top in some lists void SetScrollToTop(bool t) { scrollToTopOnSizeChange_ = t; } @@ -316,16 +316,18 @@ public: } void SetCurrentTab(int tab) { - tabs_[currentTab_]->SetVisibility(V_GONE); - currentTab_ = tab; - tabs_[currentTab_]->SetVisibility(V_VISIBLE); + if (tab != currentTab_) { + tabs_[currentTab_]->SetVisibility(V_GONE); + currentTab_ = tab; + tabs_[currentTab_]->SetVisibility(V_VISIBLE); + } tabStrip_->SetSelection(tab); } int GetCurrentTab() const { return currentTab_; } std::string Describe() const override { return "TabHolder: " + View::Describe(); } - void PersistData(PersistStatus status, PersistMap &storage) override; + void PersistData(PersistStatus status, std::string anonId, PersistMap &storage) override; private: EventReturn OnTabClick(EventParams &e);