mirror of
https://github.com/virtcode/hypr-dynamic-cursors
synced 2025-09-20 00:23:22 +02:00
feat: clearer config naming and docs
This commit is contained in:
parent
416f6efc2f
commit
086c9a8c48
4 changed files with 80 additions and 45 deletions
65
README.md
65
README.md
|
@ -1,26 +1,34 @@
|
||||||
# hypr-dynamic-cursors
|
# hypr-dynamic-cursors
|
||||||
This plugin makes your cursor more realistic by simulating how it would behave if it was an actual object being dragged across your screen. This means that it will change orientation based on in which direction you are moving.
|
This plugin makes your cursor more realistic by simulating how it would behave if it was an actual object being dragged across your screen. This means that your cursor can change based on how it is used, e.g. tilt in the direction you are moving or straight out rotate towards it.
|
||||||
|
|
||||||
Why did I implement this again?
|
Why did I implement this again?
|
||||||
|
|
||||||
## showcase
|
## showcase
|
||||||
Currently, the cursor is being simulated as a stick being dragged across a surface. In action, this looks like this.
|
The plugin supports two different modes, `rotate` and `tilt`. They both are customizable and have a different base behaviour.
|
||||||
|
|
||||||
|
#### rotate
|
||||||
|
In this mode, the cursor is simulated as a stick which is dragged across the screen on one end. This means it will rotate towards the movement direction, and feels really realistic.
|
||||||
|
|
||||||
https://github.com/VirtCode/hypr-dynamic-cursor/assets/41426325/ccd6d742-8e2b-4073-a35e-318c7e19705c
|
https://github.com/VirtCode/hypr-dynamic-cursor/assets/41426325/ccd6d742-8e2b-4073-a35e-318c7e19705c
|
||||||
|
|
||||||
|
#### tilt
|
||||||
|
In this mode, the cursor is tilted based on the X direction and speed it is moving at. It was intended to simulate how an object would be affected by air drag, but implemented is only a rough approximation. This mode can also be customized extensively with different activation functions.
|
||||||
|
|
||||||
|
https://github.com/VirtCode/hypr-dynamic-cursors/assets/41426325/ae25415c-e77f-4c85-864c-2eedbfe432e3
|
||||||
|
|
||||||
## state
|
## state
|
||||||
This plugin is still very early in its development. **Currently, only the `-git` version of hyprland is supported**. There are also multiple things which may or may not be implemented in the future:
|
This plugin is still very early in its development. **Currently, only the `-git` version of hyprland is supported**. There are also multiple things which may or may not be implemented in the future:
|
||||||
|
|
||||||
- [X] Software Cursor rendering
|
- [X] software cursor rendering
|
||||||
- [X] Hardware Cursor rendering (as good as possible)
|
- [X] hardware cursor rendering (as far as possible with wlroots)
|
||||||
- [X] Stick simulation
|
- [X] stick simulation
|
||||||
- [ ] Per-shape length and starting angle (at least with serverside cursors)
|
- [X] air drag simulation
|
||||||
- [ ] Pendulum simulation
|
- [ ] pendulum simulation
|
||||||
- [X] Air Drag simulation
|
- [ ] per-shape length and starting angle (if possible)
|
||||||
|
|
||||||
If anything here sounds interesting to you, don't hesitate to contribute.
|
If anything here sounds interesting to you, don't hesitate to contribute.
|
||||||
|
|
||||||
Please note that this plugin was created more or less as a joke. I mainly wanted to see how using a rotating cursor was like. So I will not guarantee any future updates and bugfixes.
|
Please note that this plugin was created more or less as a joke. I mainly wanted to see how using a rotating or tilted cursor was like. So I will not guarantee any future updates and bugfixes.
|
||||||
|
|
||||||
## installation
|
## installation
|
||||||
Installation is supported via `hyprpm`. Supported hyprland versions are `v0.42.0` (yet unreleased) and upwards. The main branch generally tries to target `-git`.
|
Installation is supported via `hyprpm`. Supported hyprland versions are `v0.42.0` (yet unreleased) and upwards. The main branch generally tries to target `-git`.
|
||||||
|
@ -40,11 +48,36 @@ plugin:dynamic-cursors {
|
||||||
# enables the plugin
|
# enables the plugin
|
||||||
enabled = true
|
enabled = true
|
||||||
|
|
||||||
# length in px of the simulated stick used to rotate the cursor
|
# sets the cursor behaviour, supports these values:
|
||||||
# it is recommended to set this to your actual cursor size
|
# tilt - tilt the cursor based on x-velocity
|
||||||
# longer sticks feel more "drifty"
|
# rotate - rotate the cursor based on movement direction
|
||||||
length = 20
|
mode = tilt
|
||||||
|
|
||||||
|
# minimum angle difference in degrees after which the shape is changed
|
||||||
|
# smaller values are smoother, but more expensive for hw cursors
|
||||||
|
threshold = 2
|
||||||
|
|
||||||
|
# for mode = rotate
|
||||||
|
rotate {
|
||||||
|
|
||||||
|
# length in px of the simulated stick used to rotate the cursor
|
||||||
|
# most realistic if this is your actual cursor size
|
||||||
|
length = 20
|
||||||
|
}
|
||||||
|
|
||||||
|
# for mode = tilt
|
||||||
|
tilt {
|
||||||
|
|
||||||
|
# controls how powerful the tilt is, the lower the more power
|
||||||
|
# this value controls at which speed (px/s) the full tilt is reached
|
||||||
|
limit = 5000
|
||||||
|
|
||||||
|
# relationship between speed and tilt, supports these vaules:
|
||||||
|
# linear - a linear function is used
|
||||||
|
# quadratic - a quadratic function is used (most realistic to actual air drag)
|
||||||
|
# negative_quadratic - negative version of the quadratic one, feels more aggressive
|
||||||
|
function = negative_quadratic
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -57,6 +90,8 @@ Rotating the cursor can be done in the same draw call that is used to draw the c
|
||||||
**Hardware Cursors**: Medium performance impact. <br>
|
**Hardware Cursors**: Medium performance impact. <br>
|
||||||
To rotate the cursor smoothly, the cursor shape needs to be changed quite often. This is not exactly compatible with how hardware cursors are intended to work. With this plugin, the overhead of changing the cursor shape can be noticed more often, making it use more resources. Compared to normal hardware cursors, there is a big performance hit, but it is still more efficient than using software cursor though.
|
To rotate the cursor smoothly, the cursor shape needs to be changed quite often. This is not exactly compatible with how hardware cursors are intended to work. With this plugin, the overhead of changing the cursor shape can be noticed more often, making it use more resources. Compared to normal hardware cursors, there is a big performance hit, but it is still more efficient than using software cursor though.
|
||||||
|
|
||||||
|
The plugin also has a base performance impact, which is practically zero when mode is `rotate` and still low if it is `tilt`.
|
||||||
|
|
||||||
## development
|
## development
|
||||||
To work on this plugin, you can clone this repository and use the Makefile to build it. I suggest opening a nested Hyprland session, and loading the plugin there:
|
To work on this plugin, you can clone this repository and use the Makefile to build it. I suggest opening a nested Hyprland session, and loading the plugin there:
|
||||||
|
|
||||||
|
@ -64,7 +99,9 @@ To work on this plugin, you can clone this repository and use the Makefile to bu
|
||||||
make load
|
make load
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to debug hardware cursors, this plugin also has an additional configuration option, `hw_debug` which when true will show where the whole cursor buffer is, and also shows when it is updated.
|
If you want to debug hardware cursors, this plugin also has an additional configuration option, `plugin:dynamic-cursors:hw_debug` which when true will show where the whole cursor buffer is, and also shows when it is updated.
|
||||||
|
|
||||||
|
Also make sure you disable the plugin on your host session, otherwise your cursor will be rotated twice.
|
||||||
|
|
||||||
## license
|
## license
|
||||||
This plugin is licensed under the MIT License. Have a look at the `LICENSE.md` file for more information.
|
This plugin is licensed under the MIT License. Have a look at the `LICENSE.md` file for more information.
|
||||||
|
|
|
@ -198,22 +198,6 @@ bool CDynamicCursors::setHardware(CPointerManager* pointers, SP<CPointerManager:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Should the cursor be updated after move?
|
|
||||||
*/
|
|
||||||
bool shouldMove() {
|
|
||||||
static auto const* PMODE = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_MODE)->getDataStaticPtr();
|
|
||||||
return !strcmp(*PMODE, "stick");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Should the cursor be updated after tick?
|
|
||||||
*/
|
|
||||||
bool shouldUpdate() {
|
|
||||||
static auto const* PMODE = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_MODE)->getDataStaticPtr();
|
|
||||||
return !strcmp(*PMODE, "air");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Handles cursor move events.
|
Handles cursor move events.
|
||||||
*/
|
*/
|
||||||
|
@ -233,24 +217,33 @@ void CDynamicCursors::onCursorMoved(CPointerManager* pointers) {
|
||||||
m->output->impl->move_cursor(m->output, CURSORPOS.x, CURSORPOS.y);
|
m->output->impl->move_cursor(m->output, CURSORPOS.x, CURSORPOS.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldMove()) calculate();
|
static auto const* PMODE = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_MODE)->getDataStaticPtr();
|
||||||
|
if (!strcmp(*PMODE, "rotate")) calculate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Handle cursor tick events.
|
||||||
|
*/
|
||||||
void CDynamicCursors::onTick(CPointerManager* pointers) {
|
void CDynamicCursors::onTick(CPointerManager* pointers) {
|
||||||
if (shouldUpdate()) calculate();
|
static auto const* PMODE = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_MODE)->getDataStaticPtr();
|
||||||
|
|
||||||
|
if (!strcmp(*PMODE, "tilt")) calculate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDynamicCursors::calculate() {
|
void CDynamicCursors::calculate() {
|
||||||
static auto const* PMODE = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_MODE)->getDataStaticPtr();
|
static auto const* PMODE = (Hyprlang::STRING const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_MODE)->getDataStaticPtr();
|
||||||
|
static auto* const* PTHRESHOLD = (Hyprlang::INT* const*)HyprlandAPI::getConfigValue(PHANDLE, CONFIG_THRESHOLD)->getDataStaticPtr();
|
||||||
|
|
||||||
double angle = 0;
|
double angle = 0;
|
||||||
if (!strcmp(*PMODE, "stick"))
|
if (!strcmp(*PMODE, "rotate"))
|
||||||
angle = calculateStick();
|
angle = calculateStick();
|
||||||
else if (!strcmp(*PMODE, "air"))
|
else if (!strcmp(*PMODE, "tilt"))
|
||||||
angle = calculateAir();
|
angle = calculateAir();
|
||||||
|
else
|
||||||
|
Debug::log(WARN, "[dynamic-cursors] unknown mode specified");
|
||||||
|
|
||||||
// we only consider the angle changed if it is larger than 1 degree
|
// we only consider the angle changed if it is larger than 1 degree
|
||||||
if (abs(this->angle - angle) > (PI / 180)) {
|
if (abs(this->angle - angle) > ((PI / 180) * **PTHRESHOLD)) {
|
||||||
this->angle = angle;
|
this->angle = angle;
|
||||||
|
|
||||||
// damage software and change hardware cursor shape
|
// damage software and change hardware cursor shape
|
||||||
|
@ -291,9 +284,8 @@ double airFunction(double speed) {
|
||||||
if (x > mass) result = 1; // need to clamp manually, as the function would decrease again
|
if (x > mass) result = 1; // need to clamp manually, as the function would decrease again
|
||||||
|
|
||||||
result *= (speed > 0 ? 1 : -1);
|
result *= (speed > 0 ? 1 : -1);
|
||||||
} else {
|
} else
|
||||||
Debug::log(WARN, "[dynamic-cursors] unknown air function specified");
|
Debug::log(WARN, "[dynamic-cursors] unknown air function specified");
|
||||||
}
|
|
||||||
|
|
||||||
return std::clamp(result, -1.0, 1.0);
|
return std::clamp(result, -1.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
#include <hyprland/src/plugins/PluginAPI.hpp>
|
#include <hyprland/src/plugins/PluginAPI.hpp>
|
||||||
|
|
||||||
#define CONFIG_ENABLED "plugin:dynamic-cursors:enabled"
|
#define CONFIG_ENABLED "plugin:dynamic-cursors:enabled"
|
||||||
#define CONFIG_LENGTH "plugin:dynamic-cursors:length"
|
|
||||||
#define CONFIG_MODE "plugin:dynamic-cursors:mode"
|
#define CONFIG_MODE "plugin:dynamic-cursors:mode"
|
||||||
#define CONFIG_MASS "plugin:dynamic-cursors:mass"
|
#define CONFIG_THRESHOLD "plugin:dynamic-cursors:threshold"
|
||||||
#define CONFIG_FUNCTION "plugin:dynamic-cursors:function"
|
#define CONFIG_LENGTH "plugin:dynamic-cursors:rotate:length"
|
||||||
|
#define CONFIG_MASS "plugin:dynamic-cursors:tilt:limit"
|
||||||
|
#define CONFIG_FUNCTION "plugin:dynamic-cursors:tilt:function"
|
||||||
|
|
||||||
#define CONFIG_HW_DEBUG "plugin:dynamic-cursors:hw_debug"
|
#define CONFIG_HW_DEBUG "plugin:dynamic-cursors:hw_debug"
|
||||||
|
|
||||||
inline HANDLE PHANDLE = nullptr;
|
inline HANDLE PHANDLE = nullptr;
|
||||||
|
|
10
src/main.cpp
10
src/main.cpp
|
@ -108,12 +108,16 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||||||
wl_event_source_timer_update(tick, 1);
|
wl_event_source_timer_update(tick, 1);
|
||||||
|
|
||||||
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_ENABLED, Hyprlang::INT{1});
|
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_ENABLED, Hyprlang::INT{1});
|
||||||
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_MODE, Hyprlang::STRING{"air"});
|
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_MODE, Hyprlang::STRING{"tilt"});
|
||||||
|
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_THRESHOLD, Hyprlang::INT{2});
|
||||||
|
|
||||||
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_FUNCTION, Hyprlang::STRING{"negative_quadratic"});
|
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_FUNCTION, Hyprlang::STRING{"negative_quadratic"});
|
||||||
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_LENGTH, Hyprlang::INT{20});
|
|
||||||
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_HW_DEBUG, Hyprlang::INT{0});
|
|
||||||
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_MASS, Hyprlang::INT{5000});
|
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_MASS, Hyprlang::INT{5000});
|
||||||
|
|
||||||
|
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_LENGTH, Hyprlang::INT{20});
|
||||||
|
|
||||||
|
HyprlandAPI::addConfigValue(PHANDLE, CONFIG_HW_DEBUG, Hyprlang::INT{0});
|
||||||
|
|
||||||
HyprlandAPI::reloadConfig();
|
HyprlandAPI::reloadConfig();
|
||||||
|
|
||||||
return {"dynamic-cursors", "make your cursor more realistic", "Virt", "0.1"};
|
return {"dynamic-cursors", "make your cursor more realistic", "Virt", "0.1"};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue