#pragma once #define CONFIG_MANAGER_H #include #include "../debug/Log.hpp" #include #include "../defines.hpp" #include #include #include #include #include #include #include #include #include "../helpers/WLClasses.hpp" #include "../helpers/Monitor.hpp" #include "../helpers/varlist/VarList.hpp" #include "../desktop/Window.hpp" #include "../desktop/LayerSurface.hpp" #include "defaultConfig.hpp" #include "ConfigDataValues.hpp" #include #define INITANIMCFG(name) animationConfig[name] = {} #define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]} #define HANDLE void* struct SWorkspaceRule { std::string monitor = ""; std::string workspaceString = ""; std::string workspaceName = ""; WORKSPACEID workspaceId = -1; bool isDefault = false; bool isPersistent = false; std::optional gapsIn; std::optional gapsOut; std::optional borderSize; std::optional decorate; std::optional noRounding; std::optional noBorder; std::optional noShadow; std::optional onCreatedEmptyRunCmd; std::optional defaultName; std::map layoutopts; }; 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 SPluginKeyword { HANDLE handle = 0; std::string name = ""; Hyprlang::PCONFIGHANDLERFUNC fn = nullptr; }; struct SPluginVariable { HANDLE handle = 0; std::string name = ""; }; struct SExecRequestedRule { std::string szRule = ""; uint64_t iPid = 0; }; enum eConfigOptionType : uint16_t { CONFIG_OPTION_BOOL = 0, CONFIG_OPTION_INT = 1, /* e.g. 0/1/2*/ CONFIG_OPTION_FLOAT = 2, CONFIG_OPTION_STRING_SHORT = 3, /* e.g. "auto" */ CONFIG_OPTION_STRING_LONG = 4, /* e.g. a command */ CONFIG_OPTION_COLOR = 5, CONFIG_OPTION_CHOICE = 6, /* e.g. "one", "two", "three" */ CONFIG_OPTION_GRADIENT = 7, CONFIG_OPTION_VECTOR = 8, }; enum eConfigOptionFlags : uint32_t { CONFIG_OPTION_FLAG_PERCENTAGE = (1 << 0), }; struct SConfigOptionDescription { struct SBoolData { bool value = false; }; struct SRangeData { int value = 0, min = 0, max = 2; }; struct SFloatData { float value = 0, min = 0, max = 100; }; struct SStringData { std::string value; }; struct SColorData { CColor color; }; struct SChoiceData { int firstIndex = 0; std::string choices; // comma-separated }; struct SGradientData { std::string gradient; }; struct SVectorData { Vector2D vec, min, max; }; std::string value; // e.g. general:gaps_in std::string description; std::string specialCategory; // if value is special (e.g. device:abc) value will be abc and special device bool specialKey = false; eConfigOptionType type = CONFIG_OPTION_BOOL; uint32_t flags = 0; // eConfigOptionFlags std::string jsonify() const; // std::variant data; }; class CConfigManager { public: CConfigManager(); void tick(); void init(); int getDeviceInt(const std::string&, const std::string&, const std::string& fallback = ""); float getDeviceFloat(const std::string&, const std::string&, const std::string& fallback = ""); Vector2D getDeviceVec(const std::string&, const std::string&, const std::string& fallback = ""); std::string getDeviceString(const std::string&, const std::string&, const std::string& fallback = ""); bool deviceConfigExists(const std::string&); Hyprlang::CConfigValue* getConfigValueSafeDevice(const std::string& dev, const std::string& val, const std::string& fallback); bool shouldBlurLS(const std::string&); void* const* getConfigValuePtr(const std::string&); Hyprlang::CConfigValue* getHyprlangConfigValuePtr(const std::string& name, const std::string& specialCat = ""); void onPluginLoadUnload(const std::string& name, bool load); static std::string getMainConfigPath(); const std::string getConfigString(); SMonitorRule getMonitorRuleFor(const SP); SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace); std::string getDefaultWorkspaceFor(const std::string&); CMonitor* getBoundMonitorForWS(const std::string&); std::string getBoundMonitorStringForWS(const std::string&); const std::deque& getAllWorkspaceRules(); std::vector getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false); std::vector getMatchingRules(PHLLS); const std::vector& getAllDescriptions(); std::unordered_map m_mAdditionalReservedAreas; std::unordered_map getAnimationConfig(); void addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value); void addPluginKeyword(HANDLE handle, const std::string& name, Hyprlang::PCONFIGHANDLERFUNC fun, Hyprlang::SHandlerOptions opts = {}); void removePluginConfig(HANDLE handle); // no-op when done. void dispatchExecOnce(); void dispatchExecShutdown(); void performMonitorReload(); void appendMonitorRule(const SMonitorRule&); bool replaceMonitorRule(const SMonitorRule&); void ensureMonitorStatus(); void ensureVRR(CMonitor* pMonitor = nullptr); std::string parseKeyword(const std::string&, const std::string&); void addParseError(const std::string&); SAnimationPropertyConfig* getAnimationPropertyConfig(const std::string&); void addExecRule(const SExecRequestedRule&); void handlePluginLoads(); std::string getErrors(); // keywords std::optional handleRawExec(const std::string&, const std::string&); std::optional handleExecOnce(const std::string&, const std::string&); std::optional handleExecShutdown(const std::string&, const std::string&); std::optional handleMonitor(const std::string&, const std::string&); std::optional handleBind(const std::string&, const std::string&); std::optional handleUnbind(const std::string&, const std::string&); std::optional handleWindowRule(const std::string&, const std::string&); std::optional handleLayerRule(const std::string&, const std::string&); std::optional handleWindowRuleV2(const std::string&, const std::string&); std::optional handleWorkspaceRules(const std::string&, const std::string&); std::optional handleBezier(const std::string&, const std::string&); std::optional handleAnimation(const std::string&, const std::string&); std::optional handleSource(const std::string&, const std::string&); std::optional handleSubmap(const std::string&, const std::string&); std::optional handleBlurLS(const std::string&, const std::string&); std::optional handleBindWS(const std::string&, const std::string&); std::optional handleEnv(const std::string&, const std::string&); std::optional handlePlugin(const std::string&, const std::string&); std::string configCurrentPath; std::unordered_map*(PHLWINDOW)>> mbWindowProperties = { {"allowsinput", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.allowsInput; }}, {"dimaround", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.dimAround; }}, {"decorate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.decorate; }}, {"focusonactivate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.focusOnActivate; }}, {"keepaspectratio", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.keepAspectRatio; }}, {"nearestneighbor", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.nearestNeighbor; }}, {"noanim", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noAnim; }}, {"noblur", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noBlur; }}, {"noborder", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noBorder; }}, {"nodim", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noDim; }}, {"nofocus", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noFocus; }}, {"nomaxsize", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noMaxSize; }}, {"norounding", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noRounding; }}, {"noshadow", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShadow; }}, {"noshortcutsinhibit", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShortcutsInhibit; }}, {"opaque", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.opaque; }}, {"forcergbx", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.RGBX; }}, {"syncfullscreen", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.syncFullscreen; }}, {"immediate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.tearing; }}, {"xray", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.xray; }}, }; std::unordered_map*(PHLWINDOW)>> miWindowProperties = { {"rounding", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.rounding; }}, {"bordersize", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.borderSize; }}}; bool m_bWantsMonitorReload = false; bool m_bForceReload = false; bool m_bNoMonitorReload = false; bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking private: std::unique_ptr m_pConfig; std::deque configPaths; // stores all the config paths std::unordered_map configModifyTimes; // stores modify times std::unordered_map animationConfig; // stores all the animations with their set values 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::vector pluginKeywords; std::vector pluginVariables; 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::deque finalExecRequests; std::vector> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins std::string m_szConfigErrors = ""; // internal methods void setAnimForChildren(SAnimationPropertyConfig* const); void updateBlurredLS(const std::string&, const bool); void setDefaultAnimationVars(); std::optional resetHLConfig(); static std::optional generateConfig(std::string configPath); static std::optional verifyConfigExists(); void postConfigReload(const Hyprlang::CParseResult& result); void reload(); SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&); }; inline std::unique_ptr g_pConfigManager;