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 https://github.com/VirtCode/hypr-dynamic-cursors/assets/41426325/7b8289e7-9dd2-4b57-b406-4fa28779a260
### shake to find ### 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 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). - **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. - **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 ## 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. > **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 "../globals.hpp"
#include "../cursor.hpp" #include "../cursor.hpp"
#include "SharedDefs.hpp"
#include "debug/Log.hpp"
#include "src/render/Renderer.hpp" #include "src/render/Renderer.hpp"
#include "config.hpp" #include "config.hpp"
#include <hyprland/src/plugins/PluginAPI.hpp> #include <hyprland/src/plugins/PluginAPI.hpp>
@ -74,3 +76,17 @@ void addRulesConfig() {
void finishConfig() { void finishConfig() {
HyprlandAPI::reloadConfig(); 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 #pragma once
#include <functional>
#include <hyprlang.hpp> #include <hyprlang.hpp>
#include <hyprutils/string/VarList.hpp>
#include "ShapeRule.hpp" #include "ShapeRule.hpp"
#define NAMESPACE "plugin:dynamic-cursors:" #define NAMESPACE "plugin:dynamic-cursors:"
@ -37,6 +39,8 @@
#define CONFIG_SHAPERULE "shaperule" #define CONFIG_SHAPERULE "shaperule"
#define CONFIG_DISPATCHER_MAGNIFY "magnify"
/* is the plugin enabled */ /* is the plugin enabled */
bool isEnabled(); bool isEnabled();
@ -59,3 +63,6 @@ void* const* getConfig(std::string name);
/* get static pointer a hyprland config value */ /* get static pointer a hyprland config value */
void* const* getHyprlandConfig(std::string name); 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() { void CDynamicCursors::setMove() {
isMove = true; 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 */ /* hook on move, indicate that next onCursorMoved is actual move */
void setMove(); void setMove();
void dispatchMagnify(std::optional<int> duration, std::optional<float> size);
private: private:
SP<CEventLoopTimer> tick; SP<CEventLoopTimer> tick;

View file

@ -5,6 +5,8 @@
#include <hyprland/src/helpers/Monitor.hpp> #include <hyprland/src/helpers/Monitor.hpp>
#include <hyprland/src/Compositor.hpp> #include <hyprland/src/Compositor.hpp>
#include <hyprlang.hpp> #include <hyprlang.hpp>
#include <optional>
#include <string>
#include <unistd.h> #include <unistd.h>
#include "globals.hpp" #include "globals.hpp"
@ -165,6 +167,31 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
throw std::runtime_error("hooks failed"); 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"}; 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(); 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) { void CShake::warp(Vector2D old, Vector2D pos) {
auto delta = pos - old; auto delta = pos - old;

View file

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