2023-02-27 14:02:21 +00:00
# define WLR_USE_UNSTABLE
# include <unistd.h>
2023-04-27 01:44:12 +03:00
# include <hyprland/src/Compositor.hpp>
2025-11-26 23:10:33 +01:00
# include <hyprland/src/desktop/state/FocusState.hpp>
2024-03-20 03:02:10 +00:00
# include <hyprland/src/desktop/Window.hpp>
2023-04-27 01:44:12 +03:00
# include <hyprland/src/config/ConfigManager.hpp>
2024-05-30 19:09:23 +02:00
# include <hyprland/src/xwayland/XSurface.hpp>
2024-05-31 18:08:07 +02:00
# include <hyprland/src/managers/SeatManager.hpp>
2025-01-17 19:20:10 +01:00
# include <hyprland/src/render/Renderer.hpp>
2023-02-27 14:02:21 +00:00
# include "globals.hpp"
2025-07-30 18:51:22 +02:00
# include <hyprutils/string/ConstVarList.hpp>
using namespace Hyprutils : : String ;
2023-02-27 14:02:21 +00:00
// Methods
2024-03-02 17:10:59 +00:00
inline CFunctionHook * g_pMouseMotionHook = nullptr ;
inline CFunctionHook * g_pSurfaceSizeHook = nullptr ;
inline CFunctionHook * g_pWLSurfaceDamageHook = nullptr ;
2024-05-31 18:08:07 +02:00
typedef void ( * origMotion ) ( CSeatManager * , uint32_t , const Vector2D & ) ;
2024-05-30 19:09:23 +02:00
typedef void ( * origSurfaceSize ) ( CXWaylandSurface * , const CBox & ) ;
2024-03-02 17:10:59 +00:00
typedef CRegion ( * origWLSurfaceDamage ) ( CWLSurface * ) ;
2023-02-27 14:02:21 +00:00
// Do NOT change this function.
2023-09-03 16:40:39 +02:00
APICALL EXPORT std : : string PLUGIN_API_VERSION ( ) {
return HYPRLAND_API_VERSION ;
}
2023-02-27 14:02:21 +00:00
2025-07-30 18:51:22 +02:00
struct SAppConfig {
std : : string szClass ;
Vector2D res ;
} ;
std : : vector < SAppConfig > g_appConfigs ;
static const SAppConfig * getAppConfig ( const std : : string & appClass ) {
for ( const auto & ac : g_appConfigs ) {
if ( ac . szClass ! = appClass )
continue ;
return & ac ;
}
return nullptr ;
}
2024-05-31 18:08:07 +02:00
void hkNotifyMotion ( CSeatManager * thisptr , uint32_t time_msec , const Vector2D & local ) {
2025-07-30 18:51:22 +02:00
static auto * const PFIX = ( Hyprlang : : INT * const * ) HyprlandAPI : : getConfigValue ( PHANDLE , " plugin:csgo-vulkan-fix:fix_mouse " ) - > getDataStaticPtr ( ) ;
2023-09-28 22:21:37 +01:00
2025-11-26 23:10:33 +01:00
Vector2D newCoords = local ;
auto focusState = Desktop : : focusState ( ) ;
auto window = focusState - > window ( ) ;
auto monitor = focusState - > monitor ( ) ;
2024-05-31 18:08:07 +02:00
2025-11-26 23:10:33 +01:00
const auto CONFIG = window & & monitor ? getAppConfig ( window - > m_initialClass ) : nullptr ;
2025-07-30 18:51:22 +02:00
if ( * * PFIX & & CONFIG ) {
2023-09-28 22:21:37 +01:00
// fix the coords
2025-11-26 23:10:33 +01:00
newCoords . x * = ( CONFIG - > res . x / monitor - > m_size . x ) / window - > m_X11SurfaceScaledBy ;
newCoords . y * = ( CONFIG - > res . y / monitor - > m_size . y ) / window - > m_X11SurfaceScaledBy ;
2023-09-28 22:21:37 +01:00
}
2025-05-03 19:38:51 +02:00
( * ( origMotion ) g_pMouseMotionHook - > m_original ) ( thisptr , time_msec , newCoords ) ;
2023-09-28 22:21:37 +01:00
}
2024-05-30 19:09:23 +02:00
void hkSetWindowSize ( CXWaylandSurface * surface , const CBox & box ) {
2023-09-03 16:40:39 +02:00
if ( ! surface ) {
2025-05-03 19:38:51 +02:00
( * ( origSurfaceSize ) g_pSurfaceSizeHook - > m_original ) ( surface , box ) ;
2023-09-03 16:40:39 +02:00
return ;
}
2025-05-07 20:55:53 +02:00
const auto SURF = surface - > m_surface . lock ( ) ;
2023-09-03 16:40:39 +02:00
const auto PWINDOW = g_pCompositor - > getWindowFromSurface ( SURF ) ;
2024-05-30 19:09:23 +02:00
CBox newBox = box ;
2025-07-30 18:51:22 +02:00
if ( ! PWINDOW ) {
( * ( origSurfaceSize ) g_pSurfaceSizeHook - > m_original ) ( surface , newBox ) ;
return ;
}
if ( const auto CONFIG = getAppConfig ( PWINDOW - > m_initialClass ) ; CONFIG ) {
newBox . w = CONFIG - > res . x ;
newBox . h = CONFIG - > res . y ;
2023-10-20 20:22:37 +01:00
2025-04-25 21:50:46 +02:00
CWLSurface : : fromResource ( SURF ) - > m_fillIgnoreSmall = true ;
2023-02-27 14:02:21 +00:00
}
2025-05-03 19:38:51 +02:00
( * ( origSurfaceSize ) g_pSurfaceSizeHook - > m_original ) ( surface , newBox ) ;
2023-02-27 14:02:21 +00:00
}
2024-03-02 17:10:59 +00:00
CRegion hkWLSurfaceDamage ( CWLSurface * thisptr ) {
2025-07-30 18:51:22 +02:00
const auto RG = ( * ( origWLSurfaceDamage ) g_pWLSurfaceDamageHook - > m_original ) ( thisptr ) ;
if ( thisptr - > exists ( ) & & thisptr - > getWindow ( ) ) {
const auto CONFIG = getAppConfig ( thisptr - > getWindow ( ) - > m_initialClass ) ;
if ( CONFIG ) {
const auto PMONITOR = thisptr - > getWindow ( ) - > m_monitor . lock ( ) ;
if ( PMONITOR )
g_pHyprRenderer - > damageMonitor ( PMONITOR ) ;
else
g_pHyprRenderer - > damageWindow ( thisptr - > getWindow ( ) ) ;
}
2024-03-02 17:10:59 +00:00
}
return RG ;
}
2023-02-27 14:02:21 +00:00
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT ( HANDLE handle ) {
PHANDLE = handle ;
2025-10-23 20:54:45 +01:00
const std : : string HASH = __hyprland_api_get_hash ( ) ;
const std : : string CLIENT_HASH = __hyprland_api_get_client_hash ( ) ;
2024-03-19 22:18:47 +00:00
2025-10-23 20:54:45 +01:00
if ( HASH ! = CLIENT_HASH ) {
2024-03-19 22:18:47 +00:00
HyprlandAPI : : addNotification ( PHANDLE , " [csgo-vulkan-fix] Failure in initialization: Version mismatch (headers ver is not equal to running hyprland ver) " ,
2024-12-04 09:58:09 -05:00
CHyprColor { 1.0 , 0.2 , 0.2 , 1.0 } , 5000 ) ;
2024-03-19 22:18:47 +00:00
throw std : : runtime_error ( " [vkfix] Version mismatch " ) ;
}
2024-02-18 15:30:21 +00:00
HyprlandAPI : : addConfigValue ( PHANDLE , " plugin:csgo-vulkan-fix:res_w " , Hyprlang : : INT { 1680 } ) ;
HyprlandAPI : : addConfigValue ( PHANDLE , " plugin:csgo-vulkan-fix:res_h " , Hyprlang : : INT { 1050 } ) ;
2024-08-03 23:03:24 +02:00
HyprlandAPI : : addConfigValue ( PHANDLE , " plugin:csgo-vulkan-fix:fix_mouse " , Hyprlang : : INT { 1 } ) ;
2024-02-18 15:30:21 +00:00
HyprlandAPI : : addConfigValue ( PHANDLE , " plugin:csgo-vulkan-fix:class " , Hyprlang : : STRING { " cs2 " } ) ;
2023-02-27 14:02:21 +00:00
2025-07-30 18:51:22 +02:00
static auto P = HyprlandAPI : : registerCallbackDynamic ( PHANDLE , " preConfigReload " , [ & ] ( void * self , SCallbackInfo & info , std : : any data ) {
g_appConfigs . clear ( ) ;
static auto * const RESX = ( Hyprlang : : INT * const * ) HyprlandAPI : : getConfigValue ( PHANDLE , " plugin:csgo-vulkan-fix:res_w " ) - > getDataStaticPtr ( ) ;
static auto * const RESY = ( Hyprlang : : INT * const * ) HyprlandAPI : : getConfigValue ( PHANDLE , " plugin:csgo-vulkan-fix:res_h " ) - > getDataStaticPtr ( ) ;
static auto * const PCLASS = ( Hyprlang : : STRING const * ) HyprlandAPI : : getConfigValue ( PHANDLE , " plugin:csgo-vulkan-fix:class " ) - > getDataStaticPtr ( ) ;
g_appConfigs . emplace_back ( SAppConfig { . szClass = * PCLASS , . res = Vector2D { ( int ) * * RESX , ( int ) * * RESY } } ) ;
} ) ;
2025-10-23 20:54:45 +01:00
HyprlandAPI : : addConfigKeyword (
PHANDLE , " vkfix-app " ,
[ ] ( const char * l , const char * r ) - > Hyprlang : : CParseResult {
const std : : string str = r ;
CConstVarList data ( str , 0 , ' , ' , true ) ;
Hyprlang : : CParseResult result ;
if ( data . size ( ) ! = 3 ) {
result . setError ( " vkfix-app requires 3 params " ) ;
return result ;
}
try {
SAppConfig config ;
config . szClass = data [ 0 ] ;
config . res = Vector2D { std : : stoi ( std : : string { data [ 1 ] } ) , std : : stoi ( std : : string { data [ 2 ] } ) } ;
g_appConfigs . emplace_back ( std : : move ( config ) ) ;
} catch ( std : : exception & e ) {
result . setError ( " failed to parse line " ) ;
return result ;
}
2025-07-30 18:51:22 +02:00
return result ;
2025-10-23 20:54:45 +01:00
} ,
Hyprlang : : SHandlerOptions { } ) ;
2025-07-30 18:51:22 +02:00
2024-08-03 23:03:24 +02:00
auto FNS = HyprlandAPI : : findFunctionsByName ( PHANDLE , " sendPointerMotion " ) ;
for ( auto & fn : FNS ) {
if ( ! fn . demangled . contains ( " CSeatManager " ) )
continue ;
g_pMouseMotionHook = HyprlandAPI : : createFunctionHook ( PHANDLE , fn . address , ( void * ) : : hkNotifyMotion ) ;
break ;
}
2024-05-30 19:09:23 +02:00
FNS = HyprlandAPI : : findFunctionsByName ( PHANDLE , " configure " ) ;
for ( auto & fn : FNS ) {
2024-08-03 23:03:24 +02:00
if ( ! fn . demangled . contains ( " XWaylandSurface " ) )
2024-05-30 19:09:23 +02:00
continue ;
g_pSurfaceSizeHook = HyprlandAPI : : createFunctionHook ( PHANDLE , fn . address , ( void * ) : : hkSetWindowSize ) ;
2024-08-03 23:03:24 +02:00
break ;
2024-05-30 19:09:23 +02:00
}
2024-07-22 19:10:51 +02:00
FNS = HyprlandAPI : : findFunctionsByName ( PHANDLE , " computeDamage " ) ;
2024-03-15 14:16:03 +00:00
for ( auto & r : FNS ) {
2024-03-02 17:10:59 +00:00
if ( ! r . demangled . contains ( " CWLSurface " ) )
continue ;
g_pWLSurfaceDamageHook = HyprlandAPI : : createFunctionHook ( PHANDLE , r . address , ( void * ) : : hkWLSurfaceDamage ) ;
break ;
}
2024-08-03 23:03:24 +02:00
bool success = g_pSurfaceSizeHook & & g_pWLSurfaceDamageHook & & g_pMouseMotionHook ;
2024-07-22 19:13:25 +02:00
if ( ! success ) {
2024-12-04 09:58:09 -05:00
HyprlandAPI : : addNotification ( PHANDLE , " [csgo-vulkan-fix] Failure in initialization: Failed to find required hook fns " , CHyprColor { 1.0 , 0.2 , 0.2 , 1.0 } , 5000 ) ;
2024-07-22 19:13:25 +02:00
throw std : : runtime_error ( " [vkfix] Hooks fn init failed " ) ;
}
2024-03-15 14:16:03 +00:00
success = success & & g_pWLSurfaceDamageHook - > hook ( ) ;
success = success & & g_pMouseMotionHook - > hook ( ) ;
success = success & & g_pSurfaceSizeHook - > hook ( ) ;
2023-02-27 14:02:21 +00:00
2024-03-15 14:16:03 +00:00
if ( success )
2024-12-04 09:58:09 -05:00
HyprlandAPI : : addNotification ( PHANDLE , " [csgo-vulkan-fix] Initialized successfully! (Anything version) " , CHyprColor { 0.2 , 1.0 , 0.2 , 1.0 } , 5000 ) ;
2023-10-29 21:25:17 +00:00
else {
2024-12-04 09:58:09 -05:00
HyprlandAPI : : addNotification ( PHANDLE , " [csgo-vulkan-fix] Failure in initialization (hook failed)! " , CHyprColor { 1.0 , 0.2 , 0.2 , 1.0 } , 5000 ) ;
2023-10-29 21:25:17 +00:00
throw std : : runtime_error ( " [csgo-vk-fix] Hooks failed " ) ;
}
2023-02-27 14:02:21 +00:00
2023-10-31 17:45:55 +00:00
return { " csgo-vulkan-fix " , " A plugin to force specific apps to a fake resolution " , " Vaxry " , " 1.2 " } ;
2023-02-27 14:02:21 +00:00
}
2023-09-03 16:40:39 +02:00
APICALL EXPORT void PLUGIN_EXIT ( ) {
;
2024-03-02 17:15:35 +00:00
}