From a52fbfcff7274d55c57e40267cfc28627a1235c6 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Sep 2016 11:26:35 -0700 Subject: [PATCH] UI: Lock input while mutating views/screens. This way we can't get an axis event while switching screens and crash. --- UI/ControlMappingScreen.cpp | 6 ------ UI/ControlMappingScreen.h | 3 --- ext/native/ui/screen.cpp | 9 +++++++++ ext/native/ui/screen.h | 3 +++ ext/native/ui/ui_screen.cpp | 2 ++ 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 8086cf59d6..63734d1dd1 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -439,8 +439,6 @@ bool AnalogTestScreen::key(const KeyInput &key) { return true; } - lock_guard guard(eventLock_); - char buf[512]; snprintf(buf, sizeof(buf), "Keycode: %d Device ID: %d [%s%s%s%s]", key.keyCode, key.deviceId, (key.flags & KEY_IS_REPEAT) ? "REP" : "", @@ -461,8 +459,6 @@ bool AnalogTestScreen::axis(const AxisInput &axis) { // a controller would be confusing for the user. char buf[512]; - lock_guard guard(eventLock_); - if (IgnoreAxisForMapping(axis.axisId)) return false; @@ -482,8 +478,6 @@ bool AnalogTestScreen::axis(const AxisInput &axis) { void AnalogTestScreen::CreateViews() { using namespace UI; - lock_guard guard(eventLock_); - I18NCategory *di = GetI18NCategory("Dialog"); root_ = new LinearLayout(ORIENT_VERTICAL); diff --git a/UI/ControlMappingScreen.h b/UI/ControlMappingScreen.h index 69fd34e73a..b971839906 100644 --- a/UI/ControlMappingScreen.h +++ b/UI/ControlMappingScreen.h @@ -19,7 +19,6 @@ #include #include "base/functional.h" -#include "base/mutex.h" #include "ui/view.h" #include "ui/ui_screen.h" @@ -81,6 +80,4 @@ protected: UI::TextView *lastKeyEvent_; UI::TextView *lastLastKeyEvent_; - - recursive_mutex eventLock_; }; diff --git a/ext/native/ui/screen.cpp b/ext/native/ui/screen.cpp index 6cb9fa0a5f..e745d8cff9 100644 --- a/ext/native/ui/screen.cpp +++ b/ext/native/ui/screen.cpp @@ -47,6 +47,7 @@ void ScreenManager::update(InputState &input) { } void ScreenManager::switchToNext() { + lock_guard guard(inputLock_); if (!nextScreen_) { ELOG("switchToNext: No nextScreen_!"); } @@ -66,6 +67,7 @@ void ScreenManager::switchToNext() { } bool ScreenManager::touch(const TouchInput &touch) { + lock_guard guard(inputLock_); if (!stack_.empty()) { return stack_.back().screen->touch(touch); } else { @@ -74,6 +76,7 @@ bool ScreenManager::touch(const TouchInput &touch) { } bool ScreenManager::key(const KeyInput &key) { + lock_guard guard(inputLock_); if (!stack_.empty()) { return stack_.back().screen->key(key); } else { @@ -82,6 +85,7 @@ bool ScreenManager::key(const KeyInput &key) { } bool ScreenManager::axis(const AxisInput &axis) { + lock_guard guard(inputLock_); if (!stack_.empty()) { return stack_.back().screen->axis(axis); } else { @@ -90,6 +94,7 @@ bool ScreenManager::axis(const AxisInput &axis) { } void ScreenManager::resized() { + lock_guard guard(inputLock_); // Have to notify the whole stack, otherwise there will be problems when going back // to non-top screens. for (auto iter = stack_.begin(); iter != stack_.end(); ++iter) { @@ -163,6 +168,7 @@ Screen *ScreenManager::topScreen() const { } void ScreenManager::shutdown() { + lock_guard guard(inputLock_); for (auto x = stack_.begin(); x != stack_.end(); x++) delete x->screen; stack_.clear(); @@ -171,6 +177,7 @@ void ScreenManager::shutdown() { } void ScreenManager::push(Screen *screen, int layerFlags) { + lock_guard guard(inputLock_); if (nextScreen_ && stack_.empty()) { // we're during init, this is OK switchToNext(); @@ -185,6 +192,7 @@ void ScreenManager::push(Screen *screen, int layerFlags) { } void ScreenManager::pop() { + lock_guard guard(inputLock_); if (stack_.size()) { delete stack_.back().screen; stack_.pop_back(); @@ -215,6 +223,7 @@ void ScreenManager::finishDialog(Screen *dialog, DialogResult result) { void ScreenManager::processFinishDialog() { if (dialogFinished_) { + lock_guard guard(inputLock_); // Another dialog may have been pushed before the render, so search for it. Screen *caller = 0; for (size_t i = 0; i < stack_.size(); ++i) { diff --git a/ext/native/ui/screen.h b/ext/native/ui/screen.h index 248f9f5f50..f8f7282c9e 100644 --- a/ext/native/ui/screen.h +++ b/ext/native/ui/screen.h @@ -17,6 +17,7 @@ #include "base/basictypes.h" #include "base/logging.h" +#include "base/mutex.h" #include "base/NativeApp.h" namespace UI { @@ -126,6 +127,8 @@ public: Screen *topScreen() const; + recursive_mutex inputLock_; + private: void pop(); void switchToNext(); diff --git a/ext/native/ui/ui_screen.cpp b/ext/native/ui/ui_screen.cpp index 3914296e89..399b668190 100644 --- a/ext/native/ui/ui_screen.cpp +++ b/ext/native/ui/ui_screen.cpp @@ -19,6 +19,8 @@ UIScreen::~UIScreen() { } void UIScreen::DoRecreateViews() { + lock_guard guard(screenManager()->inputLock_); + if (recreateViews_) { UI::PersistMap persisted; bool persisting = root_ != nullptr;