Skip to content

Commit

Permalink
Merge pull request #18065 from hrydgard/dismiss-notifications
Browse files Browse the repository at this point in the history
Add ability to dismiss notifications
  • Loading branch information
hrydgard committed Sep 4, 2023
2 parents 9690a71 + 78c064c commit 412c3a0
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 11 deletions.
7 changes: 7 additions & 0 deletions Common/System/OSD.cpp
Expand Up @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions Common/System/OSD.h
Expand Up @@ -87,6 +87,9 @@ class OnScreenDisplay {

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; }

Expand Down
14 changes: 12 additions & 2 deletions Common/UI/Screen.cpp
Expand Up @@ -48,6 +48,9 @@ void ScreenManager::update() {
switchToNext();
}

if (overlayScreen_) {
overlayScreen_->update();
}
if (stack_.size()) {
stack_.back().screen->update();
}
Expand Down Expand Up @@ -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));
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion Common/UI/Screen.h
Expand Up @@ -59,7 +59,9 @@ class Screen {
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;

Expand Down
3 changes: 2 additions & 1 deletion Common/UI/UIScreen.cpp
Expand Up @@ -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;
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion Common/UI/UIScreen.h
Expand Up @@ -46,7 +46,7 @@ class UIScreen : public Screen {
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;

Expand Down
13 changes: 12 additions & 1 deletion UI/DevScreens.cpp
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion UI/DevScreens.h
Expand Up @@ -110,11 +110,11 @@ class SystemInfoScreen : public TabbedUIDialogScreenWithGameBackground {
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 {
Expand Down
5 changes: 3 additions & 2 deletions UI/EmuScreen.cpp
Expand Up @@ -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_)
Expand All @@ -582,6 +582,7 @@ void EmuScreen::UnsyncTouch(const TouchInput &touch) {
if (root_) {
root_->Touch(touch);
}
return true;
}

void EmuScreen::onVKey(int virtualKeyCode, bool down) {
Expand Down
2 changes: 1 addition & 1 deletion UI/EmuScreen.h
Expand Up @@ -51,7 +51,7 @@ class EmuScreen : public UIScreen {

// 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;

Expand Down
45 changes: 44 additions & 1 deletion UI/OnScreenDisplay.cpp
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 {
Expand All @@ -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() {
Expand Down
16 changes: 16 additions & 0 deletions UI/OnScreenDisplay.h
Expand Up @@ -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 {
Expand Down

0 comments on commit 412c3a0

Please sign in to comment.