diff --git a/src/bar/Bar.cpp b/src/bar/Bar.cpp index 3ba8dd5..3021d1f 100644 --- a/src/bar/Bar.cpp +++ b/src/bar/Bar.cpp @@ -352,11 +352,17 @@ void CStatusBar::setup(int MonitorID) { // fix tray fixTrayOnCreate(); + + + m_bIsDestroyed = false; } void CStatusBar::destroy() { Debug::log(LOG, "Destroying the bar!"); + if (m_bIsDestroyed) + return; + saveTrayOnDestroy(); xcb_close_font(g_pWindowManager->DisplayConnection, m_mContexts["HITEXT"].Font); @@ -371,6 +377,8 @@ void CStatusBar::destroy() { // Free cairo cairo_destroy(m_pCairo); m_pCairo = nullptr; + + m_bIsDestroyed = true; } int CStatusBar::getTextWidth(std::string text, std::string font) { @@ -401,6 +409,20 @@ int CStatusBar::getTextHalfY() { return m_vecSize.y - (m_vecSize.y - 9) / 2.f; } +void CStatusBar::drawErrorScreen() { + drawCairoRectangle(Vector2D(0, 0), m_vecSize, 0xFFaa1111); + drawText(Vector2D(1, getTextHalfY()), ConfigManager::parseError, 0xff000000, ConfigManager::getString("bar:font.main")); + + + // do all the drawing cuz we return later + cairo_surface_flush(m_pCairoSurface); + + xcb_copy_area(g_pWindowManager->DisplayConnection, m_iPixmap, m_iWindowID, m_mContexts["BG"].GContext, + 0, 0, 0, 0, m_vecSize.x, m_vecSize.y); + + xcb_flush(g_pWindowManager->DisplayConnection); +} + void CStatusBar::draw() { if (m_bIsCovered) @@ -418,6 +440,12 @@ void CStatusBar::draw() { cairo_restore(m_pCairo); // + if (ConfigManager::parseError != "") { + // draw a special error screen + drawErrorScreen(); + return; + } + drawCairoRectangle(Vector2D(0, 0), m_vecSize, ConfigManager::getInt("bar:col.bg")); // diff --git a/src/bar/Bar.hpp b/src/bar/Bar.hpp index 3da30ef..a3b4699 100644 --- a/src/bar/Bar.hpp +++ b/src/bar/Bar.hpp @@ -64,6 +64,9 @@ public: std::vector modules; private: + // for not deleting nulls + bool m_bIsDestroyed = true; + Vector2D m_vecSize; Vector2D m_vecPosition; @@ -81,6 +84,7 @@ private: int drawModule(SBarModule*, int); int drawWorkspacesModule(SBarModule*, int); int getTextHalfY(); + void drawErrorScreen(); std::unordered_map m_mContexts; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 3a6c921..f46f519 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -64,18 +64,21 @@ void configSetValueSafe(const std::string& COMMAND, const std::string& VALUE) { CONFIGENTRY.intValue = stol(VALUE); } catch (...) { Debug::log(WARN, "Error reading value of " + COMMAND); + ConfigManager::parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">."; } } else if (CONFIGENTRY.floatValue != -1) { try { CONFIGENTRY.floatValue = stof(VALUE); } catch (...) { Debug::log(WARN, "Error reading value of " + COMMAND); + ConfigManager::parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">."; } } else if (CONFIGENTRY.strValue != "") { try { CONFIGENTRY.strValue = VALUE; } catch (...) { Debug::log(WARN, "Error reading value of " + COMMAND); + ConfigManager::parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">."; } } } @@ -148,6 +151,7 @@ void parseModule(const std::string& COMMANDC, const std::string& VALUE) { module.pad = stol(PADW); } catch (...) { Debug::log(ERR, "Module creation pad error: invalid pad"); + ConfigManager::parseError = "Module creation error in pad: invalid pad."; return; } @@ -184,6 +188,7 @@ void parseModule(const std::string& COMMANDC, const std::string& VALUE) { 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."; return; } @@ -191,6 +196,7 @@ void parseModule(const std::string& COMMANDC, const std::string& VALUE) { module.updateEveryMs = stol(UPDATE); } catch (...) { Debug::log(ERR, "Module creation error: invalid update interval"); + ConfigManager::parseError = "Module creation error in interval: invalid interval."; return; } @@ -282,6 +288,8 @@ void parseLine(std::string& line) { void ConfigManager::loadConfigLoadVars() { Debug::log(LOG, "Reloading the config!"); + ConfigManager::parseError = ""; // reset the error + ConfigManager::isBar = false; // reset the bar if (loadBar && g_pWindowManager->statusBar) { // clear modules as we overwrite them @@ -302,10 +310,12 @@ void ConfigManager::loadConfigLoadVars() { if (!ifs.good()) { Debug::log(WARN, "Config reading error. (No file?)"); + ConfigManager::parseError = "The config could not be read. (No file?)"; return; } std::string line = ""; + int linenum = 1; if (ifs.is_open()) { while (std::getline(ifs, line)) { // Read line by line. @@ -314,7 +324,17 @@ void ConfigManager::loadConfigLoadVars() { } catch(...) { Debug::log(ERR, "Error reading line from config. Line:"); Debug::log(NONE, line); + + parseError = "Config error at line " + std::to_string(linenum) + ": Line parsing error."; + break; } + + if (parseError != "") { + parseError = "Config error at line " + std::to_string(linenum) + ": " + parseError; + break; + } + + ++linenum; } @@ -325,9 +345,17 @@ void ConfigManager::loadConfigLoadVars() { g_pWindowManager->recalcAllWorkspaces(); // Reload the bar as well, don't load it before the default is loaded. - if (loadBar && g_pWindowManager->statusBar) { + if (loadBar && g_pWindowManager->statusBar && (configValues["bar:enabled"].intValue == 1 || parseError != "")) { g_pWindowManager->statusBar->destroy(); + + // make the bar height visible + if (parseError != "") { + configValues["bar:height"].intValue = 15; + } + g_pWindowManager->statusBar->setup(configValues["bar:monitor"].intValue); + } else if (g_pWindowManager->statusBar) { + g_pWindowManager->statusBar->destroy(); } // Ensure correct layout diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index a7b96b8..cca52db 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -24,6 +24,8 @@ namespace ConfigManager { inline bool isFirstLaunch = false; + inline std::string parseError = ""; // For storing a parse error to display later + void init(); void loadConfigLoadVars(); void tick();