feat: implemented shaperules

This commit is contained in:
Virt 2024-07-03 00:38:50 +02:00
commit 9fd1b6a1c2
13 changed files with 448 additions and 95 deletions

118
src/config/ShapeRule.cpp Normal file
View file

@ -0,0 +1,118 @@
#include "ShapeRule.hpp"
#include <hyprutils/string/VarList.hpp>
#include <stdexcept>
#include <string>
#include <hyprutils/string/String.hpp>
#include <hyprutils/string/VarList.hpp>
using namespace Hyprutils::String;
void CShapeRuleHandler::clear() {
rules.clear();
active = nullptr;
}
void CShapeRuleHandler::activate(std::string key) {
if (rules.contains(key))
active = &rules[key];
else
active = nullptr;
}
void CShapeRuleHandler::addProperty(std::string key, EShapeRuleType type) {
content[key] = type;
}
std::variant<std::string, float, int> parse(std::string value, EShapeRuleType type) {
switch (type) {
case EShapeRuleType::STRING:
return value;
case EShapeRuleType::FLOAT:
return std::stof(value);
case EShapeRuleType::INT:
return std::stoi(value);
}
throw std::logic_error("unknown type");
}
void CShapeRuleHandler::parseRule(std::string string) {
std::optional<std::string> name;
SShapeRule rule;
CVarList list = CVarList(string);
for (auto arg : list) {
if (!name.has_value()) name = arg;
else {
auto pos = arg.rfind(':');
// mode value
if (pos == std::string::npos) {
if (rule.mode.has_value())
throw std::logic_error("cannot specify mode twice");
rule.mode = arg;
// settings value
} else {
auto key = arg.substr(0, pos);
auto value = arg.substr(pos + 1);
if (rule.content.contains(key))
throw std::logic_error("cannot specify property " + key + " twice");
if (!content.contains(key))
throw std::logic_error("unkown property " + key);
auto type = content[key];
try {
rule.content[key] = parse(value, type);
} catch (...) {
throw std::logic_error("invalid type for property " + key);
}
}
}
}
if (!name.has_value())
throw std::logic_error("need to specify at least shape name");
if (rules.contains(name.value()))
throw std::logic_error("cannot have two rules for shape " + name.value());
rules[name.value()] = rule;
}
Hyprlang::CParseResult onShapeRuleKeyword(const char* COMMAND, const char* VALUE) {
Hyprlang::CParseResult res;
try {
g_pShapeRuleHandler->parseRule(std::string{VALUE});
} catch (const std::exception& ex) {
res.setError(ex.what());
}
return res;
}
std::string CShapeRuleHandler::getModeOr(std::string def) {
if (active) return active->mode.value_or(def);
else return def;
}
std::string CShapeRuleHandler::getStringOr(std::string key, std::string def) {
if (active && active->content.contains(key)) return std::get<std::string>(active->content[key]);
else return def;
}
int CShapeRuleHandler::getIntOr(std::string key, int def) {
if (active && active->content.contains(key)) return std::get<int>(active->content[key]);
else return def;
}
float CShapeRuleHandler::getFloatOr(std::string key, float def) {
if (active && active->content.contains(key)) return std::get<float>(active->content[key]);
else return def;
}

52
src/config/ShapeRule.hpp Normal file
View file

@ -0,0 +1,52 @@
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <variant>
#include <hyprlang.hpp>
/* stores possible types in a shape rule */
enum EShapeRuleType {
STRING,
FLOAT,
INT
};
struct SShapeRule {
std::optional<std::string> mode;
std::unordered_map<std::string, std::variant<std::string, float, int>> content;
};
class CShapeRuleHandler {
/* induvidual rule content */
std::unordered_map<std::string, EShapeRuleType> content;
/* possible rules */
std::unordered_map<std::string, SShapeRule> rules;
/* currently active rule, nullptr if none */
SShapeRule* active = nullptr;
public:
/* adds a valid shape rule property */
void addProperty(std::string key, EShapeRuleType type);
/* removes currently added shape rules */
void clear();
/* adds a new shape rule from string */
void parseRule(std::string string);
/* activates the shape rule for the given shape */
void activate(std::string name);
std::string getModeOr(std::string def);
std::string getStringOr(std::string key, std::string def);
int getIntOr(std::string key, int def);
float getFloatOr(std::string key, float def);
};
/* method called by hyprland api */
Hyprlang::CParseResult onShapeRuleKeyword(const char* COMMAND, const char* VALUE);
inline std::unique_ptr<CShapeRuleHandler> g_pShapeRuleHandler;

