summaryrefslogtreecommitdiff
path: root/src/notification/NotificationOverlay.cpp
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2026-04-26 15:16:36 +0100
committerGitHub <noreply@github.com>2026-04-26 15:16:36 +0100
commit5ba33f846129f3e6c0505b19f94634b24505e828 (patch)
treeaaacabe678006040c342935481a86607c66607fd /src/notification/NotificationOverlay.cpp
parent329b2b356dd92ac07f4e2aa69cbce82ee9ba9d19 (diff)
config/lua: init lua config manager, use lua if available (#13817)
Adds a new lua config manager, which will automatically be used if there is a lua config present.
Diffstat (limited to 'src/notification/NotificationOverlay.cpp')
-rw-r--r--src/notification/NotificationOverlay.cpp180
1 files changed, 119 insertions, 61 deletions
diff --git a/src/notification/NotificationOverlay.cpp b/src/notification/NotificationOverlay.cpp
index 0f38bfa3..0c9ec08c 100644
--- a/src/notification/NotificationOverlay.cpp
+++ b/src/notification/NotificationOverlay.cpp
@@ -5,6 +5,7 @@
#include "NotificationOverlay.hpp"
#include "../Compositor.hpp"
#include "../config/ConfigValue.hpp"
+#include "../desktop/state/FocusState.hpp"
#include "../render/pass/RectPassElement.hpp"
#include "../render/pass/TexPassElement.hpp"
#include "../event/EventBus.hpp"
@@ -26,16 +27,20 @@ static inline auto iconBackendFromLayout(PangoLayout* layout) {
return ICONS_BACKEND_NONE;
}
-static constexpr auto ANIM_DURATION_MS = 600.F;
-static constexpr auto ANIM_LAG_MS = 100.F;
-static constexpr auto NOTIF_LEFTBAR_SIZE = 5.F;
-static constexpr auto NOTIF_PAD_X = 20.F;
-static constexpr auto NOTIF_PAD_Y = 10.F;
-static constexpr auto NOTIF_OFFSET_Y = 10.F;
-static constexpr auto NOTIF_GAP_Y = 10.F;
-static constexpr auto NOTIF_DAMAGE_PAD_X = 20.F;
-static constexpr auto ICON_PAD = 3.F;
-static constexpr auto ICON_SCALE = 0.9F;
+static constexpr auto ANIM_DURATION_MS = 600.F;
+static constexpr auto ANIM_LAG_MS = 100.F;
+static constexpr auto NOTIF_LEFTBAR_SIZE = 5.F;
+static constexpr auto NOTIF_PAD_X = 20.F;
+static constexpr auto NOTIF_PAD_Y = 10.F;
+static constexpr auto NOTIF_OFFSET_Y = 10.F;
+static constexpr auto NOTIF_GAP_Y = 10.F;
+static constexpr auto NOTIF_DAMAGE_PAD_X = 20.F;
+static constexpr auto ICON_PAD = 3.F;
+static constexpr auto ICON_SCALE = 0.9F;
+
+static inline CHyprColor resolvedColor(const eIcons icon, const CHyprColor& color) {
+ return color == CHyprColor(0) ? ICONS_COLORS[icon] : color;
+}
UP<CNotificationOverlay>& Notification::overlay() {
static UP<CNotificationOverlay> p = makeUnique<CNotificationOverlay>();
@@ -79,51 +84,91 @@ eIconBackend CNotificationOverlay::iconBackendForFont(const std::string& fontFam
return m_cachedIconBackend;
}
-void CNotificationOverlay::ensureNotificationCache(SNotification& notif, PHLMONITOR pMonitor, const std::string& fontFamily) {
+void CNotificationOverlay::ensureNotificationCache(CNotification& notif, PHLMONITOR pMonitor, const std::string& fontFamily) {
const auto iconBackend = iconBackendForFont(fontFamily);
- const auto fontSizePx = std::clamp(sc<int>(notif.fontSize * ((pMonitor->m_pixelSize.x * pMonitor->m_scale) / 1920.f)), 8, 40);
+ const auto fontSizePx = std::clamp(sc<int>(notif.fontSize() * ((pMonitor->m_pixelSize.x * pMonitor->m_scale) / 1920.F)), 8, 40);
- const bool cacheValid = notif.cache.monitor == pMonitor && notif.cache.fontFamily == fontFamily && notif.cache.fontSizePx == fontSizePx &&
- notif.cache.iconBackend == iconBackend && notif.cache.textTex && (notif.icon == ICON_NONE || notif.cache.iconTex);
+ const bool cacheValid = notif.m_cache.monitor == pMonitor && notif.m_cache.fontFamily == fontFamily && notif.m_cache.fontSizePx == fontSizePx &&
+ notif.m_cache.iconBackend == iconBackend && notif.m_cache.textTex && (notif.icon() == ICON_NONE || notif.m_cache.iconTex);
if (cacheValid)
return;
- notif.cache = {};
- notif.cache.monitor = pMonitor;
- notif.cache.fontFamily = fontFamily;
- notif.cache.fontSizePx = fontSizePx;
- notif.cache.iconBackend = iconBackend;
+ notif.m_cache = {};
+ notif.m_cache.monitor = pMonitor;
+ notif.m_cache.fontFamily = fontFamily;
+ notif.m_cache.fontSizePx = fontSizePx;
+ notif.m_cache.iconBackend = iconBackend;
- notif.cache.textTex = g_pHyprRenderer->renderText(notif.text, CHyprColor{1.F, 1.F, 1.F, 1.F}, fontSizePx, false, fontFamily);
- if (notif.cache.textTex)
- notif.cache.textSize = notif.cache.textTex->m_size;
+ notif.m_cache.textTex = g_pHyprRenderer->renderText(notif.text(), CHyprColor{1.F, 1.F, 1.F, 1.F}, fontSizePx, false, fontFamily);
+ if (notif.m_cache.textTex)
+ notif.m_cache.textSize = notif.m_cache.textTex->m_size;
- if (notif.icon != ICON_NONE) {
- const auto iconGlyph = ICONS_ARRAY[iconBackend][notif.icon];
+ if (notif.icon() != ICON_NONE) {
+ const auto iconGlyph = ICONS_ARRAY[iconBackend][notif.icon()];
const auto iconSizePx = std::max(8, sc<int>(std::round(fontSizePx * ICON_SCALE)));
- notif.cache.iconTex = g_pHyprRenderer->renderText(iconGlyph, CHyprColor{1.F, 1.F, 1.F, 1.F}, iconSizePx, false, fontFamily);
- if (notif.cache.iconTex)
- notif.cache.iconSize = notif.cache.iconTex->m_size;
+ notif.m_cache.iconTex = g_pHyprRenderer->renderText(iconGlyph, CHyprColor{1.F, 1.F, 1.F, 1.F}, iconSizePx, false, fontFamily);
+ if (notif.m_cache.iconTex)
+ notif.m_cache.iconSize = notif.m_cache.iconTex->m_size;
}
}
-void CNotificationOverlay::addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon, const float fontSize) {
- const auto PNOTIF = m_notifications.emplace_back(makeUnique<SNotification>()).get();
-
- PNOTIF->text = text;
- PNOTIF->color = color == CHyprColor(0) ? ICONS_COLORS[icon] : color;
- PNOTIF->started.reset();
- PNOTIF->timeMs = timeMs;
- PNOTIF->icon = icon;
- PNOTIF->fontSize = fontSize;
-
+void CNotificationOverlay::scheduleFrames() const {
for (auto const& m : g_pCompositor->m_monitors) {
g_pCompositor->scheduleFrameForMonitor(m);
}
}
+CBox CNotificationOverlay::notificationDamageForMonitor(PHLMONITOR pMonitor) {
+ if (!pMonitor || m_notifications.empty())
+ return {};
+
+ float offsetY = NOTIF_OFFSET_Y;
+ float maxWidth = 0.F;
+
+ static auto fontFamily = CConfigValue<std::string>("misc:font_family");
+
+ for (auto const& notif : m_notifications) {
+ ensureNotificationCache(*notif, pMonitor, *fontFamily);
+
+ const auto ICONPADFORNOTIF = notif->icon() == ICON_NONE ? 0.F : ICON_PAD;
+ const auto ICONW = notif->m_cache.iconSize.x;
+ const auto ICONH = notif->m_cache.iconSize.y;
+ const auto TEXTW = notif->m_cache.textSize.x;
+ const auto TEXTH = notif->m_cache.textSize.y;
+ const auto NOTIFSIZE = Vector2D{TEXTW + NOTIF_PAD_X + ICONW + (2 * ICONPADFORNOTIF), std::max(TEXTH, ICONH) + NOTIF_PAD_Y};
+
+ offsetY += NOTIFSIZE.y + NOTIF_GAP_Y;
+
+ if (maxWidth < NOTIFSIZE.x)
+ maxWidth = NOTIFSIZE.x;
+ }
+
+ return CBox{sc<int>(pMonitor->m_position.x + pMonitor->m_size.x - maxWidth - NOTIF_DAMAGE_PAD_X), sc<int>(pMonitor->m_position.y), sc<int>(maxWidth + NOTIF_DAMAGE_PAD_X),
+ sc<int>(offsetY + NOTIF_OFFSET_Y)};
+}
+
+SP<CNotification> CNotificationOverlay::addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon, const float fontSize) {
+ auto PNOTIF = makeShared<CNotification>(std::string{text}, timeMs, color, icon, fontSize);
+
+ m_notifications.emplace_back(PNOTIF);
+
+ const auto focusedMonitor = Desktop::focusState()->monitor();
+ if (focusedMonitor) {
+ const auto damage = notificationDamageForMonitor(focusedMonitor);
+
+ if (damage.width > 0 && damage.height > 0)
+ g_pHyprRenderer->damageBox(damage);
+
+ if (m_lastDamage.width > 0 && m_lastDamage.height > 0)
+ g_pHyprRenderer->damageBox(m_lastDamage);
+ }
+
+ scheduleFrames();
+ return PNOTIF;
+}
+
void CNotificationOverlay::dismissNotifications(const int amount) {
if (amount == -1)
m_notifications.clear();
@@ -135,9 +180,19 @@ void CNotificationOverlay::dismissNotifications(const int amount) {
}
}
- for (auto const& m : g_pCompositor->m_monitors) {
- g_pCompositor->scheduleFrameForMonitor(m);
- }
+ scheduleFrames();
+}
+
+void CNotificationOverlay::dismissNotification(const SP<CNotification>& notification) {
+ if (!notification)
+ return;
+
+ std::erase_if(m_notifications, [&](const auto& notif) { return notif == notification; });
+ scheduleFrames();
+}
+
+std::vector<SP<CNotification>> CNotificationOverlay::getNotifications() const {
+ return m_notifications;
}
CBox CNotificationOverlay::drawNotifications(PHLMONITOR pMonitor) {
@@ -152,27 +207,30 @@ CBox CNotificationOverlay::drawNotifications(PHLMONITOR pMonitor) {
for (auto const& notif : m_notifications) {
ensureNotificationCache(*notif, pMonitor, *fontFamily);
- const auto ICONPADFORNOTIF = notif->icon == ICON_NONE ? 0.F : ICON_PAD;
- const auto ICONW = notif->cache.iconSize.x;
- const auto ICONH = notif->cache.iconSize.y;
- const auto TEXTW = notif->cache.textSize.x;
- const auto TEXTH = notif->cache.textSize.y;
- const auto NOTIFSIZE = Vector2D{TEXTW + NOTIF_PAD_X + ICONW + 2 * ICONPADFORNOTIF, std::max(TEXTH, ICONH) + NOTIF_PAD_Y};
+ const auto ICONPADFORNOTIF = notif->icon() == ICON_NONE ? 0.F : ICON_PAD;
+ const auto ICONW = notif->m_cache.iconSize.x;
+ const auto ICONH = notif->m_cache.iconSize.y;
+ const auto TEXTW = notif->m_cache.textSize.x;
+ const auto TEXTH = notif->m_cache.textSize.y;
+ const auto NOTIFSIZE = Vector2D{TEXTW + NOTIF_PAD_X + ICONW + (2 * ICONPADFORNOTIF), std::max(TEXTH, ICONH) + NOTIF_PAD_Y};
- const float elapsed = notif->started.getMillis();
- const float lifeMs = std::max(notif->timeMs, 1.F);
+ const float elapsedSinceCreation = notif->timeElapsedSinceCreationMs();
+ const float elapsed = notif->timeElapsedMs();
+ const float lifeMs = notif->timeMs();
// first rect (bg, col)
- const float FIRSTRECTANIMP = std::clamp(
- (elapsed > (ANIM_DURATION_MS - ANIM_LAG_MS) ? (elapsed > lifeMs - (ANIM_DURATION_MS - ANIM_LAG_MS) ? lifeMs - elapsed : (ANIM_DURATION_MS - ANIM_LAG_MS)) : elapsed) /
- (ANIM_DURATION_MS - ANIM_LAG_MS),
- 0.F, 1.F);
+ const float FIRSTRECTANIMP = std::clamp((elapsedSinceCreation > (ANIM_DURATION_MS - ANIM_LAG_MS) ?
+ (elapsed > lifeMs - (ANIM_DURATION_MS - ANIM_LAG_MS) ? lifeMs - elapsed : (ANIM_DURATION_MS - ANIM_LAG_MS)) :
+ elapsedSinceCreation) /
+ (ANIM_DURATION_MS - ANIM_LAG_MS),
+ 0.F, 1.F);
const float FIRSTRECTPERC = FIRSTRECTANIMP >= 0.99f ? 1.f : PBEZIER->getYForPoint(FIRSTRECTANIMP);
// second rect (fg, black)
- const float SECONDRECTANIMP =
- std::clamp((elapsed > ANIM_DURATION_MS ? (elapsed > lifeMs - ANIM_DURATION_MS ? lifeMs - elapsed : ANIM_DURATION_MS) : elapsed) / ANIM_DURATION_MS, 0.F, 1.F);
+ const float SECONDRECTANIMP = std::clamp(
+ (elapsedSinceCreation > ANIM_DURATION_MS ? (elapsed > lifeMs - ANIM_DURATION_MS ? lifeMs - elapsed : ANIM_DURATION_MS) : elapsedSinceCreation) / ANIM_DURATION_MS, 0.F,
+ 1.F);
const float SECONDRECTPERC = SECONDRECTANIMP >= 0.99f ? 1.f : PBEZIER->getYForPoint(SECONDRECTANIMP);
@@ -187,7 +245,7 @@ CBox CNotificationOverlay::drawNotifications(PHLMONITOR pMonitor) {
CRectPassElement::SRectData bgData;
bgData.box = {firstRectX, offsetY, firstRectW, NOTIFSIZE.y};
- bgData.color = notif->color;
+ bgData.color = notif->color();
g_pHyprRenderer->m_renderPass.add(makeUnique<CRectPassElement>(bgData));
CRectPassElement::SRectData fgData;
@@ -197,20 +255,20 @@ CBox CNotificationOverlay::drawNotifications(PHLMONITOR pMonitor) {
CRectPassElement::SRectData progressData;
progressData.box = {secondRectX + 3, offsetY + NOTIFSIZE.y - 4, THIRDRECTPERC * std::max(0.0, NOTIFSIZE.x - 6.0), 2};
- progressData.color = notif->color;
+ progressData.color = notif->color();
g_pHyprRenderer->m_renderPass.add(makeUnique<CRectPassElement>(progressData));
- if (notif->icon != ICON_NONE && notif->cache.iconTex) {
+ if (notif->icon() != ICON_NONE && notif->m_cache.iconTex) {
CTexPassElement::SRenderData iconData;
- iconData.tex = notif->cache.iconTex;
+ iconData.tex = notif->m_cache.iconTex;
iconData.box = {secondRectX + NOTIF_LEFTBAR_SIZE + ICONPADFORNOTIF - 1, offsetY - 2 + std::round((NOTIFSIZE.y - ICONH) / 2.0), ICONW, ICONH};
iconData.a = 1.F;
g_pHyprRenderer->m_renderPass.add(makeUnique<CTexPassElement>(std::move(iconData)));
}
- if (notif->cache.textTex) {
+ if (notif->m_cache.textTex) {
CTexPassElement::SRenderData textData;
- textData.tex = notif->cache.textTex;
+ textData.tex = notif->m_cache.textTex;
textData.box = {secondRectX + NOTIF_LEFTBAR_SIZE + ICONW + 2 * ICONPADFORNOTIF, offsetY - 2 + std::round((NOTIFSIZE.y - TEXTH) / 2.0), TEXTW, TEXTH};
textData.a = 1.F;
g_pHyprRenderer->m_renderPass.add(makeUnique<CTexPassElement>(std::move(textData)));
@@ -224,7 +282,7 @@ CBox CNotificationOverlay::drawNotifications(PHLMONITOR pMonitor) {
}
// cleanup notifs
- std::erase_if(m_notifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; });
+ std::erase_if(m_notifications, [&](const auto& notif) { return notif->gone(); });
return CBox{sc<int>(pMonitor->m_position.x + pMonitor->m_size.x - maxWidth - NOTIF_DAMAGE_PAD_X), sc<int>(pMonitor->m_position.y), sc<int>(maxWidth + NOTIF_DAMAGE_PAD_X),
sc<int>(offsetY + NOTIF_OFFSET_Y)};