mirror of
https://github.com/virtcode/hypr-dynamic-cursors
synced 2025-09-20 00:23:22 +02:00
feat: load hyprcursor shapes on a seperate thread
This commit is contained in:
parent
fd62146299
commit
261bc1668f
3 changed files with 59 additions and 18 deletions
|
@ -271,9 +271,10 @@ To use hyprcursor for magnified shapes, the following must be met:
|
|||
|
||||
As mentioned, there are some caveats to it. Here are the most common ones:
|
||||
- **Still pixelated on GTK apps and xwayland** - These apps are using clientside cursors, so the program itself is specifying the cursor shape, hence we cannot load a higher resolution for it. You can set a specific shape to show in these cases with the `fallback` 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.
|
||||
|
||||
Loading a cursor theme at a high resolution is relatively resource intensive. This plugin thus loads the theme asynchronously on a seperate thread, meaning your session will stay interactive during this time. But this means that when loading the plugin or changing cursor theme, your CPU might spike momentarily and the high-resolution theme will only be available after a short time (usually just a couple of seconds).
|
||||
|
||||
### 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
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#include "globals.hpp"
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <future>
|
||||
#include <hyprcursor/hyprcursor.hpp>
|
||||
#include <hyprlang.hpp>
|
||||
|
||||
#include <hyprland/src/managers/eventLoop/EventLoopTimer.hpp> // required so we don't "unprivate" chrono
|
||||
#include <hyprutils/memory/UniquePtr.hpp>
|
||||
#define private public
|
||||
#include <hyprland/src/managers/CursorManager.hpp>
|
||||
#undef private
|
||||
|
@ -53,36 +56,70 @@ void CHighresHandler::update() {
|
|||
if (manager && loadedName == name && loadedSize == size)
|
||||
return;
|
||||
|
||||
// we are currently loading another theme
|
||||
if (managerFuture) {
|
||||
// in this case we don't do anything as proceeding would block until the future is done (thanks cpp apis)
|
||||
// we just skip the update, but when retrieving the future we check again and then these changes will be loaded
|
||||
|
||||
Debug::log(LOG, "Skipping hyprcursor theme reload for dynamic cursors because one is already being loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
style = Hyprcursor::SCursorStyleInfo { size };
|
||||
|
||||
loadedSize = size;
|
||||
loadedName = name;
|
||||
|
||||
Debug::log(LOG, "Creating future for loading hyprcursor theme for dynamic cursors");
|
||||
|
||||
auto fut = std::async(std::launch::async, [=, style = style] () -> UP<Hyprcursor::CHyprcursorManager> {
|
||||
Debug::log(INFO, "Starting to load hyprcursor theme '{}' of size {} for dynamic cursors asynchronously ...", name, size);
|
||||
auto time = std::chrono::system_clock::now();
|
||||
|
||||
auto options = Hyprcursor::SManagerOptions();
|
||||
options.logFn = hcLogger;
|
||||
options.allowDefaultFallback = true;
|
||||
|
||||
manager = makeUnique<Hyprcursor::CHyprcursorManager>(name.empty() ? nullptr : name.c_str(), options);
|
||||
if (!manager->valid()) {
|
||||
Debug::log(ERR, "Hyprcursor for dynamic cursors failed loading theme \"{}\", falling back to pixelated trash.", name);
|
||||
auto manager = makeUnique<Hyprcursor::CHyprcursorManager>(name.empty() ? nullptr : name.c_str(), options);
|
||||
|
||||
manager = nullptr;
|
||||
texture = nullptr;
|
||||
buffer = nullptr;
|
||||
return;
|
||||
if (!manager->valid()) {
|
||||
Debug::log(ERR, "... hyprcursor for dynamic cursors failed loading theme '{}', falling back to pixelated trash.", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto time = std::chrono::system_clock::now();
|
||||
|
||||
Debug::log(INFO, "Loading hyprcursor theme {} of size {} for dynamic cursors, this might take a while!", name, size);
|
||||
style = Hyprcursor::SCursorStyleInfo { size };
|
||||
manager->loadThemeStyle(style);
|
||||
loadedSize = size;
|
||||
loadedName = name;
|
||||
|
||||
float ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - time).count();
|
||||
Debug::log(INFO, "Loading finished, took {}ms", ms);
|
||||
Debug::log(INFO, "... hyprcursor for dynamic cursors loading finished, took {}ms", ms);
|
||||
|
||||
return manager;
|
||||
});
|
||||
|
||||
manager = nullptr; // free old manager
|
||||
managerFuture = makeUnique<std::future<UP<Hyprcursor::CHyprcursorManager>>>(std::move(fut));
|
||||
}
|
||||
|
||||
void CHighresHandler::loadShape(const std::string& name) {
|
||||
static auto const* PFALLBACK = (Hyprlang::STRING const*) getConfig(CONFIG_HIGHRES_FALLBACK);
|
||||
|
||||
if (!manager) return;
|
||||
if (!manager) {
|
||||
// don't show old, potentially outdated shapes
|
||||
texture = nullptr;
|
||||
buffer = nullptr;
|
||||
|
||||
if (!managerFuture || managerFuture->wait_for(std::chrono::seconds(0)) != std::future_status::ready) return;
|
||||
|
||||
Debug::log(INFO, "Future for hyprcursor theme for dynamic cursors is ready, using new theme");
|
||||
manager = managerFuture->get();
|
||||
managerFuture = nullptr;
|
||||
|
||||
if (!manager) return; // could've failed
|
||||
else {
|
||||
// in case someone has updated the theme again in the meantime
|
||||
update();
|
||||
if (!manager) return; // new manager could be on the way
|
||||
}
|
||||
}
|
||||
|
||||
Hyprcursor::SCursorShapeData shape = manager->getShape(name.c_str(), style);
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <future>
|
||||
#include <hyprland/src/managers/CursorManager.hpp>
|
||||
#include <hyprland/src/render/Texture.hpp>
|
||||
#include <hyprland/src/helpers/memory/Memory.hpp>
|
||||
|
@ -23,6 +24,8 @@ private:
|
|||
bool enabled = true;
|
||||
|
||||
Hyprcursor::SCursorStyleInfo style;
|
||||
|
||||
UP<std::future<UP<Hyprcursor::CHyprcursorManager>>> managerFuture;
|
||||
UP<Hyprcursor::CHyprcursorManager> manager;
|
||||
|
||||
/* keep track of loaded theme so we don't reload unnessecarily (<- i'm almost certain there's a typo in this word) */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue