mirror of
https://github.com/hyprwm/hyprland-plugins.git
synced 2024-11-26 03:55:58 +01:00
134 lines
5 KiB
C++
134 lines
5 KiB
C++
|
#define WLR_USE_UNSTABLE
|
||
|
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include <any>
|
||
|
#include <hyprland/src/Compositor.hpp>
|
||
|
#include <hyprland/src/Window.hpp>
|
||
|
#include <hyprland/src/config/ConfigManager.hpp>
|
||
|
#include <hyprland/src/render/Shaders.hpp>
|
||
|
|
||
|
#include "globals.hpp"
|
||
|
#include "shaders.hpp"
|
||
|
#include "trail.hpp"
|
||
|
|
||
|
// Do NOT change this function.
|
||
|
APICALL EXPORT std::string PLUGIN_API_VERSION() { return HYPRLAND_API_VERSION; }
|
||
|
|
||
|
void onNewWindow(void* self, std::any data) {
|
||
|
// data is guaranteed
|
||
|
auto* const PWINDOW = std::any_cast<CWindow*>(data);
|
||
|
|
||
|
HyprlandAPI::addWindowDecoration(PHANDLE, PWINDOW, new CTrail(PWINDOW));
|
||
|
}
|
||
|
|
||
|
GLuint CompileShader(const GLuint& type, std::string src) {
|
||
|
auto shader = glCreateShader(type);
|
||
|
|
||
|
auto shaderSource = src.c_str();
|
||
|
|
||
|
glShaderSource(shader, 1, (const GLchar**)&shaderSource, nullptr);
|
||
|
glCompileShader(shader);
|
||
|
|
||
|
GLint ok;
|
||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
|
||
|
|
||
|
if (ok == GL_FALSE) throw std::runtime_error("compileShader() failed!");
|
||
|
|
||
|
return shader;
|
||
|
}
|
||
|
|
||
|
GLuint CreateProgram(const std::string& vert, const std::string& frag) {
|
||
|
auto vertCompiled = CompileShader(GL_VERTEX_SHADER, vert);
|
||
|
|
||
|
if (!vertCompiled) throw std::runtime_error("Compiling vshader failed.");
|
||
|
|
||
|
auto fragCompiled = CompileShader(GL_FRAGMENT_SHADER, frag);
|
||
|
|
||
|
if (!fragCompiled) throw std::runtime_error("Compiling fshader failed.");
|
||
|
|
||
|
auto prog = glCreateProgram();
|
||
|
glAttachShader(prog, vertCompiled);
|
||
|
glAttachShader(prog, fragCompiled);
|
||
|
glLinkProgram(prog);
|
||
|
|
||
|
glDetachShader(prog, vertCompiled);
|
||
|
glDetachShader(prog, fragCompiled);
|
||
|
glDeleteShader(vertCompiled);
|
||
|
glDeleteShader(fragCompiled);
|
||
|
|
||
|
GLint ok;
|
||
|
glGetProgramiv(prog, GL_LINK_STATUS, &ok);
|
||
|
|
||
|
if (ok == GL_FALSE) throw std::runtime_error("createProgram() failed! GL_LINK_STATUS not OK!");
|
||
|
|
||
|
return prog;
|
||
|
}
|
||
|
|
||
|
int onTick(void* data) {
|
||
|
EMIT_HOOK_EVENT("trailTick", nullptr);
|
||
|
|
||
|
const int TIMEOUT = g_pHyprRenderer->m_pMostHzMonitor ? 1000.0 / g_pHyprRenderer->m_pMostHzMonitor->refreshRate : 16;
|
||
|
wl_event_source_timer_update(g_pGlobalState->tick, TIMEOUT);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void initGlobal() {
|
||
|
RASSERT(
|
||
|
eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)),
|
||
|
"Couldn't set current EGL!");
|
||
|
|
||
|
GLuint prog = CreateProgram(QUADTRAIL, FRAGTRAIL);
|
||
|
g_pGlobalState->trailShader.program = prog;
|
||
|
g_pGlobalState->trailShader.proj = glGetUniformLocation(prog, "proj");
|
||
|
g_pGlobalState->trailShader.tex = glGetUniformLocation(prog, "tex");
|
||
|
g_pGlobalState->trailShader.color = glGetUniformLocation(prog, "color");
|
||
|
g_pGlobalState->trailShader.texAttrib = glGetAttribLocation(prog, "colors");
|
||
|
g_pGlobalState->trailShader.posAttrib = glGetAttribLocation(prog, "pos");
|
||
|
g_pGlobalState->trailShader.gradient = glGetUniformLocation(prog, "snapshots");
|
||
|
|
||
|
RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT),
|
||
|
"Couldn't unset current EGL!");
|
||
|
|
||
|
g_pGlobalState->tick = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, &onTick, nullptr);
|
||
|
wl_event_source_timer_update(g_pGlobalState->tick, 1);
|
||
|
}
|
||
|
|
||
|
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||
|
PHANDLE = handle;
|
||
|
|
||
|
const std::string HASH = __hyprland_api_get_hash();
|
||
|
|
||
|
if (HASH != GIT_COMMIT_HASH) {
|
||
|
HyprlandAPI::addNotification(PHANDLE, "[ht] Failure in initialization: Version mismatch (headers ver is not equal to running hyprland ver)",
|
||
|
CColor{1.0, 0.2, 0.2, 1.0}, 5000);
|
||
|
throw std::runtime_error("[ht] Version mismatch");
|
||
|
}
|
||
|
|
||
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprtrails:bezier_step", SConfigValue{.floatValue = 0.025});
|
||
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprtrails:points_per_step", SConfigValue{.intValue = 2});
|
||
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprtrails:history_points", SConfigValue{.intValue = 20});
|
||
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprtrails:history_step", SConfigValue{.intValue = 2});
|
||
|
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprtrails:color", SConfigValue{.intValue = configStringToInt("rgba(ffaa00ff)")});
|
||
|
|
||
|
HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, SCallbackInfo& info, std::any data) { onNewWindow(self, data); });
|
||
|
|
||
|
g_pGlobalState = std::make_unique<SGlobalState>();
|
||
|
initGlobal();
|
||
|
|
||
|
// add deco to existing windows
|
||
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||
|
if (w->isHidden() || !w->m_bIsMapped) continue;
|
||
|
|
||
|
HyprlandAPI::addWindowDecoration(PHANDLE, w.get(), new CTrail(w.get()));
|
||
|
}
|
||
|
|
||
|
HyprlandAPI::reloadConfig();
|
||
|
|
||
|
HyprlandAPI::addNotification(PHANDLE, "[hyprtrails] Initialized successfully!", CColor{0.2, 1.0, 0.2, 1.0}, 5000);
|
||
|
|
||
|
return {"hyprtrails", "A plugin to add trails behind moving windows", "Vaxry", "1.0"};
|
||
|
}
|
||
|
|
||
|
APICALL EXPORT void PLUGIN_EXIT() { wl_event_source_remove(g_pGlobalState->tick); }
|