mirror of
https://github.com/hyprwm/hyprcursor.git
synced 2024-12-22 18:29:48 +01:00
lib: add user-defined logging
This commit is contained in:
parent
f870f0f980
commit
22a4195557
9 changed files with 170 additions and 78 deletions
|
@ -43,6 +43,11 @@ struct hyprcursor_cursor_style_info {
|
||||||
*/
|
*/
|
||||||
CAPI struct hyprcursor_manager_t* hyprcursor_manager_create(const char* theme_name);
|
CAPI struct hyprcursor_manager_t* hyprcursor_manager_create(const char* theme_name);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Same as hyprcursor_manager_create, but with a logger.
|
||||||
|
*/
|
||||||
|
CAPI struct hyprcursor_manager_t* hyprcursor_manager_create_with_logger(const char* theme_name, PHYPRCURSORLOGFUNC fn);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Free a hyprcursor_manager_t*
|
Free a hyprcursor_manager_t*
|
||||||
*/
|
*/
|
||||||
|
@ -71,7 +76,8 @@ CAPI int hyprcursor_load_theme_style(struct hyprcursor_manager_t* manager, struc
|
||||||
|
|
||||||
Once done with a size, call hyprcursor_style_done()
|
Once done with a size, call hyprcursor_style_done()
|
||||||
*/
|
*/
|
||||||
CAPI hyprcursor_cursor_image_data** hyprcursor_get_cursor_image_data(struct hyprcursor_manager_t* manager, const char* shape, struct hyprcursor_cursor_style_info info, int* out_size);
|
CAPI hyprcursor_cursor_image_data** hyprcursor_get_cursor_image_data(struct hyprcursor_manager_t* manager, const char* shape, struct hyprcursor_cursor_style_info info,
|
||||||
|
int* out_size);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Free a returned hyprcursor_cursor_image_data.
|
Free a returned hyprcursor_cursor_image_data.
|
||||||
|
@ -83,4 +89,15 @@ CAPI void hyprcursor_cursor_image_data_free(hyprcursor_cursor_image_data** data,
|
||||||
*/
|
*/
|
||||||
CAPI void hyprcursor_style_done(struct hyprcursor_manager_t* manager, struct hyprcursor_cursor_style_info info);
|
CAPI void hyprcursor_style_done(struct hyprcursor_manager_t* manager, struct hyprcursor_cursor_style_info info);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 0.1.5
|
||||||
|
|
||||||
|
Registers a logging function to a hyprcursor_manager_t*
|
||||||
|
|
||||||
|
PHYPRCURSORLOGFUNC's msg is owned by the caller and will be freed afterwards.
|
||||||
|
|
||||||
|
fn can be null to remove a logger.
|
||||||
|
*/
|
||||||
|
CAPI void hyprcursor_register_logging_function(struct hyprcursor_manager_t* manager, PHYPRCURSORLOGFUNC fn);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -43,6 +43,10 @@ namespace Hyprcursor {
|
||||||
class CHyprcursorManager {
|
class CHyprcursorManager {
|
||||||
public:
|
public:
|
||||||
CHyprcursorManager(const char* themeName);
|
CHyprcursorManager(const char* themeName);
|
||||||
|
/*!
|
||||||
|
\since 0.1.5
|
||||||
|
*/
|
||||||
|
CHyprcursorManager(const char* themeName, PHYPRCURSORLOGFUNC fn);
|
||||||
~CHyprcursorManager();
|
~CHyprcursorManager();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -99,9 +103,23 @@ namespace Hyprcursor {
|
||||||
*/
|
*/
|
||||||
void cursorSurfaceStyleDone(const SCursorStyleInfo&);
|
void cursorSurfaceStyleDone(const SCursorStyleInfo&);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\since 0.1.5
|
||||||
|
|
||||||
|
Registers a logging function to this manager.
|
||||||
|
PHYPRCURSORLOGFUNC's msg is owned by the caller and will be freed afterwards.
|
||||||
|
fn can be null to unregister a logger.
|
||||||
|
*/
|
||||||
|
void registerLoggingFunction(PHYPRCURSORLOGFUNC fn);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void init(const char* themeName_);
|
||||||
|
|
||||||
CHyprcursorImplementation* impl = nullptr;
|
CHyprcursorImplementation* impl = nullptr;
|
||||||
bool finalizedAndValid = false;
|
bool finalizedAndValid = false;
|
||||||
|
PHYPRCURSORLOGFUNC logFn = nullptr;
|
||||||
|
|
||||||
|
friend class CHyprcursorImplementation;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -16,4 +16,18 @@ struct SCursorImageData {
|
||||||
|
|
||||||
typedef struct SCursorImageData hyprcursor_cursor_image_data;
|
typedef struct SCursorImageData hyprcursor_cursor_image_data;
|
||||||
|
|
||||||
|
enum eHyprcursorLogLevel {
|
||||||
|
HC_LOG_NONE = 0,
|
||||||
|
HC_LOG_TRACE,
|
||||||
|
HC_LOG_INFO,
|
||||||
|
HC_LOG_WARN,
|
||||||
|
HC_LOG_ERR,
|
||||||
|
HC_LOG_CRITICAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
msg is owned by the caller and will be freed afterwards.
|
||||||
|
*/
|
||||||
|
typedef void (*PHYPRCURSORLOGFUNC)(enum eHyprcursorLogLevel level, char* msg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,53 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum eLogLevel {
|
|
||||||
TRACE = 0,
|
|
||||||
INFO,
|
|
||||||
LOG,
|
|
||||||
WARN,
|
|
||||||
ERR,
|
|
||||||
CRIT,
|
|
||||||
NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <hyprcursor/shared.h>
|
||||||
|
|
||||||
namespace Debug {
|
namespace Debug {
|
||||||
inline bool quiet = false;
|
inline bool quiet = false;
|
||||||
inline bool verbose = false;
|
inline bool verbose = false;
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void log(eLogLevel level, const std::string& fmt, Args&&... args) {
|
void log(eHyprcursorLogLevel level, PHYPRCURSORLOGFUNC fn, const std::string& fmt, Args&&... args) {
|
||||||
|
if (!fn)
|
||||||
#ifndef HYPRLAND_DEBUG
|
|
||||||
// don't log in release
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!verbose && level == TRACE)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (quiet)
|
const std::string LOG = std::vformat(fmt, std::make_format_args(args...));
|
||||||
return;
|
|
||||||
|
|
||||||
if (level != NONE) {
|
fn(level, (char*)LOG.c_str());
|
||||||
std::cout << '[';
|
|
||||||
|
|
||||||
switch (level) {
|
|
||||||
case TRACE: std::cout << "TRACE"; break;
|
|
||||||
case INFO: std::cout << "INFO"; break;
|
|
||||||
case LOG: std::cout << "LOG"; break;
|
|
||||||
case WARN: std::cout << "WARN"; break;
|
|
||||||
case ERR: std::cout << "ERR"; break;
|
|
||||||
case CRIT: std::cout << "CRITICAL"; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "] ";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << std::vformat(fmt, std::make_format_args(args...)) << "\n";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
|
@ -18,10 +18,12 @@ constexpr const std::array<const char*, 1> systemThemeDirs = {"/usr/share/icons"
|
||||||
constexpr const std::array<const char*, 2> userThemeDirs = {"/.local/share/icons", "/.icons"};
|
constexpr const std::array<const char*, 2> userThemeDirs = {"/.local/share/icons", "/.icons"};
|
||||||
|
|
||||||
//
|
//
|
||||||
static std::string themeNameFromEnv() {
|
static std::string themeNameFromEnv(PHYPRCURSORLOGFUNC logfn) {
|
||||||
const auto ENV = getenv("HYPRCURSOR_THEME");
|
const auto ENV = getenv("HYPRCURSOR_THEME");
|
||||||
if (!ENV)
|
if (!ENV) {
|
||||||
|
Debug::log(HC_LOG_INFO, logfn, "themeNameFromEnv: env unset");
|
||||||
return "";
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
return std::string{ENV};
|
return std::string{ENV};
|
||||||
}
|
}
|
||||||
|
@ -36,7 +38,7 @@ static bool themeAccessible(const std::string& path) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getFirstTheme() {
|
static std::string getFirstTheme(PHYPRCURSORLOGFUNC logfn) {
|
||||||
// try user directories first
|
// try user directories first
|
||||||
|
|
||||||
const auto HOMEENV = getenv("HOME");
|
const auto HOMEENV = getenv("HOME");
|
||||||
|
@ -57,10 +59,12 @@ static std::string getFirstTheme() {
|
||||||
|
|
||||||
const auto MANIFESTPATH = themeDir.path().string() + "/manifest.hl";
|
const auto MANIFESTPATH = themeDir.path().string() + "/manifest.hl";
|
||||||
|
|
||||||
if (std::filesystem::exists(MANIFESTPATH))
|
if (std::filesystem::exists(MANIFESTPATH)) {
|
||||||
|
Debug::log(HC_LOG_INFO, logfn, "getFirstTheme: found {}", themeDir.path().string());
|
||||||
return themeDir.path().stem().string();
|
return themeDir.path().stem().string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& dir : systemThemeDirs) {
|
for (auto& dir : systemThemeDirs) {
|
||||||
const auto FULLPATH = dir;
|
const auto FULLPATH = dir;
|
||||||
|
@ -74,15 +78,17 @@ static std::string getFirstTheme() {
|
||||||
|
|
||||||
const auto MANIFESTPATH = themeDir.path().string() + "/manifest.hl";
|
const auto MANIFESTPATH = themeDir.path().string() + "/manifest.hl";
|
||||||
|
|
||||||
if (std::filesystem::exists(MANIFESTPATH))
|
if (std::filesystem::exists(MANIFESTPATH)) {
|
||||||
|
Debug::log(HC_LOG_INFO, logfn, "getFirstTheme: found {}", themeDir.path().string());
|
||||||
return themeDir.path().stem().string();
|
return themeDir.path().stem().string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getFullPathForThemeName(const std::string& name) {
|
static std::string getFullPathForThemeName(const std::string& name, PHYPRCURSORLOGFUNC logfn) {
|
||||||
const auto HOMEENV = getenv("HOME");
|
const auto HOMEENV = getenv("HOME");
|
||||||
if (!HOMEENV)
|
if (!HOMEENV)
|
||||||
return "";
|
return "";
|
||||||
|
@ -102,8 +108,10 @@ static std::string getFullPathForThemeName(const std::string& name) {
|
||||||
const auto MANIFESTPATH = themeDir.path().string() + "/manifest.hl";
|
const auto MANIFESTPATH = themeDir.path().string() + "/manifest.hl";
|
||||||
|
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
if (std::filesystem::exists(MANIFESTPATH))
|
if (std::filesystem::exists(MANIFESTPATH)) {
|
||||||
|
Debug::log(HC_LOG_INFO, logfn, "getFullPathForThemeName: found {}", themeDir.path().string());
|
||||||
return std::filesystem::canonical(themeDir.path()).string();
|
return std::filesystem::canonical(themeDir.path()).string();
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,6 +131,7 @@ static std::string getFullPathForThemeName(const std::string& name) {
|
||||||
if (NAME != name)
|
if (NAME != name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
Debug::log(HC_LOG_INFO, logfn, "getFullPathForThemeName: found {}", themeDir.path().string());
|
||||||
return std::filesystem::canonical(themeDir.path()).string();
|
return std::filesystem::canonical(themeDir.path()).string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,49 +154,65 @@ static std::string getFullPathForThemeName(const std::string& name) {
|
||||||
|
|
||||||
const auto MANIFESTPATH = themeDir.path().string() + "/manifest.hl";
|
const auto MANIFESTPATH = themeDir.path().string() + "/manifest.hl";
|
||||||
|
|
||||||
if (std::filesystem::exists(MANIFESTPATH))
|
if (std::filesystem::exists(MANIFESTPATH)) {
|
||||||
|
Debug::log(HC_LOG_INFO, logfn, "getFullPathForThemeName: found {}", themeDir.path().string());
|
||||||
return std::filesystem::canonical(themeDir.path()).string();
|
return std::filesystem::canonical(themeDir.path()).string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!name.empty()) // try without name
|
if (!name.empty()) { // try without name
|
||||||
return getFullPathForThemeName("");
|
Debug::log(HC_LOG_INFO, logfn, "getFullPathForThemeName: failed, trying without name of {}", name);
|
||||||
|
return getFullPathForThemeName("", logfn);
|
||||||
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
CHyprcursorManager::CHyprcursorManager(const char* themeName_) {
|
CHyprcursorManager::CHyprcursorManager(const char* themeName_) {
|
||||||
|
init(themeName_);
|
||||||
|
}
|
||||||
|
|
||||||
|
CHyprcursorManager::CHyprcursorManager(const char* themeName_, PHYPRCURSORLOGFUNC fn) {
|
||||||
|
logFn = fn;
|
||||||
|
init(themeName_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CHyprcursorManager::init(const char* themeName_) {
|
||||||
std::string themeName = themeName_ ? themeName_ : "";
|
std::string themeName = themeName_ ? themeName_ : "";
|
||||||
|
|
||||||
if (themeName.empty()) {
|
if (themeName.empty()) {
|
||||||
// try reading from env
|
// try reading from env
|
||||||
themeName = themeNameFromEnv();
|
Debug::log(HC_LOG_INFO, logFn, "CHyprcursorManager: attempting to find theme from env");
|
||||||
|
themeName = themeNameFromEnv(logFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (themeName.empty()) {
|
if (themeName.empty()) {
|
||||||
// try finding first, in the hierarchy
|
// try finding first, in the hierarchy
|
||||||
themeName = getFirstTheme();
|
Debug::log(HC_LOG_INFO, logFn, "CHyprcursorManager: attempting to find any theme");
|
||||||
|
themeName = getFirstTheme(logFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (themeName.empty()) {
|
if (themeName.empty()) {
|
||||||
// holy shit we're done
|
// holy shit we're done
|
||||||
|
Debug::log(HC_LOG_INFO, logFn, "CHyprcursorManager: no themes matched");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize theme
|
// initialize theme
|
||||||
impl = new CHyprcursorImplementation;
|
impl = new CHyprcursorImplementation(this, logFn);
|
||||||
impl->themeName = themeName;
|
impl->themeName = themeName;
|
||||||
impl->themeFullDir = getFullPathForThemeName(themeName);
|
impl->themeFullDir = getFullPathForThemeName(themeName, logFn);
|
||||||
|
|
||||||
if (impl->themeFullDir.empty())
|
if (impl->themeFullDir.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug::log(LOG, "Found theme {} at {}\n", impl->themeName, impl->themeFullDir);
|
Debug::log(HC_LOG_INFO, logFn, "Found theme {} at {}\n", impl->themeName, impl->themeFullDir);
|
||||||
|
|
||||||
const auto LOADSTATUS = impl->loadTheme();
|
const auto LOADSTATUS = impl->loadTheme();
|
||||||
|
|
||||||
if (LOADSTATUS.has_value()) {
|
if (LOADSTATUS.has_value()) {
|
||||||
Debug::log(ERR, "Theme failed to load with {}\n", LOADSTATUS.value());
|
Debug::log(HC_LOG_ERR, logFn, "Theme failed to load with {}\n", LOADSTATUS.value());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +229,11 @@ bool CHyprcursorManager::valid() {
|
||||||
}
|
}
|
||||||
|
|
||||||
SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shape_, const SCursorStyleInfo& info) {
|
SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shape_, const SCursorStyleInfo& info) {
|
||||||
|
if (!shape_) {
|
||||||
|
Debug::log(HC_LOG_ERR, logFn, "getShapesC: shape of nullptr is invalid");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
std::string REQUESTEDSHAPE = shape_;
|
std::string REQUESTEDSHAPE = shape_;
|
||||||
|
|
||||||
std::vector<SLoadedCursorImage*> resultingImages;
|
std::vector<SLoadedCursorImage*> resultingImages;
|
||||||
|
@ -232,7 +262,7 @@ SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shap
|
||||||
|
|
||||||
// if we get here, means loadThemeStyle wasn't called most likely. If resize algo is specified, this is an error.
|
// if we get here, means loadThemeStyle wasn't called most likely. If resize algo is specified, this is an error.
|
||||||
if (shape->resizeAlgo != RESIZE_NONE) {
|
if (shape->resizeAlgo != RESIZE_NONE) {
|
||||||
Debug::log(ERR, "getSurfaceFor didn't match a size?");
|
Debug::log(HC_LOG_ERR, logFn, "getSurfaceFor didn't match a size?");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +276,7 @@ SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shap
|
||||||
}
|
}
|
||||||
|
|
||||||
if (leader == 13371337) { // ???
|
if (leader == 13371337) { // ???
|
||||||
Debug::log(ERR, "getSurfaceFor didn't match any nearest size?");
|
Debug::log(HC_LOG_ERR, logFn, "getSurfaceFor didn't match any nearest size?");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +293,7 @@ SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shap
|
||||||
if (foundAny)
|
if (foundAny)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Debug::log(ERR, "getSurfaceFor didn't match any nearest size (2)?");
|
Debug::log(HC_LOG_ERR, logFn, "getSurfaceFor didn't match any nearest size (2)?");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,13 +310,20 @@ SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shap
|
||||||
|
|
||||||
outSize = resultingImages.size();
|
outSize = resultingImages.size();
|
||||||
|
|
||||||
|
Debug::log(HC_LOG_INFO, logFn, "getShapesC: found {} images for {}", outSize, shape_);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
|
bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
|
||||||
|
Debug::log(HC_LOG_INFO, logFn, "loadThemeStyle: loading for size {}", info.size);
|
||||||
|
|
||||||
for (auto& shape : impl->theme.shapes) {
|
for (auto& shape : impl->theme.shapes) {
|
||||||
if (shape->resizeAlgo == RESIZE_NONE && shape->shapeType != SHAPE_SVG)
|
if (shape->resizeAlgo == RESIZE_NONE && shape->shapeType != SHAPE_SVG) {
|
||||||
continue; // don't resample NONE style cursors
|
// don't resample NONE style cursors
|
||||||
|
Debug::log(HC_LOG_TRACE, logFn, "loadThemeStyle: ignoring {}", shape->directory);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
bool sizeFound = false;
|
bool sizeFound = false;
|
||||||
|
|
||||||
|
@ -327,12 +364,14 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!leader) {
|
if (!leader) {
|
||||||
Debug::log(ERR, "Resampling failed to find a candidate???");
|
Debug::log(HC_LOG_ERR, logFn, "Resampling failed to find a candidate???");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto FRAMES = impl->getFramesFor(shape.get(), leader->side);
|
const auto FRAMES = impl->getFramesFor(shape.get(), leader->side);
|
||||||
|
|
||||||
|
Debug::log(HC_LOG_TRACE, logFn, "loadThemeStyle: png shape {} has {} frames", shape->directory, FRAMES.size());
|
||||||
|
|
||||||
for (auto& f : FRAMES) {
|
for (auto& f : FRAMES) {
|
||||||
auto& newImage = impl->loadedShapes[shape.get()].images.emplace_back(std::make_unique<SLoadedCursorImage>());
|
auto& newImage = impl->loadedShapes[shape.get()].images.emplace_back(std::make_unique<SLoadedCursorImage>());
|
||||||
newImage->artificial = true;
|
newImage->artificial = true;
|
||||||
|
@ -368,6 +407,8 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
|
||||||
} else if (shape->shapeType == SHAPE_SVG) {
|
} else if (shape->shapeType == SHAPE_SVG) {
|
||||||
const auto FRAMES = impl->getFramesFor(shape.get(), 0);
|
const auto FRAMES = impl->getFramesFor(shape.get(), 0);
|
||||||
|
|
||||||
|
Debug::log(HC_LOG_TRACE, logFn, "loadThemeStyle: svg shape {} has {} frames", shape->directory, FRAMES.size());
|
||||||
|
|
||||||
for (auto& f : FRAMES) {
|
for (auto& f : FRAMES) {
|
||||||
auto& newImage = impl->loadedShapes[shape.get()].images.emplace_back(std::make_unique<SLoadedCursorImage>());
|
auto& newImage = impl->loadedShapes[shape.get()].images.emplace_back(std::make_unique<SLoadedCursorImage>());
|
||||||
newImage->artificial = true;
|
newImage->artificial = true;
|
||||||
|
@ -387,14 +428,14 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
|
||||||
RsvgHandle* handle = rsvg_handle_new_from_data((unsigned char*)f->data, f->dataLen, &error);
|
RsvgHandle* handle = rsvg_handle_new_from_data((unsigned char*)f->data, f->dataLen, &error);
|
||||||
|
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
Debug::log(ERR, "Failed reading svg: {}", error->message);
|
Debug::log(HC_LOG_ERR, logFn, "Failed reading svg: {}", error->message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RsvgRectangle rect = {0, 0, (double)info.size, (double)info.size};
|
RsvgRectangle rect = {0, 0, (double)info.size, (double)info.size};
|
||||||
|
|
||||||
if (!rsvg_handle_render_document(handle, PCAIRO, &rect, &error)) {
|
if (!rsvg_handle_render_document(handle, PCAIRO, &rect, &error)) {
|
||||||
Debug::log(ERR, "Failed rendering svg: {}", error->message);
|
Debug::log(HC_LOG_ERR, logFn, "Failed rendering svg: {}", error->message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +444,7 @@ bool CHyprcursorManager::loadThemeStyle(const SCursorStyleInfo& info) {
|
||||||
cairo_destroy(PCAIRO);
|
cairo_destroy(PCAIRO);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Debug::log(ERR, "Invalid shapetype in loadThemeStyle");
|
Debug::log(HC_LOG_ERR, logFn, "Invalid shapetype in loadThemeStyle");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -433,6 +474,10 @@ void CHyprcursorManager::cursorSurfaceStyleDone(const SCursorStyleInfo& info) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHyprcursorManager::registerLoggingFunction(PHYPRCURSORLOGFUNC fn) {
|
||||||
|
logFn = fn;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
|
@ -535,7 +580,6 @@ static cairo_status_t readPNG(void* data, unsigned char* output, unsigned int le
|
||||||
if (DATA->readNeedle >= DATA->dataLen) {
|
if (DATA->readNeedle >= DATA->dataLen) {
|
||||||
delete[] (char*)DATA->data;
|
delete[] (char*)DATA->data;
|
||||||
DATA->data = nullptr;
|
DATA->data = nullptr;
|
||||||
Debug::log(TRACE, "cairo: png read, freeing mem");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return CAIRO_STATUS_SUCCESS;
|
return CAIRO_STATUS_SUCCESS;
|
||||||
|
@ -563,7 +607,7 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
|
||||||
manifest->commence();
|
manifest->commence();
|
||||||
manifest->parse();
|
manifest->parse();
|
||||||
} catch (const char* err) {
|
} catch (const char* err) {
|
||||||
Debug::log(ERR, "Failed parsing manifest due to {}", err);
|
Debug::log(HC_LOG_ERR, logFn, "Failed parsing manifest due to {}", err);
|
||||||
return std::string{"failed: "} + err;
|
return std::string{"failed: "} + err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,8 +618,10 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
|
||||||
return "loadTheme: cursors_directory missing or empty";
|
return "loadTheme: cursors_directory missing or empty";
|
||||||
|
|
||||||
for (auto& cursor : std::filesystem::directory_iterator(CURSORDIR)) {
|
for (auto& cursor : std::filesystem::directory_iterator(CURSORDIR)) {
|
||||||
if (!cursor.is_regular_file())
|
if (!cursor.is_regular_file()) {
|
||||||
|
Debug::log(HC_LOG_TRACE, logFn, "loadTheme: skipping {}", cursor.path().string());
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
auto& SHAPE = theme.shapes.emplace_back(std::make_unique<SCursorShape>());
|
auto& SHAPE = theme.shapes.emplace_back(std::make_unique<SCursorShape>());
|
||||||
auto& LOADEDSHAPE = loadedShapes[SHAPE.get()];
|
auto& LOADEDSHAPE = loadedShapes[SHAPE.get()];
|
||||||
|
@ -612,7 +658,10 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
|
||||||
meta->registerHandler(::parseOverride, "define_override", {.allowFlags = false});
|
meta->registerHandler(::parseOverride, "define_override", {.allowFlags = false});
|
||||||
meta->commence();
|
meta->commence();
|
||||||
meta->parse();
|
meta->parse();
|
||||||
} catch (const char* err) { return "failed parsing meta: " + std::string{err}; }
|
} catch (const char* err) {
|
||||||
|
delete[] buffer;
|
||||||
|
return "failed parsing meta: " + std::string{err};
|
||||||
|
}
|
||||||
|
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
|
|
||||||
|
@ -623,7 +672,7 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
|
||||||
else if (i.filename.ends_with(".png"))
|
else if (i.filename.ends_with(".png"))
|
||||||
SHAPE->shapeType = SHAPE_PNG;
|
SHAPE->shapeType = SHAPE_PNG;
|
||||||
else {
|
else {
|
||||||
std::cout << "WARNING: image " << i.filename << " has no known extension, assuming png.\n";
|
Debug::log(HC_LOG_WARN, logFn, "WARNING: image {} has no known extension, assuming png.", i.filename);
|
||||||
SHAPE->shapeType = SHAPE_PNG;
|
SHAPE->shapeType = SHAPE_PNG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -634,7 +683,7 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// load image
|
// load image
|
||||||
Debug::log(TRACE, "Loading {} for shape {}", i.filename, cursor.path().stem().string());
|
Debug::log(HC_LOG_TRACE, logFn, "Loading {} for shape {}", i.filename, cursor.path().stem().string());
|
||||||
auto* IMAGE = LOADEDSHAPE.images.emplace_back(std::make_unique<SLoadedCursorImage>()).get();
|
auto* IMAGE = LOADEDSHAPE.images.emplace_back(std::make_unique<SLoadedCursorImage>()).get();
|
||||||
IMAGE->side = SHAPE->shapeType == SHAPE_SVG ? 0 : i.size;
|
IMAGE->side = SHAPE->shapeType == SHAPE_SVG ? 0 : i.size;
|
||||||
IMAGE->delay = i.delay;
|
IMAGE->delay = i.delay;
|
||||||
|
@ -651,7 +700,7 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
|
||||||
|
|
||||||
zip_fclose(image_file);
|
zip_fclose(image_file);
|
||||||
|
|
||||||
Debug::log(TRACE, "Cairo: set up surface read");
|
Debug::log(HC_LOG_TRACE, logFn, "Cairo: set up surface read");
|
||||||
|
|
||||||
if (SHAPE->shapeType == SHAPE_PNG) {
|
if (SHAPE->shapeType == SHAPE_PNG) {
|
||||||
|
|
||||||
|
@ -663,7 +712,7 @@ std::optional<std::string> CHyprcursorImplementation::loadTheme() {
|
||||||
return "Failed reading cairoSurface, status " + std::to_string((int)STATUS);
|
return "Failed reading cairoSurface, status " + std::to_string((int)STATUS);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Debug::log(LOG, "Skipping cairo load for a svg surface");
|
Debug::log(HC_LOG_TRACE, logFn, "Skipping cairo load for a svg surface");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,10 @@ hyprcursor_manager_t* hyprcursor_manager_create(const char* theme_name) {
|
||||||
return (hyprcursor_manager_t*)new CHyprcursorManager(theme_name);
|
return (hyprcursor_manager_t*)new CHyprcursorManager(theme_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hyprcursor_manager_t* hyprcursor_manager_create_with_logger(const char* theme_name, PHYPRCURSORLOGFUNC fn) {
|
||||||
|
return (hyprcursor_manager_t*)new CHyprcursorManager(theme_name, fn);
|
||||||
|
}
|
||||||
|
|
||||||
void hyprcursor_manager_free(hyprcursor_manager_t* manager) {
|
void hyprcursor_manager_free(hyprcursor_manager_t* manager) {
|
||||||
delete (CHyprcursorManager*)manager;
|
delete (CHyprcursorManager*)manager;
|
||||||
}
|
}
|
||||||
|
@ -47,3 +51,8 @@ void hyprcursor_style_done(hyprcursor_manager_t* manager, hyprcursor_cursor_styl
|
||||||
info.size = info_.size;
|
info.size = info_.size;
|
||||||
return MGR->cursorSurfaceStyleDone(info);
|
return MGR->cursorSurfaceStyleDone(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hyprcursor_register_logging_function(struct hyprcursor_manager_t* manager, PHYPRCURSORLOGFUNC fn) {
|
||||||
|
const auto MGR = (CHyprcursorManager*)manager;
|
||||||
|
MGR->registerLoggingFunction(fn);
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,13 @@ struct SLoadedCursorShape {
|
||||||
|
|
||||||
class CHyprcursorImplementation {
|
class CHyprcursorImplementation {
|
||||||
public:
|
public:
|
||||||
|
CHyprcursorImplementation(Hyprcursor::CHyprcursorManager* mgr, PHYPRCURSORLOGFUNC fn) : owner(mgr), logFn(fn) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
Hyprcursor::CHyprcursorManager* owner = nullptr;
|
||||||
|
PHYPRCURSORLOGFUNC logFn = nullptr;
|
||||||
|
|
||||||
std::string themeName;
|
std::string themeName;
|
||||||
std::string themeFullDir;
|
std::string themeFullDir;
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,18 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void logFunction(enum eHyprcursorLogLevel level, char* message) {
|
||||||
|
printf("[hc] %s\n", message);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
struct hyprcursor_manager_t* mgr = hyprcursor_manager_create(NULL);
|
struct hyprcursor_manager_t* mgr = hyprcursor_manager_create_with_logger(NULL, logFunction);
|
||||||
|
|
||||||
if (!mgr) {
|
if (!mgr) {
|
||||||
printf("mgr null\n");
|
printf("mgr null\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hyprcursor_manager_valid(mgr)) {
|
if (!hyprcursor_manager_valid(mgr)) {
|
||||||
printf("mgr is invalid\n");
|
printf("mgr is invalid\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <hyprcursor/hyprcursor.hpp>
|
#include <hyprcursor/hyprcursor.hpp>
|
||||||
|
|
||||||
|
void logFunction(enum eHyprcursorLogLevel level, char* message) {
|
||||||
|
std::cout << "[hc] " << message << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
Hyprcursor::CHyprcursorManager mgr(nullptr);
|
Hyprcursor::CHyprcursorManager mgr(nullptr, logFunction);
|
||||||
|
|
||||||
if (!mgr.valid()) {
|
if (!mgr.valid()) {
|
||||||
std::cout << "mgr is invalid\n";
|
std::cout << "mgr is invalid\n";
|
||||||
|
|
Loading…
Reference in a new issue