65
src/config/config.cpp Normal file
View file

@ -0,0 +1,65 @@
#include "../globals.hpp"
#include "config.hpp"
#include <hyprland/src/plugins/PluginAPI.hpp>
#include <hyprlang.hpp>
#include <stdexcept>
#include <variant>
Hyprlang::CConfigValue toHyprlang(std::variant<std::string, float, int> value) {
if (std::holds_alternative<std::string>(value))
return Hyprlang::STRING { std::get<std::string>(value).c_str() };
if (std::holds_alternative<float>(value))
return Hyprlang::FLOAT { std::get<float>(value) };
if (std::holds_alternative<int>(value))
return Hyprlang::INT { std::get<int>(value) };
throw new std::logic_error("invalid type in variant?!");
}
EShapeRuleType toShapeRule(std::variant<std::string, float, int> value) {
if (std::holds_alternative<std::string>(value))
return EShapeRuleType::STRING;
if (std::holds_alternative<float>(value))
return EShapeRuleType::FLOAT;
if (std::holds_alternative<int>(value))
return EShapeRuleType::INT;
throw new std::logic_error("invalid type in variant?!");
}
void startConfig() {
g_pShapeRuleHandler = std::make_unique<CShapeRuleHandler>();
}
void addConfig(std::string name, std::variant<std::string, float, int> value) {
HyprlandAPI::addConfigValue(PHANDLE, NAMESPACE + name, toHyprlang(value));
}
void addShapeConfig(std::string name, std::variant<std::string, float, int> value) {
addConfig(name, value);
g_pShapeRuleHandler->addProperty(name, toShapeRule(value));
}
void* const* getConfig(std::string name) {
return HyprlandAPI::getConfigValue(PHANDLE, NAMESPACE + name)->getDataStaticPtr();
}
void addRulesConfig() {
HyprlandAPI::addConfigKeyword(PHANDLE, CONFIG_SHAPERULE, onShapeRuleKeyword, Hyprlang::SHandlerOptions {});
// clear on reload
static const auto PCALLBACK = HyprlandAPI::registerCallbackDynamic( PHANDLE, "preConfigReload", [&](void* self, SCallbackInfo&, std::any data) {
g_pShapeRuleHandler->clear();
});
}
void finishConfig() {
HyprlandAPI::reloadConfig();
}

46
src/config/config.hpp Normal file
View file

@ -0,0 +1,46 @@
#pragma once
#include <hyprlang.hpp>
#include "ShapeRule.hpp"
#define NAMESPACE "plugin:dynamic-cursors:"
#define CONFIG_ENABLED "enabled"
#define CONFIG_MODE "mode"
#define CONFIG_THRESHOLD "threshold"
#define CONFIG_HW_DEBUG "hw_debug"
#define CONFIG_SHAKE "shake:enabled"
#define CONFIG_SHAKE_NEAREST "shake:nearest"
#define CONFIG_SHAKE_THRESHOLD "shake:threshold"
#define CONFIG_SHAKE_FACTOR "shake:factor"
#define CONFIG_SHAKE_EFFECTS "shake:effects"
#define CONFIG_SHAKE_IPC "shake:ipc"
#define CONFIG_ROTATE_LENGTH "rotate:length"
#define CONFIG_ROTATE_OFFSET "rotate:offset"
#define CONFIG_TILT_LIMIT "tilt:limit"
#define CONFIG_TILT_FUNCTION "tilt:function"
#define CONFIG_STRETCH_LIMIT "stretch:limit"
#define CONFIG_STRETCH_FUNCTION "stretch:function"
#define CONFIG_SHAPERULE "shaperule"
/* initializes stuff so config can be set up */
void startConfig();
/* finishes config setup */
void finishConfig();
/* add shaperule config entry */
void addRulesConfig();
/* will add an ordinary config value */
void addConfig(std::string name, std::variant<std::string, float, int> value);
/* will add a config variable which is also a property for shape rules */
void addShapeConfig(std::string name, std::variant<std::string, float, int> value);
/* get static pointer to config value */
void* const* getConfig(std::string name);

