2022-07-01 23:05:58 +02:00
|
|
|
#include "ConfigManager.hpp"
|
|
|
|
|
#include "../Hyprpaper.hpp"
|
|
|
|
|
|
|
|
|
|
CConfigManager::CConfigManager() {
|
2022-10-11 19:46:36 +02:00
|
|
|
// Initialize the configuration
|
|
|
|
|
// Read file from default location
|
|
|
|
|
// or from an explicit location given by user
|
2022-07-01 23:05:58 +02:00
|
|
|
|
2023-07-16 18:44:16 -04:00
|
|
|
std::string configPath = getMainConfigPath();
|
2022-07-01 23:05:58 +02:00
|
|
|
|
|
|
|
|
std::ifstream ifs;
|
2022-09-28 12:29:33 +09:00
|
|
|
ifs.open(configPath);
|
2022-07-01 23:05:58 +02:00
|
|
|
|
|
|
|
|
if (!ifs.good()) {
|
2023-12-14 19:56:04 +00:00
|
|
|
Debug::log(WARN, "Config file `%s` couldn't be opened. Running without a config!", configPath.c_str());
|
|
|
|
|
return;
|
2022-07-01 23:05:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string line = "";
|
|
|
|
|
int linenum = 1;
|
|
|
|
|
if (ifs.is_open()) {
|
|
|
|
|
while (std::getline(ifs, line)) {
|
2022-10-11 19:46:36 +02:00
|
|
|
// Read line by line
|
2022-10-12 15:24:29 +02:00
|
|
|
try {
|
|
|
|
|
parseLine(line);
|
|
|
|
|
} catch (...) {
|
|
|
|
|
Debug::log(ERR, "Error reading line from config. Line:");
|
|
|
|
|
Debug::log(NONE, "%s", line.c_str());
|
|
|
|
|
|
|
|
|
|
parseError += "Config error at line " + std::to_string(linenum) + ": Line parsing error.";
|
|
|
|
|
}
|
2022-07-01 23:05:58 +02:00
|
|
|
|
2022-10-11 19:46:36 +02:00
|
|
|
if (!parseError.empty()) {
|
2022-07-01 23:05:58 +02:00
|
|
|
parseError = "Config error at line " + std::to_string(linenum) + ": " + parseError;
|
2022-10-11 19:46:36 +02:00
|
|
|
break;
|
2022-07-01 23:05:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++linenum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ifs.close();
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-30 12:18:26 +02:00
|
|
|
if (!parseError.empty()) {
|
2023-12-14 19:56:04 +00:00
|
|
|
Debug::log(WARN, "Config parse error: \n%s\n\nRunning and ignoring errors...\n", parseError.c_str());
|
2022-07-01 23:05:58 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-16 18:44:16 -04:00
|
|
|
std::string CConfigManager::getMainConfigPath() {
|
|
|
|
|
if (!g_pHyprpaper->m_szExplicitConfigPath.empty())
|
|
|
|
|
return g_pHyprpaper->m_szExplicitConfigPath;
|
|
|
|
|
|
|
|
|
|
static const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
|
|
|
|
|
std::string configPath;
|
|
|
|
|
if (!xdgConfigHome)
|
|
|
|
|
configPath = getenv("HOME") + std::string("/.config");
|
|
|
|
|
else
|
|
|
|
|
configPath = xdgConfigHome;
|
|
|
|
|
|
|
|
|
|
return configPath + "/hypr/hyprpaper.conf";
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-01 23:05:58 +02:00
|
|
|
std::string CConfigManager::removeBeginEndSpacesTabs(std::string str) {
|
|
|
|
|
while (str[0] == ' ' || str[0] == '\t') {
|
|
|
|
|
str = str.substr(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (str.length() != 0 && (str[str.length() - 1] == ' ' || str[str.length() - 1] == '\t')) {
|
|
|
|
|
str = str.substr(0, str.length() - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CConfigManager::parseLine(std::string& line) {
|
2022-10-12 15:24:29 +02:00
|
|
|
// first check if its not a comment
|
2022-07-01 23:05:58 +02:00
|
|
|
const auto COMMENTSTART = line.find_first_of('#');
|
|
|
|
|
if (COMMENTSTART == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2022-10-12 15:24:29 +02:00
|
|
|
// now, cut the comment off
|
2022-07-01 23:05:58 +02:00
|
|
|
if (COMMENTSTART != std::string::npos)
|
|
|
|
|
line = line.substr(0, COMMENTSTART);
|
|
|
|
|
|
2022-10-11 19:46:36 +02:00
|
|
|
// Strip line
|
2022-07-01 23:05:58 +02:00
|
|
|
while (line[0] == ' ' || line[0] == '\t') {
|
|
|
|
|
line = line.substr(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// And parse
|
|
|
|
|
// check if command
|
|
|
|
|
const auto EQUALSPLACE = line.find_first_of('=');
|
|
|
|
|
|
|
|
|
|
if (EQUALSPLACE == std::string::npos)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const auto COMMAND = removeBeginEndSpacesTabs(line.substr(0, EQUALSPLACE));
|
|
|
|
|
const auto VALUE = removeBeginEndSpacesTabs(line.substr(EQUALSPLACE + 1));
|
|
|
|
|
|
|
|
|
|
parseKeyword(COMMAND, VALUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CConfigManager::parseKeyword(const std::string& COMMAND, const std::string& VALUE) {
|
|
|
|
|
if (COMMAND == "wallpaper")
|
|
|
|
|
handleWallpaper(COMMAND, VALUE);
|
|
|
|
|
else if (COMMAND == "preload")
|
|
|
|
|
handlePreload(COMMAND, VALUE);
|
2022-07-17 14:17:54 +02:00
|
|
|
else if (COMMAND == "unload")
|
|
|
|
|
handleUnload(COMMAND, VALUE);
|
2022-07-31 17:28:37 +02:00
|
|
|
else if (COMMAND == "ipc")
|
|
|
|
|
g_pHyprpaper->m_bIPCEnabled = VALUE == "1" || VALUE == "yes" || VALUE == "on" || VALUE == "true";
|
2023-04-09 18:47:49 +01:00
|
|
|
else if (COMMAND == "splash")
|
|
|
|
|
g_pHyprpaper->m_bRenderSplash = VALUE == "1" || VALUE == "yes" || VALUE == "on" || VALUE == "true";
|
2023-10-08 00:29:15 +00:00
|
|
|
else if (COMMAND == "splash_offset") {
|
|
|
|
|
try {
|
|
|
|
|
g_pHyprpaper->m_fSplashOffset = std::clamp(std::stof(VALUE), 0.f, 100.f);
|
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
|
parseError = "invalid splash_offset value " + VALUE;
|
|
|
|
|
}
|
|
|
|
|
} else
|
2022-07-01 23:05:58 +02:00
|
|
|
parseError = "unknown keyword " + COMMAND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CConfigManager::handleWallpaper(const std::string& COMMAND, const std::string& VALUE) {
|
|
|
|
|
if (VALUE.find_first_of(',') == std::string::npos) {
|
|
|
|
|
parseError = "wallpaper failed (syntax)";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto MONITOR = VALUE.substr(0, VALUE.find_first_of(','));
|
2023-01-03 15:09:20 +03:00
|
|
|
auto WALLPAPER = trimPath(VALUE.substr(VALUE.find_first_of(',') + 1));
|
2022-07-01 23:05:58 +02:00
|
|
|
|
2022-08-03 18:06:33 +02:00
|
|
|
bool contain = false;
|
|
|
|
|
|
|
|
|
|
if (WALLPAPER.find("contain:") == 0) {
|
|
|
|
|
WALLPAPER = WALLPAPER.substr(8);
|
|
|
|
|
contain = true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-01 15:40:50 -04:00
|
|
|
if (WALLPAPER[0] == '~') {
|
|
|
|
|
static const char* const ENVHOME = getenv("HOME");
|
|
|
|
|
WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-01 23:05:58 +02:00
|
|
|
if (!std::filesystem::exists(WALLPAPER)) {
|
|
|
|
|
parseError = "wallpaper failed (no such file)";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-02 18:26:59 +02:00
|
|
|
if (std::find(m_dRequestedPreloads.begin(), m_dRequestedPreloads.end(), WALLPAPER) == m_dRequestedPreloads.end() && !g_pHyprpaper->isPreloaded(WALLPAPER)) {
|
2022-07-01 23:05:58 +02:00
|
|
|
parseError = "wallpaper failed (not preloaded)";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-02 18:26:59 +02:00
|
|
|
g_pHyprpaper->clearWallpaperFromMonitor(MONITOR);
|
2022-07-01 23:05:58 +02:00
|
|
|
g_pHyprpaper->m_mMonitorActiveWallpapers[MONITOR] = WALLPAPER;
|
2022-08-03 18:06:33 +02:00
|
|
|
g_pHyprpaper->m_mMonitorWallpaperRenderData[MONITOR].contain = contain;
|
2022-07-01 23:05:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CConfigManager::handlePreload(const std::string& COMMAND, const std::string& VALUE) {
|
|
|
|
|
auto WALLPAPER = VALUE;
|
|
|
|
|
|
|
|
|
|
if (WALLPAPER[0] == '~') {
|
|
|
|
|
static const char* const ENVHOME = getenv("HOME");
|
|
|
|
|
WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!std::filesystem::exists(WALLPAPER)) {
|
|
|
|
|
parseError = "preload failed (no such file)";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_dRequestedPreloads.emplace_back(WALLPAPER);
|
|
|
|
|
}
|
2022-07-17 14:17:54 +02:00
|
|
|
|
|
|
|
|
void CConfigManager::handleUnload(const std::string& COMMAND, const std::string& VALUE) {
|
|
|
|
|
auto WALLPAPER = VALUE;
|
|
|
|
|
|
2022-11-27 12:02:09 +00:00
|
|
|
if (VALUE == "all") {
|
|
|
|
|
handleUnloadAll(COMMAND, VALUE);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-17 14:17:54 +02:00
|
|
|
if (WALLPAPER[0] == '~') {
|
|
|
|
|
static const char* const ENVHOME = getenv("HOME");
|
|
|
|
|
WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_pHyprpaper->unloadWallpaper(WALLPAPER);
|
|
|
|
|
}
|
2022-11-26 18:27:19 +00:00
|
|
|
|
|
|
|
|
void CConfigManager::handleUnloadAll(const std::string& COMMAND, const std::string& VALUE) {
|
2022-11-28 11:43:08 +00:00
|
|
|
std::vector<std::string> toUnload;
|
|
|
|
|
|
2023-07-16 18:44:16 -04:00
|
|
|
for (auto& [name, target] : g_pHyprpaper->m_mWallpaperTargets) {
|
2022-11-26 18:27:19 +00:00
|
|
|
|
|
|
|
|
bool exists = false;
|
2023-07-16 18:44:16 -04:00
|
|
|
for (auto& [mon, target2] : g_pHyprpaper->m_mMonitorActiveWallpaperTargets) {
|
2022-11-26 18:27:19 +00:00
|
|
|
if (&target == target2) {
|
|
|
|
|
exists = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (exists)
|
|
|
|
|
continue;
|
|
|
|
|
|
2022-11-28 11:43:08 +00:00
|
|
|
toUnload.emplace_back(name);
|
2022-11-26 18:27:19 +00:00
|
|
|
}
|
2022-11-28 11:43:08 +00:00
|
|
|
|
|
|
|
|
for (auto& tu : toUnload)
|
|
|
|
|
g_pHyprpaper->unloadWallpaper(tu);
|
2022-11-26 18:27:19 +00:00
|
|
|
}
|
2023-01-03 15:09:20 +03:00
|
|
|
|
|
|
|
|
// trim from both ends
|
|
|
|
|
std::string CConfigManager::trimPath(std::string path) {
|
2023-12-24 01:12:34 +08:00
|
|
|
if (path.empty())
|
|
|
|
|
return "";
|
|
|
|
|
|
2023-07-16 18:44:16 -04:00
|
|
|
// trims whitespaces, tabs and new line feeds
|
2023-01-03 15:09:20 +03:00
|
|
|
size_t pathStartIndex = path.find_first_not_of(" \t\r\n");
|
|
|
|
|
size_t pathEndIndex = path.find_last_not_of(" \t\r\n");
|
|
|
|
|
return path.substr(pathStartIndex, pathEndIndex - pathStartIndex + 1);
|
2023-01-05 00:50:01 +03:00
|
|
|
}
|