mirror of
https://github.com/hyprwm/hyprpaper.git
synced 2024-12-22 12:19:49 +01:00
internal: move to libhyprlang for config handling
This commit is contained in:
parent
ef0e051255
commit
39ad021c75
7 changed files with 150 additions and 211 deletions
|
@ -65,6 +65,7 @@ target_link_libraries(hyprpaper
|
|||
GLESv2
|
||||
pthread
|
||||
magic
|
||||
hyprlang
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${CMAKE_SOURCE_DIR}/wlr-layer-shell-unstable-v1-protocol.o
|
||||
${CMAKE_SOURCE_DIR}/xdg-shell-protocol.o
|
||||
|
|
|
@ -27,14 +27,21 @@ The development files of these packages need to be installed on the system for `
|
|||
- libglvnd-core
|
||||
- libjpeg-turbo
|
||||
- libwebp
|
||||
- hyprlang
|
||||
|
||||
Also `gcc-c++` and `ninja` needs to installed.
|
||||
Please note hyprpaper > 0.5.0 depends on [hyprlang](https://github.com/hyprwm/hyprlang) which is new
|
||||
and might not be packaged for your distro yet. If that's the case, build and install it from source.
|
||||
|
||||
To install all of these in Fedora, run this command:
|
||||
```
|
||||
sudo dnf install wayland-devel wayland-protocols-devel pango-devel cairo-devel file-devel libglvnd-devel libglvnd-core-devel libjpeg-turbo-devel libwebp-devel gcc-c++
|
||||
```
|
||||
|
||||
On Arch:
|
||||
```
|
||||
sudo pacman -S ninja gcc wayland-protocols libjpeg-turbo libwebp pango cairo pkgconf cmake libglvnd wayland
|
||||
```
|
||||
|
||||
On OpenSUSE:
|
||||
```
|
||||
sudo zypper install ninja gcc-c++ wayland-protocols-devel Mesa-libGLESv3-devel file-devel
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include "Hyprpaper.hpp"
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
CHyprpaper::CHyprpaper() = default;
|
||||
|
||||
|
@ -18,6 +18,8 @@ void CHyprpaper::init() {
|
|||
g_pConfigManager = std::make_unique<CConfigManager>();
|
||||
g_pIPCSocket = std::make_unique<CIPCSocket>();
|
||||
|
||||
g_pConfigManager->parse();
|
||||
|
||||
m_sDisplay = (wl_display*)wl_display_connect(nullptr);
|
||||
|
||||
if (!m_sDisplay) {
|
||||
|
@ -27,7 +29,7 @@ void CHyprpaper::init() {
|
|||
|
||||
preloadAllWallpapersFromConfig();
|
||||
|
||||
if (m_bIPCEnabled)
|
||||
if (std::any_cast<int64_t>(g_pConfigManager->config->getConfigValue("ipc")))
|
||||
g_pIPCSocket->initialize();
|
||||
|
||||
// run
|
||||
|
@ -129,7 +131,6 @@ void CHyprpaper::preloadAllWallpapersFromConfig() {
|
|||
} else {
|
||||
m_mWallpaperTargets[wp].create(wp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
g_pConfigManager->m_dRequestedPreloads.clear();
|
||||
|
@ -450,6 +451,8 @@ SPoolBuffer* CHyprpaper::getPoolBuffer(SMonitor* pMonitor, CWallpaperTarget* pWa
|
|||
}
|
||||
|
||||
void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) {
|
||||
static auto* const PRENDERSPLASH = reinterpret_cast<int64_t*>(g_pConfigManager->config->getConfigValuePtr("splash"));
|
||||
static auto* const PSPLASHOFFSET = reinterpret_cast<float*>(g_pConfigManager->config->getConfigValuePtr("splash_offset"));
|
||||
const auto PWALLPAPERTARGET = m_mMonitorActiveWallpaperTargets[pMonitor];
|
||||
const auto CONTAIN = m_mMonitorWallpaperRenderData[pMonitor->name].contain;
|
||||
|
||||
|
@ -508,7 +511,7 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) {
|
|||
|
||||
cairo_paint(PCAIRO);
|
||||
|
||||
if (g_pHyprpaper->m_bRenderSplash && getenv("HYPRLAND_INSTANCE_SIGNATURE")) {
|
||||
if (*PRENDERSPLASH && getenv("HYPRLAND_INSTANCE_SIGNATURE")) {
|
||||
auto SPLASH = execAndGet("hyprctl splash");
|
||||
SPLASH.pop_back();
|
||||
|
||||
|
@ -524,9 +527,9 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) {
|
|||
cairo_text_extents_t textExtents;
|
||||
cairo_text_extents(PCAIRO, SPLASH.c_str(), &textExtents);
|
||||
|
||||
cairo_move_to(PCAIRO, ((DIMENSIONS.x - textExtents.width * scale) / 2.0) / scale, ((DIMENSIONS.y * (100 - m_fSplashOffset)) / 100 - textExtents.height * scale) / scale);
|
||||
cairo_move_to(PCAIRO, ((DIMENSIONS.x - textExtents.width * scale) / 2.0) / scale, ((DIMENSIONS.y * (100 - *PSPLASHOFFSET)) / 100 - textExtents.height * scale) / scale);
|
||||
|
||||
Debug::log(LOG, "Splash font size: %d, pos: %.2f, %.2f", FONTSIZE, (DIMENSIONS.x - textExtents.width) / 2.0 / scale, ((DIMENSIONS.y * (100 - m_fSplashOffset)) / 100 - textExtents.height * scale) / scale);
|
||||
Debug::log(LOG, "Splash font size: %d, pos: %.2f, %.2f", FONTSIZE, (DIMENSIONS.x - textExtents.width) / 2.0 / scale, ((DIMENSIONS.y * (100 - *PSPLASHOFFSET)) / 100 - textExtents.height * scale) / scale);
|
||||
|
||||
cairo_show_text(PCAIRO, SPLASH.c_str());
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "defines.hpp"
|
||||
#include "config/ConfigManager.hpp"
|
||||
#include "render/WallpaperTarget.hpp"
|
||||
#include "helpers/Monitor.hpp"
|
||||
#include "defines.hpp"
|
||||
#include "events/Events.hpp"
|
||||
#include "helpers/PoolBuffer.hpp"
|
||||
#include "helpers/MiscFunctions.hpp"
|
||||
#include "helpers/Monitor.hpp"
|
||||
#include "helpers/PoolBuffer.hpp"
|
||||
#include "ipc/Socket.hpp"
|
||||
#include "render/WallpaperTarget.hpp"
|
||||
#include <mutex>
|
||||
|
||||
struct SWallpaperRenderData {
|
||||
|
@ -36,9 +36,6 @@ public:
|
|||
std::vector<std::unique_ptr<SPoolBuffer>> m_vBuffers;
|
||||
std::vector<std::unique_ptr<SMonitor>> m_vMonitors;
|
||||
|
||||
bool m_bIPCEnabled = true;
|
||||
bool m_bRenderSplash = false;
|
||||
float m_fSplashOffset = 2;
|
||||
std::string m_szExplicitConfigPath;
|
||||
bool m_bNoFractionalScale = false;
|
||||
|
||||
|
@ -66,8 +63,8 @@ public:
|
|||
std::mutex m_mtTickMutex;
|
||||
|
||||
SMonitor* m_pLastMonitor = nullptr;
|
||||
private:
|
||||
|
||||
private:
|
||||
bool m_bShouldExit = false;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,135 +1,18 @@
|
|||
#include "ConfigManager.hpp"
|
||||
#include "../Hyprpaper.hpp"
|
||||
|
||||
CConfigManager::CConfigManager() {
|
||||
// Initialize the configuration
|
||||
// Read file from default location
|
||||
// or from an explicit location given by user
|
||||
static Hyprlang::CParseResult handleWallpaper(const char* C, const char* V) {
|
||||
const std::string COMMAND = C;
|
||||
const std::string VALUE = V;
|
||||
Hyprlang::CParseResult result;
|
||||
|
||||
std::string configPath = getMainConfigPath();
|
||||
|
||||
std::ifstream ifs;
|
||||
ifs.open(configPath);
|
||||
|
||||
if (!ifs.good()) {
|
||||
Debug::log(WARN, "Config file `%s` couldn't be opened. Running without a config!", configPath.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::string line = "";
|
||||
int linenum = 1;
|
||||
if (ifs.is_open()) {
|
||||
while (std::getline(ifs, line)) {
|
||||
// Read line by line
|
||||
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.";
|
||||
}
|
||||
|
||||
if (!parseError.empty()) {
|
||||
parseError = "Config error at line " + std::to_string(linenum) + ": " + parseError;
|
||||
break;
|
||||
}
|
||||
|
||||
++linenum;
|
||||
}
|
||||
|
||||
ifs.close();
|
||||
}
|
||||
|
||||
if (!parseError.empty()) {
|
||||
Debug::log(WARN, "Config parse error: \n%s\n\nRunning and ignoring errors...\n", parseError.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
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) {
|
||||
// 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(0, COMMENTSTART);
|
||||
|
||||
// Strip line
|
||||
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);
|
||||
else if (COMMAND == "unload")
|
||||
handleUnload(COMMAND, VALUE);
|
||||
else if (COMMAND == "ipc")
|
||||
g_pHyprpaper->m_bIPCEnabled = VALUE == "1" || VALUE == "yes" || VALUE == "on" || VALUE == "true";
|
||||
else if (COMMAND == "splash")
|
||||
g_pHyprpaper->m_bRenderSplash = VALUE == "1" || VALUE == "yes" || VALUE == "on" || VALUE == "true";
|
||||
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
|
||||
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;
|
||||
result.setError("wallpaper failed (syntax)");
|
||||
return result;
|
||||
}
|
||||
|
||||
auto MONITOR = VALUE.substr(0, VALUE.find_first_of(','));
|
||||
auto WALLPAPER = trimPath(VALUE.substr(VALUE.find_first_of(',') + 1));
|
||||
auto WALLPAPER = g_pConfigManager->trimPath(VALUE.substr(VALUE.find_first_of(',') + 1));
|
||||
|
||||
bool contain = false;
|
||||
|
||||
|
@ -144,21 +27,25 @@ void CConfigManager::handleWallpaper(const std::string& COMMAND, const std::stri
|
|||
}
|
||||
|
||||
if (!std::filesystem::exists(WALLPAPER)) {
|
||||
parseError = "wallpaper failed (no such file)";
|
||||
return;
|
||||
result.setError("wallpaper failed (no such file)");
|
||||
return result;
|
||||
}
|
||||
|
||||
if (std::find(m_dRequestedPreloads.begin(), m_dRequestedPreloads.end(), WALLPAPER) == m_dRequestedPreloads.end() && !g_pHyprpaper->isPreloaded(WALLPAPER)) {
|
||||
parseError = "wallpaper failed (not preloaded)";
|
||||
return;
|
||||
if (std::find(g_pConfigManager->m_dRequestedPreloads.begin(), g_pConfigManager->m_dRequestedPreloads.end(), WALLPAPER) == g_pConfigManager->m_dRequestedPreloads.end() && !g_pHyprpaper->isPreloaded(WALLPAPER)) {
|
||||
result.setError("wallpaper failed (not preloaded)");
|
||||
return result;
|
||||
}
|
||||
|
||||
g_pHyprpaper->clearWallpaperFromMonitor(MONITOR);
|
||||
g_pHyprpaper->m_mMonitorActiveWallpapers[MONITOR] = WALLPAPER;
|
||||
g_pHyprpaper->m_mMonitorWallpaperRenderData[MONITOR].contain = contain;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CConfigManager::handlePreload(const std::string& COMMAND, const std::string& VALUE) {
|
||||
static Hyprlang::CParseResult handlePreload(const char* C, const char* V) {
|
||||
const std::string COMMAND = C;
|
||||
const std::string VALUE = V;
|
||||
auto WALLPAPER = VALUE;
|
||||
|
||||
if (WALLPAPER[0] == '~') {
|
||||
|
@ -167,30 +54,19 @@ void CConfigManager::handlePreload(const std::string& COMMAND, const std::string
|
|||
}
|
||||
|
||||
if (!std::filesystem::exists(WALLPAPER)) {
|
||||
parseError = "preload failed (no such file)";
|
||||
return;
|
||||
Hyprlang::CParseResult result;
|
||||
result.setError((std::string{"no such file: "} + WALLPAPER).c_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
m_dRequestedPreloads.emplace_back(WALLPAPER);
|
||||
g_pConfigManager->m_dRequestedPreloads.emplace_back(WALLPAPER);
|
||||
|
||||
return Hyprlang::CParseResult{};
|
||||
}
|
||||
|
||||
void CConfigManager::handleUnload(const std::string& COMMAND, const std::string& VALUE) {
|
||||
auto WALLPAPER = VALUE;
|
||||
|
||||
if (VALUE == "all") {
|
||||
handleUnloadAll(COMMAND, VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (WALLPAPER[0] == '~') {
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1);
|
||||
}
|
||||
|
||||
g_pHyprpaper->unloadWallpaper(WALLPAPER);
|
||||
}
|
||||
|
||||
void CConfigManager::handleUnloadAll(const std::string& COMMAND, const std::string& VALUE) {
|
||||
static Hyprlang::CParseResult handleUnloadAll(const char* C, const char* V) {
|
||||
const std::string COMMAND = C;
|
||||
const std::string VALUE = V;
|
||||
std::vector<std::string> toUnload;
|
||||
|
||||
for (auto& [name, target] : g_pHyprpaper->m_mWallpaperTargets) {
|
||||
|
@ -211,6 +87,69 @@ void CConfigManager::handleUnloadAll(const std::string& COMMAND, const std::stri
|
|||
|
||||
for (auto& tu : toUnload)
|
||||
g_pHyprpaper->unloadWallpaper(tu);
|
||||
|
||||
return Hyprlang::CParseResult{};
|
||||
}
|
||||
|
||||
static Hyprlang::CParseResult handleUnload(const char* C, const char* V) {
|
||||
const std::string COMMAND = C;
|
||||
const std::string VALUE = V;
|
||||
auto WALLPAPER = VALUE;
|
||||
|
||||
if (VALUE == "all")
|
||||
return handleUnloadAll(C, V);
|
||||
|
||||
if (WALLPAPER[0] == '~') {
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
WALLPAPER = std::string(ENVHOME) + WALLPAPER.substr(1);
|
||||
}
|
||||
|
||||
g_pHyprpaper->unloadWallpaper(WALLPAPER);
|
||||
|
||||
return Hyprlang::CParseResult{};
|
||||
}
|
||||
|
||||
CConfigManager::CConfigManager() {
|
||||
// Initialize the configuration
|
||||
// Read file from default location
|
||||
// or from an explicit location given by user
|
||||
|
||||
std::string configPath = getMainConfigPath();
|
||||
|
||||
config = std::make_unique<Hyprlang::CConfig>(configPath.c_str(), Hyprlang::SConfigOptions{});
|
||||
|
||||
config->addConfigValue("ipc", {1L});
|
||||
config->addConfigValue("splash", {1L});
|
||||
config->addConfigValue("splash_offset", {2.F});
|
||||
|
||||
config->registerHandler(&handleWallpaper, "wallpaper", {.allowFlags = false});
|
||||
config->registerHandler(&handleUnload, "unload", {.allowFlags = false});
|
||||
config->registerHandler(&handlePreload, "preload", {.allowFlags = false});
|
||||
config->registerHandler(&handleUnloadAll, "unloadAll", {.allowFlags = false});
|
||||
|
||||
config->commence();
|
||||
}
|
||||
|
||||
void CConfigManager::parse() {
|
||||
const auto ERROR = config->parse();
|
||||
|
||||
if (ERROR.error)
|
||||
std::cout << "Error in config: \n"
|
||||
<< ERROR.getError() << "\n";
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
// trim from both ends
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "../defines.hpp"
|
||||
#include <hyprlang.hpp>
|
||||
|
||||
class CIPCSocket;
|
||||
|
||||
|
@ -7,23 +8,15 @@ class CConfigManager {
|
|||
public:
|
||||
// gets all the data from the config
|
||||
CConfigManager();
|
||||
void parse();
|
||||
|
||||
std::deque<std::string> m_dRequestedPreloads;
|
||||
std::string getMainConfigPath();
|
||||
|
||||
private:
|
||||
std::string parseError;
|
||||
|
||||
void parseLine(std::string&);
|
||||
std::string removeBeginEndSpacesTabs(std::string in);
|
||||
void parseKeyword(const std::string&, const std::string&);
|
||||
|
||||
void handleWallpaper(const std::string&, const std::string&);
|
||||
void handlePreload(const std::string&, const std::string&);
|
||||
void handleUnload(const std::string&, const std::string&);
|
||||
void handleUnloadAll(const std::string&, const std::string&);
|
||||
std::string trimPath(std::string path);
|
||||
|
||||
std::unique_ptr<Hyprlang::CConfig> config;
|
||||
|
||||
private:
|
||||
friend class CIPCSocket;
|
||||
};
|
||||
|
||||
|
|
|
@ -99,12 +99,11 @@ bool CIPCSocket::mainThreadParseRequest() {
|
|||
|
||||
// parse
|
||||
if (copy.find("wallpaper") == 0 || copy.find("preload") == 0 || copy.find("unload") == 0) {
|
||||
g_pConfigManager->parseError = ""; // reset parse error
|
||||
|
||||
g_pConfigManager->parseKeyword(copy.substr(0, copy.find_first_of(' ')), copy.substr(copy.find_first_of(' ') + 1));
|
||||
const auto RESULT = g_pConfigManager->config->parseDynamic(copy.substr(0, copy.find_first_of(' ')).c_str(), copy.substr(copy.find_first_of(' ') + 1).c_str());
|
||||
|
||||
if (!g_pConfigManager->parseError.empty()) {
|
||||
m_szReply = g_pConfigManager->parseError;
|
||||
if (RESULT.error) {
|
||||
m_szReply = RESULT.getError();
|
||||
m_bReplyReady = true;
|
||||
m_bRequestReady = false;
|
||||
return false;
|
||||
|
|
Loading…
Reference in a new issue