feat: add dispatcher to trigger magnification

closes: #51
This commit is contained in:
Virt 2025-01-10 22:06:23 +01:00
commit 94eaf75d09
8 changed files with 80 additions and 2 deletions

View file

@ -23,7 +23,7 @@ This mode tries recreating the stretching and squishing that is done to moving o
https://github.com/VirtCode/hypr-dynamic-cursors/assets/41426325/7b8289e7-9dd2-4b57-b406-4fa28779a260
### shake to find
The plugin supports shake to find, akin to how KDE Plasma, MacOS, etc. do it. It can also be extensively configured and is enabled by default. It also supports using [hyprcursor](https://github.com/hyprwm/hyprcursor) for high resolution cursor images. If you only want shake to find, and no weird cursor behaviour, you can disable the above modes with the mode `none`.
The plugin supports shake to find, akin to how KDE Plasma, MacOS, etc. do it. It can also be extensively configured and is enabled by default. It also supports using [hyprcursor](https://github.com/hyprwm/hyprcursor) for high resolution cursor images. The magnification can also be triggered as a dispatcher instead of on shake. If you only want shake to find, and no weird cursor behaviour, you can disable the above modes with the mode `none`.
https://github.com/user-attachments/assets/1346101e-4e62-4ba2-a1df-5940e0706514
@ -274,6 +274,12 @@ As mentioned, there are some caveats to it. Here are the most common ones:
- **Hyprland lags when loading the plugin** - Loading a set of high resolution cursor shapes takes some time. This means your session will freeze while the theme is being loaded. You can try setting a custom / lower `resolution` option (see config).
- **Blurred at very large sizes** - The high resolution cursors are preloaded at a fixed size. If you magnify your cursor beyond this size, your cursors will look blurry. You can increase the preload size with the `resolution` option (see config), at the expense of some memory and higher loading times.
### dispatchers
This plugin has a couple of dispatchers to trigger certain effects with a keybind. Here's a list:
- `plugin:dynamic-cursors:magnify` with arguments `duration?, size?` triggers cursor magnification like on a shake
- `duration` (optional): overrides duration in milliseconds to stay magnified
- `size` (optional): overrides magnification factor
## performance
> **TL;DR:** Hardware cursor performance is about the same as if an animated cursor shape was shown whenever you move your mouse. Sofware cursor performance is not impacted. When the cursor is magnified during a shake, the compositor will temporarily switch to software cursors.

View file

@ -1,5 +1,7 @@
#include "../globals.hpp"
#include "../cursor.hpp"
#include "SharedDefs.hpp"
#include "debug/Log.hpp"
#include "src/render/Renderer.hpp"
#include "config.hpp"
#include <hyprland/src/plugins/PluginAPI.hpp>
@ -74,3 +76,17 @@ void addRulesConfig() {
void finishConfig() {
HyprlandAPI::reloadConfig();
}
void addDispatcher(std::string name, std::function<std::optional<std::string>(Hyprutils::String::CVarList)> handler) {
HyprlandAPI::addDispatcherV2(PHANDLE, NAMESPACE + name, [=](std::string in) {
auto error = handler(CVarList(in));
SDispatchResult result;
if (error.has_value()) {
Debug::log(ERR, "[dynamic-cursors] dispatcher {} recieved invalid args: {}", name, error.value());
result.error = error.value();
}
return result;
});
}

View file

@ -1,6 +1,8 @@
#pragma once
#include <functional>
#include <hyprlang.hpp>
#include <hyprutils/string/VarList.hpp>
#include "ShapeRule.hpp"
#define NAMESPACE "plugin:dynamic-cursors:"
@ -37,6 +39,8 @@
#define CONFIG_SHAPERULE "shaperule"
#define CONFIG_DISPATCHER_MAGNIFY "magnify"
/* is the plugin enabled */
bool isEnabled();
@ -59,3 +63,6 @@ void* const* getConfig(std::string name);
/* get static pointer a hyprland config value */
void* const* getHyprlandConfig(std::string name);
/* adds a dispatcher */
void addDispatcher(std::string name, std::function<std::optional<std::string>(Hyprutils::String::CVarList)> handler);

View file

@ -516,3 +516,10 @@ void CDynamicCursors::calculate(EModeUpdate type) {
void CDynamicCursors::setMove() {
isMove = true;
}
void CDynamicCursors::dispatchMagnify(std::optional<int> duration, std::optional<float> size) {
static auto* const* PSHAKE = (Hyprlang::INT* const*) getConfig(CONFIG_SHAKE);
if (!**PSHAKE) return;
shake.force(duration, size);
}

View file

@ -43,6 +43,8 @@ class CDynamicCursors {
/* hook on move, indicate that next onCursorMoved is actual move */
void setMove();
void dispatchMagnify(std::optional<int> duration, std::optional<float> size);
private:
SP<CEventLoopTimer> tick;

View file

@ -5,6 +5,8 @@
#include <hyprland/src/helpers/Monitor.hpp>
#include <hyprland/src/Compositor.hpp>
#include <hyprlang.hpp>
#include <optional>
#include <string>
#include <unistd.h>
#include "globals.hpp"
@ -165,6 +167,31 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
throw std::runtime_error("hooks failed");
}
// add dispatchers
addDispatcher(CONFIG_DISPATCHER_MAGNIFY, [&](CVarList args) {
std::optional<std::string> error;
std::optional<int> duration;
std::optional<float> size;
try {
auto it = args.begin();
if (it != args.end() && *it != "") {
duration = std::stoi(*it);
it++;
if (it != args.end())
size = std::stof(*it);
}
} catch (...) {
error = "types did not match";
}
g_pDynamicCursors->dispatchMagnify(duration, size);
return error;
});
return {"dynamic-cursors", "a plugin to make your hyprland cursor more realistic, also adds shake to find", "Virt", "0.1"};
}

View file

@ -110,6 +110,15 @@ double CShake::update(Vector2D pos) {
return this->zoom->value();
}
void CShake::force(std::optional<int> duration, std::optional<float> size) {
static auto* const* PTIMEOUT = (Hyprlang::INT* const*) getConfig(CONFIG_SHAKE_TIMEOUT);
static auto* const* PBASE = (Hyprlang::FLOAT* const*) getConfig(CONFIG_SHAKE_BASE);
started = true;
*this->zoom = size.value_or(**PBASE);
this->end = steady_clock::now() + milliseconds(duration.value_or(**PTIMEOUT));
}
void CShake::warp(Vector2D old, Vector2D pos) {
auto delta = pos - old;

View file

@ -1,4 +1,5 @@
#include "helpers/AnimatedVariable.hpp"
#include <bits/getopt_ext.h>
#include <hyprutils/animation/AnimatedVariable.hpp>
#include <hyprutils/math/Vector2D.hpp>
#include <vector>
@ -20,6 +21,9 @@ class CShake {
/* called when a cursor warp has happened (to avoid magnifying on warps) */
void warp(Vector2D old, Vector2D pos);
/* force magnification regardless of speed now */
void force(std::optional<int> duration, std::optional<float> size);
private:
/* tracks whether the current shake has already been announced in the ipc */
bool ipc = false;