From 5ba33f846129f3e6c0505b19f94634b24505e828 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sun, 26 Apr 2026 15:16:36 +0100 Subject: 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. --- src/notification/NotificationOverlay.cpp | 180 ++++++++++++++++++++----------- 1 file changed, 119 insertions(+), 61 deletions(-) (limited to 'src/notification/NotificationOverlay.cpp') 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& Notification::overlay() { static UP p = makeUnique(); @@ -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(notif.fontSize * ((pMonitor->m_pixelSize.x * pMonitor->m_scale) / 1920.f)), 8, 40); + const auto fontSizePx = std::clamp(sc(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(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()).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("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(pMonitor->m_position.x + pMonitor->m_size.x - maxWidth - NOTIF_DAMAGE_PAD_X), sc(pMonitor->m_position.y), sc(maxWidth + NOTIF_DAMAGE_PAD_X), + sc(offsetY + NOTIF_OFFSET_Y)}; +} + +SP CNotificationOverlay::addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon, const float fontSize) { + auto PNOTIF = makeShared(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& notification) { + if (!notification) + return; + + std::erase_if(m_notifications, [&](const auto& notif) { return notif == notification; }); + scheduleFrames(); +} + +std::vector> 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(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(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(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(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(pMonitor->m_position.x + pMonitor->m_size.x - maxWidth - NOTIF_DAMAGE_PAD_X), sc(pMonitor->m_position.y), sc(maxWidth + NOTIF_DAMAGE_PAD_X), sc(offsetY + NOTIF_OFFSET_Y)}; -- cgit v1.2.3