Merge pull request #18065 from hrydgard/dismiss-notifications

Add ability to dismiss notifications
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2023-09-04 12:46:50 +02:00
commit 412c3a0cd9
12 files changed
+105 -11

No files matched your search

+7
View File
@@ -39,6 +39,13 @@ float OnScreenDisplay::SidebarAlpha() const {
return saturatef(1.0f - ((float)timeSinceNudge - 0.1f) * 4.0f);
}
void OnScreenDisplay::DismissEntry(size_t index, double now) {
std::lock_guard<std::mutex> guard(mutex_);
if (index < entries_.size() && entries_[index].type != OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR) {
entries_[index].endTime = std::min(now + FadeoutTime(), entries_[index].endTime);
}
}
void OnScreenDisplay::Show(OSDType type, const std::string &text, const std::string &text2, const std::string &icon, float duration_s, const char *id) {
// Automatic duration based on type.
if (duration_s <= 0.0f) {
+3
View File
@@ -87,6 +87,9 @@ public:
std::vector<Entry> Entries();
// TODO: Use something more stable than the index.
void DismissEntry(size_t index, double now);
static float FadeinTime() { return 0.1f; }
static float FadeoutTime() { return 0.25f; }
+12 -2
View File
@@ -48,6 +48,9 @@ void ScreenManager::update() {
switchToNext();
}
if (overlayScreen_) {
overlayScreen_->update();
}
if (stack_.size()) {
stack_.back().screen->update();
}
@@ -90,8 +93,15 @@ void ScreenManager::touch(const TouchInput &touch) {
layer.screen->UnsyncTouch(screen->transformTouch(touch));
}
} else if (!stack_.empty()) {
Screen *screen = stack_.back().screen;
stack_.back().screen->UnsyncTouch(screen->transformTouch(touch));
// Let the overlay know about touch-downs, to be able to dismiss popups.
bool skip = false;
if (overlayScreen_ && (touch.flags & TOUCH_DOWN)) {
skip = overlayScreen_->UnsyncTouch(overlayScreen_->transformTouch(touch));
}
if (!skip) {
Screen *screen = stack_.back().screen;
stack_.back().screen->UnsyncTouch(screen->transformTouch(touch));
}
}
}
+3 -1
View File
@@ -59,7 +59,9 @@ public:
virtual void deviceLost() {}
virtual void deviceRestored() {}
virtual void UnsyncTouch(const TouchInput &touch) = 0;
// 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.
virtual bool UnsyncKey(const KeyInput &touch) = 0;
virtual void UnsyncAxis(const AxisInput &touch) = 0;
+2 -1
View File
@@ -81,7 +81,7 @@ bool UIScreen::key(const KeyInput &key) {
}
}
void UIScreen::UnsyncTouch(const TouchInput &touch) {
bool UIScreen::UnsyncTouch(const TouchInput &touch) {
if (ClickDebug && root_ && (touch.flags & TOUCH_DOWN)) {
INFO_LOG(SYSTEM, "Touch down!");
std::vector<UI::View *> views;
@@ -96,6 +96,7 @@ void UIScreen::UnsyncTouch(const TouchInput &touch) {
ev.type = QueuedEventType::TOUCH;
ev.touch = touch;
eventQueue_.push_back(ev);
return false;
}
void UIScreen::UnsyncAxis(const AxisInput &axis) {
+1 -1
View File
@@ -46,7 +46,7 @@ public:
virtual bool key(const KeyInput &key);
virtual void axis(const AxisInput &axis);
void UnsyncTouch(const TouchInput &touch) override;
bool UnsyncTouch(const TouchInput &touch) override;
bool UnsyncKey(const KeyInput &key) override;
void UnsyncAxis(const AxisInput &axis) override;
+12 -1
View File
@@ -858,7 +858,19 @@ void SystemInfoScreen::CreateTabs() {
}
}
#ifdef _DEBUG
LinearLayout *internals = AddTab("DevSystemInfoInternals", si->T("Internals"));
CreateInternalsTab(internals);
#endif
}
void SystemInfoScreen::CreateInternalsTab(UI::ViewGroup *internals) {
using namespace UI;
auto di = GetI18NCategory(I18NCat::DIALOG);
auto si = GetI18NCategory(I18NCat::SYSINFO);
auto sy = GetI18NCategory(I18NCat::SYSTEM);
auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS);
internals->Add(new ItemHeader(si->T("Icon cache")));
IconCacheStats iconStats = g_iconCache.GetStats();
@@ -929,7 +941,6 @@ void SystemInfoScreen::CreateTabs() {
});
static const char *positions[] = { "Bottom Left", "Bottom Center", "Bottom Right", "Top Left", "Top Center", "Top Right", "Center Left", "Center Right", "None" };
auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS);
internals->Add(new ItemHeader(ac->T("Notifications")));
internals->Add(new PopupMultiChoice(&g_Config.iAchievementsLeaderboardTrackerPos, ac->T("Leaderboard tracker"), positions, 0, ARRAY_SIZE(positions), I18NCat::DIALOG, screenManager()))->SetEnabledPtr(&g_Config.bAchievementsEnable);
+1 -1
View File
@@ -110,11 +110,11 @@ public:
const char *tag() const override { return "SystemInfo"; }
void CreateTabs() override;
void update() override;
protected:
bool ShowSearchControls() const override { return false; }
void CreateInternalsTab(UI::ViewGroup *internals);
};
class AddressPromptScreen : public PopupScreen {
+3 -2
View File
@@ -563,14 +563,14 @@ void EmuScreen::sendMessage(const char *message, const char *value) {
}
}
void EmuScreen::UnsyncTouch(const TouchInput &touch) {
bool EmuScreen::UnsyncTouch(const TouchInput &touch) {
System_Notify(SystemNotification::ACTIVITY);
if (chatMenu_ && chatMenu_->GetVisibility() == UI::V_VISIBLE) {
// Avoid pressing touch button behind the chat
if (chatMenu_->Contains(touch.x, touch.y)) {
chatMenu_->Touch(touch);
return;
return true;
} else if ((touch.flags & TOUCH_DOWN) != 0) {
chatMenu_->Close();
if (chatButton_)
@@ -582,6 +582,7 @@ void EmuScreen::UnsyncTouch(const TouchInput &touch) {
if (root_) {
root_->Touch(touch);
}
return true;
}
void EmuScreen::onVKey(int virtualKeyCode, bool down) {
+1 -1
View File
@@ -51,7 +51,7 @@ public:
// Note: Unlike your average boring UIScreen, here we override the Unsync* functions
// to get minimal latency and full control. We forward to UIScreen when needed.
void UnsyncTouch(const TouchInput &touch) override;
bool UnsyncTouch(const TouchInput &touch) override;
bool UnsyncKey(const KeyInput &key) override;
void UnsyncAxis(const AxisInput &axis) override;
+44 -1
View File
@@ -367,6 +367,8 @@ void OnScreenMessagesView::Draw(UIContext &dc) {
edges[(size_t)pos].maxWidth = std::max(edges[(size_t)pos].maxWidth, measuredEntry.w);
}
std::vector<ClickZone> dismissZones;
// Now, perform layout for all 8 edges.
for (size_t i = 0; i < (size_t)ScreenEdgePosition::VALUE_COUNT; i++) {
if (edges[i].height == 0.0f) {
@@ -444,13 +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;
}
}
y += (measuredEntry.h + 4.0f) * measuredEntry.alpha;
}
}
std::lock_guard<std::mutex> lock(clickMutex_);
clickZones_ = dismissZones;
}
std::string OnScreenMessagesView::DescribeText() const {
@@ -465,10 +484,34 @@ std::string OnScreenMessagesView::DescribeText() const {
return ss.str();
}
// Asynchronous!
bool OnScreenMessagesView::Dismiss(float x, float y) {
bool dismissed = false;
std::lock_guard<std::mutex> 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;
}
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;
}
}
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() {
+16
View File
@@ -21,14 +21,30 @@ class OnScreenMessagesView : public UI::InertView {
public:
OnScreenMessagesView(UI::LayoutParams *layoutParams = nullptr) : UI::InertView(layoutParams) {}
void Draw(UIContext &dc) override;
bool Dismiss(float x, float y); // Not reusing Touch since it's asynchronous.
std::string DescribeText() const override;
private:
struct ClickZone {
int index;
Bounds bounds;
};
// Argh, would really like to avoid this.
std::mutex clickMutex_;
std::vector<ClickZone> 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 {