From 5a5ecafd91798f2684ae8d35e86f161d510b1933 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sun, 21 Nov 2021 12:40:03 +0100 Subject: [PATCH] Basic CFG system --- README.md | 2 +- src/bar/Bar.cpp | 38 +++++++++- src/bar/Bar.hpp | 1 + src/config/ConfigManager.cpp | 142 +++++++++++++++++++++++++++++++++++ src/config/ConfigManager.hpp | 23 ++++++ src/events/events.cpp | 18 +---- src/windowManager.cpp | 48 +++++------- src/windowManager.hpp | 12 +-- 8 files changed, 226 insertions(+), 58 deletions(-) create mode 100644 src/config/ConfigManager.cpp create mode 100644 src/config/ConfigManager.hpp diff --git a/README.md b/README.md index 7cd7a5c..6ba03f4 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Hypr is a Linux tiling window manager for Xorg. It's written in XCB with modern - [ ] Multi-monitor support - [x] Status bar ~ UNFINISHED, someone help please - [ ] Floating windows support -- [ ] Config system +- [x] Config system ~ Basic done - [x] Workspaces - [x] Moving windows / user input (e.g. fullscreening) ~ More to be done probably - [ ] True lerp animations diff --git a/src/bar/Bar.cpp b/src/bar/Bar.cpp index f26dcc2..c26c35c 100644 --- a/src/bar/Bar.cpp +++ b/src/bar/Bar.cpp @@ -6,15 +6,34 @@ #include "../windowManager.hpp" void CStatusBar::setup(Vector2D origin, Vector2D size) { - m_vecPosition = origin; - m_vecSize = size; + if (origin.x != -1 && origin.y != -1) { + m_vecPosition = origin; + } + + if (size.x != -1 && size.y != -1) { + m_vecSize = size; + } + + uint32_t values[4]; + + // window + m_iWindowID = (xcb_generate_id(g_pWindowManager->DisplayConnection)); + + values[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE; + + xcb_create_window(g_pWindowManager->DisplayConnection, g_pWindowManager->Depth, m_iWindowID, + g_pWindowManager->Screen->root, m_vecPosition.x, m_vecPosition.y, m_vecSize.x, m_vecSize.y, + 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, g_pWindowManager->Screen->root_visual, + XCB_CW_EVENT_MASK, values); + + // map + xcb_map_window(g_pWindowManager->DisplayConnection, m_iWindowID); // Create a pixmap for writing to. m_iPixmap = xcb_generate_id(g_pWindowManager->DisplayConnection); xcb_create_pixmap(g_pWindowManager->DisplayConnection, g_pWindowManager->Depth, m_iPixmap, m_iWindowID, m_vecSize.x, m_vecSize.y); - // setup contexts.. ugh. - uint32_t values[4]; + // setup contexts.. ugh.. auto contextBG = &m_mContexts["BG"]; contextBG->GContext = xcb_generate_id(g_pWindowManager->DisplayConnection); @@ -63,6 +82,17 @@ void CStatusBar::setup(Vector2D origin, Vector2D size) { //xcb_close_font(g_pWindowManager->DisplayConnection, contextBASETEXT->Font); } +void CStatusBar::destroy() { + xcb_close_font(g_pWindowManager->DisplayConnection, m_mContexts["HITEXT"].Font); + xcb_destroy_window(g_pWindowManager->DisplayConnection, m_iWindowID); + xcb_destroy_window(g_pWindowManager->DisplayConnection, m_iPixmap); + + xcb_free_gc(g_pWindowManager->DisplayConnection, m_mContexts["BG"].GContext); + xcb_free_gc(g_pWindowManager->DisplayConnection, m_mContexts["MEDBG"].GContext); + xcb_free_gc(g_pWindowManager->DisplayConnection, m_mContexts["TEXT"].GContext); + xcb_free_gc(g_pWindowManager->DisplayConnection, m_mContexts["HITEXT"].GContext); +} + int getTextWidth(std::string text, xcb_font_t font) { // conv from utf8 to UCS-2 (what the fuck Xorg why) diff --git a/src/bar/Bar.hpp b/src/bar/Bar.hpp index 8434c2a..d7b5aad 100644 --- a/src/bar/Bar.hpp +++ b/src/bar/Bar.hpp @@ -16,6 +16,7 @@ public: void draw(); void setup(Vector2D, Vector2D); + void destroy(); private: Vector2D m_vecSize; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp new file mode 100644 index 0000000..1a72b65 --- /dev/null +++ b/src/config/ConfigManager.cpp @@ -0,0 +1,142 @@ +#include "ConfigManager.hpp" +#include "../windowManager.hpp" + +#include +#include +#include + +#include +#include + +void ConfigManager::init() { + configValues["border_size"].intValue = 1; + configValues["gaps_in"].intValue = 5; + configValues["gaps_out"].intValue = 20; + configValues["bar_height"].intValue = 15; + configValues["max_fps"].intValue = 60; + + ConfigManager::loadConfigLoadVars(); +} + +void parseLine(std::string& line) { + // first check if its not a comment + const auto COMMENTSTART = line.find_first_of('#'); + if (COMMENTSTART == 0) + return; + + // now, cut the comment off + if (COMMENTSTART != std::string::npos) + line = line.substr(COMMENTSTART); + + // And parse + // check if command + const auto EQUALSPLACE = line.find_first_of('='); + + if (EQUALSPLACE == std::string::npos) + return; + + const auto COMMAND = line.substr(0, EQUALSPLACE); + const auto VALUE = line.substr(EQUALSPLACE + 1); + + if (ConfigManager::configValues.find(COMMAND) == ConfigManager::configValues.end()) + return; + + auto& CONFIGENTRY = ConfigManager::configValues.at(COMMAND); + if (CONFIGENTRY.intValue != -1) { + try { + CONFIGENTRY.intValue = stoi(VALUE); + } catch (...) { + Debug::log(WARN, "Error reading value of " + COMMAND); + } + } else if (CONFIGENTRY.floatValue != -1) { + try { + CONFIGENTRY.floatValue = stof(VALUE); + } catch (...) { + Debug::log(WARN, "Error reading value of " + COMMAND); + } + } else if (CONFIGENTRY.strValue != "") { + try { + CONFIGENTRY.strValue = VALUE; + } catch (...) { + Debug::log(WARN, "Error reading value of " + COMMAND); + } + } +} + +void ConfigManager::loadConfigLoadVars() { + Debug::log(LOG, "Reloading the config!"); + + const char* const ENVHOME = getenv("HOME"); + + const std::string CONFIGPATH = ENVHOME + (std::string) "/.config/hypr/hypr.conf"; + + std::ifstream ifs; + ifs.open(CONFIGPATH.c_str()); + + if (!ifs.good()) { + Debug::log(WARN, "Config reading error. (No file?)"); + return; + } + + std::string line = ""; + if (ifs.is_open()) { + while (std::getline(ifs, line)) { + // Read line by line. + parseLine(line); + } + } + + ifs.close(); + + g_pWindowManager->setAllWindowsDirty(); + + // Reload the bar as well + g_pWindowManager->statusBar.destroy(); + g_pWindowManager->statusBar.setup(Vector2D(-1,-1), Vector2D(g_pWindowManager->Screen->width_in_pixels, configValues["bar_height"].intValue)); +} + +void emptyEvent() { + xcb_expose_event_t exposeEvent; + exposeEvent.window = g_pWindowManager->statusBar.getWindowID(); + exposeEvent.response_type = 0; + exposeEvent.x = 0; + exposeEvent.y = 0; + exposeEvent.width = g_pWindowManager->Screen->width_in_pixels; + exposeEvent.height = g_pWindowManager->Screen->height_in_pixels; + xcb_send_event(g_pWindowManager->DisplayConnection, false, g_pWindowManager->Screen->root, XCB_EVENT_MASK_EXPOSURE, (char*)&exposeEvent); + xcb_flush(g_pWindowManager->DisplayConnection); +} + +void ConfigManager::tick() { + const char* const ENVHOME = getenv("HOME"); + + const std::string CONFIGPATH = ENVHOME + (std::string)"/.config/hypr/hypr.conf"; + + struct stat fileStat; + int err = stat(CONFIGPATH.c_str(), &fileStat); + if (err != 0) { + Debug::log(WARN, "Error at ticking config, error" + std::to_string(errno)); + } + + // check if we need to reload cfg + if(fileStat.st_mtime > lastModifyTime) { + lastModifyTime = fileStat.st_mtime; + + ConfigManager::loadConfigLoadVars(); + + // so that the WM reloads the windows. + emptyEvent(); + } +} + +int ConfigManager::getInt(std::string_view v) { + return configValues[v].intValue; +} + +float ConfigManager::getFloat(std::string_view v) { + return configValues[v].floatValue; +} + +std::string ConfigManager::getString(std::string_view v) { + return configValues[v].strValue; +} \ No newline at end of file diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp new file mode 100644 index 0000000..2560107 --- /dev/null +++ b/src/config/ConfigManager.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include "../utilities/Debug.hpp" + +struct SConfigValue { + int intValue = -1; + float floatValue = -1; + std::string strValue = ""; +}; + +namespace ConfigManager { + inline std::map configValues; + inline time_t lastModifyTime = 0; + + void init(); + void loadConfigLoadVars(); + void tick(); + + int getInt(std::string_view); + float getFloat(std::string_view); + std::string getString(std::string_view); +}; \ No newline at end of file diff --git a/src/events/events.cpp b/src/events/events.cpp index bd43f46..9812921 100644 --- a/src/events/events.cpp +++ b/src/events/events.cpp @@ -1,20 +1,10 @@ #include "events.hpp" -void Events::redraw() { - xcb_expose_event_t exposeEvent; - exposeEvent.window = g_pWindowManager->statusBar.getWindowID(); - exposeEvent.response_type = XCB_EXPOSE; - exposeEvent.x = 0; - exposeEvent.y = 0; - exposeEvent.width = g_pWindowManager->Screen->width_in_pixels; - exposeEvent.height = g_pWindowManager->Screen->height_in_pixels; - xcb_send_event(g_pWindowManager->DisplayConnection, false, g_pWindowManager->statusBar.getWindowID(), XCB_EVENT_MASK_EXPOSURE, (char*)&exposeEvent); - xcb_flush(g_pWindowManager->DisplayConnection); -} - void handle(sigval val) { - //Events::redraw(); g_pWindowManager->statusBar.draw(); + + // check config + ConfigManager::tick(); } void Events::setThread() { @@ -25,7 +15,7 @@ void Events::setThread() { eventsig.sigev_value.sival_ptr = &timerid; timer_create(CLOCK_REALTIME, &eventsig, &timerid); - itimerspec t = {{0, 1000 * (1000 / MAX_FPS)}, {1, 0}}; + itimerspec t = {{0, 1000 * (1000 / ConfigManager::getInt("max_fps"))}, {1, 0}}; timer_settime(timerid, 0, &t, 0); } diff --git a/src/windowManager.cpp b/src/windowManager.cpp index ce22152..5719e14 100644 --- a/src/windowManager.cpp +++ b/src/windowManager.cpp @@ -16,6 +16,7 @@ xcb_visualtype_t* CWindowManager::setupColors() { void CWindowManager::setupManager() { KeybindManager::reloadAllKeybinds(); + ConfigManager::init(); Values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE; xcb_change_window_attributes_checked(DisplayConnection, Screen->root, @@ -60,20 +61,7 @@ void CWindowManager::setupManager() { // ---- INIT THE BAR ---- // - // window - statusBar.setWindowID(xcb_generate_id(DisplayConnection)); - - Values[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE; - - xcb_create_window(DisplayConnection, Depth, statusBar.getWindowID(), - Screen->root, 0, 0, Screen->width_in_pixels, BAR_HEIGHT, - 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, Screen->root_visual, - XCB_CW_EVENT_MASK, Values); - - // map - xcb_map_window(DisplayConnection, statusBar.getWindowID()); - - statusBar.setup(Vector2D(0, 0), Vector2D(Screen->width_in_pixels, BAR_HEIGHT)); + statusBar.setup(Vector2D(0, 0), Vector2D(Screen->width_in_pixels, ConfigManager::getInt("bar_height"))); // start its' update thread Events::setThread(); @@ -163,6 +151,8 @@ void CWindowManager::refreshDirtyWindows() { for(auto& window : windows) { if (window.getDirty()) { + setEffectiveSizePosUsingConfig(&window); + // Fullscreen flag bool bHasFullscreenWindow = activeWorkspace->getHasFullscreenWindow(); @@ -211,13 +201,13 @@ void CWindowManager::refreshDirtyWindows() { // Focused special border. if (window.getDrawable() == LastWindow) { - Values[0] = (int)BORDERSIZE; + Values[0] = (int)ConfigManager::getInt("border_size"); xcb_configure_window(DisplayConnection, window.getDrawable(), XCB_CONFIG_WINDOW_BORDER_WIDTH, Values); // Update the position because the border makes the window jump // I have added the bordersize vec2d before in the setEffectiveSizePosUsingConfig function. - Values[0] = (int)window.getEffectivePosition().x - BORDERSIZE; - Values[1] = (int)window.getEffectivePosition().y - BORDERSIZE; + Values[0] = (int)window.getEffectivePosition().x - ConfigManager::getInt("border_size"); + Values[1] = (int)window.getEffectivePosition().y - ConfigManager::getInt("border_size"); xcb_configure_window(DisplayConnection, window.getDrawable(), XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, Values); Values[0] = 0xFF3333; // RED :) @@ -294,15 +284,15 @@ void CWindowManager::setEffectiveSizePosUsingConfig(CWindow* pWindow) { const bool DISPLAYTOP = pWindow->getPosition().y == 0; const bool DISPLAYBOTTOM = pWindow->getPosition().y + pWindow->getSize().y == Screen->height_in_pixels; - pWindow->setEffectivePosition(pWindow->getPosition() + Vector2D(BORDERSIZE, BORDERSIZE)); - pWindow->setEffectiveSize(pWindow->getSize() - (Vector2D(BORDERSIZE, BORDERSIZE) * 2)); + pWindow->setEffectivePosition(pWindow->getPosition() + Vector2D(ConfigManager::getInt("border_size"), ConfigManager::getInt("border_size"))); + pWindow->setEffectiveSize(pWindow->getSize() - (Vector2D(ConfigManager::getInt("border_size"), ConfigManager::getInt("border_size")) * 2)); // do gaps, set top left - pWindow->setEffectivePosition(pWindow->getEffectivePosition() + Vector2D(DISPLAYLEFT ? GAPS_OUT : GAPS_IN, DISPLAYTOP ? GAPS_OUT + BAR_HEIGHT : GAPS_IN)); + pWindow->setEffectivePosition(pWindow->getEffectivePosition() + Vector2D(DISPLAYLEFT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYTOP ? ConfigManager::getInt("gaps_out") + ConfigManager::getInt("bar_height") : ConfigManager::getInt("gaps_in"))); // fix to old size bottom right - pWindow->setEffectiveSize(pWindow->getEffectiveSize() - Vector2D(DISPLAYLEFT ? GAPS_OUT : GAPS_IN, DISPLAYTOP ? GAPS_OUT + BAR_HEIGHT : GAPS_IN)); + pWindow->setEffectiveSize(pWindow->getEffectiveSize() - Vector2D(DISPLAYLEFT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYTOP ? ConfigManager::getInt("gaps_out") + ConfigManager::getInt("bar_height") : ConfigManager::getInt("gaps_in"))); // set bottom right - pWindow->setEffectiveSize(pWindow->getEffectiveSize() - Vector2D(DISPLAYRIGHT ? GAPS_OUT : GAPS_IN, DISPLAYBOTTOM ? GAPS_OUT : GAPS_IN)); + pWindow->setEffectiveSize(pWindow->getEffectiveSize() - Vector2D(DISPLAYRIGHT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYBOTTOM ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"))); } void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) { @@ -327,9 +317,6 @@ void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) { pWindow->setSize(Vector2D(Screen->width_in_pixels, Screen->height_in_pixels)); pWindow->setPosition(Vector2D(0, 0)); } - - setEffectiveSizePosUsingConfig(pWindow); - setEffectiveSizePosUsingConfig(PLASTWINDOW); } void CWindowManager::calculateNewWindowParams(CWindow* pWindow) { @@ -449,8 +436,6 @@ void CWindowManager::fixWindowOnClose(CWindow* pClosedWindow) { neighbor->setDirty(true); setFocusedWindow(neighbor->getDrawable()); // Set focus. :) - - setEffectiveSizePosUsingConfig(neighbor); } CWindow* CWindowManager::getNeighborInDir(char dir) { @@ -533,9 +518,6 @@ void CWindowManager::moveActiveWindowTo(char dir) { CURRENTWINDOW->setDirty(true); neighbor->setDirty(true); - setEffectiveSizePosUsingConfig(neighbor); - setEffectiveSizePosUsingConfig(CURRENTWINDOW); - // finish by moving the cursor to the current window warpCursorTo(CURRENTWINDOW->getPosition() + CURRENTWINDOW->getSize() / 2.f); } @@ -557,6 +539,12 @@ void CWindowManager::changeWorkspaceByID(int ID) { LastWindow = -1; } +void CWindowManager::setAllWindowsDirty() { + for (auto& window : windows) { + window.setDirty(true); + } +} + void CWindowManager::setAllWorkspaceWindowsDirtyByID(int ID) { int workspaceID = -1; for (auto& workspace : workspaces) { diff --git a/src/windowManager.hpp b/src/windowManager.hpp index 8df74c3..a5bd97b 100644 --- a/src/windowManager.hpp +++ b/src/windowManager.hpp @@ -10,15 +10,7 @@ #include "KeybindManager.hpp" #include "utilities/Workspace.hpp" #include "bar/Bar.hpp" - - -// temp config values -#define BORDERSIZE 1 -#define GAPS_IN 5 -#define GAPS_OUT 20 -#define BAR_HEIGHT 15 - -#define MAX_FPS 60 +#include "config/ConfigManager.hpp" class CWindowManager { public: @@ -59,6 +51,8 @@ public: int getHighestWorkspaceID(); CWorkspace* getWorkspaceByID(int); + void setAllWindowsDirty(); + private: // Internal WM functions that don't have to be exposed