diff --git a/VERSION b/VERSION index 2003b63..965065d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.9.2 +0.9.3 diff --git a/assets/example.conf b/assets/example.conf index 94b887e..2e28cb5 100644 --- a/assets/example.conf +++ b/assets/example.conf @@ -57,6 +57,9 @@ input-field { placeholder_text = Input password... fail_text = $PAMFAIL + # uncomment if you wish to display a message during authentication + # check_text = Authenticating... + # uncomment to use a letter instead of a dot to indicate the typed password # dots_text_format = * # dots_size = 0.4 diff --git a/src/auth/Auth.cpp b/src/auth/Auth.cpp index 15824ac..c0f5584 100644 --- a/src/auth/Auth.cpp +++ b/src/auth/Auth.cpp @@ -106,7 +106,7 @@ void CAuth::enqueueFail(const std::string& failText, eAuthImplementations implTy m_sCurrentFail.failSource = implType; m_sCurrentFail.failedAttempts++; - Debug::log(LOG, "Failed attempts: {}", m_sCurrentFail.failedAttempts); + Log::logger->log(Log::INFO, "Failed attempts: {}", m_sCurrentFail.failedAttempts); if (m_resetDisplayFailTimer) { m_resetDisplayFailTimer->cancel(); diff --git a/src/auth/Fingerprint.cpp b/src/auth/Fingerprint.cpp index db4bba7..780c079 100644 --- a/src/auth/Fingerprint.cpp +++ b/src/auth/Fingerprint.cpp @@ -51,14 +51,14 @@ void CFingerprint::init() { m_sDBUSState.connection = sdbus::createSystemBusConnection(); m_sDBUSState.login = sdbus::createProxy(*m_sDBUSState.connection, sdbus::ServiceName{"org.freedesktop.login1"}, sdbus::ObjectPath{"/org/freedesktop/login1"}); } catch (sdbus::Error& e) { - Debug::log(ERR, "fprint: Failed to setup dbus ({})", e.what()); + Log::logger->log(Log::ERR, "fprint: Failed to setup dbus ({})", e.what()); m_sDBUSState.connection.reset(); return; } m_sDBUSState.login->getPropertyAsync("PreparingForSleep").onInterface(LOGIN_MANAGER).uponReplyInvoke([this](std::optional e, sdbus::Variant preparingForSleep) { if (e) { - Debug::log(WARN, "fprint: Failed getting value for PreparingForSleep: {}", e->what()); + Log::logger->log(Log::WARN, "fprint: Failed getting value for PreparingForSleep: {}", e->what()); return; } m_sDBUSState.sleeping = preparingForSleep.get(); @@ -68,7 +68,7 @@ void CFingerprint::init() { startVerify(); }); m_sDBUSState.login->uponSignal("PrepareForSleep").onInterface(LOGIN_MANAGER).call([this](bool start) { - Debug::log(LOG, "fprint: PrepareForSleep (start: {})", start); + Log::logger->log(Log::INFO, "fprint: PrepareForSleep (start: {})", start); m_sDBUSState.sleeping = start; if (!m_sDBUSState.sleeping && !m_sDBUSState.verifying) startVerify(); @@ -111,13 +111,15 @@ bool CFingerprint::createDeviceProxy() { try { proxy->callMethod("GetDefaultDevice").onInterface(MANAGER).storeResultsTo(path); } catch (sdbus::Error& e) { - Debug::log(WARN, "fprint: couldn't connect to Fprint service ({})", e.what()); + Log::logger->log(Log::WARN, "fprint: couldn't connect to Fprint service ({})", e.what()); return false; } - Debug::log(LOG, "fprint: using device path {}", path.c_str()); + Log::logger->log(Log::INFO, "fprint: using device path {}", path.c_str()); m_sDBUSState.device = sdbus::createProxy(*m_sDBUSState.connection, FPRINT, path); - m_sDBUSState.device->uponSignal("VerifyFingerSelected").onInterface(DEVICE).call([](const std::string& finger) { Debug::log(LOG, "fprint: finger selected: {}", finger); }); + m_sDBUSState.device->uponSignal("VerifyFingerSelected").onInterface(DEVICE).call([](const std::string& finger) { + Log::logger->log(Log::INFO, "fprint: finger selected: {}", finger); + }); m_sDBUSState.device->uponSignal("VerifyStatus").onInterface(DEVICE).call([this](const std::string& result, const bool done) { handleVerifyStatus(result, done); }); m_sDBUSState.device->uponSignal("PropertiesChanged") @@ -140,17 +142,17 @@ bool CFingerprint::createDeviceProxy() { } void CFingerprint::handleVerifyStatus(const std::string& result, bool done) { - Debug::log(LOG, "fprint: handling status {}", result); + Log::logger->log(Log::INFO, "fprint: handling status {}", result); auto matchResult = s_mapStringToTestType[result]; bool authenticated = false; bool retry = false; if (m_sDBUSState.sleeping) { stopVerify(); - Debug::log(LOG, "fprint: device suspended"); + Log::logger->log(Log::INFO, "fprint: device suspended"); return; } switch (matchResult) { - case MATCH_INVALID: Debug::log(WARN, "fprint: unknown status: {}", result); break; + case MATCH_INVALID: Log::logger->log(Log::WARN, "fprint: unknown status: {}", result); break; case MATCH_NO_MATCH: stopVerify(); if (m_sDBUSState.retries >= 3) { @@ -206,9 +208,9 @@ void CFingerprint::claimDevice() { const auto currentUser = ""; // Empty string means use the caller's id. m_sDBUSState.device->callMethodAsync("Claim").onInterface(DEVICE).withArguments(currentUser).uponReplyInvoke([this](std::optional e) { if (e) - Debug::log(WARN, "fprint: could not claim device, {}", e->what()); + Log::logger->log(Log::WARN, "fprint: could not claim device, {}", e->what()); else { - Debug::log(LOG, "fprint: claimed device"); + Log::logger->log(Log::INFO, "fprint: claimed device"); startVerify(); } }); @@ -226,12 +228,12 @@ void CFingerprint::startVerify(bool isRetry) { auto finger = "any"; // Any finger. m_sDBUSState.device->callMethodAsync("VerifyStart").onInterface(DEVICE).withArguments(finger).uponReplyInvoke([this, isRetry](std::optional e) { if (e) { - Debug::log(WARN, "fprint: could not start verifying, {}", e->what()); + Log::logger->log(Log::WARN, "fprint: could not start verifying, {}", e->what()); if (isRetry) m_sFailureReason = "Fingerprint auth disabled (failed to restart)"; } else { - Debug::log(LOG, "fprint: started verifying"); + Log::logger->log(Log::INFO, "fprint: started verifying"); if (isRetry) { m_sDBUSState.retries++; m_sPrompt = "Could not match fingerprint. Try again."; @@ -249,10 +251,10 @@ bool CFingerprint::stopVerify() { try { m_sDBUSState.device->callMethod("VerifyStop").onInterface(DEVICE); } catch (sdbus::Error& e) { - Debug::log(WARN, "fprint: could not stop verifying, {}", e.what()); + Log::logger->log(Log::WARN, "fprint: could not stop verifying, {}", e.what()); return false; } - Debug::log(LOG, "fprint: stopped verification"); + Log::logger->log(Log::INFO, "fprint: stopped verification"); return true; } @@ -262,9 +264,9 @@ bool CFingerprint::releaseDevice() { try { m_sDBUSState.device->callMethod("Release").onInterface(DEVICE); } catch (sdbus::Error& e) { - Debug::log(WARN, "fprint: could not release device, {}", e.what()); + Log::logger->log(Log::WARN, "fprint: could not release device, {}", e.what()); return false; } - Debug::log(LOG, "fprint: released device"); + Log::logger->log(Log::INFO, "fprint: released device"); return true; } diff --git a/src/auth/Pam.cpp b/src/auth/Pam.cpp index 9e1f2ac..813ab92 100644 --- a/src/auth/Pam.cpp +++ b/src/auth/Pam.cpp @@ -1,11 +1,11 @@ #include "Pam.hpp" +#include "../config/ConfigManager.hpp" #include "../core/hyprlock.hpp" #include "../helpers/Log.hpp" -#include "../config/ConfigManager.hpp" +#include "../helpers/MiscFunctions.hpp" #include #include -#include #include #if __has_include() #include @@ -25,7 +25,7 @@ int conv(int num_msg, const struct pam_message** msg, struct pam_response** resp case PAM_PROMPT_ECHO_ON: { const auto PROMPT = std::string(msg[i]->msg); const auto PROMPTCHANGED = PROMPT != CONVERSATIONSTATE->prompt; - Debug::log(LOG, "PAM_PROMPT: {}", PROMPT); + Log::logger->log(Log::INFO, "PAM_PROMPT: {}", PROMPT); if (PROMPTCHANGED) g_pHyprlock->enqueueForceUpdateTimers(); @@ -44,9 +44,9 @@ int conv(int num_msg, const struct pam_message** msg, struct pam_response** resp pamReply[i].resp = strdup(CONVERSATIONSTATE->input.c_str()); initialPrompt = false; } break; - case PAM_ERROR_MSG: Debug::log(ERR, "PAM: {}", msg[i]->msg); break; + case PAM_ERROR_MSG: Log::logger->log(Log::ERR, "PAM: {}", msg[i]->msg); break; case PAM_TEXT_INFO: - Debug::log(LOG, "PAM: {}", msg[i]->msg); + Log::logger->log(Log::INFO, "PAM: {}", msg[i]->msg); // Targets this log from pam_faillock: https://github.com/linux-pam/linux-pam/blob/fa3295e079dbbc241906f29bde5fb71bc4172771/modules/pam_faillock/pam_faillock.c#L417 if (const auto MSG = std::string(msg[i]->msg); MSG.contains("left to unlock")) { CONVERSATIONSTATE->failText = MSG; @@ -65,10 +65,12 @@ CPam::CPam() { m_sPamModule = *PAMMODULE; if (!std::filesystem::exists(std::filesystem::path("/etc/pam.d/") / m_sPamModule)) { - Debug::log(ERR, R"(Pam module "/etc/pam.d/{}" does not exist! Falling back to "/etc/pam.d/su")", m_sPamModule); + Log::logger->log(Log::ERR, R"(Pam module "/etc/pam.d/{}" does not exist! Falling back to "/etc/pam.d/su")", m_sPamModule); m_sPamModule = "su"; } + m_username = getUsernameForCurrentUid(); + m_sConversationState.waitForInput = [this]() { this->waitForInput(); }; } @@ -106,16 +108,19 @@ void CPam::init() { } bool CPam::auth() { - const pam_conv localConv = {.conv = conv, .appdata_ptr = (void*)&m_sConversationState}; - pam_handle_t* handle = nullptr; - auto uidPassword = getpwuid(getuid()); - RASSERT(uidPassword && uidPassword->pw_name, "Failed to get username (getpwuid)"); + const pam_conv localConv = {.conv = conv, .appdata_ptr = (void*)&m_sConversationState}; + pam_handle_t* handle = nullptr; - int ret = pam_start(m_sPamModule.c_str(), uidPassword->pw_name, &localConv, &handle); + if (m_username.empty()) { + m_sConversationState.failText = "Username not set"; + return false; + } + + int ret = pam_start(m_sPamModule.c_str(), m_username.c_str(), &localConv, &handle); if (ret != PAM_SUCCESS) { m_sConversationState.failText = "pam_start failed"; - Debug::log(ERR, "auth: pam_start failed for {}", m_sPamModule); + Log::logger->log(Log::ERR, "auth: pam_start failed for {}", m_sPamModule); return false; } @@ -128,12 +133,12 @@ bool CPam::auth() { if (ret != PAM_SUCCESS) { if (!m_sConversationState.failTextFromPam) m_sConversationState.failText = ret == PAM_AUTH_ERR ? "Authentication failed" : "pam_authenticate failed"; - Debug::log(ERR, "auth: {} for {}", m_sConversationState.failText, m_sPamModule); + Log::logger->log(Log::ERR, "auth: {} for {}", m_sConversationState.failText, m_sPamModule); return false; } m_sConversationState.failText = "Successfully authenticated"; - Debug::log(LOG, "auth: authenticated for {}", m_sPamModule); + Log::logger->log(Log::INFO, "auth: authenticated for {}", m_sPamModule); return true; } @@ -151,7 +156,7 @@ void CPam::handleInput(const std::string& input) { std::unique_lock lk(m_sConversationState.inputMutex); if (!m_sConversationState.inputRequested) - Debug::log(ERR, "SubmitInput called, but the auth thread is not waiting for input!"); + Log::logger->log(Log::ERR, "SubmitInput called, but the auth thread is not waiting for input!"); m_sConversationState.input = input; m_sConversationState.inputRequested = false; diff --git a/src/auth/Pam.hpp b/src/auth/Pam.hpp index 831fbf2..cb96cea 100644 --- a/src/auth/Pam.hpp +++ b/src/auth/Pam.hpp @@ -46,7 +46,8 @@ class CPam : public IAuthImplementation { bool m_bBlockInput = true; - std::string m_sPamModule; + std::string m_sPamModule = ""; + std::string m_username = ""; bool auth(); void resetConversation(); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 00365d7..2c200f8 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include using namespace Hyprutils::String; using namespace Hyprutils::Animation; @@ -130,7 +130,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** try { DATA->m_fAngle = std::stoi(var.substr(0, var.find("deg"))) * (M_PI / 180.0); // radians } catch (...) { - Debug::log(WARN, "Error parsing gradient {}", V); + Log::logger->log(Log::WARN, "Error parsing gradient {}", V); parseError = "Error parsing gradient " + V; } @@ -139,7 +139,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** rolling = trim(rolling.substr(LAST ? rolling.length() : SPACEPOS + 1)); if (DATA->m_vColors.size() >= 10) { - Debug::log(WARN, "Error parsing gradient {}: max colors is 10.", V); + Log::logger->log(Log::WARN, "Error parsing gradient {}: max colors is 10.", V); parseError = "Error parsing gradient " + V + ": max colors is 10."; break; } @@ -150,7 +150,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** try { DATA->m_vColors.emplace_back(configStringToInt(var)); } catch (std::exception& e) { - Debug::log(WARN, "Error parsing gradient {}", V); + Log::logger->log(Log::WARN, "Error parsing gradient {}", V); parseError = "Error parsing gradient " + V + ": " + e.what(); } } @@ -161,7 +161,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** } if (DATA->m_vColors.size() == 0) { - Debug::log(WARN, "Error parsing gradient {}", V); + Log::logger->log(Log::WARN, "Error parsing gradient {}", V); parseError = "Error parsing gradient " + V + ": No colors?"; DATA->m_vColors.emplace_back(0); // transparent @@ -181,17 +181,40 @@ static void configHandleGradientDestroy(void** data) { delete reinterpret_cast(*data); } -static std::string getMainConfigPath() { - static const auto paths = Hyprutils::Path::findConfig("hyprlock"); - if (paths.first.has_value()) - return paths.first.value(); +static std::expected getMainConfigPath() { + static const auto PATHS = Hyprutils::Path::findConfig("hyprlock"); + if (PATHS.first.has_value()) + return PATHS.first.value(); else - throw std::runtime_error("Could not find config in HOME, XDG_CONFIG_HOME, XDG_CONFIG_DIRS or /etc/hypr."); + return std::unexpected{"Could not find config in HOME, XDG_CONFIG_HOME, XDG_CONFIG_DIRS or /etc/hypr."}; } -CConfigManager::CConfigManager(std::string configPath) : - m_config(configPath.empty() ? getMainConfigPath().c_str() : configPath.c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = configPath.empty()}) { - configCurrentPath = configPath.empty() ? getMainConfigPath() : configPath; +std::expected CConfigManager::resolveConfigPath(std::optional explicitPath) { + std::string configPath = ""; + if (explicitPath.has_value()) { + configPath = explicitPath.value(); + configPath = absolutePath(configPath, ""); + } else { + auto mainConfigPath = getMainConfigPath(); + if (!mainConfigPath.has_value()) + return std::unexpected{mainConfigPath.error()}; + + configPath = mainConfigPath.value(); + } + + if (!std::filesystem::exists(configPath)) + return std::unexpected{std::vformat("No config file at \"{}\"", std::make_format_args(configPath))}; + + return configPath; +} + +CConfigManager::CConfigManager(const char* configPath) : + m_configCurrentPath(configPath), m_config(configPath, + Hyprlang::SConfigOptions{ + .throwAllErrors = true, + .allowMissingConfig = false, + }) { + ; } inline static constexpr auto GRADIENTCONFIG = [](const char* default_value) -> Hyprlang::CUSTOMTYPE { @@ -303,6 +326,7 @@ void CConfigManager::init() { m_config.addSpecialConfigValue("input-field", "check_color", GRADIENTCONFIG("0xFF22CC88")); m_config.addSpecialConfigValue("input-field", "fail_color", GRADIENTCONFIG("0xFFCC2222")); m_config.addSpecialConfigValue("input-field", "fail_text", Hyprlang::STRING{"$FAIL"}); + m_config.addSpecialConfigValue("input-field", "check_text", Hyprlang::STRING{""}); m_config.addSpecialConfigValue("input-field", "capslock_color", GRADIENTCONFIG("")); m_config.addSpecialConfigValue("input-field", "numlock_color", GRADIENTCONFIG("")); m_config.addSpecialConfigValue("input-field", "bothlock_color", GRADIENTCONFIG("")); @@ -358,7 +382,7 @@ void CConfigManager::init() { auto result = m_config.parse(); if (result.error) - Debug::log(ERR, "Config has errors:\n{}\nProceeding ignoring faulty entries", result.getError()); + Log::logger->log(Log::ERR, "Config has errors:\n{}\nProceeding ignoring faulty entries", result.getError()); #undef SHADOWABLE #undef CLICKABLE @@ -369,11 +393,10 @@ std::vector CConfigManager::getWidgetConfigs() { #define SHADOWABLE(name) \ {"shadow_size", m_config.getSpecialConfigValue(name, "shadow_size", k.c_str())}, {"shadow_passes", m_config.getSpecialConfigValue(name, "shadow_passes", k.c_str())}, \ - {"shadow_color", m_config.getSpecialConfigValue(name, "shadow_color", k.c_str())}, { \ - "shadow_boost", m_config.getSpecialConfigValue(name, "shadow_boost", k.c_str()) \ - } + {"shadow_color", m_config.getSpecialConfigValue(name, "shadow_color", k.c_str())}, {"shadow_boost", m_config.getSpecialConfigValue(name, "shadow_boost", k.c_str())} -#define CLICKABLE(name) {"onclick", m_config.getSpecialConfigValue(name, "onclick", k.c_str())} +#define CLICKABLE(name) \ + { "onclick", m_config.getSpecialConfigValue(name, "onclick", k.c_str()) } // auto keys = m_config.listKeysForSpecialCategory("background"); @@ -485,6 +508,7 @@ std::vector CConfigManager::getWidgetConfigs() { {"check_color", m_config.getSpecialConfigValue("input-field", "check_color", k.c_str())}, {"fail_color", m_config.getSpecialConfigValue("input-field", "fail_color", k.c_str())}, {"fail_text", m_config.getSpecialConfigValue("input-field", "fail_text", k.c_str())}, + {"check_text", m_config.getSpecialConfigValue("input-field", "check_text", k.c_str())}, {"capslock_color", m_config.getSpecialConfigValue("input-field", "capslock_color", k.c_str())}, {"numlock_color", m_config.getSpecialConfigValue("input-field", "numlock_color", k.c_str())}, {"bothlock_color", m_config.getSpecialConfigValue("input-field", "bothlock_color", k.c_str())}, @@ -526,45 +550,45 @@ std::vector CConfigManager::getWidgetConfigs() { std::optional CConfigManager::handleSource(const std::string& command, const std::string& rawpath) { if (rawpath.length() < 2) { - Debug::log(ERR, "source= path garbage"); + Log::logger->log(Log::ERR, "source= path garbage"); return "source path " + rawpath + " bogus!"; } std::unique_ptr glob_buf{new glob_t, [](glob_t* g) { globfree(g); }}; memset(glob_buf.get(), 0, sizeof(glob_t)); - const auto CURRENTDIR = std::filesystem::path(configCurrentPath).parent_path().string(); + const auto CURRENTDIR = std::filesystem::path(m_configCurrentPath).parent_path().string(); if (auto r = glob(absolutePath(rawpath, CURRENTDIR).c_str(), GLOB_TILDE, nullptr, glob_buf.get()); r != 0) { std::string err = std::format("source= globbing error: {}", r == GLOB_NOMATCH ? "found no match" : GLOB_ABORTED ? "read error" : "out of memory"); - Debug::log(ERR, "{}", err); + Log::logger->log(Log::ERR, "{}", err); return err; } for (size_t i = 0; i < glob_buf->gl_pathc; i++) { const auto PATH = absolutePath(glob_buf->gl_pathv[i], CURRENTDIR); - if (PATH.empty() || PATH == configCurrentPath) { - Debug::log(WARN, "source= skipping invalid path"); + if (PATH.empty() || PATH == m_configCurrentPath) { + Log::logger->log(Log::WARN, "source= skipping invalid path"); continue; } if (!std::filesystem::is_regular_file(PATH)) { if (std::filesystem::exists(PATH)) { - Debug::log(WARN, "source= skipping non-file {}", PATH); + Log::logger->log(Log::WARN, "source= skipping non-file {}", PATH); continue; } - Debug::log(ERR, "source= file doesnt exist"); + Log::logger->log(Log::ERR, "source= file doesnt exist"); return "source file " + PATH + " doesn't exist!"; } // allow for nested config parsing - auto backupConfigPath = configCurrentPath; - configCurrentPath = PATH; + auto backupConfigPath = m_configCurrentPath; + m_configCurrentPath = PATH; m_config.parseFile(PATH.c_str()); - configCurrentPath = backupConfigPath; + m_configCurrentPath = backupConfigPath; } return {}; diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 9183f2b..d1c3b6f 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -4,14 +4,17 @@ #include #include -#include +#include +#include #include +#include #include "../defines.hpp" class CConfigManager { public: - CConfigManager(std::string configPath); + static std::expected resolveConfigPath(std::optional explicitPath); + CConfigManager(const char* configPath); void init(); template @@ -32,7 +35,7 @@ class CConfigManager { std::optional handleBezier(const std::string&, const std::string&); std::optional handleAnimation(const std::string&, const std::string&); - std::string configCurrentPath; + std::string m_configCurrentPath; Hyprutils::Animation::CAnimationConfigTree m_AnimationTree; diff --git a/src/core/Egl.cpp b/src/core/Egl.cpp index e6e1004..c44a901 100644 --- a/src/core/Egl.cpp +++ b/src/core/Egl.cpp @@ -42,27 +42,27 @@ CEGL::CEGL(wl_display* display) { eglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_WAYLAND_EXT, display, nullptr); EGLint matched = 0; if (eglDisplay == EGL_NO_DISPLAY) { - Debug::log(CRIT, "Failed to create EGL display"); + Log::logger->log(Log::CRIT, "Failed to create EGL display"); goto error; } if (eglInitialize(eglDisplay, nullptr, nullptr) == EGL_FALSE) { - Debug::log(CRIT, "Failed to initialize EGL"); + Log::logger->log(Log::CRIT, "Failed to initialize EGL"); goto error; } if (!eglChooseConfig(eglDisplay, config_attribs, &eglConfig, 1, &matched)) { - Debug::log(CRIT, "eglChooseConfig failed"); + Log::logger->log(Log::CRIT, "eglChooseConfig failed"); goto error; } if (matched == 0) { - Debug::log(CRIT, "Failed to match an EGL config"); + Log::logger->log(Log::CRIT, "Failed to match an EGL config"); goto error; } eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, context_attribs); if (eglContext == EGL_NO_CONTEXT) { - Debug::log(CRIT, "Failed to create EGL context"); + Log::logger->log(Log::CRIT, "Failed to create EGL context"); goto error; } diff --git a/src/core/LockSurface.cpp b/src/core/LockSurface.cpp index 4a996ad..2bdec49 100644 --- a/src/core/LockSurface.cpp +++ b/src/core/LockSurface.cpp @@ -33,7 +33,7 @@ CSessionLockSurface::CSessionLockSurface(const SP& pOutput) : m_outputR const bool SAMESCALE = fractionalScale == scale / 120.0; fractionalScale = scale / 120.0; - Debug::log(LOG, "Got fractional scale: {:.1f}%", fractionalScale * 100.F); + Log::logger->log(Log::INFO, "Got fractional scale: {:.1f}%", fractionalScale * 100.F); if (!SAMESCALE && readyForFrame) onScaleUpdate(); @@ -43,9 +43,9 @@ CSessionLockSurface::CSessionLockSurface(const SP& pOutput) : m_outputR } if (!PFRACTIONALMGR) - Debug::log(LOG, "No fractional-scale support! Oops, won't be able to scale!"); + Log::logger->log(Log::INFO, "No fractional-scale support! Oops, won't be able to scale!"); if (!PVIEWPORTER) - Debug::log(LOG, "No viewporter support! Oops, won't be able to scale!"); + Log::logger->log(Log::INFO, "No viewporter support! Oops, won't be able to scale!"); lockSurface = makeShared(g_pHyprlock->getSessionLock()->sendGetLockSurface(surface->resource(), pOutput->m_wlOutput->resource())); RASSERT(lockSurface, "Couldn't create ext_session_lock_surface_v1"); @@ -54,7 +54,7 @@ CSessionLockSurface::CSessionLockSurface(const SP& pOutput) : m_outputR } void CSessionLockSurface::configure(const Vector2D& size_, uint32_t serial_) { - Debug::log(LOG, "configure with serial {}", serial_); + Log::logger->log(Log::INFO, "configure with serial {}", serial_); const bool SAMESERIAL = serial == serial_; const bool SAMESIZE = logicalSize == size_; @@ -78,7 +78,7 @@ void CSessionLockSurface::configure(const Vector2D& size_, uint32_t serial_) { if (!SAMESERIAL) lockSurface->sendAckConfigure(serial); - Debug::log(LOG, "Configuring surface for logical {} and pixel {}", logicalSize, size); + Log::logger->log(Log::INFO, "Configuring surface for logical {} and pixel {}", logicalSize, size); surface->sendDamageBuffer(0, 0, 0xFFFF, 0xFFFF); @@ -94,7 +94,7 @@ void CSessionLockSurface::configure(const Vector2D& size_, uint32_t serial_) { } if (readyForFrame && !(SAMESIZE && SAMESCALE)) { - Debug::log(LOG, "output {} changed, reloading widgets!", POUTPUT->stringPort); + Log::logger->log(Log::INFO, "output {} changed, reloading widgets!", POUTPUT->stringPort); g_pRenderer->reconfigureWidgetsFor(POUTPUT->m_ID); } @@ -120,9 +120,9 @@ void CSessionLockSurface::render() { if (g_pHyprlock->m_bTerminate) return; - if (Debug::verbose) { + if (Log::logger->verbose()) { const auto POUTPUT = m_outputRef.lock(); - Debug::log(TRACE, "[{}] frame {}, Current fps: {:.2f}", POUTPUT->stringPort, m_frames, 1000.f / (frameTime - m_lastFrameTime)); + Log::logger->log(Log::TRACE, "[{}] frame {}, Current fps: {:.2f}", POUTPUT->stringPort, m_frames, 1000.f / (frameTime - m_lastFrameTime)); } m_lastFrameTime = frameTime; diff --git a/src/core/Output.cpp b/src/core/Output.cpp index 07d27c7..ee5ea24 100644 --- a/src/core/Output.cpp +++ b/src/core/Output.cpp @@ -9,22 +9,22 @@ void COutput::create(WP pSelf, SP pWlOutput, uint32_t _name m_wlOutput->setDescription([this](CCWlOutput* r, const char* description) { stringDesc = description ? std::string{description} : ""; - Debug::log(LOG, "output {} description {}", m_ID, stringDesc); + Log::logger->log(Log::INFO, "output {} description {}", m_ID, stringDesc); }); m_wlOutput->setName([this](CCWlOutput* r, const char* name) { stringName = std::string{name} + stringName; stringPort = std::string{name}; - Debug::log(LOG, "output {} name {}", name, name); + Log::logger->log(Log::INFO, "output {} name {}", name, name); }); m_wlOutput->setScale([this](CCWlOutput* r, int32_t sc) { scale = sc; }); m_wlOutput->setDone([this](CCWlOutput* r) { done = true; - Debug::log(LOG, "output {} done", m_ID); + Log::logger->log(Log::INFO, "output {} done", m_ID); if (g_pHyprlock->m_lockAquired && !m_sessionLockSurface) { - Debug::log(LOG, "output {} creating a new lock surface", m_ID); + Log::logger->log(Log::INFO, "output {} creating a new lock surface", m_ID); createSessionLockSurface(); } }); @@ -41,23 +41,23 @@ void COutput::create(WP pSelf, SP pWlOutput, uint32_t _name [this](CCWlOutput* r, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char* make, const char* model, int32_t transform_) { transform = (wl_output_transform)transform_; - Debug::log(LOG, "output {} make {} model {}", m_ID, make ? make : "", model ? model : ""); + Log::logger->log(Log::INFO, "output {} make {} model {}", m_ID, make ? make : "", model ? model : ""); }); } void COutput::createSessionLockSurface() { if (!m_self.valid()) { - Debug::log(ERR, "output {} dead??", m_ID); + Log::logger->log(Log::ERR, "output {} dead??", m_ID); return; } if (m_sessionLockSurface) { - Debug::log(ERR, "output {} already has a session lock surface", m_ID); + Log::logger->log(Log::ERR, "output {} already has a session lock surface", m_ID); return; } if (size == Vector2D{0, 0}) { - Debug::log(WARN, "output {} refusing to create a lock surface with size 0x0", m_ID); + Log::logger->log(Log::WARN, "output {} refusing to create a lock surface with size 0x0", m_ID); return; } diff --git a/src/core/Seat.cpp b/src/core/Seat.cpp index 713b8de..6fe27ca 100644 --- a/src/core/Seat.cpp +++ b/src/core/Seat.cpp @@ -24,7 +24,7 @@ void CSeatManager::registerSeat(SP seat) { m_pXKBContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!m_pXKBContext) - Debug::log(ERR, "Failed to create xkb context"); + Log::logger->log(Log::ERR, "Failed to create xkb context"); m_pSeat->setCapabilities([this](CCWlSeat* r, wl_seat_capability caps) { if (caps & WL_SEAT_CAPABILITY_POINTER) { @@ -41,7 +41,7 @@ void CSeatManager::registerSeat(SP seat) { return; if (!g_pHyprlock->isUnlocked() && g_pHyprlock->m_vLastEnterCoords.distance({wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)}) > 5) { - Debug::log(LOG, "In grace and cursor moved more than 5px, unlocking!"); + Log::logger->log(Log::INFO, "In grace and cursor moved more than 5px, unlocking!"); g_pHyprlock->unlock(); } }); @@ -95,13 +95,13 @@ void CSeatManager::registerSeat(SP seat) { return; if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { - Debug::log(ERR, "Could not recognise keymap format"); + Log::logger->log(Log::ERR, "Could not recognise keymap format"); return; } const char* buf = (const char*)mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0); if (buf == MAP_FAILED) { - Debug::log(ERR, "Failed to mmap xkb keymap: {}", errno); + Log::logger->log(Log::ERR, "Failed to mmap xkb keymap: {}", errno); return; } @@ -111,20 +111,20 @@ void CSeatManager::registerSeat(SP seat) { close(fd); if (!m_pXKBKeymap) { - Debug::log(ERR, "Failed to compile xkb keymap"); + Log::logger->log(Log::ERR, "Failed to compile xkb keymap"); return; } m_pXKBState = xkb_state_new(m_pXKBKeymap); if (!m_pXKBState) { - Debug::log(ERR, "Failed to create xkb state"); + Log::logger->log(Log::ERR, "Failed to create xkb state"); return; } const auto PCOMOPOSETABLE = xkb_compose_table_new_from_locale(m_pXKBContext, setlocale(LC_CTYPE, nullptr), XKB_COMPOSE_COMPILE_NO_FLAGS); if (!PCOMOPOSETABLE) { - Debug::log(ERR, "Failed to create xkb compose table"); + Log::logger->log(Log::ERR, "Failed to create xkb compose table"); return; } @@ -161,7 +161,7 @@ void CSeatManager::registerSeat(SP seat) { } }); - m_pSeat->setName([](CCWlSeat* r, const char* name) { Debug::log(LOG, "Exposed seat name: {}", name ? name : "nullptr"); }); + m_pSeat->setName([](CCWlSeat* r, const char* name) { Log::logger->log(Log::INFO, "Exposed seat name: {}", name ? name : "nullptr"); }); } void CSeatManager::registerCursorShape(SP shape) { diff --git a/src/core/hyprlock.cpp b/src/core/hyprlock.cpp index 14f9cda..2782788 100644 --- a/src/core/hyprlock.cpp +++ b/src/core/hyprlock.cpp @@ -35,10 +35,10 @@ static void setMallocThreshold() { #endif } -CHyprlock::CHyprlock(const std::string& wlDisplay, const bool immediateRender, const int graceSeconds) { +CHyprlock::CHyprlock(std::string_view wlDisplay, const bool immediateRender, const int graceSeconds) { setMallocThreshold(); - m_sWaylandState.display = wl_display_connect(wlDisplay.empty() ? nullptr : wlDisplay.c_str()); + m_sWaylandState.display = wl_display_connect(wlDisplay.empty() ? nullptr : std::string{wlDisplay}.c_str()); RASSERT(m_sWaylandState.display, "Couldn't connect to a wayland compositor"); g_pEGL = makeUnique(m_sWaylandState.display); @@ -71,7 +71,7 @@ static void registerSignalAction(int sig, void (*handler)(int), int sa_flags = 0 static void handleUnlockSignal(int sig) { if (sig == SIGUSR1) { - Debug::log(LOG, "Unlocking with a SIGUSR1"); + Log::logger->log(Log::INFO, "Unlocking with a SIGUSR1"); g_pAuth->enqueueUnlock(); } } @@ -116,15 +116,15 @@ gbm_device* CHyprlock::createGBMDevice(drmDevice* dev) { char* renderNode = gbm_find_render_node(dev); if (!renderNode) { - Debug::log(ERR, "[core] Couldn't find a render node"); + Log::logger->log(Log::ERR, "[core] Couldn't find a render node"); return nullptr; } - Debug::log(TRACE, "[core] createGBMDevice: render node {}", renderNode); + Log::logger->log(Log::TRACE, "[core] createGBMDevice: render node {}", renderNode); int fd = open(renderNode, O_RDWR | O_CLOEXEC); if (fd < 0) { - Debug::log(ERR, "[core] couldn't open render node"); + Log::logger->log(Log::ERR, "[core] couldn't open render node"); free(renderNode); return nullptr; } @@ -135,13 +135,13 @@ gbm_device* CHyprlock::createGBMDevice(drmDevice* dev) { void CHyprlock::addDmabufListener() { dma.linuxDmabufFeedback->setTrancheDone([this](CCZwpLinuxDmabufFeedbackV1* r) { - Debug::log(TRACE, "[core] dmabufFeedbackTrancheDone"); + Log::logger->log(Log::TRACE, "[core] dmabufFeedbackTrancheDone"); dma.deviceUsed = false; }); dma.linuxDmabufFeedback->setTrancheFormats([this](CCZwpLinuxDmabufFeedbackV1* r, wl_array* indices) { - Debug::log(TRACE, "[core] dmabufFeedbackTrancheFormats"); + Log::logger->log(Log::TRACE, "[core] dmabufFeedbackTrancheFormats"); if (!dma.deviceUsed || !dma.formatTable) return; @@ -162,14 +162,14 @@ void CHyprlock::addDmabufListener() { if (*idx >= n_modifiers) continue; - Debug::log(TRACE, "GPU Reports supported format {:x} with modifier {:x}", (fm_entry + *idx)->format, (fm_entry + *idx)->modifier); + Log::logger->log(Log::TRACE, "GPU Reports supported format {:x} with modifier {:x}", (fm_entry + *idx)->format, (fm_entry + *idx)->modifier); dma.dmabufMods.push_back({(fm_entry + *idx)->format, (fm_entry + *idx)->modifier}); } }); dma.linuxDmabufFeedback->setTrancheTargetDevice([this](CCZwpLinuxDmabufFeedbackV1* r, wl_array* device_arr) { - Debug::log(TRACE, "[core] dmabufFeedbackTrancheTargetDevice"); + Log::logger->log(Log::TRACE, "[core] dmabufFeedbackTrancheTargetDevice"); dev_t device; assert(device_arr->size == sizeof(device)); @@ -190,7 +190,7 @@ void CHyprlock::addDmabufListener() { }); dma.linuxDmabufFeedback->setDone([this](CCZwpLinuxDmabufFeedbackV1* r) { - Debug::log(TRACE, "[core] dmabufFeedbackDone"); + Log::logger->log(Log::TRACE, "[core] dmabufFeedbackDone"); if (dma.formatTable) munmap(dma.formatTable, dma.formatTableSize); @@ -200,14 +200,14 @@ void CHyprlock::addDmabufListener() { }); dma.linuxDmabufFeedback->setFormatTable([this](CCZwpLinuxDmabufFeedbackV1* r, int fd, uint32_t size) { - Debug::log(TRACE, "[core] dmabufFeedbackFormatTable"); + Log::logger->log(Log::TRACE, "[core] dmabufFeedbackFormatTable"); dma.dmabufMods.clear(); dma.formatTable = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0); if (dma.formatTable == MAP_FAILED) { - Debug::log(ERR, "[core] format table failed to mmap"); + Log::logger->log(Log::ERR, "[core] format table failed to mmap"); dma.formatTable = nullptr; dma.formatTableSize = 0; return; @@ -217,7 +217,7 @@ void CHyprlock::addDmabufListener() { }); dma.linuxDmabufFeedback->setMainDevice([this](CCZwpLinuxDmabufFeedbackV1* r, wl_array* device_arr) { - Debug::log(LOG, "[core] dmabufFeedbackMainDevice"); + Log::logger->log(Log::INFO, "[core] dmabufFeedbackMainDevice"); RASSERT(!dma.gbm, "double dmabuf feedback"); @@ -253,11 +253,11 @@ void CHyprlock::run() { m_sWaylandState.registry = makeShared((wl_proxy*)wl_display_get_registry(m_sWaylandState.display)); m_sWaylandState.registry->setGlobal([this](CCWlRegistry* r, uint32_t name, const char* interface, uint32_t version) { const std::string IFACE = interface; - Debug::log(LOG, " | got iface: {} v{}", IFACE, version); + Log::logger->log(Log::INFO, " | got iface: {} v{}", IFACE, version); if (IFACE == zwp_linux_dmabuf_v1_interface.name) { if (version < 4) { - Debug::log(ERR, "cannot use linux_dmabuf with ver < 4"); + Log::logger->log(Log::ERR, "cannot use linux_dmabuf with ver < 4"); return; } @@ -267,7 +267,7 @@ void CHyprlock::run() { addDmabufListener(); } else if (IFACE == wl_seat_interface.name) { if (g_pSeatManager->registered()) { - Debug::log(WARN, "Hyprlock does not support multi-seat configurations. Only binding to the first seat."); + Log::logger->log(Log::WARN, "Hyprlock does not support multi-seat configurations. Only binding to the first seat."); return; } @@ -297,10 +297,10 @@ void CHyprlock::run() { else return; - Debug::log(LOG, " > Bound to {} v{}", IFACE, version); + Log::logger->log(Log::INFO, " > Bound to {} v{}", IFACE, version); }); m_sWaylandState.registry->setGlobalRemove([this](CCWlRegistry* r, uint32_t name) { - Debug::log(LOG, " | removed iface {}", name); + Log::logger->log(Log::INFO, " | removed iface {}", name); auto outputIt = std::ranges::find_if(m_vOutputs, [id = name](const auto& other) { return other->m_ID == id; }); if (outputIt != m_vOutputs.end()) { g_pRenderer->removeWidgetsFor((*outputIt)->m_ID); @@ -311,11 +311,11 @@ void CHyprlock::run() { wl_display_roundtrip(m_sWaylandState.display); if (!m_sWaylandState.sessionLock) { - Debug::log(CRIT, "Couldn't bind to ext-session-lock-v1, does your compositor support it?"); + Log::logger->log(Log::CRIT, "Couldn't bind to ext-session-lock-v1, does your compositor support it?"); exit(1); } - // gather info about monitors + // Gather info about monitors wl_display_roundtrip(m_sWaylandState.display); g_pRenderer = makeUnique(); @@ -323,7 +323,7 @@ void CHyprlock::run() { g_pAuth = makeUnique(); g_pAuth->start(); - Debug::log(LOG, "Running on {}", m_sCurrentDesktop); + Log::logger->log(Log::INFO, "Running on {}", m_sCurrentDesktop); g_asyncResourceManager->enqueueStaticAssets(); g_asyncResourceManager->enqueueScreencopyFrames(); @@ -385,7 +385,7 @@ void CHyprlock::run() { } if (events > 0 || !preparedToRead) { - Debug::log(TRACE, "[core] got poll event"); + Log::logger->log(Log::TRACE, "[core] got poll event"); std::unique_lock lk(m_sLoopState.eventLoopMutex); m_sLoopState.event = true; m_sLoopState.loopCV.notify_all(); @@ -414,7 +414,7 @@ void CHyprlock::run() { // notify main std::lock_guard lg2(m_sLoopState.eventLoopMutex); - Debug::log(TRACE, "timer thread firing"); + Log::logger->log(Log::TRACE, "timer thread firing"); m_sLoopState.event = true; m_sLoopState.loopCV.notify_all(); } @@ -477,12 +477,12 @@ void CHyprlock::run() { wl_display_disconnect(DPY); - Debug::log(LOG, "Reached the end, exiting"); + Log::logger->log(Log::INFO, "Reached the end, exiting"); } void CHyprlock::unlock() { if (!m_bLocked) { - Debug::log(WARN, "Unlock called, but not locked yet. This can happen when dpms is off during the grace period."); + Log::logger->log(Log::WARN, "Unlock called, but not locked yet. This can happen when dpms is off during the grace period."); return; } @@ -565,10 +565,10 @@ void CHyprlock::onKey(uint32_t key, bool down) { } if (down && std::ranges::find(m_vPressedKeys, key) != m_vPressedKeys.end()) { - Debug::log(ERR, "Invalid key down event (key already pressed?)"); + Log::logger->log(Log::ERR, "Invalid key down event (key already pressed?)"); return; } else if (!down && std::ranges::find(m_vPressedKeys, key) == m_vPressedKeys.end()) { - Debug::log(ERR, "Invalid key down event (stray release event?)"); + Log::logger->log(Log::ERR, "Invalid key down event (stray release event?)"); return; } @@ -618,16 +618,16 @@ void CHyprlock::handleKeySym(xkb_keysym_t sym, bool composed) { const auto SYM = sym; if (SYM == XKB_KEY_Escape || (m_bCtrl && (SYM == XKB_KEY_u || SYM == XKB_KEY_BackSpace || SYM == XKB_KEY_a))) { - Debug::log(LOG, "Clearing password buffer"); + Log::logger->log(Log::INFO, "Clearing password buffer"); m_sPasswordState.passBuffer = ""; } else if (SYM == XKB_KEY_Return || SYM == XKB_KEY_KP_Enter) { - Debug::log(LOG, "Authenticating"); + Log::logger->log(Log::INFO, "Authenticating"); static const auto IGNOREEMPTY = g_pConfigManager->getValue("general:ignore_empty_input"); if (m_sPasswordState.passBuffer.empty() && *IGNOREEMPTY) { - Debug::log(LOG, "Ignoring empty input"); + Log::logger->log(Log::INFO, "Ignoring empty input"); return; } @@ -712,10 +712,10 @@ void CHyprlock::onHover(const Vector2D& pos) { } bool CHyprlock::acquireSessionLock() { - Debug::log(LOG, "Locking session"); + Log::logger->log(Log::INFO, "Locking session"); m_sLockState.lock = makeShared(m_sWaylandState.sessionLock->sendLock()); if (!m_sLockState.lock) { - Debug::log(ERR, "Failed to create a lock object!"); + Log::logger->log(Log::ERR, "Failed to create a lock object!"); return false; } @@ -732,7 +732,7 @@ bool CHyprlock::acquireSessionLock() { m_lockAquired = true; - // create a session lock surface for exiting outputs + // create a session lock surface for existing outputs for (auto& o : m_vOutputs) { if (!o->done) continue; @@ -744,28 +744,28 @@ bool CHyprlock::acquireSessionLock() { } void CHyprlock::releaseSessionLock() { - Debug::log(LOG, "Unlocking session"); + Log::logger->log(Log::INFO, "Unlocking session"); if (m_bTerminate) { - Debug::log(ERR, "Unlock already happend?"); + Log::logger->log(Log::ERR, "Unlock already happend?"); return; } if (!m_sLockState.lock) { - Debug::log(ERR, "Unlock without a lock object!"); + Log::logger->log(Log::ERR, "Unlock without a lock object!"); return; } if (!m_bLocked) { // Would be a protocol error to allow this - Debug::log(ERR, "Trying to unlock the session, but never recieved the locked event!"); + Log::logger->log(Log::ERR, "Trying to unlock the session, but never recieved the locked event!"); return; } m_sLockState.lock->sendUnlockAndDestroy(); m_sLockState.lock = nullptr; - Debug::log(LOG, "Unlocked, exiting!"); + Log::logger->log(Log::INFO, "Unlocked, exiting!"); m_bTerminate = true; m_bLocked = false; @@ -774,16 +774,16 @@ void CHyprlock::releaseSessionLock() { } void CHyprlock::onLockLocked() { - Debug::log(LOG, "onLockLocked called"); + Log::logger->log(Log::INFO, "onLockLocked called"); m_bLocked = true; } void CHyprlock::onLockFinished() { - Debug::log(LOG, "onLockFinished called. Seems we got yeeten. Is another lockscreen running?"); + Log::logger->log(Log::INFO, "onLockFinished called. Seems we got yeeten. Is another lockscreen running?"); if (!m_sLockState.lock) { - Debug::log(ERR, "onLockFinished without a lock object!"); + Log::logger->log(Log::ERR, "onLockFinished without a lock object!"); return; } diff --git a/src/core/hyprlock.hpp b/src/core/hyprlock.hpp index 309c8bf..a938e9e 100644 --- a/src/core/hyprlock.hpp +++ b/src/core/hyprlock.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,7 @@ struct SDMABUFModifier { class CHyprlock { public: - CHyprlock(const std::string& wlDisplay, const bool immediateRender, const int gracePeriod); + CHyprlock(std::string_view wlDisplay, const bool immediateRender, const int gracePeriod); ~CHyprlock(); void run(); diff --git a/src/helpers/Log.hpp b/src/helpers/Log.hpp index 7604e90..0190258 100644 --- a/src/helpers/Log.hpp +++ b/src/helpers/Log.hpp @@ -1,54 +1,60 @@ #pragma once -#include -#include -#include +#include "../defines.hpp" -enum eLogLevel { - TRACE = 0, - INFO, - LOG, - WARN, - ERR, - CRIT, - NONE -}; +#include +#include +#include #define RASSERT(expr, reason, ...) \ if (!(expr)) { \ - Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n{}\n\nat: line {} in {}", \ - std::format(reason, ##__VA_ARGS__), __LINE__, \ - ([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str()); \ + Log::logger->log(Log::CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n{}\n\nat: line {} in {}", \ + std::format(reason, ##__VA_ARGS__), __LINE__, \ + ([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str()); \ std::abort(); \ } #define ASSERT(expr) RASSERT(expr, "?") -namespace Debug { - constexpr const char* logLevelString(eLogLevel level) { - switch (level) { - case TRACE: return "TRACE"; break; - case INFO: return "INFO"; break; - case LOG: return "LOG"; break; - case WARN: return "WARN"; break; - case ERR: return "ERR"; break; - case CRIT: return "CRITICAL"; break; - default: return "??"; +namespace Log { + class CLogger { + public: + template + void log(Hyprutils::CLI::eLogLevel level, std::format_string fmt, Args&&... args) { + if (m_quiet) + return; + + if (level == Hyprutils::CLI::LOG_TRACE && !m_verbose) + return; + + m_logger.log(level, std::vformat(fmt.get(), std::make_format_args(args...))); } - } - inline bool quiet = false; - inline bool verbose = false; - template - void log(eLogLevel level, const std::string& fmt, Args&&... args) { - - if (!verbose && level == TRACE) - return; - - if (quiet) - return; - - if (level != NONE) { - std::println("[{}] {}", logLevelString(level), std::vformat(fmt, std::make_format_args(args...))); + void setVerbose() { + m_verbose = true; + m_logger.setLogLevel(Hyprutils::CLI::LOG_TRACE); } - } + + void setQuiet() { + m_quiet = true; + } + + bool verbose() { + return m_verbose; + } + + private: + bool m_quiet = false; + bool m_verbose = false; + + Hyprutils::CLI::CLogger m_logger; + }; + + inline UP logger = makeUnique(); + + // + inline constexpr const Hyprutils::CLI::eLogLevel WARN = Hyprutils::CLI::LOG_WARN; + inline constexpr const Hyprutils::CLI::eLogLevel ERR = Hyprutils::CLI::LOG_ERR; + inline constexpr const Hyprutils::CLI::eLogLevel CRIT = Hyprutils::CLI::LOG_CRIT; + inline constexpr const Hyprutils::CLI::eLogLevel INFO = Hyprutils::CLI::LOG_DEBUG; + inline constexpr const Hyprutils::CLI::eLogLevel TRACE = Hyprutils::CLI::LOG_TRACE; }; diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 33ac120..8bd70f4 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -1,11 +1,13 @@ -#include +#include "MiscFunctions.hpp" +#include "Log.hpp" + #include #include #include -#include "MiscFunctions.hpp" -#include "Log.hpp" -#include +#include #include +#include +#include #include using namespace Hyprutils::String; @@ -107,7 +109,7 @@ int64_t configStringToInt(const std::string& VALUE) { int createPoolFile(size_t size, std::string& name) { const auto XDGRUNTIMEDIR = getenv("XDG_RUNTIME_DIR"); if (!XDGRUNTIMEDIR) { - Debug::log(CRIT, "XDG_RUNTIME_DIR not set!"); + Log::logger->log(Log::CRIT, "XDG_RUNTIME_DIR not set!"); return -1; } @@ -115,7 +117,7 @@ int createPoolFile(size_t size, std::string& name) { const auto FD = mkstemp((char*)name.c_str()); if (FD < 0) { - Debug::log(CRIT, "createPoolFile: fd < 0"); + Log::logger->log(Log::CRIT, "createPoolFile: fd < 0"); return -1; } // set cloexec @@ -127,13 +129,13 @@ int createPoolFile(size_t size, std::string& name) { if (fcntl(FD, F_SETFD, flags | FD_CLOEXEC) == -1) { close(FD); - Debug::log(CRIT, "createPoolFile: fcntl < 0"); + Log::logger->log(Log::CRIT, "createPoolFile: fcntl < 0"); return -1; } if (ftruncate(FD, size) < 0) { close(FD); - Debug::log(CRIT, "createPoolFile: ftruncate < 0"); + Log::logger->log(Log::CRIT, "createPoolFile: ftruncate < 0"); return -1; } @@ -143,12 +145,12 @@ int createPoolFile(size_t size, std::string& name) { std::string spawnSync(const std::string& cmd) { CProcess proc("/bin/sh", {"-c", cmd}); if (!proc.runSync()) { - Debug::log(ERR, "Failed to run \"{}\"", cmd); + Log::logger->log(Log::ERR, "Failed to run \"{}\"", cmd); return ""; } if (!proc.stdErr().empty()) - Debug::log(ERR, "Shell command \"{}\" STDERR:\n{}", cmd, proc.stdErr()); + Log::logger->log(Log::ERR, "Shell command \"{}\" STDERR:\n{}", cmd, proc.stdErr()); return proc.stdOut(); } @@ -156,5 +158,16 @@ std::string spawnSync(const std::string& cmd) { void spawnAsync(const std::string& cmd) { CProcess proc("/bin/sh", {"-c", cmd}); if (!proc.runAsync()) - Debug::log(ERR, "Failed to start \"{}\"", cmd); + Log::logger->log(Log::ERR, "Failed to start \"{}\"", cmd); +} + +std::string getUsernameForCurrentUid() { + const uid_t UID = getuid(); + auto uidPassword = getpwuid(UID); + if (!uidPassword || !uidPassword->pw_name) { + Log::logger->log(Log::ERR, "Failed to get username for uid {} (getpwuid)", UID); + return ""; + } + + return std::string{uidPassword->pw_name}; } diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 6e7a259..0240155 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -9,3 +9,4 @@ int64_t configStringToInt(const std::string& VALUE); int createPoolFile(size_t size, std::string& name); std::string spawnSync(const std::string& cmd); void spawnAsync(const std::string& cmd); +std::string getUsernameForCurrentUid(); diff --git a/src/main.cpp b/src/main.cpp index d71a59a..0c84038 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,31 +3,10 @@ #include "core/hyprlock.hpp" #include "helpers/Log.hpp" #include "core/AnimationManager.hpp" -#include + #include -void help() { - std::println("Usage: hyprlock [options]\n\n" - "Options:\n" - " -v, --verbose - Enable verbose logging\n" - " -q, --quiet - Disable logging\n" - " -c FILE, --config FILE - Specify config file to use\n" - " --display NAME - Specify the Wayland display to connect to\n" - " --grace SECONDS - Set grace period in seconds before requiring authentication\n" - " --immediate-render - Do not wait for resources before drawing the background\n" - " --no-fade-in - Disable the fade-in animation when the lock screen appears\n" - " -V, --version - Show version information\n" - " -h, --help - Show this help message"); -} - -std::optional parseArg(const std::vector& args, const std::string& flag, std::size_t& i) { - if (i + 1 < args.size()) { - return args[++i]; - } else { - std::println(stderr, "Error: Missing value for {} option.", flag); - return std::nullopt; - } -} +#include static void printVersion() { constexpr bool ISTAGGEDRELEASE = std::string_view(HYPRLOCK_COMMIT) == HYPRLOCK_VERSION_COMMIT; @@ -38,89 +17,70 @@ static void printVersion() { } int main(int argc, char** argv, char** envp) { - std::string configPath; - std::string wlDisplay; - bool immediateRender = false; - bool noFadeIn = false; - int graceSeconds = 0; + std::vector args(argv, argv + argc); - std::vector args(argv, argv + argc); + Hyprutils::CLI::CArgumentParser argParser(args); - for (std::size_t i = 1; i < args.size(); ++i) { - const std::string arg = argv[i]; + ASSERT(argParser.registerBoolOption("help", "h", "Show this help message").has_value()); + ASSERT(argParser.registerBoolOption("version", "V", "Print hyprlock version, then exit").has_value()); + ASSERT(argParser.registerBoolOption("verbose", "v", "Enable verbose logging").has_value()); + ASSERT(argParser.registerBoolOption("quiet", "q", "Disable logging").has_value()); + ASSERT(argParser.registerStringOption("config", "c", "Specify config file to use").has_value()); + ASSERT(argParser.registerIntOption("grace", "g", "Seconds before authentication is required").has_value()); + ASSERT(argParser.registerBoolOption("immediate-render", "", "Draw background immediately (Don't wait for resources)").has_value()); + ASSERT(argParser.registerBoolOption("no-fade-in", "", "Disable the fade-in animation").has_value()); + ASSERT(argParser.registerStringOption("display", "", "Specify the Wayland display to connect to").has_value()); + ASSERT(argParser.registerIntOption("immediate", "", "[Deprecated] (Use \"--grace 0\" instead)").has_value()); - if (arg == "--help" || arg == "-h") { - help(); - return 0; - } + auto options = argParser.parse(); - if (arg == "--version" || arg == "-V") { - printVersion(); - return 0; - } - - if (arg == "--verbose" || arg == "-v") - Debug::verbose = true; - - else if (arg == "--quiet" || arg == "-q") - Debug::quiet = true; - - else if ((arg == "--config" || arg == "-c") && i + 1 < (std::size_t)argc) { - if (auto value = parseArg(args, arg, i); value) - configPath = *value; - else - return 1; - - } else if (arg == "--display" && i + 1 < (std::size_t)argc) { - if (auto value = parseArg(args, arg, i); value) - wlDisplay = *value; - else - return 1; - - } else if (arg == "--grace" && i + 1 < (std::size_t)argc) { - if (auto value = parseArg(args, arg, i); value) { - try { - graceSeconds = std::stoi(*value); - if (graceSeconds < 0) { - std::println(stderr, "Error: Grace period must be non-negative."); - return 1; - } - } catch (const std::exception&) { - std::println(stderr, "Error: Invalid grace period value: {}", *value); - return 1; - } - } else - return 1; - - } else if (arg == "--immediate") { - graceSeconds = 0; - Debug::log(WARN, R"("--immediate" is deprecated. Use the "--grace" option instead.)"); - } - - else if (arg == "--immediate-render") - immediateRender = true; - - else if (arg == "--no-fade-in") - noFadeIn = true; - - else { - std::println(stderr, "Unknown option: {}", arg); - help(); - return 1; - } + if (!options.has_value()) { + Log::logger->log(Log::ERR, "Invalid argument: {}", options.error()); + return 1; } - printVersion(); + if (argParser.getBool("help")) { + std::print("{}", argParser.getDescription("Hyprlock CLI Arguments", 87)); + return 0; + } + + if (argParser.getBool("version")) { + printVersion(); + return 0; + } + + if (argParser.getBool("verbose")) + Log::logger->setVerbose(); + + bool quiet = argParser.getBool("quiet").value_or(false); + if (quiet) + Log::logger->setQuiet(); + + int graceSeconds = argParser.getInt("grace").value_or(0); + if (argParser.getBool("immediate")) { + graceSeconds = 0; + Log::logger->log(Log::WARN, R"("--immediate" is deprecated. Use the "--grace" option instead.)"); + } + + bool immediateRender = argParser.getBool("immediate-render").value_or(false); + bool noFadeIn = argParser.getBool("no-fade-in").value_or(false); + + if (!quiet) + printVersion(); + g_pAnimationManager = makeUnique(); + auto configPath = CConfigManager::resolveConfigPath(argParser.getString("config")); + if (!configPath.has_value()) { + Log::logger->log(Log::CRIT, " Config path error: {}", configPath.error()); + return 1; + } + try { - g_pConfigManager = makeUnique(configPath); + g_pConfigManager = makeUnique(configPath.value().c_str()); g_pConfigManager->init(); } catch (const std::exception& ex) { - Debug::log(CRIT, "ConfigManager threw: {}", ex.what()); - if (std::string(ex.what()).contains("File does not exist")) - Debug::log(NONE, " Make sure you have a config."); - + Log::logger->log(Log::CRIT, "Config threw: {}", ex.what()); return 1; } @@ -128,10 +88,10 @@ int main(int argc, char** argv, char** envp) { g_pConfigManager->m_AnimationTree.setConfigForNode("fadeIn", false, 0.f, "default"); try { - g_pHyprlock = makeUnique(wlDisplay, immediateRender, graceSeconds); + g_pHyprlock = makeUnique(argParser.getString("display").value_or(""), immediateRender, graceSeconds); g_pHyprlock->run(); } catch (const std::exception& ex) { - Debug::log(CRIT, "Hyprlock threw: {}", ex.what()); + Log::logger->log(Log::CRIT, "Hyprlock threw: {}", ex.what()); return 1; } diff --git a/src/renderer/AsyncResourceManager.cpp b/src/renderer/AsyncResourceManager.cpp index a1ef99f..c94992f 100644 --- a/src/renderer/AsyncResourceManager.cpp +++ b/src/renderer/AsyncResourceManager.cpp @@ -44,14 +44,14 @@ ResourceID CAsyncResourceManager::resourceIDForScreencopy(const std::string& por ResourceID CAsyncResourceManager::requestText(const CTextResource::STextResourceData& params, const AWP& widget) { const auto RESOURCEID = resourceIDForTextRequest(params); if (request(RESOURCEID, widget)) { - Debug::log(TRACE, "Reusing text resource \"{}\" (resourceID: {})", params.text, RESOURCEID, (uintptr_t)widget.get()); + Log::logger->log(Log::TRACE, "Reusing text resource \"{}\" (resourceID: {})", params.text, RESOURCEID, (uintptr_t)widget.get()); return RESOURCEID; } auto resource = makeAtomicShared(CTextResource::STextResourceData{params}); CAtomicSharedPointer resourceGeneric{resource}; - Debug::log(TRACE, "Requesting text resource \"{}\" (resourceID: {})", params.text, RESOURCEID, (uintptr_t)widget.get()); + Log::logger->log(Log::TRACE, "Requesting text resource \"{}\" (resourceID: {})", params.text, RESOURCEID, (uintptr_t)widget.get()); enqueue(RESOURCEID, resourceGeneric, widget); return RESOURCEID; } @@ -59,14 +59,14 @@ ResourceID CAsyncResourceManager::requestText(const CTextResource::STextResource ResourceID CAsyncResourceManager::requestTextCmd(const CTextResource::STextResourceData& params, size_t revision, const AWP& widget) { const auto RESOURCEID = resourceIDForTextCmdRequest(params, revision); if (request(RESOURCEID, widget)) { - Debug::log(TRACE, "Reusing text cmd resource \"{}\" revision {} (resourceID: {})", params.text, revision, RESOURCEID, (uintptr_t)widget.get()); + Log::logger->log(Log::TRACE, "Reusing text cmd resource \"{}\" revision {} (resourceID: {})", params.text, revision, RESOURCEID, (uintptr_t)widget.get()); return RESOURCEID; } auto resource = makeAtomicShared(CTextResource::STextResourceData{params}); CAtomicSharedPointer resourceGeneric{resource}; - Debug::log(TRACE, "Requesting text cmd resource \"{}\" revision {} (resourceID: {})", params.text, revision, RESOURCEID, (uintptr_t)widget.get()); + Log::logger->log(Log::TRACE, "Requesting text cmd resource \"{}\" revision {} (resourceID: {})", params.text, revision, RESOURCEID, (uintptr_t)widget.get()); enqueue(RESOURCEID, resourceGeneric, widget); return RESOURCEID; } @@ -74,14 +74,14 @@ ResourceID CAsyncResourceManager::requestTextCmd(const CTextResource::STextResou ResourceID CAsyncResourceManager::requestImage(const std::string& path, size_t revision, const AWP& widget) { const auto RESOURCEID = resourceIDForImageRequest(path, revision); if (request(RESOURCEID, widget)) { - Debug::log(TRACE, "Reusing image resource {} revision {} (resourceID: {})", path, revision, RESOURCEID, (uintptr_t)widget.get()); + Log::logger->log(Log::TRACE, "Reusing image resource {} revision {} (resourceID: {})", path, revision, RESOURCEID, (uintptr_t)widget.get()); return RESOURCEID; } auto resource = makeAtomicShared(absolutePath(path, "")); CAtomicSharedPointer resourceGeneric{resource}; - Debug::log(TRACE, "Requesting image resource {} revision {} (resourceID: {})", path, revision, RESOURCEID, (uintptr_t)widget.get()); + Log::logger->log(Log::TRACE, "Requesting image resource {} revision {} (resourceID: {})", path, revision, RESOURCEID, (uintptr_t)widget.get()); enqueue(RESOURCEID, resourceGeneric, widget); return RESOURCEID; } @@ -126,7 +126,7 @@ void CAsyncResourceManager::enqueueScreencopyFrames() { }); if (!BGSCREENSHOT && !FADENEEDSSC) { - Debug::log(LOG, "Skipping screencopy"); + Log::logger->log(Log::INFO, "Skipping screencopy"); return; } @@ -140,18 +140,18 @@ void CAsyncResourceManager::enqueueScreencopyFrames() { void CAsyncResourceManager::screencopyToTexture(const CScreencopyFrame& scFrame) { if (!scFrame.m_ready || !m_assets.contains(scFrame.m_resourceID)) { - Debug::log(ERR, "Bogus call to CAsyncResourceManager::screencopyToTexture. This is a bug!"); + Log::logger->log(Log::ERR, "Bogus call to CAsyncResourceManager::screencopyToTexture. This is a bug!"); return; } m_assets[scFrame.m_resourceID].texture = scFrame.m_asset; - Debug::log(TRACE, "Done sc frame {}", scFrame.m_resourceID); + Log::logger->log(Log::TRACE, "Done sc frame {}", scFrame.m_resourceID); std::erase_if(m_scFrames, [&scFrame](const auto& f) { return f.get() == &scFrame; }); if (m_scFrames.empty()) { - Debug::log(LOG, "Gathered all screencopy frames - removing dmabuf listeners"); + Log::logger->log(Log::INFO, "Gathered all screencopy frames - removing dmabuf listeners"); g_pHyprlock->removeDmabufListener(); } } @@ -197,14 +197,15 @@ void CAsyncResourceManager::gatherInitialResources(wl_display* display) { g_pHyprlock->processTimers(); if (std::chrono::duration_cast(std::chrono::system_clock::now() - STARTGATHERTP).count() > MAXDELAYMS) { - Debug::log(WARN, "Gathering resources timed out after {} milliseconds. Backgrounds may be delayed and render `background:color` at first.", MAXDELAYMS); + Log::logger->log(Log::WARN, "Gathering resources timed out after {} milliseconds. Backgrounds may be delayed and render `background:color` at first.", MAXDELAYMS); break; } gathered = m_resources.empty() && m_scFrames.empty(); } - Debug::log(LOG, "Resources gathered after {} milliseconds", std::chrono::duration_cast(std::chrono::system_clock::now() - STARTGATHERTP).count()); + Log::logger->log(Log::INFO, "Resources gathered after {} milliseconds", + std::chrono::duration_cast(std::chrono::system_clock::now() - STARTGATHERTP).count()); } bool CAsyncResourceManager::checkIdPresent(ResourceID id) { @@ -219,7 +220,7 @@ void CAsyncResourceManager::unload(ASP texture) { preload->second.refs--; if (preload->second.refs == 0) { - Debug::log(TRACE, "Releasing resourceID: {}!", preload->first); + Log::logger->log(Log::TRACE, "Releasing resourceID: {}!", preload->first); m_assets.erase(preload->first); } } @@ -231,7 +232,7 @@ void CAsyncResourceManager::unloadById(ResourceID id) { m_assets[id].refs--; if (m_assets[id].refs == 0) { - Debug::log(TRACE, "Releasing resourceID: {}!", id); + Log::logger->log(Log::TRACE, "Releasing resourceID: {}!", id); m_assets.erase(id); } } @@ -258,7 +259,7 @@ bool CAsyncResourceManager::request(ResourceID id, const AWP& widget) { // Asset currently in-flight. Add the widget reference to in order for the callback to get dispatched later. m_resourcesMutex.lock(); if (!m_resources.contains(id)) { - Debug::log(ERR, "In-flight resourceID: {} not found! This is a bug.", id); + Log::logger->log(Log::ERR, "In-flight resourceID: {} not found! This is a bug.", id); m_resourcesMutex.unlock(); return true; } @@ -274,7 +275,7 @@ void CAsyncResourceManager::enqueue(ResourceID resourceID, const ASPlog(Log::ERR, "Resource already enqueued! This is a bug."); m_resources[resourceID] = {resource, {widget}}; m_resourcesMutex.unlock(); @@ -311,7 +312,7 @@ void CAsyncResourceManager::onResourceFinished(ResourceID id) { if (!RESOURCE || !RESOURCE->m_asset.cairoSurface) return; - Debug::log(TRACE, "Resource to texture id:{}", id); + Log::logger->log(Log::TRACE, "Resource to texture id:{}", id); const auto texture = makeAtomicShared(); @@ -322,7 +323,7 @@ void CAsyncResourceManager::onResourceFinished(ResourceID id) { const GLint glType = CAIROFORMAT == CAIRO_FORMAT_RGB96F ? GL_FLOAT : GL_UNSIGNED_BYTE; if (SURFACESTATUS != CAIRO_STATUS_SUCCESS) { - Debug::log(ERR, "resourceID: {} invalid ({})", id, cairo_status_to_string(SURFACESTATUS)); + Log::logger->log(Log::ERR, "resourceID: {} invalid ({})", id, cairo_status_to_string(SURFACESTATUS)); texture->m_iType = TEXTURE_INVALID; } diff --git a/src/renderer/Framebuffer.cpp b/src/renderer/Framebuffer.cpp index 306721a..6b58578 100644 --- a/src/renderer/Framebuffer.cpp +++ b/src/renderer/Framebuffer.cpp @@ -59,11 +59,11 @@ bool CFramebuffer::alloc(int w, int h, bool highres) { auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { - Debug::log(ERR, "Framebuffer incomplete, couldn't create! (FB status: {})", status); + Log::logger->log(Log::ERR, "Framebuffer incomplete, couldn't create! (FB status: {})", status); abort(); } - Debug::log(TRACE, "Framebuffer created, status {}", status); + Log::logger->log(Log::TRACE, "Framebuffer created, status {}", status); } glBindTexture(GL_TEXTURE_2D, 0); @@ -76,7 +76,7 @@ bool CFramebuffer::alloc(int w, int h, bool highres) { void CFramebuffer::addStencil() { if (!m_pStencilTex) { - Debug::log(ERR, "No stencil texture allocated."); + Log::logger->log(Log::ERR, "No stencil texture allocated."); return; } diff --git a/src/renderer/Renderer.cpp b/src/renderer/Renderer.cpp index 0352950..09ca576 100644 --- a/src/renderer/Renderer.cpp +++ b/src/renderer/Renderer.cpp @@ -71,7 +71,7 @@ static GLuint createProgram(const std::string& vert, const std::string& frag) { static void glMessageCallbackA(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) { if (type != GL_DEBUG_TYPE_ERROR) return; - Debug::log(LOG, "[gl] {}", (const char*)message); + Log::logger->log(Log::INFO, "[gl] {}", (const char*)message); } CRenderer::CRenderer() { @@ -413,7 +413,7 @@ std::vector>& CRenderer::getOrCreateWidgetsFor(const CSessionLockSu } else if (c.type == "image") { createWidget(widgets[surf.m_outputID]); } else { - Debug::log(ERR, "Unknown widget type: {}", c.type); + Log::logger->log(Log::ERR, "Unknown widget type: {}", c.type); continue; } @@ -599,7 +599,7 @@ void CRenderer::reconfigureWidgetsFor(OUTPUTID id) { } void CRenderer::startFadeIn() { - Debug::log(LOG, "Starting fade in"); + Log::logger->log(Log::INFO, "Starting fade in"); *opacity = 1.f; opacity->setCallbackOnEnd([this](auto) { opacity->setConfig(g_pConfigManager->m_AnimationTree.getConfig("fadeOut")); }, true); diff --git a/src/renderer/Screencopy.cpp b/src/renderer/Screencopy.cpp index fa363e5..68bd33f 100644 --- a/src/renderer/Screencopy.cpp +++ b/src/renderer/Screencopy.cpp @@ -40,29 +40,29 @@ void CScreencopyFrame::capture(SP pOutput) { m_frame = makeUnique(m_sc); m_sc->setBufferDone([this](CCZwlrScreencopyFrameV1* r) { - Debug::log(TRACE, "[sc] wlrOnBufferDone for {}", (void*)this); + Log::logger->log(Log::TRACE, "[sc] wlrOnBufferDone for {}", (void*)this); if (!m_frame || !m_frame->onBufferDone() || !m_frame->m_wlBuffer) { - Debug::log(ERR, "[sc] Failed to create a wayland buffer for the screencopy frame"); + Log::logger->log(Log::ERR, "[sc] Failed to create a wayland buffer for the screencopy frame"); return; } m_sc->sendCopy(m_frame->m_wlBuffer->resource()); - Debug::log(TRACE, "[sc] wlr frame copied"); + Log::logger->log(Log::TRACE, "[sc] wlr frame copied"); }); m_sc->setFailed([this](CCZwlrScreencopyFrameV1* r) { - Debug::log(ERR, "[sc] wlrOnFailed for {}", (void*)r); + Log::logger->log(Log::ERR, "[sc] wlrOnFailed for {}", (void*)r); m_frame.reset(); }); m_sc->setReady([this](CCZwlrScreencopyFrameV1* r, uint32_t, uint32_t, uint32_t) { - Debug::log(TRACE, "[sc] wlrOnReady for {}", (void*)this); + Log::logger->log(Log::TRACE, "[sc] wlrOnReady for {}", (void*)this); if (!m_frame || !m_frame->onBufferReady(m_asset)) { - Debug::log(ERR, "[sc] Failed to bind the screencopy buffer to a texture"); + Log::logger->log(Log::ERR, "[sc] Failed to bind the screencopy buffer to a texture"); return; } @@ -76,18 +76,18 @@ CSCDMAFrame::CSCDMAFrame(SP sc) : m_sc(sc) { if (!glEGLImageTargetTexture2DOES) { glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); if (!glEGLImageTargetTexture2DOES) { - Debug::log(ERR, "[sc] No glEGLImageTargetTexture2DOES??"); + Log::logger->log(Log::ERR, "[sc] No glEGLImageTargetTexture2DOES??"); return; } } if (!g_pHyprlock->dma.linuxDmabuf) { - Debug::log(ERR, "[sc] No DMABUF support?"); + Log::logger->log(Log::ERR, "[sc] No DMABUF support?"); return; } if (!g_pHyprlock->dma.gbmDevice) { - Debug::log(ERR, "[sc] No gbmDevice for DMABUF was created?"); + Log::logger->log(Log::ERR, "[sc] No gbmDevice for DMABUF was created?"); return; } @@ -95,13 +95,13 @@ CSCDMAFrame::CSCDMAFrame(SP sc) : m_sc(sc) { eglQueryDmaBufModifiersEXT = (PFNEGLQUERYDMABUFMODIFIERSEXTPROC)eglGetProcAddress("eglQueryDmaBufModifiersEXT"); m_sc->setLinuxDmabuf([this](CCZwlrScreencopyFrameV1* r, uint32_t format, uint32_t width, uint32_t height) { - Debug::log(TRACE, "[sc] wlrOnDmabuf for {}", (void*)this); + Log::logger->log(Log::TRACE, "[sc] wlrOnDmabuf for {}", (void*)this); m_w = width; m_h = height; m_fmt = format; - Debug::log(TRACE, "[sc] DMABUF format reported: {:x}", format); + Log::logger->log(Log::TRACE, "[sc] DMABUF format reported: {:x}", format); }); m_sc->setBuffer([](CCZwlrScreencopyFrameV1* r, uint32_t format, uint32_t width, uint32_t height, uint32_t stride) { @@ -120,25 +120,25 @@ bool CSCDMAFrame::onBufferDone() { uint32_t flags = GBM_BO_USE_RENDERING; if (!eglQueryDmaBufModifiersEXT) { - Debug::log(WARN, "Querying modifiers without eglQueryDmaBufModifiersEXT support"); + Log::logger->log(Log::WARN, "Querying modifiers without eglQueryDmaBufModifiersEXT support"); m_bo = gbm_bo_create(g_pHyprlock->dma.gbmDevice, m_w, m_h, m_fmt, flags); } else { std::array mods; std::array externalOnly; int num = 0; if (!eglQueryDmaBufModifiersEXT(g_pEGL->eglDisplay, m_fmt, 64, mods.data(), externalOnly.data(), &num) || num == 0) { - Debug::log(WARN, "eglQueryDmaBufModifiersEXT failed, falling back to regular bo"); + Log::logger->log(Log::WARN, "eglQueryDmaBufModifiersEXT failed, falling back to regular bo"); m_bo = gbm_bo_create(g_pHyprlock->dma.gbmDevice, m_w, m_h, m_fmt, flags); } else { - Debug::log(LOG, "eglQueryDmaBufModifiersEXT found {} mods", num); + Log::logger->log(Log::INFO, "eglQueryDmaBufModifiersEXT found {} mods", num); std::vector goodMods; for (int i = 0; i < num; ++i) { if (externalOnly[i]) { - Debug::log(TRACE, "Modifier {:x} failed test", mods[i]); + Log::logger->log(Log::TRACE, "Modifier {:x} failed test", mods[i]); continue; } - Debug::log(TRACE, "Modifier {:x} passed test", mods[i]); + Log::logger->log(Log::TRACE, "Modifier {:x} passed test", mods[i]); goodMods.emplace_back(mods[i]); } @@ -147,19 +147,19 @@ bool CSCDMAFrame::onBufferDone() { } if (!m_bo) { - Debug::log(ERR, "[bo] Couldn't create a drm buffer"); + Log::logger->log(Log::ERR, "[bo] Couldn't create a drm buffer"); return false; } m_planes = gbm_bo_get_plane_count(m_bo); - Debug::log(LOG, "[bo] has {} plane(s)", m_planes); + Log::logger->log(Log::INFO, "[bo] has {} plane(s)", m_planes); m_mod = gbm_bo_get_modifier(m_bo); - Debug::log(LOG, "[bo] chose modifier {:x}", m_mod); + Log::logger->log(Log::INFO, "[bo] chose modifier {:x}", m_mod); auto params = makeShared(g_pHyprlock->dma.linuxDmabuf->sendCreateParams()); if (!params) { - Debug::log(ERR, "zwp_linux_dmabuf_v1_create_params failed"); + Log::logger->log(Log::ERR, "zwp_linux_dmabuf_v1_create_params failed"); gbm_bo_destroy(m_bo); return false; } @@ -170,7 +170,7 @@ bool CSCDMAFrame::onBufferDone() { m_fd[plane] = gbm_bo_get_fd_for_plane(m_bo, plane); if (m_fd[plane] < 0) { - Debug::log(ERR, "gbm_m_bo_get_fd_for_plane failed"); + Log::logger->log(Log::ERR, "gbm_m_bo_get_fd_for_plane failed"); params.reset(); gbm_bo_destroy(m_bo); for (size_t plane_tmp = 0; plane_tmp < plane; plane_tmp++) { @@ -186,7 +186,7 @@ bool CSCDMAFrame::onBufferDone() { params.reset(); if (!m_wlBuffer) { - Debug::log(ERR, "[pw] zwp_linux_buffer_params_v1_create_immed failed"); + Log::logger->log(Log::ERR, "[pw] zwp_linux_buffer_params_v1_create_immed failed"); gbm_bo_destroy(m_bo); for (size_t plane = 0; plane < (size_t)m_planes; plane++) close(m_fd[plane]); @@ -247,7 +247,7 @@ bool CSCDMAFrame::onBufferReady(ASP texture) { m_image = eglCreateImage(g_pEGL->eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs.data()); if (m_image == EGL_NO_IMAGE) { - Debug::log(ERR, "Failed creating an egl image"); + Log::logger->log(Log::ERR, "Failed creating an egl image"); return false; } @@ -261,16 +261,16 @@ bool CSCDMAFrame::onBufferReady(ASP texture) { glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image); glBindTexture(GL_TEXTURE_2D, 0); - Debug::log(LOG, "Got dma frame with size {}", texture->m_vSize); + Log::logger->log(Log::INFO, "Got dma frame with size {}", texture->m_vSize); return true; } CSCSHMFrame::CSCSHMFrame(SP sc) : m_sc(sc) { - Debug::log(TRACE, "[sc] [shm] Creating a SHM frame"); + Log::logger->log(Log::TRACE, "[sc] [shm] Creating a SHM frame"); m_sc->setBuffer([this](CCZwlrScreencopyFrameV1* r, uint32_t format, uint32_t width, uint32_t height, uint32_t stride) { - Debug::log(TRACE, "[sc] [shm] wlrOnBuffer for {}", (void*)this); + Log::logger->log(Log::TRACE, "[sc] [shm] wlrOnBuffer for {}", (void*)this); const auto SIZE = stride * height; m_shmFmt = format; @@ -283,20 +283,20 @@ CSCSHMFrame::CSCSHMFrame(SP sc) : m_sc(sc) { const auto FD = createPoolFile(SIZE, shmPoolFile); if (FD < 0) { - Debug::log(ERR, "[sc] [shm] failed to create a pool file"); + Log::logger->log(Log::ERR, "[sc] [shm] failed to create a pool file"); return; } m_shmData = mmap(nullptr, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, FD, 0); if (m_shmData == MAP_FAILED) { - Debug::log(ERR, "[sc] [shm] failed to (errno {})", strerror(errno)); + Log::logger->log(Log::ERR, "[sc] [shm] failed to (errno {})", strerror(errno)); close(FD); m_ok = false; return; } if (!g_pHyprlock->getShm()) { - Debug::log(ERR, "[sc] [shm] Failed to get WLShm global"); + Log::logger->log(Log::ERR, "[sc] [shm] Failed to get WLShm global"); close(FD); m_ok = false; return; @@ -328,7 +328,7 @@ void CSCSHMFrame::convertBuffer() { switch (m_shmFmt) { case WL_SHM_FORMAT_ARGB8888: case WL_SHM_FORMAT_XRGB8888: { - Debug::log(LOG, "[sc] [shm] Converting ARGB to RGBA"); + Log::logger->log(Log::INFO, "[sc] [shm] Converting ARGB to RGBA"); uint8_t* data = (uint8_t*)m_shmData; for (uint32_t y = 0; y < m_h; ++y) { @@ -348,7 +348,7 @@ void CSCSHMFrame::convertBuffer() { } break; case WL_SHM_FORMAT_ABGR8888: case WL_SHM_FORMAT_XBGR8888: { - Debug::log(LOG, "[sc] [shm] Converting ABGR to RGBA"); + Log::logger->log(Log::INFO, "[sc] [shm] Converting ABGR to RGBA"); uint8_t* data = (uint8_t*)m_shmData; for (uint32_t y = 0; y < m_h; ++y) { @@ -370,7 +370,7 @@ void CSCSHMFrame::convertBuffer() { case WL_SHM_FORMAT_ARGB2101010: case WL_SHM_FORMAT_XRGB2101010: case WL_SHM_FORMAT_XBGR2101010: { - Debug::log(LOG, "[sc] [shm] Converting 10-bit channels to 8-bit"); + Log::logger->log(Log::INFO, "[sc] [shm] Converting 10-bit channels to 8-bit"); uint8_t* data = (uint8_t*)m_shmData; const bool FLIP = m_shmFmt != WL_SHM_FORMAT_XBGR2101010; @@ -391,18 +391,18 @@ void CSCSHMFrame::convertBuffer() { } } break; default: { - Debug::log(WARN, "[sc] [shm] Unsupported format {}", m_shmFmt); + Log::logger->log(Log::WARN, "[sc] [shm] Unsupported format {}", m_shmFmt); } } } else if (BYTESPERPX == 3) { - Debug::log(LOG, "[sc] [shm] Converting 24 bit to 32 bit"); + Log::logger->log(Log::INFO, "[sc] [shm] Converting 24 bit to 32 bit"); m_convBuffer = malloc(m_w * m_h * 4); const int NEWSTRIDE = m_w * 4; RASSERT(m_convBuffer, "malloc failed"); switch (m_shmFmt) { case WL_SHM_FORMAT_BGR888: { - Debug::log(LOG, "[sc] [shm] Converting BGR to RGBA"); + Log::logger->log(Log::INFO, "[sc] [shm] Converting BGR to RGBA"); for (uint32_t y = 0; y < m_h; ++y) { for (uint32_t x = 0; x < m_w; ++x) { struct pixel3 { @@ -423,7 +423,7 @@ void CSCSHMFrame::convertBuffer() { } } break; case WL_SHM_FORMAT_RGB888: { - Debug::log(LOG, "[sc] [shm] Converting RGB to RGBA"); + Log::logger->log(Log::INFO, "[sc] [shm] Converting RGB to RGBA"); for (uint32_t y = 0; y < m_h; ++y) { for (uint32_t x = 0; x < m_w; ++x) { struct pixel3 { @@ -444,12 +444,12 @@ void CSCSHMFrame::convertBuffer() { } } break; default: { - Debug::log(ERR, "[sc] [shm] Unsupported format for 24bit buffer {}", m_shmFmt); + Log::logger->log(Log::ERR, "[sc] [shm] Unsupported format for 24bit buffer {}", m_shmFmt); } } } else { - Debug::log(ERR, "[sc] [shm] Unsupported bytes per pixel {}", BYTESPERPX); + Log::logger->log(Log::ERR, "[sc] [shm] Unsupported bytes per pixel {}", BYTESPERPX); } } @@ -471,7 +471,7 @@ bool CSCSHMFrame::onBufferReady(ASP texture) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_w, m_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); glBindTexture(GL_TEXTURE_2D, 0); - Debug::log(LOG, "[sc] [shm] Got screenshot with size {}", texture->m_vSize); + Log::logger->log(Log::INFO, "[sc] [shm] Got screenshot with size {}", texture->m_vSize); return true; } diff --git a/src/renderer/widgets/Background.cpp b/src/renderer/widgets/Background.cpp index e3015c1..407ac90 100644 --- a/src/renderer/widgets/Background.cpp +++ b/src/renderer/widgets/Background.cpp @@ -72,7 +72,7 @@ void CBackground::configure(const std::unordered_map& pro g_pAnimationManager->createAnimation(0.f, crossFadeProgress, g_pConfigManager->m_AnimationTree.getConfig("fadeIn")); if (!g_asyncResourceManager->checkIdPresent(scResourceID)) { - Debug::log(LOG, "Missing screenshot for output {}", outputPort); + Log::logger->log(Log::INFO, "Missing screenshot for output {}", outputPort); scResourceID = 0; } @@ -83,7 +83,7 @@ void CBackground::configure(const std::unordered_map& pro resourceID = scResourceID; // Fallback to solid background:color when scResourceID==0 if (!g_pHyprlock->getScreencopy()) { - Debug::log(ERR, "No screencopy support! path=screenshot won't work. Falling back to background color."); + Log::logger->log(Log::ERR, "No screencopy support! path=screenshot won't work. Falling back to background color."); resourceID = 0; } } else if (!path.empty()) { @@ -112,7 +112,7 @@ void CBackground::configure(const std::unordered_map& pro try { if (!isScreenshot) modificationTime = std::filesystem::last_write_time(absolutePath(path, "")); - } catch (std::exception& e) { Debug::log(ERR, "{}", e.what()); } + } catch (std::exception& e) { Log::logger->log(Log::ERR, "{}", e.what()); } plantReloadTimer(); // No reloads if reloadCommand is empty } @@ -343,10 +343,10 @@ void CBackground::onAssetUpdate(ResourceID id, ASP newAsset) { pendingResource = false; if (!newAsset) - Debug::log(ERR, "Background asset update failed, resourceID: {} not available on update!", id); + Log::logger->log(Log::ERR, "Background asset update failed, resourceID: {} not available on update!", id); else if (newAsset->m_iType == TEXTURE_INVALID) { g_asyncResourceManager->unload(newAsset); - Debug::log(ERR, "New background asset has an invalid texture!"); + Log::logger->log(Log::ERR, "New background asset has an invalid texture!"); } else { pendingAsset = newAsset; crossFadeProgress->setValueAndWarp(0); @@ -401,7 +401,7 @@ void CBackground::onReloadTimerUpdate() { m_imageRevision = 0; } catch (std::exception& e) { path = OLDPATH; - Debug::log(ERR, "{}", e.what()); + Log::logger->log(Log::ERR, "{}", e.what()); return; } diff --git a/src/renderer/widgets/IWidget.cpp b/src/renderer/widgets/IWidget.cpp index 77ffa0c..45a9c08 100644 --- a/src/renderer/widgets/IWidget.cpp +++ b/src/renderer/widgets/IWidget.cpp @@ -44,7 +44,7 @@ Vector2D IWidget::posFromHVAlign(const Vector2D& viewport, const Vector2D& size, else if (halign == "right") pos.x += viewport.x - size.x + rot.x; else if (halign != "none") - Debug::log(ERR, "IWidget: invalid halign {}", halign); + Log::logger->log(Log::ERR, "IWidget: invalid halign {}", halign); if (valign == "center") pos.y += viewport.y / 2.0 - size.y / 2.0; @@ -53,7 +53,7 @@ Vector2D IWidget::posFromHVAlign(const Vector2D& viewport, const Vector2D& size, else if (valign == "bottom") pos.y += 0 - rot.y; else if (valign != "none") - Debug::log(ERR, "IWidget: invalid valign {}", valign); + Log::logger->log(Log::ERR, "IWidget: invalid valign {}", valign); return pos; } @@ -126,7 +126,7 @@ static void replaceAllLayout(std::string& str) { const std::string REPL = str.substr(pos + 8, str.find_first_of(']', pos) - 8 - pos); const CVarList LANGS(REPL); if (LAYOUTIDX >= LANGS.size()) { - Debug::log(ERR, "Layout index {} out of bounds. Max is {}.", LAYOUTIDX, LANGS.size() - 1); + Log::logger->log(Log::ERR, "Layout index {} out of bounds. Max is {}.", LAYOUTIDX, LANGS.size() - 1); return; } @@ -147,7 +147,7 @@ static std::chrono::hh_mm_ss getTime() { auto name = std::getenv("TZ"); if (name) pCurrentTz = std::chrono::locate_zone(name); - } catch (std::runtime_error&) { Debug::log(WARN, "Invalid TZ value. Falling back to current timezone!"); } + } catch (std::runtime_error&) { Log::logger->log(Log::WARN, "Invalid TZ value. Falling back to current timezone!"); } if (!pCurrentTz) pCurrentTz = std::chrono::current_zone(); @@ -158,7 +158,7 @@ static std::chrono::hh_mm_ss getTime() { std::chrono::hh_mm_ss hhmmss; if (!pCurrentTz) { if (logMissingTzOnce) { - Debug::log(WARN, "Current timezone unknown. Falling back to UTC!"); + Log::logger->log(Log::WARN, "Current timezone unknown. Falling back to UTC!"); logMissingTzOnce = false; } hhmmss = std::chrono::hh_mm_ss{TPNOW - std::chrono::floor(TPNOW)}; @@ -190,10 +190,10 @@ IWidget::SFormatResult IWidget::formatString(std::string in) { char* user_gecos = uidPassword ? uidPassword->pw_gecos : nullptr; if (!username) - Debug::log(ERR, "Error in formatString, username null. Errno: ", errno); + Log::logger->log(Log::ERR, "Error in formatString, username null. Errno: ", errno); if (!user_gecos) - Debug::log(WARN, "Error in formatString, user_gecos null. Errno: ", errno); + Log::logger->log(Log::WARN, "Error in formatString, user_gecos null. Errno: ", errno); IWidget::SFormatResult result; replaceInString(in, "$DESC", std::string{user_gecos ? user_gecos : ""}); @@ -263,9 +263,9 @@ IWidget::SFormatResult IWidget::formatString(std::string in) { } result.updateEveryMs = std::stoull(v.substr(7)); - } catch (std::exception& e) { Debug::log(ERR, "Error parsing {} in cmd[]", v); } + } catch (std::exception& e) { Log::logger->log(Log::ERR, "Error parsing {} in cmd[]", v); } } else { - Debug::log(ERR, "Unknown prop in string format {}", v); + Log::logger->log(Log::ERR, "Unknown prop in string format {}", v); } } diff --git a/src/renderer/widgets/Image.cpp b/src/renderer/widgets/Image.cpp index 1846d70..d2efd2a 100644 --- a/src/renderer/widgets/Image.cpp +++ b/src/renderer/widgets/Image.cpp @@ -26,7 +26,7 @@ static void onTimer(AWP ref) { void CImage::onTimerUpdate() { if (m_pendingResource) { - Debug::log(WARN, "Trying to update image, but a resource is still pending! Skipping update."); + Log::logger->log(Log::WARN, "Trying to update image, but a resource is still pending! Skipping update."); return; } @@ -57,7 +57,7 @@ void CImage::onTimerUpdate() { m_imageRevision = 0; } catch (std::exception& e) { path = OLDPATH; - Debug::log(ERR, "{}", e.what()); + Log::logger->log(Log::ERR, "{}", e.what()); return; } @@ -109,7 +109,7 @@ void CImage::configure(const std::unordered_map& props, c if (reloadTime > -1) { try { modificationTime = std::filesystem::last_write_time(absolutePath(path, "")); - } catch (std::exception& e) { Debug::log(ERR, "{}", e.what()); } + } catch (std::exception& e) { Log::logger->log(Log::ERR, "{}", e.what()); } plantTimer(); } @@ -213,10 +213,10 @@ void CImage::onAssetUpdate(ResourceID id, ASP newAsset) { m_pendingResource = false; if (!newAsset) - Debug::log(ERR, "asset update failed, resourceID: {} not available on update!", id); + Log::logger->log(Log::ERR, "asset update failed, resourceID: {} not available on update!", id); else if (newAsset->m_iType == TEXTURE_INVALID) { g_asyncResourceManager->unload(newAsset); - Debug::log(ERR, "New image asset has an invalid texture!"); + Log::logger->log(Log::ERR, "New image asset has an invalid texture!"); } else { g_asyncResourceManager->unload(asset); imageFB.destroyBuffer(); diff --git a/src/renderer/widgets/Label.cpp b/src/renderer/widgets/Label.cpp index 263dca8..8fda78f 100644 --- a/src/renderer/widgets/Label.cpp +++ b/src/renderer/widgets/Label.cpp @@ -29,7 +29,7 @@ static void onTimer(AWP ref) { void CLabel::onTimerUpdate() { if (m_pendingResource) { - Debug::log(WARN, "Trying to update label, but a resource is still pending! Skipping update."); + Log::logger->log(Log::WARN, "Trying to update label, but a resource is still pending! Skipping update."); return; } @@ -47,7 +47,7 @@ void CLabel::onTimerUpdate() { AWP widget(m_self); if (label.cmd) { // Don't increment by one to avoid clashes with multiple widget using the same label command. - m_dynamicRevision += label.updateEveryMs; + m_dynamicRevision += (label.updateEveryMs == 0) ? 1 : label.updateEveryMs; g_asyncResourceManager->requestTextCmd(request, m_dynamicRevision, widget.lock()); } else g_asyncResourceManager->requestText(request, widget.lock()); @@ -74,8 +74,8 @@ void CLabel::configure(const std::unordered_map& props, c labelPreFormat = std::any_cast(props.at("text")); halign = std::any_cast(props.at("halign")); valign = std::any_cast(props.at("valign")); - angle = std::any_cast(props.at("rotate")); - angle = angle * M_PI / 180.0; + m_angle = std::any_cast(props.at("rotate")); + m_angle = m_angle * M_PI / 180.0; onclickCommand = std::any_cast(props.at("onclick")); std::string textAlign = std::any_cast(props.at("text_align")); @@ -89,6 +89,7 @@ void CLabel::configure(const std::unordered_map& props, c request.font = fontFamily; request.fontSize = fontSize; request.color = labelColor.asRGB(); + m_alpha = labelColor.a; if (!textAlign.empty()) request.align = parseTextAlignment(textAlign); @@ -142,24 +143,24 @@ bool CLabel::draw(const SRenderData& data) { shadow.draw(data); // calc pos - pos = posFromHVAlign(viewport, asset->m_vSize, configPos, halign, valign, angle); + pos = posFromHVAlign(viewport, asset->m_vSize, configPos, halign, valign, m_angle); CBox box = {pos.x, pos.y, asset->m_vSize.x, asset->m_vSize.y}; - box.rot = angle; - g_pRenderer->renderTexture(box, *asset, data.opacity); + box.rot = m_angle; + g_pRenderer->renderTexture(box, *asset, data.opacity * m_alpha); return false; } void CLabel::onAssetUpdate(ResourceID id, ASP newAsset) { - Debug::log(TRACE, "Label update for resourceID {}", id); + Log::logger->log(Log::TRACE, "Label update for resourceID {}", id); m_pendingResource = false; if (!newAsset) - Debug::log(ERR, "asset update failed, resourceID: {} not available on update!", id); + Log::logger->log(Log::ERR, "asset update failed, resourceID: {} not available on update!", id); else if (newAsset->m_iType == TEXTURE_INVALID) { g_asyncResourceManager->unload(newAsset); - Debug::log(ERR, "New image asset has an invalid texture!"); + Log::logger->log(Log::ERR, "New image asset has an invalid texture!"); } else { // new asset is ready :D g_asyncResourceManager->unload(asset); diff --git a/src/renderer/widgets/Label.hpp b/src/renderer/widgets/Label.hpp index 4529432..62dbcbf 100644 --- a/src/renderer/widgets/Label.hpp +++ b/src/renderer/widgets/Label.hpp @@ -46,7 +46,8 @@ class CLabel : public IWidget { Vector2D viewport; Vector2D pos; Vector2D configPos; - double angle; + double m_angle = 0; + double m_alpha = 0; ResourceID resourceID = 0; bool m_pendingResource = false; diff --git a/src/renderer/widgets/PasswordInputField.cpp b/src/renderer/widgets/PasswordInputField.cpp index e7f63ee..67f05b4 100644 --- a/src/renderer/widgets/PasswordInputField.cpp +++ b/src/renderer/widgets/PasswordInputField.cpp @@ -50,6 +50,7 @@ void CPasswordInputField::configure(const std::unordered_map(props.at("rounding")); configPlaceholderText = std::any_cast(props.at("placeholder_text")); configFailText = std::any_cast(props.at("fail_text")); + configCheckText = std::any_cast(props.at("check_text")); fontFamily = std::any_cast(props.at("font_family")); colorConfig.outer = CGradientValueData::fromAnyPv(props.at("outer_color")); colorConfig.inner = std::any_cast(props.at("inner_color")); @@ -72,7 +73,7 @@ void CPasswordInputField::configure(const std::unordered_mapm_bIsFallback ? colorConfig.fail : colorConfig.caps; @@ -163,7 +164,7 @@ void CPasswordInputField::updateDots() { if (dots.currentAmount->goal() == passwordLength) return; - if (checkWaiting) + if (checkWaiting && configCheckText.empty()) return; if (passwordLength == 0) @@ -299,7 +300,9 @@ bool CPasswordInputField::draw(const SRenderData& data) { } } - if (passwordLength == 0 && !checkWaiting && placeholder.resourceID > 0) { + bool placeholderPasswordCondition = (passwordLength == 0 && placeholder.resourceID > 0); + + if (placeholderPasswordCondition && (!checkWaiting || (checkWaiting && !configCheckText.empty()))) { ASP currAsset = nullptr; if (!placeholder.asset) @@ -325,6 +328,7 @@ bool CPasswordInputField::draw(const SRenderData& data) { } void CPasswordInputField::updatePlaceholder() { + if (passwordLength != 0) { if (placeholder.asset && /* keep prompt asset cause it is likely to be used again */ displayFail) { g_asyncResourceManager->unload(placeholder.asset); @@ -339,16 +343,23 @@ void CPasswordInputField::updatePlaceholder() { if (displayFail && placeholder.failedAttempts == g_pAuth->getFailedAttempts()) return; - placeholder.failedAttempts = g_pAuth->getFailedAttempts(); + std::string& templateText = configPlaceholderText; - std::string newText = (displayFail) ? formatString(configFailText).formatted : formatString(configPlaceholderText).formatted; + if (displayFail) { + templateText = configFailText; + placeholder.failedAttempts = g_pAuth->getFailedAttempts(); + } else if (checkWaiting && !configCheckText.empty()) { + templateText = configCheckText; + } + + const std::string newText = formatString(templateText).formatted; // if the text is unchanged we don't need to do anything, unless we are swapping font color const auto ALLOWCOLORSWAP = outThick == 0 && colorConfig.swapFont; if (!ALLOWCOLORSWAP && newText == placeholder.currentText) return; - Debug::log(LOG, "Updating placeholder text: {}", newText); + Log::logger->log(Log::INFO, "Updating placeholder text: {}", newText); placeholder.currentText = newText; placeholder.asset = nullptr; @@ -435,7 +446,12 @@ void CPasswordInputField::updateColors() { CGradientValueData* outerTarget = colorConfig.outer; CHyprColor innerTarget = colorConfig.inner; - CHyprColor fontTarget = (displayFail) ? colorConfig.fail->m_vColors.front() : colorConfig.font; + CHyprColor fontTarget = colorConfig.font; + + if (displayFail) + fontTarget = colorConfig.fail->m_vColors.front(); + else if (checkWaiting) + fontTarget = configCheckText.empty() ? colorConfig.font : colorConfig.check->m_vColors.front(); if (targetGrad) { if (BORDERLESS && colorConfig.swapFont) { diff --git a/src/renderer/widgets/PasswordInputField.hpp b/src/renderer/widgets/PasswordInputField.hpp index ec0aa11..62e8ed9 100644 --- a/src/renderer/widgets/PasswordInputField.hpp +++ b/src/renderer/widgets/PasswordInputField.hpp @@ -56,7 +56,7 @@ class CPasswordInputField : public IWidget { Vector2D configPos; Vector2D configSize; - std::string halign, valign, configFailText, outputStringPort, configPlaceholderText, fontFamily; + std::string halign, valign, configFailText, configCheckText, outputStringPort, configPlaceholderText, fontFamily; uint64_t configFailTimeoutMs = 2000; int outThick, rounding; diff --git a/src/renderer/widgets/Shape.cpp b/src/renderer/widgets/Shape.cpp index 51dfa4a..c1fa8b1 100644 --- a/src/renderer/widgets/Shape.cpp +++ b/src/renderer/widgets/Shape.cpp @@ -80,7 +80,7 @@ bool CShape::draw(const SRenderData& data) { if (!shapeFB.isAllocated()) { const int ROUND = roundingForBox(shapeBox, rounding); const int BORDERROUND = roundingForBorderBox(borderBox, rounding, border); - Debug::log(LOG, "round: {}, borderround: {}", ROUND, BORDERROUND); + Log::logger->log(Log::INFO, "round: {}, borderround: {}", ROUND, BORDERROUND); shapeFB.alloc(borderBox.width + (borderBox.x * 2.0), borderBox.height + (borderBox.y * 2.0), true); g_pRenderer->pushFb(shapeFB.m_iFb);