Made the bar modules async

This commit is contained in:
vaxerski 2022-03-01 20:40:44 +01:00
parent 13744ae7c8
commit d12c35ce1b
4 changed files with 68 additions and 41 deletions

View file

@ -142,6 +142,9 @@ void CStatusBar::setupModule(SBarModule* module) {
void CStatusBar::destroyModule(SBarModule* module) { void CStatusBar::destroyModule(SBarModule* module) {
if (module->bgcontext) if (module->bgcontext)
xcb_free_gc(g_pWindowManager->DisplayConnection, module->bgcontext); xcb_free_gc(g_pWindowManager->DisplayConnection, module->bgcontext);
// delete it from the heap
delete module;
} }
void CStatusBar::setupTray() { void CStatusBar::setupTray() {
@ -181,8 +184,8 @@ void CStatusBar::setupTray() {
// Check if the tray module is active // Check if the tray module is active
SBarModule* pBarModule = nullptr; SBarModule* pBarModule = nullptr;
for (auto& mod : modules) { for (auto& mod : modules) {
if (mod.value == "tray") { if (mod->value == "tray") {
pBarModule = &mod; pBarModule = mod;
break; break;
} }
} }
@ -299,7 +302,7 @@ void CStatusBar::setup(int MonitorID) {
m_bHasTray = false; m_bHasTray = false;
for (auto& mod : g_pWindowManager->statusBar->modules) { for (auto& mod : g_pWindowManager->statusBar->modules) {
if (mod.value == "tray") { if (mod->value == "tray") {
m_bHasTray = true; m_bHasTray = true;
break; break;
} }
@ -474,18 +477,18 @@ void CStatusBar::draw() {
for (auto& module : modules) { for (auto& module : modules) {
if (!module.bgcontext && !module.isPad) if (!module->bgcontext && !module->isPad)
setupModule(&module); setupModule(module);
if (module.value == "workspaces") { if (module->value == "workspaces") {
offLeft += drawWorkspacesModule(&module, offLeft); offLeft += drawWorkspacesModule(module, offLeft);
} else { } else {
if (module.alignment == LEFT) { if (module->alignment == LEFT) {
offLeft += drawModule(&module, offLeft); offLeft += drawModule(module, offLeft);
} else if (module.alignment == RIGHT) { } else if (module->alignment == RIGHT) {
offRight += drawModule(&module, offRight); offRight += drawModule(module, offRight);
} else { } else {
drawModule(&module, 0); drawModule(module, 0);
} }
} }
} }
@ -609,10 +612,13 @@ int CStatusBar::drawModule(SBarModule* mod, int off) {
// check if we need to update // check if we need to update
if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - mod->updateLast).count() > mod->updateEveryMs) { if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - mod->updateLast).count() > mod->updateEveryMs) {
// Yes. Set the new last and do it. // This is done asynchronously to prevent lag on especially slower PCs
mod->updateLast = std::chrono::system_clock::now(); // but ngl it also did hang on more powerful ones
std::thread([=](){
mod->valueCalculated = BarCommands::parseCommand(mod->value); 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! // 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 MODULEWIDTH = getTextWidth(mod->valueCalculated, ConfigManager::getString("bar:font.main")) + PAD;
const auto ICONWIDTH = getTextWidth(mod->icon, ConfigManager::getString("bar:font.secondary")); const auto ICONWIDTH = getTextWidth(mod->icon, ConfigManager::getString("bar:font.secondary"));
if (!MODULEWIDTH || mod->valueCalculated == "") if (!MODULEWIDTH || mod->accessValueCalculated(false) == "")
return 0; // empty module return 0; // empty module
Vector2D position; Vector2D position;
@ -639,7 +645,7 @@ int CStatusBar::drawModule(SBarModule* mod, int off) {
drawCairoRectangle(position, Vector2D(MODULEWIDTH + ICONWIDTH, m_vecSize.y), mod->bgcolor); 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, 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; return MODULEWIDTH + ICONWIDTH;
} }

View file

@ -6,6 +6,8 @@
#include "../ipc/ipc.hpp" #include "../ipc/ipc.hpp"
#include "BarCommands.hpp" #include "BarCommands.hpp"
#include <chrono> #include <chrono>
#include <atomic>
#include <mutex>
inline int barScreen = 0; inline int barScreen = 0;
@ -20,7 +22,7 @@ enum ModuleAlignment {
RIGHT RIGHT
}; };
struct SBarModule { NONMOVABLE NONCOPYABLE struct SBarModule {
ModuleAlignment alignment; ModuleAlignment alignment;
std::string value; std::string value;
std::string icon; std::string icon;
@ -36,6 +38,19 @@ struct SBarModule {
// PADS // PADS
bool isPad = false; bool isPad = false;
int pad = 0; int pad = 0;
// Simple but working thread safe value accessor
std::mutex mtx;
std::string accessValueCalculated(bool write, std::string val = "") {
std::lock_guard<std::mutex> lg(mtx);
if (write)
valueCalculated = val;
else
return valueCalculated;
return "";
}
}; };
class CStatusBar { class CStatusBar {
@ -61,7 +76,7 @@ public:
std::vector<int> openWorkspaces; std::vector<int> openWorkspaces;
EXPOSED_MEMBER(CurrentWorkspace, int, i); EXPOSED_MEMBER(CurrentWorkspace, int, i);
std::vector<SBarModule> modules; std::vector<SBarModule*> modules;
xcb_window_t trayWindowID = 0; xcb_window_t trayWindowID = 0;

View file

@ -143,7 +143,8 @@ void handleStatusCommand(const std::string& command, const std::string& args) {
} }
void parseModule(const std::string& COMMANDC, const std::string& VALUE) { 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; auto valueCopy = VALUE;
@ -156,24 +157,22 @@ void parseModule(const std::string& COMMANDC, const std::string& VALUE) {
const auto PADW = valueCopy; const auto PADW = valueCopy;
if (ALIGNR == "left") module.alignment = LEFT; if (ALIGNR == "left") module->alignment = LEFT;
else if (ALIGNR == "right") module.alignment = RIGHT; else if (ALIGNR == "right") module->alignment = RIGHT;
else if (ALIGNR == "center") module.alignment = CENTER; else if (ALIGNR == "center") module->alignment = CENTER;
try { try {
module.pad = stol(PADW); module->pad = stol(PADW);
} catch (...) { } catch (...) {
Debug::log(ERR, "Module creation pad error: invalid pad"); Debug::log(ERR, "Module creation pad error: invalid pad");
ConfigManager::parseError = "Module creation error in pad: invalid pad."; ConfigManager::parseError = "Module creation error in pad: invalid pad.";
return; return;
} }
module.isPad = true; module->isPad = true;
module.color = 0; module->color = 0;
module.bgcolor = 0; module->bgcolor = 0;
g_pWindowManager->statusBar->modules.push_back(module);
return; return;
} }
@ -192,32 +191,34 @@ void parseModule(const std::string& COMMANDC, const std::string& VALUE) {
const auto COMMAND = valueCopy; const auto COMMAND = valueCopy;
if (ALIGN == "left") module.alignment = LEFT; if (ALIGN == "left") module->alignment = LEFT;
else if (ALIGN == "right") module.alignment = RIGHT; else if (ALIGN == "right") module->alignment = RIGHT;
else if (ALIGN == "center") module.alignment = CENTER; else if (ALIGN == "center") module->alignment = CENTER;
try { try {
module.color = stol(COL1.substr(2), nullptr, 16); module->color = stol(COL1.substr(2), nullptr, 16);
module.bgcolor = stol(COL2.substr(2), nullptr, 16); module->bgcolor = stol(COL2.substr(2), nullptr, 16);
} catch (...) { } catch (...) {
Debug::log(ERR, "Module creation color error: invalid color"); Debug::log(ERR, "Module creation color error: invalid color");
ConfigManager::parseError = "Module creation error in color: invalid color."; ConfigManager::parseError = "Module creation error in color: invalid color.";
g_pWindowManager->statusBar->modules.pop_back();
delete module;
return; return;
} }
try { try {
module.updateEveryMs = stol(UPDATE); module->updateEveryMs = stol(UPDATE);
} catch (...) { } catch (...) {
Debug::log(ERR, "Module creation error: invalid update interval"); Debug::log(ERR, "Module creation error: invalid update interval");
ConfigManager::parseError = "Module creation error in interval: invalid interval."; ConfigManager::parseError = "Module creation error in interval: invalid interval.";
g_pWindowManager->statusBar->modules.pop_back();
delete module;
return; return;
} }
module.icon = ICON; module->icon = ICON;
module.value = COMMAND; module->value = COMMAND;
g_pWindowManager->statusBar->modules.push_back(module);
} }
void parseBarLine(const std::string& line) { void parseBarLine(const std::string& line) {
@ -363,7 +364,7 @@ void ConfigManager::loadConfigLoadVars() {
if (loadBar && g_pWindowManager->statusBar) { if (loadBar && g_pWindowManager->statusBar) {
// clear modules as we overwrite them // clear modules as we overwrite them
for (auto& m : g_pWindowManager->statusBar->modules) { for (auto& m : g_pWindowManager->statusBar->modules) {
g_pWindowManager->statusBar->destroyModule(&m); g_pWindowManager->statusBar->destroyModule(m);
} }
g_pWindowManager->statusBar->modules.clear(); g_pWindowManager->statusBar->modules.clear();
} }

View file

@ -40,6 +40,11 @@
#define ISDEBUG false #define ISDEBUG false
#endif #endif
// hints
#define NONMOVABLE
#define NONCOPYABLE
//
#define EXPOSED_MEMBER(var, type, prefix) \ #define EXPOSED_MEMBER(var, type, prefix) \
private: \ private: \
type m_##prefix##var; \ type m_##prefix##var; \