New upstream version 0.1.9

This commit is contained in:
alan (NyxTrail) 2024-06-13 06:59:57 +00:00
parent f6be58e58e
commit 7f4eaa029d
7 changed files with 85 additions and 45 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.19) cmake_minimum_required(VERSION 3.19)
set(HYPRCURSOR_VERSION "0.1.7") set(HYPRCURSOR_VERSION "0.1.9")
add_compile_definitions(HYPRCURSOR_VERSION="${HYPRCURSOR_VERSION}") add_compile_definitions(HYPRCURSOR_VERSION="${HYPRCURSOR_VERSION}")
project(hyprcursor project(hyprcursor

View File

@ -57,7 +57,7 @@ Util:
### Build ### Build
```sh ```sh
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf _NPROCESSORS_CONF`
``` ```
Install with: Install with:

View File

@ -5,14 +5,16 @@
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
"systems": "systems" "systems": [
"systems"
]
}, },
"locked": { "locked": {
"lastModified": 1709914708, "lastModified": 1713121246,
"narHash": "sha256-bR4o3mynoTa1Wi4ZTjbnsZ6iqVcPGriXp56bZh5UFTk=", "narHash": "sha256-502X0Q0fhN6tJK7iEUA8CghONKSatW/Mqj4Wappd++0=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprlang", "repo": "hyprlang",
"rev": "a685493fdbeec01ca8ccdf1f3655c044a8ce2fe2", "rev": "78fcaa27ae9e1d782faa3ff06c8ea55ddce63706",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -23,11 +25,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1708475490, "lastModified": 1712963716,
"narHash": "sha256-g1v0TsWBQPX97ziznfJdWhgMyMGtoBFs102xSYO4syU=", "narHash": "sha256-WKm9CvgCldeIVvRz87iOMi8CFVB1apJlkUT4GGvA0iM=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "0e74ca98a74bc7270d28838369593635a5db3260", "rev": "cfd6b5fc90b15709b780a5a1619695a88505a176",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -41,7 +43,7 @@
"inputs": { "inputs": {
"hyprlang": "hyprlang", "hyprlang": "hyprlang",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"systems": "systems_2" "systems": "systems"
} }
}, },
"systems": { "systems": {
@ -58,21 +60,6 @@
"repo": "default-linux", "repo": "default-linux",
"type": "github" "type": "github"
} }
},
"systems_2": {
"locked": {
"lastModified": 1689347949,
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
"owner": "nix-systems",
"repo": "default-linux",
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default-linux",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View File

@ -5,11 +5,16 @@
#include <array> #include <array>
#include <format> #include <format>
#include <algorithm> #include <algorithm>
#include <regex>
#include <hyprlang.hpp> #include <hyprlang.hpp>
#include "internalSharedTypes.hpp" #include "internalSharedTypes.hpp"
#include "manifest.hpp" #include "manifest.hpp"
#include "meta.hpp" #include "meta.hpp"
#ifndef ZIP_LENGTH_TO_END
#define ZIP_LENGTH_TO_END -1
#endif
enum eOperation { enum eOperation {
OPERATION_CREATE = 0, OPERATION_CREATE = 0,
OPERATION_EXTRACT = 1, OPERATION_EXTRACT = 1,
@ -87,7 +92,7 @@ static std::optional<std::string> createCursorThemeFromPath(const std::string& p
const std::string THEMENAME = manifest.parsedData.name; const std::string THEMENAME = manifest.parsedData.name;
std::string out = (out_.empty() ? path.substr(0, path.find_last_of('/') + 1) : out_) + "/theme_" + THEMENAME + "/"; std::string out = (out_.empty() ? path.substr(0, path.find_last_of('/')) : out_) + "/theme_" + THEMENAME;
const std::string CURSORSSUBDIR = manifest.parsedData.cursorsDirectory; const std::string CURSORSSUBDIR = manifest.parsedData.cursorsDirectory;
const std::string CURSORDIR = path + "/" + CURSORSSUBDIR; const std::string CURSORDIR = path + "/" + CURSORSSUBDIR;
@ -98,6 +103,9 @@ static std::optional<std::string> createCursorThemeFromPath(const std::string& p
// iterate over the directory and record all cursors // iterate over the directory and record all cursors
for (auto& dir : std::filesystem::directory_iterator(CURSORDIR)) { for (auto& dir : std::filesystem::directory_iterator(CURSORDIR)) {
if (!std::regex_match(dir.path().stem().string(), std::regex("^[A-Za-z0-9_\\-\\.]+$")))
return "Invalid cursor directory name at " + dir.path().string() + " : characters must be within [A-Za-z0-9_\\-\\.]";
const auto METAPATH = dir.path().string() + "/meta"; const auto METAPATH = dir.path().string() + "/meta";
auto& SHAPE = currentTheme.shapes.emplace_back(std::make_unique<SCursorShape>()); auto& SHAPE = currentTheme.shapes.emplace_back(std::make_unique<SCursorShape>());
@ -113,6 +121,8 @@ static std::optional<std::string> createCursorThemeFromPath(const std::string& p
SHAPE->images.push_back(SCursorImage{i.file, i.size, i.delayMs}); SHAPE->images.push_back(SCursorImage{i.file, i.size, i.delayMs});
} }
SHAPE->overrides = meta.parsedData.overrides;
// check if we have at least one image. // check if we have at least one image.
for (auto& i : SHAPE->images) { for (auto& i : SHAPE->images) {
@ -178,7 +188,7 @@ static std::optional<std::string> createCursorThemeFromPath(const std::string& p
// add meta.hl // add meta.hl
const auto METADIR = std::filesystem::exists(CURRENTCURSORSDIR + "/meta.hl") ? (CURRENTCURSORSDIR + "/meta.hl") : (CURRENTCURSORSDIR + "/meta.toml"); const auto METADIR = std::filesystem::exists(CURRENTCURSORSDIR + "/meta.hl") ? (CURRENTCURSORSDIR + "/meta.hl") : (CURRENTCURSORSDIR + "/meta.toml");
zip_source_t* meta = zip_source_file(zip, METADIR.c_str(), 0, 0); zip_source_t* meta = zip_source_file(zip, METADIR.c_str(), 0, ZIP_LENGTH_TO_END);
if (!meta) if (!meta)
return "(1) failed to add meta " + METADIR + " to hlc"; return "(1) failed to add meta " + METADIR + " to hlc";
if (zip_file_add(zip, (std::string{"meta."} + (METADIR.ends_with(".hl") ? "hl" : "toml")).c_str(), meta, ZIP_FL_ENC_UTF_8) < 0) if (zip_file_add(zip, (std::string{"meta."} + (METADIR.ends_with(".hl") ? "hl" : "toml")).c_str(), meta, ZIP_FL_ENC_UTF_8) < 0)
@ -186,9 +196,9 @@ static std::optional<std::string> createCursorThemeFromPath(const std::string& p
meta = nullptr; meta = nullptr;
// add each cursor png // add each cursor image
for (auto& i : shape->images) { for (auto& i : shape->images) {
zip_source_t* image = zip_source_file(zip, (CURRENTCURSORSDIR + "/" + i.filename).c_str(), 0, 0); zip_source_t* image = zip_source_file(zip, (CURRENTCURSORSDIR + "/" + i.filename).c_str(), 0, ZIP_LENGTH_TO_END);
if (!image) if (!image)
return "(1) failed to add image " + (CURRENTCURSORSDIR + "/" + i.filename) + " to hlc"; return "(1) failed to add image " + (CURRENTCURSORSDIR + "/" + i.filename) + " to hlc";
if (zip_file_add(zip, (i.filename).c_str(), image, ZIP_FL_ENC_UTF_8) < 0) if (zip_file_add(zip, (i.filename).c_str(), image, ZIP_FL_ENC_UTF_8) < 0)
@ -199,9 +209,8 @@ static std::optional<std::string> createCursorThemeFromPath(const std::string& p
// close zip and write // close zip and write
if (zip_close(zip) < 0) { if (zip_close(zip) < 0) {
zip_error_t ziperror; zip_error_t* ziperror = zip_get_error(zip);
zip_error_init_with_code(&ziperror, errp); return "Failed to write " + OUTPUTFILE + ": " + zip_error_strerror(ziperror);
return "Failed to write " + OUTPUTFILE + ": " + zip_error_strerror(&ziperror);
} }
std::cout << "Written " << OUTPUTFILE << "\n"; std::cout << "Written " << OUTPUTFILE << "\n";
@ -449,4 +458,4 @@ int main(int argc, char** argv, char** envp) {
} }
return 0; return 0;
} }

View File

@ -47,6 +47,22 @@ namespace Hyprcursor {
eHyprcursorDataType type = HC_DATA_PNG; eHyprcursorDataType type = HC_DATA_PNG;
}; };
/*!
struct for cursor manager options
*/
struct SManagerOptions {
explicit SManagerOptions();
/*!
The function used for logging by the cursor manager
*/
PHYPRCURSORLOGFUNC logFn;
/*!
Allow fallback to env and first theme found
*/
bool allowDefaultFallback;
};
/*! /*!
Basic Hyprcursor manager. Basic Hyprcursor manager.
@ -58,6 +74,8 @@ namespace Hyprcursor {
If none found, bool valid() will be false. If none found, bool valid() will be false.
If loading fails, bool valid() will be false. If loading fails, bool valid() will be false.
If theme has no valid cursor shapes, bool valid() will be false.
*/ */
class CHyprcursorManager { class CHyprcursorManager {
public: public:
@ -66,6 +84,7 @@ namespace Hyprcursor {
\since 0.1.6 \since 0.1.6
*/ */
CHyprcursorManager(const char* themeName, PHYPRCURSORLOGFUNC fn); CHyprcursorManager(const char* themeName, PHYPRCURSORLOGFUNC fn);
CHyprcursorManager(const char* themeName, SManagerOptions options);
~CHyprcursorManager(); ~CHyprcursorManager();
/*! /*!
@ -170,9 +189,10 @@ namespace Hyprcursor {
private: private:
void init(const char* themeName_); void init(const char* themeName_);
CHyprcursorImplementation* impl = nullptr; CHyprcursorImplementation* impl = nullptr;
bool finalizedAndValid = false; bool finalizedAndValid = false;
PHYPRCURSORLOGFUNC logFn = nullptr; bool allowDefaultFallback = true;
PHYPRCURSORLOGFUNC logFn = nullptr;
friend class CHyprcursorImplementation; friend class CHyprcursorImplementation;
}; };

View File

@ -108,7 +108,7 @@ static std::string getFirstTheme(PHYPRCURSORLOGFUNC logfn) {
return ""; return "";
} }
static std::string getFullPathForThemeName(const std::string& name, PHYPRCURSORLOGFUNC logfn) { static std::string getFullPathForThemeName(const std::string& name, PHYPRCURSORLOGFUNC logfn, bool allowDefaultFallback) {
const auto HOMEENV = getenv("HOME"); const auto HOMEENV = getenv("HOME");
if (!HOMEENV) if (!HOMEENV)
return ""; return "";
@ -134,7 +134,7 @@ static std::string getFullPathForThemeName(const std::string& name, PHYPRCURSORL
const auto MANIFESTPATH = themeDir.path().string() + "/manifest"; const auto MANIFESTPATH = themeDir.path().string() + "/manifest";
if (name.empty()) { if (allowDefaultFallback && name.empty()) {
if (std::filesystem::exists(MANIFESTPATH + ".hl") || std::filesystem::exists(MANIFESTPATH + ".toml")) { if (std::filesystem::exists(MANIFESTPATH + ".hl") || std::filesystem::exists(MANIFESTPATH + ".toml")) {
Debug::log(HC_LOG_INFO, logfn, "getFullPathForThemeName: found {}", themeDir.path().string()); 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();
@ -193,14 +193,19 @@ static std::string getFullPathForThemeName(const std::string& name, PHYPRCURSORL
} }
} }
if (!name.empty()) { // try without name if (allowDefaultFallback && !name.empty()) { // try without name
Debug::log(HC_LOG_INFO, logfn, "getFullPathForThemeName: failed, trying without name of {}", name); Debug::log(HC_LOG_INFO, logfn, "getFullPathForThemeName: failed, trying without name of {}", name);
return getFullPathForThemeName("", logfn); return getFullPathForThemeName("", logfn, allowDefaultFallback);
} }
return ""; return "";
} }
SManagerOptions::SManagerOptions() {
logFn = nullptr;
allowDefaultFallback = true;
}
CHyprcursorManager::CHyprcursorManager(const char* themeName_) { CHyprcursorManager::CHyprcursorManager(const char* themeName_) {
init(themeName_); init(themeName_);
} }
@ -210,16 +215,22 @@ CHyprcursorManager::CHyprcursorManager(const char* themeName_, PHYPRCURSORLOGFUN
init(themeName_); init(themeName_);
} }
CHyprcursorManager::CHyprcursorManager(const char* themeName_, SManagerOptions options) {
logFn = options.logFn;
allowDefaultFallback = options.allowDefaultFallback;
init(themeName_);
}
void CHyprcursorManager::init(const char* themeName_) { void CHyprcursorManager::init(const char* themeName_) {
std::string themeName = themeName_ ? themeName_ : ""; std::string themeName = themeName_ ? themeName_ : "";
if (themeName.empty()) { if (allowDefaultFallback && themeName.empty()) {
// try reading from env // try reading from env
Debug::log(HC_LOG_INFO, logFn, "CHyprcursorManager: attempting to find theme from env"); Debug::log(HC_LOG_INFO, logFn, "CHyprcursorManager: attempting to find theme from env");
themeName = themeNameFromEnv(logFn); themeName = themeNameFromEnv(logFn);
} }
if (themeName.empty()) { if (allowDefaultFallback && themeName.empty()) {
// try finding first, in the hierarchy // try finding first, in the hierarchy
Debug::log(HC_LOG_INFO, logFn, "CHyprcursorManager: attempting to find any theme"); Debug::log(HC_LOG_INFO, logFn, "CHyprcursorManager: attempting to find any theme");
themeName = getFirstTheme(logFn); themeName = getFirstTheme(logFn);
@ -234,7 +245,7 @@ void CHyprcursorManager::init(const char* themeName_) {
// initialize theme // initialize theme
impl = new CHyprcursorImplementation(this, logFn); impl = new CHyprcursorImplementation(this, logFn);
impl->themeName = themeName; impl->themeName = themeName;
impl->themeFullDir = getFullPathForThemeName(themeName, logFn); impl->themeFullDir = getFullPathForThemeName(themeName, logFn, allowDefaultFallback);
if (impl->themeFullDir.empty()) if (impl->themeFullDir.empty())
return; return;
@ -248,6 +259,11 @@ void CHyprcursorManager::init(const char* themeName_) {
return; return;
} }
if (impl->theme.shapes.empty()) {
Debug::log(HC_LOG_ERR, logFn, "Theme {} has no valid cursor shapes\n", impl->themeName);
return;
}
finalizedAndValid = true; finalizedAndValid = true;
} }
@ -301,7 +317,7 @@ SCursorImageData** CHyprcursorManager::getShapesC(int& outSize, const char* shap
// find nearest // find nearest
int leader = 13371337; int leader = 13371337;
for (auto& image : impl->loadedShapes[shape.get()].images) { for (auto& image : impl->loadedShapes[shape.get()].images) {
if (std::abs((int)(image->side - info.size)) > leader) if (std::abs((int)(image->side - info.size)) > std::abs((int)(leader - info.size)))
continue; continue;
leader = image->side; leader = image->side;

View File

@ -3,6 +3,7 @@
#include <hyprlang.hpp> #include <hyprlang.hpp>
#include <toml++/toml.hpp> #include <toml++/toml.hpp>
#include <filesystem> #include <filesystem>
#include <regex>
#include "VarList.hpp" #include "VarList.hpp"
@ -95,6 +96,11 @@ static Hyprlang::CParseResult parseDefineSize(const char* C, const char* V) {
RHS = LL; RHS = LL;
} }
if (!std::regex_match(RHS, std::regex("^[A-Za-z0-9_\\-\\.]+$"))) {
result.setError("Invalid cursor file name, characters must be within [A-Za-z0-9_\\-\\.] (if this seems like a mistake, check for invisible characters)");
return result;
}
size.file = RHS; size.file = RHS;
if (!size.file.ends_with(".svg")) { if (!size.file.ends_with(".svg")) {
@ -132,7 +138,9 @@ std::optional<std::string> CMeta::parseHL() {
meta->registerHandler(::parseDefineSize, "define_size", {.allowFlags = false}); meta->registerHandler(::parseDefineSize, "define_size", {.allowFlags = false});
meta->registerHandler(::parseOverride, "define_override", {.allowFlags = false}); meta->registerHandler(::parseOverride, "define_override", {.allowFlags = false});
meta->commence(); meta->commence();
meta->parse(); const auto RESULT = meta->parse();
if (RESULT.error)
return RESULT.getError();
} catch (const char* err) { return "failed parsing meta: " + std::string{err}; } } catch (const char* err) { return "failed parsing meta: " + std::string{err}; }
parsedData.hotspotX = std::any_cast<Hyprlang::FLOAT>(meta->getConfigValue("hotspot_x")); parsedData.hotspotX = std::any_cast<Hyprlang::FLOAT>(meta->getConfigValue("hotspot_x"));