#pragma once #define CONFIG_MANAGER_H #include #include "../debug/Log.hpp" #include #include "../defines.hpp" #include #include #include #include #include #include "../Window.hpp" #include "../helpers/WLClasses.hpp" #include "defaultConfig.hpp" #include "ConfigDataValues.hpp" #define STRVAL_EMPTY "[[EMPTY]]" #define INITANIMCFG(name) animationConfig[name] = {} #define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]} #define HANDLE void* struct SConfigValue { int64_t intValue = -INT64_MAX; float floatValue = -__FLT_MAX__; std::string strValue = ""; Vector2D vecValue = Vector2D(-__FLT_MAX__, -__FLT_MAX__); std::shared_ptr data; bool set = false; // used for device configs }; struct SMonitorRule { std::string name = ""; Vector2D resolution = Vector2D(1280, 720); Vector2D offset = Vector2D(0, 0); float scale = 1; float refreshRate = 60; bool disabled = false; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; std::string mirrorOf = ""; bool enable10bit = false; }; struct SWorkspaceRule { std::string monitor = ""; std::string workspaceString = ""; std::string workspaceName = ""; int workspaceId = -1; bool isDefault = false; std::optional gapsIn; std::optional gapsOut; std::optional borderSize; std::optional border; std::optional rounding; std::optional decorate; }; struct SMonitorAdditionalReservedArea { int top = 0; int bottom = 0; int left = 0; int right = 0; }; struct SAnimationPropertyConfig { bool overridden = true; std::string internalBezier = ""; std::string internalStyle = ""; float internalSpeed = 0.f; int internalEnabled = -1; SAnimationPropertyConfig* pValues = nullptr; SAnimationPropertyConfig* pParentAnimation = nullptr; }; struct SExecRequestedRule { std::string szRule = ""; uint64_t iPid = 0; }; class CVarList { public: /* passing 's' as a separator will use std::isspace */ CVarList(const std::string& in, long unsigned int lastArgNo = 0, const char separator = ',') { std::string curitem = ""; std::string argZ = in; const bool SPACESEP = separator == 's'; auto nextItem = [&]() { auto idx = lastArgNo != 0 && m_vArgs.size() >= lastArgNo - 1 ? std::string::npos : ([&]() -> size_t { if (!SPACESEP) return argZ.find_first_of(separator); uint64_t pos = -1; while (!std::isspace(argZ[++pos]) && pos < argZ.length()) ; return pos < argZ.length() ? pos : std::string::npos; }()); if (idx != std::string::npos) { curitem = argZ.substr(0, idx); argZ = argZ.substr(idx + 1); } else { curitem = argZ; argZ = STRVAL_EMPTY; } }; nextItem(); while (curitem != STRVAL_EMPTY) { m_vArgs.push_back(removeBeginEndSpacesTabs(curitem)); nextItem(); } }; ~CVarList() = default; size_t size() const { return m_vArgs.size(); } std::string operator[](const long unsigned int& idx) const { if (idx >= m_vArgs.size()) return ""; return m_vArgs[idx]; } // for range-based loops std::vector::iterator begin() { return m_vArgs.begin(); } std::vector::const_iterator begin() const { return m_vArgs.begin(); } std::vector::iterator end() { return m_vArgs.end(); } std::vector::const_iterator end() const { return m_vArgs.end(); } private: std::vector m_vArgs; }; class CConfigManager { public: CConfigManager(); void tick(); void init(); int getInt(const std::string&); float getFloat(const std::string&); std::string getString(const std::string&); void setFloat(const std::string&, float); void setInt(const std::string&, int); void setString(const std::string&, const std::string&); int getDeviceInt(const std::string&, const std::string&); float getDeviceFloat(const std::string&, const std::string&); std::string getDeviceString(const std::string&, const std::string&); bool deviceConfigExists(const std::string&); bool shouldBlurLS(const std::string&); SConfigValue* getConfigValuePtr(const std::string&); SConfigValue* getConfigValuePtrSafe(const std::string&); SMonitorRule getMonitorRuleFor(const std::string&, const std::string& displayName = ""); SWorkspaceRule getWorkspaceRuleFor(CWorkspace*); std::string getDefaultWorkspaceFor(const std::string&); CMonitor* getBoundMonitorForWS(const std::string&); std::string getBoundMonitorStringForWS(const std::string&); const std::deque& getAllWorkspaceRules(); std::vector getMatchingRules(CWindow*); std::vector getMatchingRules(SLayerSurface*); std::unordered_map m_mAdditionalReservedAreas; std::unordered_map getAnimationConfig(); void addPluginConfigVar(HANDLE handle, const std::string& name, const SConfigValue& value); void removePluginConfig(HANDLE handle); // no-op when done. void dispatchExecOnce(); void performMonitorReload(); bool m_bWantsMonitorReload = false; bool m_bForceReload = false; bool m_bNoMonitorReload = false; void ensureMonitorStatus(); void ensureVRR(CMonitor* pMonitor = nullptr); std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false); void addParseError(const std::string&); SAnimationPropertyConfig* getAnimationPropertyConfig(const std::string&); void addExecRule(const SExecRequestedRule&); void handlePluginLoads(); std::string configCurrentPath; private: std::deque configPaths; // stores all the config paths std::unordered_map configModifyTimes; // stores modify times std::vector> configDynamicVars; // stores dynamic vars declared by the user std::unordered_map configValues; std::unordered_map> deviceConfigs; // stores device configs std::unordered_map animationConfig; // stores all the animations with their set values std::string currentCategory = ""; // For storing the category of the current item std::string parseError = ""; // For storing a parse error to display later std::string m_szCurrentSubmap = ""; // For storing the current keybind submap std::vector execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty std::vector m_vDeclaredPlugins; std::unordered_map>> pluginConfigs; // stores plugin configs bool isFirstLaunch = true; // For exec-once std::deque m_dMonitorRules; std::deque m_dWorkspaceRules; std::deque m_dWindowRules; std::deque m_dLayerRules; std::deque m_dBlurLSNamespaces; bool firstExecDispatched = false; bool m_bManualCrashInitiated = false; std::deque firstExecRequests; std::vector> environmentVariables; // internal methods void setDefaultVars(); void setDefaultAnimationVars(); void setDeviceDefaultVars(const std::string&); void populateEnvironment(); void setAnimForChildren(SAnimationPropertyConfig* const); void updateBlurredLS(const std::string&, const bool); void applyUserDefinedVars(std::string&, const size_t); void loadConfigLoadVars(); SConfigValue getConfigValueSafe(const std::string&); SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&); void parseLine(std::string&); void configSetValueSafe(const std::string&, const std::string&); void handleDeviceConfig(const std::string&, const std::string&); void handleRawExec(const std::string&, const std::string&); void handleMonitor(const std::string&, const std::string&); void handleBind(const std::string&, const std::string&); void handleUnbind(const std::string&, const std::string&); void handleWindowRule(const std::string&, const std::string&); void handleLayerRule(const std::string&, const std::string&); void handleWindowRuleV2(const std::string&, const std::string&); void handleWorkspaceRules(const std::string&, const std::string&); void handleBezier(const std::string&, const std::string&); void handleAnimation(const std::string&, const std::string&); void handleSource(const std::string&, const std::string&); void handleSubmap(const std::string&, const std::string&); void handleBlurLS(const std::string&, const std::string&); void handleBindWS(const std::string&, const std::string&); void handleEnv(const std::string&, const std::string&); void handlePlugin(const std::string&, const std::string&); }; inline std::unique_ptr g_pConfigManager;