diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2026-04-26 15:16:36 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-04-26 15:16:36 +0100 |
| commit | 5ba33f846129f3e6c0505b19f94634b24505e828 (patch) | |
| tree | aaacabe678006040c342935481a86607c66607fd /src/config/lua/objects/LuaNotification.cpp | |
| parent | 329b2b356dd92ac07f4e2aa69cbce82ee9ba9d19 (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/config/lua/objects/LuaNotification.cpp')
| -rw-r--r-- | src/config/lua/objects/LuaNotification.cpp | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/src/config/lua/objects/LuaNotification.cpp b/src/config/lua/objects/LuaNotification.cpp new file mode 100644 index 00000000..f116e2eb --- /dev/null +++ b/src/config/lua/objects/LuaNotification.cpp @@ -0,0 +1,377 @@ +#include "LuaNotification.hpp" + +#include "../../../helpers/MiscFunctions.hpp" + +#include <array> +#include <algorithm> +#include <cctype> +#include <optional> +#include <string_view> + +using namespace Config::Lua; + +static constexpr const char* MT = "HL.Notification"; + +namespace { + struct SNotificationRef { + WP<Notification::CNotification> notification; + bool paused = false; + }; + + std::optional<CHyprColor> parseColor(lua_State* L, int idx) { + if (lua_isnumber(L, idx)) + return CHyprColor(sc<uint64_t>(lua_tonumber(L, idx))); + + if (lua_isstring(L, idx)) { + auto parsed = configStringToInt(lua_tostring(L, idx)); + if (!parsed) + return std::nullopt; + + return CHyprColor(sc<uint64_t>(*parsed)); + } + + return std::nullopt; + } + + std::optional<eIcons> iconFromString(std::string iconName) { + std::ranges::transform(iconName, iconName.begin(), [](const unsigned char c) { return std::tolower(c); }); + + static constexpr std::array<std::pair<const char*, eIcons>, 10> ICON_NAMES = { + std::pair{"warning", ICON_WARNING}, std::pair{"warn", ICON_WARNING}, std::pair{"info", ICON_INFO}, std::pair{"hint", ICON_HINT}, + std::pair{"error", ICON_ERROR}, std::pair{"err", ICON_ERROR}, std::pair{"confused", ICON_CONFUSED}, std::pair{"question", ICON_CONFUSED}, + std::pair{"ok", ICON_OK}, std::pair{"none", ICON_NONE}, + }; + + for (const auto& [name, icon] : ICON_NAMES) { + if (name == iconName) + return icon; + } + + return std::nullopt; + } + + std::optional<eIcons> parseIcon(lua_State* L, int idx) { + if (lua_isnumber(L, idx)) { + const auto raw = sc<int>(lua_tonumber(L, idx)); + if (raw >= ICON_WARNING && raw <= ICON_NONE) + return sc<eIcons>(raw); + + return std::nullopt; + } + + if (lua_isstring(L, idx)) + return iconFromString(lua_tostring(L, idx)); + + return std::nullopt; + } +} + +static int notificationEq(lua_State* L) { + const auto* lhs = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + const auto* rhs = sc<SNotificationRef*>(luaL_checkudata(L, 2, MT)); + + lua_pushboolean(L, lhs->notification.lock() == rhs->notification.lock()); + return 1; +} + +static int notificationToString(lua_State* L) { + const auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + const auto notification = ref->notification.lock(); + + if (!notification) + lua_pushstring(L, "HL.Notification(expired)"); + else + lua_pushfstring(L, "HL.Notification(%p)", notification.get()); + + return 1; +} + +static int notificationGC(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + if (ref->paused) { + if (const auto notification = ref->notification.lock(); notification) + notification->unlock(); + } + + ref->~SNotificationRef(); + return 0; +} + +static int notificationPause(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto notification = ref->notification.lock(); + if (!notification) + return 0; + + if (ref->paused) + return 0; + + notification->lock(); + ref->paused = true; + return 0; +} + +static int notificationResume(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto notification = ref->notification.lock(); + if (!notification) + return 0; + + if (!ref->paused) + return 0; + + notification->unlock(); + ref->paused = false; + return 0; +} + +static int notificationSetPaused(lua_State* L) { + luaL_checkudata(L, 1, MT); + luaL_checktype(L, 2, LUA_TBOOLEAN); + + if (lua_toboolean(L, 2)) + return notificationPause(L); + + return notificationResume(L); +} + +static int notificationIsPaused(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto notification = ref->notification.lock(); + if (!notification) { + lua_pushnil(L); + return 1; + } + + lua_pushboolean(L, notification->isLocked()); + return 1; +} + +static int notificationSetText(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + const auto* text = luaL_checkstring(L, 2); + + if (const auto notification = ref->notification.lock(); notification) + notification->setText(text); + + return 0; +} + +static int notificationSetTimeout(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto timeoutMs = sc<float>(luaL_checknumber(L, 2)); + if (timeoutMs < 0.F) + return Config::Lua::Bindings::Internal::configError(L, "HL.Notification:set_timeout: timeout must be >= 0"); + + if (const auto notification = ref->notification.lock(); notification) + notification->resetTimeout(timeoutMs); + + return 0; +} + +static int notificationSetColor(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto color = parseColor(L, 2); + if (!color) + return Config::Lua::Bindings::Internal::configError(L, "HL.Notification:set_color: expected a color string or number"); + + if (const auto notification = ref->notification.lock(); notification) + notification->setColor(*color); + + return 0; +} + +static int notificationSetIcon(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto icon = parseIcon(L, 2); + if (!icon) + return Config::Lua::Bindings::Internal::configError(L, "HL.Notification:set_icon: expected an icon name or number"); + + if (const auto notification = ref->notification.lock(); notification) + notification->setIcon(*icon); + + return 0; +} + +static int notificationSetFontSize(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto fontSize = sc<float>(luaL_checknumber(L, 2)); + if (fontSize <= 0.F) + return Config::Lua::Bindings::Internal::configError(L, "HL.Notification:set_font_size: font size must be > 0"); + + if (const auto notification = ref->notification.lock(); notification) + notification->setFontSize(fontSize); + + return 0; +} + +static int notificationDismiss(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + if (const auto notification = ref->notification.lock(); notification) + Notification::overlay()->dismissNotification(notification); + + return 0; +} + +static int notificationGetText(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto notification = ref->notification.lock(); + if (!notification) { + lua_pushnil(L); + return 1; + } + + lua_pushstring(L, notification->text().c_str()); + return 1; +} + +static int notificationGetTimeout(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto notification = ref->notification.lock(); + if (!notification) { + lua_pushnil(L); + return 1; + } + + lua_pushnumber(L, notification->timeMs()); + return 1; +} + +static int notificationGetColor(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto notification = ref->notification.lock(); + if (!notification) { + lua_pushnil(L); + return 1; + } + + lua_pushinteger(L, sc<lua_Integer>(notification->color().getAsHex())); + return 1; +} + +static int notificationGetIcon(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto notification = ref->notification.lock(); + if (!notification) { + lua_pushnil(L); + return 1; + } + + lua_pushinteger(L, sc<lua_Integer>(notification->icon())); + return 1; +} + +static int notificationGetFontSize(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto notification = ref->notification.lock(); + if (!notification) { + lua_pushnil(L); + return 1; + } + + lua_pushnumber(L, notification->fontSize()); + return 1; +} + +static int notificationGetElapsed(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto notification = ref->notification.lock(); + if (!notification) { + lua_pushnil(L); + return 1; + } + + lua_pushnumber(L, notification->timeElapsedMs()); + return 1; +} + +static int notificationGetElapsedSinceCreation(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + const auto notification = ref->notification.lock(); + if (!notification) { + lua_pushnil(L); + return 1; + } + + lua_pushnumber(L, notification->timeElapsedSinceCreationMs()); + return 1; +} + +static int notificationIsAlive(lua_State* L) { + auto* ref = sc<SNotificationRef*>(luaL_checkudata(L, 1, MT)); + + lua_pushboolean(L, ref->notification.lock().get() != nullptr); + return 1; +} + +static int notificationIndex(lua_State* L) { + luaL_checkudata(L, 1, MT); + const std::string_view key = luaL_checkstring(L, 2); + + if (key == "pause") + lua_pushcfunction(L, notificationPause); + else if (key == "resume") + lua_pushcfunction(L, notificationResume); + else if (key == "set_paused") + lua_pushcfunction(L, notificationSetPaused); + else if (key == "is_paused") + lua_pushcfunction(L, notificationIsPaused); + else if (key == "set_text") + lua_pushcfunction(L, notificationSetText); + else if (key == "set_timeout") + lua_pushcfunction(L, notificationSetTimeout); + else if (key == "set_color") + lua_pushcfunction(L, notificationSetColor); + else if (key == "set_icon") + lua_pushcfunction(L, notificationSetIcon); + else if (key == "set_font_size") + lua_pushcfunction(L, notificationSetFontSize); + else if (key == "dismiss") + lua_pushcfunction(L, notificationDismiss); + else if (key == "get_text") + lua_pushcfunction(L, notificationGetText); + else if (key == "get_timeout") + lua_pushcfunction(L, notificationGetTimeout); + else if (key == "get_color") + lua_pushcfunction(L, notificationGetColor); + else if (key == "get_icon") + lua_pushcfunction(L, notificationGetIcon); + else if (key == "get_font_size") + lua_pushcfunction(L, notificationGetFontSize); + else if (key == "get_elapsed") + lua_pushcfunction(L, notificationGetElapsed); + else if (key == "get_elapsed_since_creation") + lua_pushcfunction(L, notificationGetElapsedSinceCreation); + else if (key == "is_alive") + lua_pushcfunction(L, notificationIsAlive); + else + lua_pushnil(L); + + return 1; +} + +void Objects::CLuaNotification::setup(lua_State* L) { + registerMetatable(L, MT, notificationIndex, notificationGC, notificationEq, notificationToString); +} + +void Objects::CLuaNotification::push(lua_State* L, const SP<Notification::CNotification>& notification) { + new (lua_newuserdata(L, sizeof(SNotificationRef))) SNotificationRef{.notification = WP<Notification::CNotification>(notification)}; + luaL_getmetatable(L, MT); + lua_setmetatable(L, -2); +} |
