hypr-dynamic-cursors/src/main.cpp

164 lines
7.4 KiB
C++
Raw Normal View History

2024-06-21 13:40:57 +02:00
#include <hyprland/src/helpers/memory/Memory.hpp>
#include <hyprland/src/plugins/HookSystem.hpp>
#include <hyprland/src/plugins/PluginAPI.hpp>
#include <hyprland/src/helpers/Monitor.hpp>
2024-06-26 17:14:16 +02:00
#include <hyprland/src/Compositor.hpp>
2024-06-21 16:06:55 +02:00
#include <hyprlang.hpp>
2024-06-21 13:40:57 +02:00
#include <unistd.h>
#include "globals.hpp"
2024-06-21 16:06:55 +02:00
#include "cursor.hpp"
2024-07-03 00:38:50 +02:00
#include "config/config.hpp"
#include "src/debug/Log.hpp"
2024-06-26 17:14:16 +02:00
#include "src/managers/PointerManager.hpp"
#include "src/version.h"
2024-06-21 13:40:57 +02:00
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) {
2024-07-03 00:38:50 +02:00
if (isEnabled()) g_pDynamicCursors->renderSoftware((CPointerManager*) thisptr, pMonitor, now, damage, overridePos);
else (*(origRenderSofwareCursorsFor)g_pRenderSoftwareCursorsForHook->m_pOriginal)(thisptr, pMonitor, now, damage, overridePos);
2024-06-21 16:36:10 +02:00
}
typedef void (*origDamageIfSoftware)(void*);
inline CFunctionHook* g_pDamageIfSoftwareHook = nullptr;
void hkDamageIfSoftware(void* thisptr) {
2024-07-03 00:38:50 +02:00
if (isEnabled()) g_pDynamicCursors->damageSoftware((CPointerManager*) thisptr);
else (*(origDamageIfSoftware)g_pDamageIfSoftwareHook->m_pOriginal)(thisptr);
2024-06-21 13:40:57 +02:00
}
2024-07-21 15:38:46 +02:00
typedef SP<Aquamarine::IBuffer> (*origRenderHWCursorBuffer)(void*, SP<CPointerManager::SMonitorPointerState>, SP<CTexture>);
inline CFunctionHook* g_pRenderHWCursorBufferHook = nullptr;
2024-07-21 15:38:46 +02:00
SP<Aquamarine::IBuffer> hkRenderHWCursorBuffer(void* thisptr, SP<CPointerManager::SMonitorPointerState> state, SP<CTexture> texture) {
2024-07-03 00:38:50 +02:00
if (isEnabled()) return g_pDynamicCursors->renderHardware((CPointerManager*) thisptr, state, texture);
else return (*(origRenderHWCursorBuffer)g_pRenderHWCursorBufferHook->m_pOriginal)(thisptr, state, texture);
}
2024-07-21 15:38:46 +02:00
typedef bool (*origSetHWCursorBuffer)(void*, SP<CPointerManager::SMonitorPointerState>, SP<Aquamarine::IBuffer>);
inline CFunctionHook* g_pSetHWCursorBufferHook = nullptr;
2024-07-21 15:38:46 +02:00
bool hkSetHWCursorBuffer(void* thisptr, SP<CPointerManager::SMonitorPointerState> state, SP<Aquamarine::IBuffer> buffer) {
2024-07-03 00:38:50 +02:00
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) {
2024-07-03 00:38:50 +02:00
if (isEnabled()) return g_pDynamicCursors->onCursorMoved((CPointerManager*) thisptr);
else return (*(origOnCursorMoved)g_pOnCursorMovedHook->m_pOriginal)(thisptr);
}
2024-07-03 00:38:50 +02:00
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);
}
2024-08-25 22:58:55 +02:00
typedef void (*origMove)(void*, const Vector2D&);
inline CFunctionHook* g_pMoveHook = nullptr;
void hkMove(void* thisptr, const Vector2D& deltaLogical) {
if (isEnabled()) g_pDynamicCursors->setMove();
(*(origMove)g_pMoveHook->m_pOriginal)(thisptr, deltaLogical);
}
/* hooks a function hook */
2024-07-03 00:38:50 +02:00
CFunctionHook* hook(std::string name, std::string object, void* function) {
auto names = HyprlandAPI::findFunctionsByName(PHANDLE, name);
2024-06-27 17:21:39 +02:00
2024-07-03 00:38:50 +02:00
// we hook on member functions, so search for them
for (auto match : names) {
if (!match.demangled.starts_with(object)) continue;
Debug::log(LOG, "[dynamic-cursors] hooking on {} for {}::{}", match.demangled, object, name);
2024-06-26 17:14:16 +02:00
2024-07-03 00:38:50 +02:00
auto hook = HyprlandAPI::createFunctionHook(PHANDLE, match.address, function);
hook->hook();
2024-06-26 17:14:16 +02:00
2024-07-03 00:38:50 +02:00
return hook;
}
Debug::log(ERR, "Could not find hooking candidate for {}::{}", object, name);
throw std::runtime_error("no hook candidate found");
2024-06-26 17:14:16 +02:00
}
2024-06-21 13:40:57 +02:00
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
PHANDLE = handle;
// check that header version aligns with running version
const std::string HASH = __hyprland_api_get_hash();
2024-06-21 13:40:57 +02:00
if (HASH != GIT_COMMIT_HASH) {
HyprlandAPI::addNotification(PHANDLE, "[dynamic-cursors] Failed to load, mismatched headers!", CColor{1.0, 0.2, 0.2, 1.0}, 5000);
HyprlandAPI::addNotification(PHANDLE, std::format("[dynamic-cursors] Built with: {}, running: {}", GIT_COMMIT_HASH, HASH), CColor{1.0, 0.2, 0.2, 1.0}, 5000);
throw std::runtime_error("version mismatch");
2024-06-21 13:40:57 +02:00
}
// setup config
2024-07-03 00:38:50 +02:00
startConfig();
addConfig(CONFIG_ENABLED, true);
addConfig(CONFIG_MODE, "tilt");
addConfig(CONFIG_THRESHOLD, 2);
2024-06-26 18:02:09 +02:00
2024-07-03 00:38:50 +02:00
addConfig(CONFIG_SHAKE, true);
addConfig(CONFIG_SHAKE_NEAREST, true);
addConfig(CONFIG_SHAKE_EFFECTS, false);
addConfig(CONFIG_SHAKE_IPC, false);
2024-08-25 20:00:16 +02:00
addConfig(CONFIG_SHAKE_THRESHOLD, 6.0f);
addConfig(CONFIG_SHAKE_BASE, 4.0F);
addConfig(CONFIG_SHAKE_SPEED, 4.0F);
addConfig(CONFIG_SHAKE_INFLUENCE, 0.0F);
addConfig(CONFIG_SHAKE_LIMIT, 0.0F);
addConfig(CONFIG_SHAKE_TIMEOUT, 2000);
2024-06-27 17:21:39 +02:00
2024-07-03 00:38:50 +02:00
addShapeConfig(CONFIG_TILT_FUNCTION, "negative_quadratic");
addShapeConfig(CONFIG_TILT_LIMIT, 5000);
2024-06-26 18:02:09 +02:00
2024-07-03 00:38:50 +02:00
addShapeConfig(CONFIG_STRETCH_FUNCTION, "negative_quadratic");
addShapeConfig(CONFIG_STRETCH_LIMIT, 3000);
2024-07-02 15:35:37 +02:00
2024-07-03 00:38:50 +02:00
addShapeConfig(CONFIG_ROTATE_LENGTH, 20);
addShapeConfig(CONFIG_ROTATE_OFFSET, 0.0f);
2024-06-26 18:02:09 +02:00
2024-07-03 00:38:50 +02:00
addConfig(CONFIG_HW_DEBUG, false);
2024-08-25 22:58:55 +02:00
addConfig(CONFIG_IGNORE_WARPS, true);
2024-06-21 14:32:42 +02:00
2024-07-03 00:38:50 +02:00
addRulesConfig();
finishConfig();
// init things
g_pDynamicCursors = std::make_unique<CDynamicCursors>();
// try hooking
try {
2024-07-03 00:38:50 +02:00
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);
2024-08-25 22:58:55 +02:00
g_pMoveHook = hook("moveER", "CPointerManager", (void*) &hkMove); // this `ER` makes it faster because `move` is very generic
2024-07-03 00:38:50 +02:00
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");
}
2024-06-21 13:40:57 +02:00
return {"dynamic-cursors", "a plugin to make your hyprland cursor more realistic, also adds shake to find", "Virt", "0.1"};
2024-06-21 13:40:57 +02:00
}
APICALL EXPORT void PLUGIN_EXIT() { }
2024-06-21 13:40:57 +02:00
// Do NOT change this function.
APICALL EXPORT std::string PLUGIN_API_VERSION() {
return HYPRLAND_API_VERSION;
}