View file

@ -1,4 +1,4 @@
#include "globals.hpp"
#include "config/config.hpp"
#include "mode/Mode.hpp"
#include "src/debug/Log.hpp"
#include "src/managers/eventLoop/EventLoopManager.hpp"
@ -25,7 +25,7 @@
#include "renderer.hpp"
void tickRaw(SP<CEventLoopTimer> self, void* data) {
static auto* const* PENABLED = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_ENABLED)->getDataStaticPtr();
static auto* const* PENABLED = (Hyprlang::INT* const*) getConfig(CONFIG_ENABLED);
if (**PENABLED && g_pDynamicCursors)
g_pDynamicCursors->onTick(g_pPointerManager.get());
@ -56,7 +56,7 @@ Reimplements rendering of the software cursor.
Is also largely identical to hyprlands impl, but uses our custom rendering to rotate the cursor.
*/
void CDynamicCursors::renderSoftware(CPointerManager* pointers, SP<CMonitor> pMonitor, timespec* now, CRegion& damage, std::optional<Vector2D> overridePos) {
static auto* const* PNEAREST = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_SHAKE_NEAREST)->getDataStaticPtr();
static auto* const* PNEAREST = (Hyprlang::INT* const*) getConfig(CONFIG_SHAKE_NEAREST);
if (!pointers->hasCursor())
return;
@ -125,8 +125,8 @@ This function reimplements the hardware cursor buffer drawing.
It is largely copied from hyprland, but adjusted to allow the cursor to be rotated.
*/
wlr_buffer* CDynamicCursors::renderHardware(CPointerManager* pointers, SP<CPointerManager::SMonitorPointerState> state, SP<CTexture> texture) {
static auto* const* PHW_DEBUG= (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_HW_DEBUG)->getDataStaticPtr();
static auto* const* PNEAREST = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_SHAKE_NEAREST)->getDataStaticPtr();
static auto* const* PHW_DEBUG= (Hyprlang::INT* const*) getConfig(CONFIG_HW_DEBUG);
static auto* const* PNEAREST = (Hyprlang::INT* const*) getConfig(CONFIG_SHAKE_NEAREST);
auto output = state->monitor->output;
auto zoom = resultShown.scale;
@ -261,6 +261,14 @@ void CDynamicCursors::onCursorMoved(CPointerManager* pointers) {
calculate(MOVE);
}
void CDynamicCursors::setShape(const std::string& shape) {
g_pShapeRuleHandler->activate(shape);
}
void CDynamicCursors::unsetShape() {
g_pShapeRuleHandler->activate("clientside");
}
/*
Handle cursor tick events.
*/
@ -269,18 +277,19 @@ void CDynamicCursors::onTick(CPointerManager* pointers) {
}
IMode* CDynamicCursors::currentMode() {
static auto const* PMODE = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_MODE)->getDataStaticPtr();
static auto const* PMODE = (Hyprlang::STRING const*) getConfig(CONFIG_MODE);
auto mode = g_pShapeRuleHandler->getModeOr(*PMODE);
if (!strcmp(*PMODE, "rotate")) return &rotate;
else if (!strcmp(*PMODE, "tilt")) return &tilt;
else if (!strcmp(*PMODE, "stretch")) return &stretch;
if (mode == "rotate") return &rotate;
else if (mode == "tilt") return &tilt;
else if (mode == "stretch") return &stretch;
else return nullptr;
}
void CDynamicCursors::calculate(EModeUpdate type) {
static auto* const* PTHRESHOLD = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_THRESHOLD)->getDataStaticPtr();
static auto* const* PSHAKE = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_SHAKE)->getDataStaticPtr();
static auto* const* PSHAKE_EFFECTS = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_SHAKE_EFFECTS)->getDataStaticPtr();
static auto* const* PTHRESHOLD = (Hyprlang::INT* const*) getConfig(CONFIG_THRESHOLD);
static auto* const* PSHAKE = (Hyprlang::INT* const*) getConfig(CONFIG_SHAKE);
static auto* const* PSHAKE_EFFECTS = (Hyprlang::INT* const*) getConfig(CONFIG_SHAKE_EFFECTS);
IMode* mode = currentMode();
@ -322,12 +331,24 @@ void CDynamicCursors::calculate(EModeUpdate type) {
// damage software and change hardware cursor shape
g_pPointerManager->damageIfSoftware();
bool entered = false;
for (auto& m : g_pCompositor->m_vMonitors) {
auto state = g_pPointerManager->stateFor(m);
if (state->entered) entered = true;
if (state->hardwareFailed || !state->entered)
continue;
g_pPointerManager->attemptHardwareCursor(state);
}
// there should always be one monitor entered
// this fixes an issue wheter the cursor shape would not properly update after change
if (!entered) {
Debug::log(LOG, "[dynamic-cursors] updating because none entered");
g_pPointerManager->recheckEnteredOutputs();
g_pPointerManager->updateCursorBackend();
}
}
}

