2023-11-04 01:39:14 +01:00
# 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.
2023-11-11 15:39:46 +01:00
APICALL EXPORT std : : string PLUGIN_API_VERSION ( ) {
return HYPRLAND_API_VERSION ;
}
2023-11-04 01:39:14 +01:00
void onNewWindow ( void * self , std : : any data ) {
// data is guaranteed
auto * const PWINDOW = std : : any_cast < CWindow * > ( data ) ;
2023-11-11 15:39:46 +01:00
HyprlandAPI : : addWindowDecoration ( PHANDLE , PWINDOW , std : : make_unique < CTrail > ( PWINDOW ) ) ;
2023-11-04 01:39:14 +01:00
}
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 ) ;
2023-11-11 15:39:46 +01:00
if ( ok = = GL_FALSE )
throw std : : runtime_error ( " compileShader() failed! " ) ;
2023-11-04 01:39:14 +01:00
return shader ;
}
GLuint CreateProgram ( const std : : string & vert , const std : : string & frag ) {
auto vertCompiled = CompileShader ( GL_VERTEX_SHADER , vert ) ;
2023-11-11 15:39:46 +01:00
if ( ! vertCompiled )
throw std : : runtime_error ( " Compiling vshader failed. " ) ;
2023-11-04 01:39:14 +01:00
auto fragCompiled = CompileShader ( GL_FRAGMENT_SHADER , frag ) ;
2023-11-11 15:39:46 +01:00
if ( ! fragCompiled )
throw std : : runtime_error ( " Compiling fshader failed. " ) ;
2023-11-04 01:39:14 +01:00
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 ) ;
2023-11-11 15:39:46 +01:00
if ( ok = = GL_FALSE )
throw std : : runtime_error ( " createProgram() failed! GL_LINK_STATUS not OK! " ) ;
2023-11-04 01:39:14 +01:00
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 ( ) {
2023-11-11 15:39:46 +01:00
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 " ) ;
2023-11-04 01:39:14 +01:00
g_pGlobalState - > trailShader . texAttrib = glGetAttribLocation ( prog , " colors " ) ;
g_pGlobalState - > trailShader . posAttrib = glGetAttribLocation ( prog , " pos " ) ;
2023-11-11 15:39:46 +01:00
g_pGlobalState - > trailShader . gradient = glGetUniformLocation ( prog , " snapshots " ) ;
2023-11-04 01:39:14 +01:00
2023-11-11 15:39:46 +01:00
RASSERT ( eglMakeCurrent ( wlr_egl_get_display ( g_pCompositor - > m_sWLREGL ) , EGL_NO_SURFACE , EGL_NO_SURFACE , EGL_NO_CONTEXT ) , " Couldn't unset current EGL! " ) ;
2023-11-04 01:39:14 +01:00
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 ) {
2023-11-11 15:39:46 +01:00
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 ) ;
2023-11-04 01:39:14 +01:00
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 ) {
2023-11-11 15:39:46 +01:00
if ( w - > isHidden ( ) | | ! w - > m_bIsMapped )
continue ;
2023-11-04 01:39:14 +01:00
2023-11-11 15:39:46 +01:00
HyprlandAPI : : addWindowDecoration ( PHANDLE , w . get ( ) , std : : make_unique < CTrail > ( w . get ( ) ) ) ;
2023-11-04 01:39:14 +01:00
}
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 " } ;
}
2023-11-11 15:39:46 +01:00
APICALL EXPORT void PLUGIN_EXIT ( ) {
wl_event_source_remove ( g_pGlobalState - > tick ) ;
}