diff --git a/src/bar/Bar.cpp b/src/bar/Bar.cpp index 78a8776..cc5d5e6 100644 --- a/src/bar/Bar.cpp +++ b/src/bar/Bar.cpp @@ -142,6 +142,9 @@ void CStatusBar::setupModule(SBarModule* module) { void CStatusBar::destroyModule(SBarModule* module) { if (module->bgcontext) xcb_free_gc(g_pWindowManager->DisplayConnection, module->bgcontext); + + // delete it from the heap + delete module; } void CStatusBar::setupTray() { @@ -181,8 +184,8 @@ void CStatusBar::setupTray() { // Check if the tray module is active SBarModule* pBarModule = nullptr; for (auto& mod : modules) { - if (mod.value == "tray") { - pBarModule = &mod; + if (mod->value == "tray") { + pBarModule = mod; break; } } @@ -299,7 +302,7 @@ void CStatusBar::setup(int MonitorID) { m_bHasTray = false; for (auto& mod : g_pWindowManager->statusBar->modules) { - if (mod.value == "tray") { + if (mod->value == "tray") { m_bHasTray = true; break; } @@ -474,18 +477,18 @@ void CStatusBar::draw() { for (auto& module : modules) { - if (!module.bgcontext && !module.isPad) - setupModule(&module); + if (!module->bgcontext && !module->isPad) + setupModule(module); - if (module.value == "workspaces") { - offLeft += drawWorkspacesModule(&module, offLeft); + if (module->value == "workspaces") { + offLeft += drawWorkspacesModule(module, offLeft); } else { - if (module.alignment == LEFT) { - offLeft += drawModule(&module, offLeft); - } else if (module.alignment == RIGHT) { - offRight += drawModule(&module, offRight); + if (module->alignment == LEFT) { + offLeft += drawModule(module, offLeft); + } else if (module->alignment == RIGHT) { + offRight += drawModule(module, offRight); } else { - drawModule(&module, 0); + drawModule(module, 0); } } } @@ -609,10 +612,13 @@ int CStatusBar::drawModule(SBarModule* mod, int off) { // check if we need to update if (std::chrono::duration_cast(std::chrono::system_clock::now() - mod->updateLast).count() > mod->updateEveryMs) { - // Yes. Set the new last and do it. - mod->updateLast = std::chrono::system_clock::now(); - - mod->valueCalculated = BarCommands::parseCommand(mod->value); + // This is done asynchronously to prevent lag on especially slower PCs + // but ngl it also did hang on more powerful ones + std::thread([=](){ + const auto RETVAL = BarCommands::parseCommand(mod->value); + mod->accessValueCalculated(true, RETVAL); + mod->updateLast = std::chrono::system_clock::now(); + }).detach(); } // We have the value, draw the module! @@ -620,7 +626,7 @@ int CStatusBar::drawModule(SBarModule* mod, int off) { const auto MODULEWIDTH = getTextWidth(mod->valueCalculated, ConfigManager::getString("bar:font.main")) + PAD; const auto ICONWIDTH = getTextWidth(mod->icon, ConfigManager::getString("bar:font.secondary")); - if (!MODULEWIDTH || mod->valueCalculated == "") + if (!MODULEWIDTH || mod->accessValueCalculated(false) == "") return 0; // empty module Vector2D position; @@ -639,7 +645,7 @@ int CStatusBar::drawModule(SBarModule* mod, int off) { drawCairoRectangle(position, Vector2D(MODULEWIDTH + ICONWIDTH, m_vecSize.y), mod->bgcolor); drawText(position + Vector2D(PAD / 2, getTextHalfY()), mod->icon, mod->color, ConfigManager::getString("bar:font.secondary")); - drawText(position + Vector2D(PAD / 2 + ICONWIDTH, getTextHalfY()), mod->valueCalculated, mod->color, ConfigManager::getString("bar:font.main")); + drawText(position + Vector2D(PAD / 2 + ICONWIDTH, getTextHalfY()), mod->accessValueCalculated(false), mod->color, ConfigManager::getString("bar:font.main")); return MODULEWIDTH + ICONWIDTH; } diff --git a/src/bar/Bar.hpp b/src/bar/Bar.hpp index 647a862..c81fe1f 100644 --- a/src/bar/Bar.hpp +++ b/src/bar/Bar.hpp @@ -6,6 +6,8 @@ #include "../ipc/ipc.hpp" #include "BarCommands.hpp" #include +#include +#include inline int barScreen = 0; @@ -20,7 +22,7 @@ enum ModuleAlignment { RIGHT }; -struct SBarModule { +NONMOVABLE NONCOPYABLE struct SBarModule { ModuleAlignment alignment; std::string value; std::string icon; @@ -36,6 +38,19 @@ struct SBarModule { // PADS bool isPad = false; int pad = 0; + + + // Simple but working thread safe value accessor + std::mutex mtx; + std::string accessValueCalculated(bool write, std::string val = "") { + std::lock_guard lg(mtx); + + if (write) + valueCalculated = val; + else + return valueCalculated; + return ""; + } }; class CStatusBar { @@ -61,7 +76,7 @@ public: std::vector openWorkspaces; EXPOSED_MEMBER(CurrentWorkspace, int, i); - std::vector modules; + std::vector modules; xcb_window_t trayWindowID = 0; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index a09b18d..ab268d4 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -143,7 +143,8 @@ void handleStatusCommand(const std::string& command, const std::string& args) { } void parseModule(const std::string& COMMANDC, const std::string& VALUE) { - SBarModule module; + SBarModule* module = new SBarModule(); + g_pWindowManager->statusBar->modules.push_back(module); auto valueCopy = VALUE; @@ -156,24 +157,22 @@ void parseModule(const std::string& COMMANDC, const std::string& VALUE) { const auto PADW = valueCopy; - if (ALIGNR == "left") module.alignment = LEFT; - else if (ALIGNR == "right") module.alignment = RIGHT; - else if (ALIGNR == "center") module.alignment = CENTER; + if (ALIGNR == "left") module->alignment = LEFT; + else if (ALIGNR == "right") module->alignment = RIGHT; + else if (ALIGNR == "center") module->alignment = CENTER; try { - module.pad = stol(PADW); + module->pad = stol(PADW); } catch (...) { Debug::log(ERR, "Module creation pad error: invalid pad"); ConfigManager::parseError = "Module creation error in pad: invalid pad."; return; } - module.isPad = true; + module->isPad = true; - module.color = 0; - module.bgcolor = 0; - - g_pWindowManager->statusBar->modules.push_back(module); + module->color = 0; + module->bgcolor = 0; return; } @@ -192,32 +191,34 @@ void parseModule(const std::string& COMMANDC, const std::string& VALUE) { const auto COMMAND = valueCopy; - if (ALIGN == "left") module.alignment = LEFT; - else if (ALIGN == "right") module.alignment = RIGHT; - else if (ALIGN == "center") module.alignment = CENTER; + if (ALIGN == "left") module->alignment = LEFT; + else if (ALIGN == "right") module->alignment = RIGHT; + else if (ALIGN == "center") module->alignment = CENTER; try { - module.color = stol(COL1.substr(2), nullptr, 16); - module.bgcolor = stol(COL2.substr(2), nullptr, 16); + module->color = stol(COL1.substr(2), nullptr, 16); + module->bgcolor = stol(COL2.substr(2), nullptr, 16); } catch (...) { Debug::log(ERR, "Module creation color error: invalid color"); ConfigManager::parseError = "Module creation error in color: invalid color."; + g_pWindowManager->statusBar->modules.pop_back(); + delete module; return; } try { - module.updateEveryMs = stol(UPDATE); + module->updateEveryMs = stol(UPDATE); } catch (...) { Debug::log(ERR, "Module creation error: invalid update interval"); ConfigManager::parseError = "Module creation error in interval: invalid interval."; + g_pWindowManager->statusBar->modules.pop_back(); + delete module; return; } - module.icon = ICON; + module->icon = ICON; - module.value = COMMAND; - - g_pWindowManager->statusBar->modules.push_back(module); + module->value = COMMAND; } void parseBarLine(const std::string& line) { @@ -363,7 +364,7 @@ void ConfigManager::loadConfigLoadVars() { if (loadBar && g_pWindowManager->statusBar) { // clear modules as we overwrite them for (auto& m : g_pWindowManager->statusBar->modules) { - g_pWindowManager->statusBar->destroyModule(&m); + g_pWindowManager->statusBar->destroyModule(m); } g_pWindowManager->statusBar->modules.clear(); } diff --git a/src/defines.hpp b/src/defines.hpp index a437088..451ee10 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -40,6 +40,11 @@ #define ISDEBUG false #endif +// hints +#define NONMOVABLE +#define NONCOPYABLE +// + #define EXPOSED_MEMBER(var, type, prefix) \ private: \ type m_##prefix##var; \