mirror of
https://github.com/virtcode/hypr-dynamic-cursors
synced 2025-09-19 16:13:21 +02:00
parent
c13cbd5ed2
commit
94eaf75d09
8 changed files with 80 additions and 2 deletions
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
27
src/main.cpp
27
src/main.cpp
|
@ -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"};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue