From 78c064cc9634f46a96eaa4b7049912221e17502d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 4 Sep 2023 11:04:15 +0200 Subject: [PATCH] Bypass normal UI messages to avoid slowing down unsynchrononized touch messages. --- UI/OnScreenDisplay.cpp | 52 ++++++++++++++++++++++++++++-------------- UI/OnScreenDisplay.h | 14 ++++++++---- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/UI/OnScreenDisplay.cpp b/UI/OnScreenDisplay.cpp index 15658fbd3b..96a53eaee7 100644 --- a/UI/OnScreenDisplay.cpp +++ b/UI/OnScreenDisplay.cpp @@ -367,7 +367,7 @@ void OnScreenMessagesView::Draw(UIContext &dc) { edges[(size_t)pos].maxWidth = std::max(edges[(size_t)pos].maxWidth, measuredEntry.w); } - std::vector dismissZones; + std::vector dismissZones; // Now, perform layout for all 8 edges. for (size_t i = 0; i < (size_t)ScreenEdgePosition::VALUE_COUNT; i++) { @@ -446,19 +446,30 @@ void OnScreenMessagesView::Draw(UIContext &dc) { float alpha = Clamp((float)(entry.endTime - now) * 4.0f, 0.0f, 1.0f); RenderOSDEntry(dc, entry, b, measuredEntry.h1, measuredEntry.align, alpha); + + switch (entry.type) { + case OSDType::MESSAGE_INFO: + case OSDType::MESSAGE_SUCCESS: + case OSDType::MESSAGE_WARNING: + case OSDType::MESSAGE_ERROR: + case OSDType::MESSAGE_ERROR_DUMP: + case OSDType::MESSAGE_FILE_LINK: + case OSDType::ACHIEVEMENT_UNLOCKED: + // Save the location of the popup, for easy dismissal. + dismissZones.push_back(ClickZone{ (int)j, b }); + break; + } break; } } - // Save the location of the popup, for easy dismissal. - dismissZones.push_back(DismissZone{ (int)j, b }); y += (measuredEntry.h + 4.0f) * measuredEntry.alpha; } } - std::lock_guard lock(dismissMutex_); - dismissZones_ = dismissZones; + std::lock_guard lock(clickMutex_); + clickZones_ = dismissZones; } std::string OnScreenMessagesView::DescribeText() const { @@ -473,18 +484,25 @@ std::string OnScreenMessagesView::DescribeText() const { return ss.str(); } -bool OnScreenMessagesView::Touch(const TouchInput &input) { - if (input.flags & TOUCH_DOWN) { - bool dismissed = false; - std::lock_guard lock(dismissMutex_); - double now = time_now_d(); - for (auto &zone : dismissZones_) { - if (zone.bounds.Contains(input.x, input.y)) { - g_OSD.DismissEntry(zone.index, now); - dismissed = true; - } +// Asynchronous! +bool OnScreenMessagesView::Dismiss(float x, float y) { + bool dismissed = false; + std::lock_guard lock(clickMutex_); + double now = time_now_d(); + for (auto &zone : clickZones_) { + if (zone.bounds.Contains(x, y)) { + g_OSD.DismissEntry(zone.index, now); + dismissed = true; } - return dismissed; + } + return dismissed; +} + +bool OSDOverlayScreen::UnsyncTouch(const TouchInput &touch) { + // Don't really need to forward. + // UIScreen::UnsyncTouch(touch); + if ((touch.flags & TOUCH_DOWN) && osmView_) { + return osmView_->Dismiss(touch.x, touch.y); } else { return false; } @@ -493,7 +511,7 @@ bool OnScreenMessagesView::Touch(const TouchInput &input) { void OSDOverlayScreen::CreateViews() { root_ = new UI::AnchorLayout(); root_->SetTag("OSDOverlayScreen"); - root_->Add(new OnScreenMessagesView(new UI::AnchorLayoutParams(0.0f, 0.0f, 0.0f, 0.0f))); + osmView_ = root_->Add(new OnScreenMessagesView(new UI::AnchorLayoutParams(0.0f, 0.0f, 0.0f, 0.0f))); } void OSDOverlayScreen::render() { diff --git a/UI/OnScreenDisplay.h b/UI/OnScreenDisplay.h index 70de6dcdb4..597fa6e5b9 100644 --- a/UI/OnScreenDisplay.h +++ b/UI/OnScreenDisplay.h @@ -21,24 +21,30 @@ class OnScreenMessagesView : public UI::InertView { public: OnScreenMessagesView(UI::LayoutParams *layoutParams = nullptr) : UI::InertView(layoutParams) {} void Draw(UIContext &dc) override; - bool Touch(const TouchInput &input) override; + bool Dismiss(float x, float y); // Not reusing Touch since it's asynchronous. std::string DescribeText() const override; private: - struct DismissZone { + struct ClickZone { int index; Bounds bounds; }; // Argh, would really like to avoid this. - std::mutex dismissMutex_; - std::vector dismissZones_; + std::mutex clickMutex_; + std::vector clickZones_; }; class OSDOverlayScreen : public UIScreen { public: const char *tag() const override { return "OSDOverlayScreen"; } + + bool UnsyncTouch(const TouchInput &touch) override; + void CreateViews() override; void render() override; + +private: + OnScreenMessagesView *osmView_ = nullptr; }; enum class NoticeLevel {