View file

@ -30,6 +30,11 @@ class CDynamicCursors {
/* hook on setHWCursorBuffer */
bool setHardware(CPointerManager* pointers, SP<CPointerManager::SMonitorPointerState> state, wlr_buffer* buf);
/* hook on setCursorFromName */
void setShape(const std::string& name);
/* hook on setCursorSoftware */
void unsetShape();
private:
SP<CEventLoopTimer> tick;

View file

@ -2,25 +2,4 @@
#include <hyprland/src/plugins/PluginAPI.hpp>
#define CONFIG_ENABLED "plugin:dynamic-cursors:enabled"
#define CONFIG_MODE "plugin:dynamic-cursors:mode"
#define CONFIG_THRESHOLD "plugin:dynamic-cursors:threshold"
#define CONFIG_HW_DEBUG "plugin:dynamic-cursors:hw_debug"
#define CONFIG_SHAKE "plugin:dynamic-cursors:shake:enabled"
#define CONFIG_SHAKE_NEAREST "plugin:dynamic-cursors:shake:nearest"
#define CONFIG_SHAKE_THRESHOLD "plugin:dynamic-cursors:shake:threshold"
#define CONFIG_SHAKE_FACTOR "plugin:dynamic-cursors:shake:factor"
#define CONFIG_SHAKE_EFFECTS "plugin:dynamic-cursors:shake:effects"
#define CONFIG_SHAKE_IPC "plugin:dynamic-cursors:shake:ipc"
#define CONFIG_ROTATE_LENGTH "plugin:dynamic-cursors:rotate:length"
#define CONFIG_ROTATE_OFFSET "plugin:dynamic-cursors:rotate:offset"
#define CONFIG_TILT_LIMIT "plugin:dynamic-cursors:tilt:limit"
#define CONFIG_TILT_FUNCTION "plugin:dynamic-cursors:tilt:function"
#define CONFIG_STRETCH_LIMIT "plugin:dynamic-cursors:stretch:limit"
#define CONFIG_STRETCH_FUNCTION "plugin:dynamic-cursors:stretch:function"
inline HANDLE PHANDLE = nullptr;

View file

@ -8,65 +8,82 @@
#include "globals.hpp"
#include "cursor.hpp"
#include "config/config.hpp"
#include "src/debug/Log.hpp"
#include "src/managers/PointerManager.hpp"
bool isEnabled() {
static auto* const* PENABLED = (Hyprlang::INT* const*) getConfig(CONFIG_ENABLED);
return **PENABLED;
}
typedef void (*origRenderSofwareCursorsFor)(void*, SP<CMonitor>, timespec*, CRegion&, std::optional<Vector2D>);
inline CFunctionHook* g_pRenderSoftwareCursorsForHook = nullptr;
void hkRenderSoftwareCursorsFor(void* thisptr, SP<CMonitor> pMonitor, timespec* now, CRegion& damage, std::optional<Vector2D> overridePos) {
static auto* const* PENABLED = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_ENABLED)->getDataStaticPtr();
if (**PENABLED) g_pDynamicCursors->renderSoftware((CPointerManager*) thisptr, pMonitor, now, damage, overridePos);
if (isEnabled()) g_pDynamicCursors->renderSoftware((CPointerManager*) thisptr, pMonitor, now, damage, overridePos);
else (*(origRenderSofwareCursorsFor)g_pRenderSoftwareCursorsForHook->m_pOriginal)(thisptr, pMonitor, now, damage, overridePos);
}
typedef void (*origDamageIfSoftware)(void*);
inline CFunctionHook* g_pDamageIfSoftwareHook = nullptr;
void hkDamageIfSoftware(void* thisptr) {
static auto* const* PENABLED = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_ENABLED)->getDataStaticPtr();
if (**PENABLED) g_pDynamicCursors->damageSoftware((CPointerManager*) thisptr);
if (isEnabled()) g_pDynamicCursors->damageSoftware((CPointerManager*) thisptr);
else (*(origDamageIfSoftware)g_pDamageIfSoftwareHook->m_pOriginal)(thisptr);
}
typedef wlr_buffer* (*origRenderHWCursorBuffer)(void*, SP<CPointerManager::SMonitorPointerState>, SP<CTexture>);
inline CFunctionHook* g_pRenderHWCursorBufferHook = nullptr;
wlr_buffer* hkRenderHWCursorBuffer(void* thisptr, SP<CPointerManager::SMonitorPointerState> state, SP<CTexture> texture) {
static auto* const* PENABLED = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_ENABLED)->getDataStaticPtr();
if (**PENABLED) return g_pDynamicCursors->renderHardware((CPointerManager*) thisptr, state, texture);
if (isEnabled()) return g_pDynamicCursors->renderHardware((CPointerManager*) thisptr, state, texture);
else return (*(origRenderHWCursorBuffer)g_pRenderHWCursorBufferHook->m_pOriginal)(thisptr, state, texture);
}
typedef bool (*origSetHWCursorBuffer)(void*, SP<CPointerManager::SMonitorPointerState>, wlr_buffer*);
inline CFunctionHook* g_pSetHWCursorBufferHook = nullptr;
bool hkSetHWCursorBuffer(void* thisptr, SP<CPointerManager::SMonitorPointerState> state, wlr_buffer* buffer) {
static auto* const* PENABLED = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_ENABLED)->getDataStaticPtr();
if (**PENABLED) return g_pDynamicCursors->setHardware((CPointerManager*) thisptr, state, buffer);
if (isEnabled()) return g_pDynamicCursors->setHardware((CPointerManager*) thisptr, state, buffer);
else return (*(origSetHWCursorBuffer)g_pSetHWCursorBufferHook->m_pOriginal)(thisptr, state, buffer);
}
typedef void (*origOnCursorMoved)(void*);
inline CFunctionHook* g_pOnCursorMovedHook = nullptr;
void hkOnCursorMoved(void* thisptr) {
static auto* const* PENABLED = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_ENABLED)->getDataStaticPtr();
if (**PENABLED) return g_pDynamicCursors->onCursorMoved((CPointerManager*) thisptr);
if (isEnabled()) return g_pDynamicCursors->onCursorMoved((CPointerManager*) thisptr);
else return (*(origOnCursorMoved)g_pOnCursorMovedHook->m_pOriginal)(thisptr);
}
typedef void (*origSetCusorFromName)(void*, const std::string& name);
inline CFunctionHook* g_pSetCursorFromNameHook = nullptr;
void hkSetCursorFromName(void* thisptr, const std::string& name) {
if (isEnabled()) g_pDynamicCursors->setShape(name);
(*(origSetCusorFromName)g_pSetCursorFromNameHook->m_pOriginal)(thisptr, name);
}
typedef void (*origSetCursorSurface)(void*, SP<CWLSurface>, const Vector2D&);
inline CFunctionHook* g_pSetCursorSurfaceHook = nullptr;
void hkSetCursorSurface(void* thisptr, SP<CWLSurface> surf, const Vector2D& hotspot) {
if (isEnabled()) g_pDynamicCursors->unsetShape();
(*(origSetCursorSurface)g_pSetCursorSurfaceHook->m_pOriginal)(thisptr, surf, hotspot);
}
/* hooks a function hook */
CFunctionHook* hook(std::string name, void* function) {
CFunctionHook* hook(std::string name, std::string object, void* function) {
auto names = HyprlandAPI::findFunctionsByName(PHANDLE, name);
auto match = names.at(0);
Debug::log(LOG, "[dynamic-cursors] hooking on {} for {}", match.signature, name);
// we hook on member functions, so search for them
for (auto match : names) {
if (!match.demangled.starts_with(object)) continue;
auto hook = HyprlandAPI::createFunctionHook(PHANDLE, match.address, function);
hook->hook();
Debug::log(LOG, "[dynamic-cursors] hooking on {} for {}::{}", match.demangled, object, name);
return hook;
auto hook = HyprlandAPI::createFunctionHook(PHANDLE, match.address, function);
hook->hook();
return hook;
}
Debug::log(ERR, "Could not find hooking candidate for {}::{}", object, name);
throw std::runtime_error("no hook candidate found");
}
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
@ -80,40 +97,46 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
}
// setup config
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_ENABLED, Hyprlang::INT{1});
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_MODE, Hyprlang::STRING{"tilt"});
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_THRESHOLD, Hyprlang::INT{2});
startConfig();
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_SHAKE, Hyprlang::INT{1});
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_SHAKE_NEAREST, Hyprlang::INT{1});
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_SHAKE_EFFECTS, Hyprlang::INT{0});
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_SHAKE_IPC, Hyprlang::INT{0});
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_SHAKE_THRESHOLD, Hyprlang::FLOAT{4});
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_SHAKE_FACTOR, Hyprlang::FLOAT{1.5});
addConfig(CONFIG_ENABLED, true);
addConfig(CONFIG_MODE, "tilt");
addConfig(CONFIG_THRESHOLD, 2);
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_TILT_FUNCTION, Hyprlang::STRING{"negative_quadratic"});
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_TILT_LIMIT, Hyprlang::INT{5000});
addConfig(CONFIG_SHAKE, true);
addConfig(CONFIG_SHAKE_NEAREST, true);
addConfig(CONFIG_SHAKE_EFFECTS, false);
addConfig(CONFIG_SHAKE_IPC, false);
addConfig(CONFIG_SHAKE_THRESHOLD, 4.0f);
addConfig(CONFIG_SHAKE_FACTOR, 1.5f);
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_STRETCH_FUNCTION, Hyprlang::STRING{"negative_quadratic"});
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_STRETCH_LIMIT, Hyprlang::INT{3000});
addShapeConfig(CONFIG_TILT_FUNCTION, "negative_quadratic");
addShapeConfig(CONFIG_TILT_LIMIT, 5000);
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_ROTATE_LENGTH, Hyprlang::INT{20});
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_ROTATE_OFFSET, Hyprlang::FLOAT{0});
addShapeConfig(CONFIG_STRETCH_FUNCTION, "negative_quadratic");
addShapeConfig(CONFIG_STRETCH_LIMIT, 3000);
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_HW_DEBUG, Hyprlang::INT{0});
addShapeConfig(CONFIG_ROTATE_LENGTH, 20);
addShapeConfig(CONFIG_ROTATE_OFFSET, 0.0f);
HyprlandAPI::reloadConfig();
addConfig(CONFIG_HW_DEBUG, false);
addRulesConfig();
finishConfig();
// init things
g_pDynamicCursors = std::make_unique<CDynamicCursors>();
// try hooking
try {
g_pRenderSoftwareCursorsForHook = hook("renderSoftwareCursorsFor", (void*) &hkRenderSoftwareCursorsFor);
g_pDamageIfSoftwareHook = hook("damageIfSoftware", (void*) &hkDamageIfSoftware);
g_pRenderHWCursorBufferHook = hook("renderHWCursorBuffer", (void*) &hkRenderHWCursorBuffer);
g_pSetHWCursorBufferHook = hook("setHWCursorBuffer", (void*) &hkSetHWCursorBuffer);
g_pOnCursorMovedHook = hook("onCursorMoved", (void*) &hkOnCursorMoved);
g_pRenderSoftwareCursorsForHook = hook("renderSoftwareCursorsFor", "CPointerManager", (void*) &hkRenderSoftwareCursorsFor);
g_pDamageIfSoftwareHook = hook("damageIfSoftware", "CPointerManager", (void*) &hkDamageIfSoftware);
g_pRenderHWCursorBufferHook = hook("renderHWCursorBuffer", "CPointerManager", (void*) &hkRenderHWCursorBuffer);
g_pSetHWCursorBufferHook = hook("setHWCursorBuffer", "CPointerManager", (void*) &hkSetHWCursorBuffer);
g_pOnCursorMovedHook = hook("onCursorMoved", "CPointerManager", (void*) &hkOnCursorMoved);
g_pSetCursorFromNameHook = hook("setCursorFromName", "CCursorManager", (void*) &hkSetCursorFromName);
g_pSetCursorSurfaceHook = hook("setCursorSurface", "CCursorManager", (void*) &hkSetCursorSurface);
} catch (...) {
HyprlandAPI::addNotification(PHANDLE, "[dynamic-cursors] Failed to load, hooks could not be made!", CColor{1.0, 0.2, 0.2, 1.0}, 5000);
throw std::runtime_error("hooks failed");

View file

@ -1,4 +1,6 @@
#include "../globals.hpp"
#include "../config/config.hpp"
#include "src/macros.hpp"
#include <cmath>
#include "ModeRotate.hpp"
EModeUpdate CModeRotate::strategy() {
@ -6,8 +8,10 @@ EModeUpdate CModeRotate::strategy() {
}
SModeResult CModeRotate::update(Vector2D pos) {
static auto* const* PLENGTH = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_ROTATE_LENGTH)->getDataStaticPtr();
static auto* const* POFFSET = (Hyprlang::FLOAT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_ROTATE_OFFSET)->getDataStaticPtr();
static auto* const* PLENGTH = (Hyprlang::INT* const*) getConfig(CONFIG_ROTATE_LENGTH);
static auto* const* POFFSET = (Hyprlang::FLOAT* const*) getConfig(CONFIG_ROTATE_OFFSET);
auto length = g_pShapeRuleHandler->getIntOr(CONFIG_ROTATE_LENGTH, **PLENGTH);
auto offset = g_pShapeRuleHandler->getFloatOr(CONFIG_ROTATE_OFFSET, **POFFSET);
// translate to origin
end.x -= pos.x;
@ -19,14 +23,14 @@ SModeResult CModeRotate::update(Vector2D pos) {
end.y /= size;
// scale to length
end.x *= **PLENGTH;
end.y *= **PLENGTH;
end.x *= length;
end.y *= length;
// calculate angle
double angle = -std::atan(end.x / end.y);
if (end.y > 0) angle += PI;
angle += PI;
angle += **POFFSET * ((2 * PI) / 360); // convert to radiants
angle += offset * ((2 * PI) / 360); // convert to radiants
// translate back
end.x += pos.x;

View file

@ -1,6 +1,6 @@
#include "ModeStretch.hpp"
#include "utils.hpp"
#include "../globals.hpp"
#include "../config/config.hpp"
#include <hyprland/src/Compositor.hpp>
EModeUpdate CModeStretch::strategy() {
@ -8,8 +8,10 @@ EModeUpdate CModeStretch::strategy() {
}
SModeResult CModeStretch::update(Vector2D pos) {
static auto const* PFUNCTION = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_STRETCH_FUNCTION)->getDataStaticPtr();
static auto* const* PLIMIT = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_STRETCH_LIMIT)->getDataStaticPtr();
static auto const* PFUNCTION = (Hyprlang::STRING const*) getConfig(CONFIG_STRETCH_FUNCTION);
static auto* const* PLIMIT = (Hyprlang::INT* const*) getConfig(CONFIG_STRETCH_LIMIT);
auto function = g_pShapeRuleHandler->getStringOr(CONFIG_STRETCH_FUNCTION, *PFUNCTION);
auto limit = g_pShapeRuleHandler->getIntOr(CONFIG_STRETCH_LIMIT, **PLIMIT);
// create samples array
int max = g_pHyprRenderer->m_pMostHzMonitor->refreshRate / 10; // 100ms worth of history
@ -29,7 +31,7 @@ SModeResult CModeStretch::update(Vector2D pos) {
if (speed.y > 0) angle += PI;
if (mag == 0) angle = 0;
double scale = activation(*PFUNCTION, **PLIMIT, mag);
double scale = activation(function, limit, mag);
auto result = SModeResult();
result.stretch.angle = angle;

View file

@ -1,6 +1,6 @@
#include "ModeTilt.hpp"
#include "utils.hpp"
#include "../globals.hpp"
#include "../config/config.hpp"
#include <hyprland/src/Compositor.hpp>
EModeUpdate CModeTilt::strategy() {
@ -8,8 +8,10 @@ EModeUpdate CModeTilt::strategy() {
}
SModeResult CModeTilt::update(Vector2D pos) {
static auto const* PFUNCTION = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_TILT_FUNCTION)->getDataStaticPtr();
static auto* const* PMASS = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_TILT_LIMIT)->getDataStaticPtr();
static auto const* PFUNCTION = (Hyprlang::STRING const*) getConfig(CONFIG_TILT_FUNCTION);
static auto* const* PLIMIT = (Hyprlang::INT* const*) getConfig(CONFIG_TILT_LIMIT);
auto function = g_pShapeRuleHandler->getStringOr(CONFIG_TILT_FUNCTION, *PFUNCTION);
auto limit = g_pShapeRuleHandler->getIntOr(CONFIG_TILT_LIMIT, **PLIMIT);
// create samples array
int max = g_pHyprRenderer->m_pMostHzMonitor->refreshRate / 10; // 100ms worth of history
@ -25,6 +27,6 @@ SModeResult CModeTilt::update(Vector2D pos) {
double speed = (samples[current].x - samples[first].x) / 0.1;
auto result = SModeResult();
result.rotation = activation(*PFUNCTION, **PMASS, speed) * (PI / 3); // 120° in both directions
result.rotation = activation(function, limit, speed) * (PI / 3); // 120° in both directions
return result;
}

View file

@ -1,12 +1,13 @@
#include "../globals.hpp"
#include "../config/config.hpp"
#include "src/managers/EventManager.hpp"
#include "Shake.hpp"
#include <hyprland/src/Compositor.hpp>
double CShake::update(Vector2D pos) {
static auto* const* PTHRESHOLD = (Hyprlang::FLOAT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_SHAKE_THRESHOLD)->getDataStaticPtr();
static auto* const* PFACTOR = (Hyprlang::FLOAT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_SHAKE_FACTOR)->getDataStaticPtr();
static auto* const* PIPC = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_SHAKE_IPC)->getDataStaticPtr();
static auto* const* PTHRESHOLD = (Hyprlang::FLOAT* const*) getConfig(CONFIG_SHAKE_THRESHOLD);
static auto* const* PFACTOR = (Hyprlang::FLOAT* const*) getConfig(CONFIG_SHAKE_FACTOR);
static auto* const* PIPC = (Hyprlang::INT* const*) getConfig(CONFIG_SHAKE_IPC);
int max = g_pHyprRenderer->m_pMostHzMonitor->refreshRate; // 1s worth of history
samples.resize(max);