2024-12-16 19:21:44 +01:00
# include <re2/re2.h>
2022-03-17 15:53:45 +01:00
# include "ConfigManager.hpp"
2025-01-19 15:39:19 +01:00
# include "ConfigWatcher.hpp"
2022-03-19 17:48:18 +01:00
# include "../managers/KeybindManager.hpp"
2024-12-07 18:51:18 +01:00
# include "../Compositor.hpp"
2022-03-17 15:53:45 +01:00
2023-11-26 17:59:49 +00:00
# include "../render/decorations/CHyprGroupBarDecoration.hpp"
2024-02-21 12:07:39 +01:00
# include "config/ConfigDataValues.hpp"
2024-08-06 14:52:19 +01:00
# include "config/ConfigValue.hpp"
2025-09-26 00:33:58 +02:00
# include "../desktop/WindowRule.hpp"
2024-05-09 21:47:21 +01:00
# include "../protocols/LayerShell.hpp"
2024-09-05 11:26:46 -05:00
# include "../xwayland/XWayland.hpp"
2024-09-26 11:10:53 +01:00
# include "../protocols/OutputManagement.hpp"
2025-08-28 11:20:29 +02:00
# include "../managers/animation/AnimationManager.hpp"
2025-01-17 15:21:35 +00:00
# include "../desktop/LayerSurface.hpp"
# include "defaultConfig.hpp"
2023-11-26 17:59:49 +00:00
2025-01-17 15:21:35 +00:00
# include "../render/Renderer.hpp"
# include "../hyprerror/HyprError.hpp"
# include "../managers/input/InputManager.hpp"
2025-01-24 20:30:12 +00:00
# include "../managers/eventLoop/EventLoopManager.hpp"
2025-01-17 15:21:35 +00:00
# include "../managers/LayoutManager.hpp"
# include "../managers/EventManager.hpp"
2025-04-08 19:39:53 +02:00
# include "../managers/permissions/DynamicPermissionManager.hpp"
2025-01-17 15:21:35 +00:00
# include "../debug/HyprNotificationOverlay.hpp"
# include "../plugins/PluginSystem.hpp"
2025-08-28 11:20:29 +02:00
# include "../managers/input/trackpad/TrackpadGestures.hpp"
# include "../managers/input/trackpad/gestures/DispatcherGesture.hpp"
# include "../managers/input/trackpad/gestures/WorkspaceSwipeGesture.hpp"
# include "../managers/input/trackpad/gestures/ResizeGesture.hpp"
# include "../managers/input/trackpad/gestures/MoveGesture.hpp"
# include "../managers/input/trackpad/gestures/SpecialWorkspaceGesture.hpp"
# include "../managers/input/trackpad/gestures/CloseGesture.hpp"
# include "../managers/input/trackpad/gestures/FloatGesture.hpp"
# include "../managers/input/trackpad/gestures/FullscreenGesture.hpp"
2025-02-02 22:16:00 +00:00
# include "../managers/HookSystemManager.hpp"
# include "../protocols/types/ContentType.hpp"
2024-06-11 19:49:54 +02:00
# include <cstddef>
2024-05-16 10:48:30 +00:00
# include <cstdint>
2024-07-16 22:23:37 +03:00
# include <hyprutils/path/Path.hpp>
2024-12-07 18:51:18 +01:00
# include <cstring>
2023-10-22 19:11:03 -03:00
# include <string>
2022-03-17 15:53:45 +01:00
# include <sys/stat.h>
# include <sys/types.h>
# include <unistd.h>
2023-09-12 11:54:05 +00:00
# include <glob.h>
2024-06-11 17:17:45 +02:00
# include <xkbcommon/xkbcommon.h>
2022-03-17 15:53:45 +01:00
# include <algorithm>
# include <fstream>
# include <iostream>
2024-05-03 17:58:40 +01:00
# include <ranges>
2024-05-29 05:37:24 +08:00
# include <unordered_set>
2024-06-11 17:17:45 +02:00
# include <hyprutils/string/String.hpp>
2025-08-28 11:20:29 +02:00
# include <hyprutils/string/ConstVarList.hpp>
2024-07-21 13:09:54 +02:00
# include <filesystem>
2025-01-23 21:55:41 +01:00
# include <memory>
2024-06-11 17:17:45 +02:00
using namespace Hyprutils : : String ;
2025-01-07 17:55:14 +00:00
using namespace Hyprutils : : Animation ;
2025-03-21 16:33:07 +03:00
using enum NContentType : : eContentType ;
2022-03-17 15:53:45 +01:00
2024-12-07 18:51:18 +01:00
//NOLINTNEXTLINE
2024-08-17 17:33:16 +01:00
extern " C " char * * environ ;
# include "ConfigDescriptions.hpp"
2023-03-05 18:39:46 +00:00
2024-02-18 15:00:34 +00:00
static Hyprlang : : CParseResult configHandleGradientSet ( const char * VALUE , void * * data ) {
std : : string V = VALUE ;
2023-10-10 16:42:45 +00:00
2024-02-18 15:00:34 +00:00
if ( ! * data )
* data = new CGradientValueData ( ) ;
2023-10-10 16:42:45 +00:00
2025-08-14 19:44:56 +05:00
const auto DATA = sc < CGradientValueData * > ( * data ) ;
2022-11-26 17:56:43 +00:00
2024-02-18 15:00:34 +00:00
CVarList varlist ( V , 0 , ' ' ) ;
2025-04-20 20:39:33 +02:00
DATA - > m_colors . clear ( ) ;
2023-11-26 18:02:23 +00:00
2024-02-18 15:00:34 +00:00
std : : string parseError = " " ;
2024-08-26 20:24:30 +02:00
for ( auto const & var : varlist ) {
2024-02-18 15:00:34 +00:00
if ( var . find ( " deg " ) ! = std : : string : : npos ) {
// last arg
try {
2025-04-20 20:39:33 +02:00
DATA - > m_angle = std : : stoi ( var . substr ( 0 , var . find ( " deg " ) ) ) * ( PI / 180.0 ) ; // radians
2024-02-18 15:00:34 +00:00
} catch ( . . . ) {
Debug : : log ( WARN , " Error parsing gradient {} " , V ) ;
parseError = " Error parsing gradient " + V ;
}
break ;
}
2025-04-20 20:39:33 +02:00
if ( DATA - > m_colors . size ( ) > = 10 ) {
2024-02-18 15:00:34 +00:00
Debug : : log ( WARN , " Error parsing gradient {}: max colors is 10. " , V ) ;
parseError = " Error parsing gradient " + V + " : max colors is 10. " ;
break ;
}
try {
2024-11-24 02:46:24 +00:00
const auto COL = configStringToInt ( var ) ;
if ( ! COL )
throw std : : runtime_error ( std : : format ( " failed to parse {} as a color " , var ) ) ;
2025-04-20 20:39:33 +02:00
DATA - > m_colors . emplace_back ( COL . value ( ) ) ;
2024-02-18 15:00:34 +00:00
} catch ( std : : exception & e ) {
Debug : : log ( WARN , " Error parsing gradient {} " , V ) ;
parseError = " Error parsing gradient " + V + " : " + e . what ( ) ;
}
}
2025-05-31 23:49:50 +05:00
if ( DATA - > m_colors . empty ( ) ) {
2024-02-18 15:00:34 +00:00
Debug : : log ( WARN , " Error parsing gradient {} " , V ) ;
2024-11-24 14:53:36 +00:00
if ( parseError . empty ( ) )
parseError = " Error parsing gradient " + V + " : No colors? " ;
2024-02-18 15:00:34 +00:00
2025-04-20 20:39:33 +02:00
DATA - > m_colors . emplace_back ( 0 ) ; // transparent
2024-02-18 15:00:34 +00:00
}
2024-12-03 18:58:24 +00:00
DATA - > updateColorsOk ( ) ;
2024-02-18 15:00:34 +00:00
Hyprlang : : CParseResult result ;
if ( ! parseError . empty ( ) )
result . setError ( parseError . c_str ( ) ) ;
return result ;
}
static void configHandleGradientDestroy ( void * * data ) {
if ( * data )
2025-08-14 19:44:56 +05:00
delete sc < CGradientValueData * > ( * data ) ;
2024-02-18 15:00:34 +00:00
}
2024-02-21 12:07:39 +01:00
static Hyprlang : : CParseResult configHandleGapSet ( const char * VALUE , void * * data ) {
std : : string V = VALUE ;
if ( ! * data )
* data = new CCssGapData ( ) ;
2025-08-14 19:44:56 +05:00
const auto DATA = sc < CCssGapData * > ( * data ) ;
2024-02-21 12:07:39 +01:00
CVarList varlist ( V ) ;
Hyprlang : : CParseResult result ;
try {
DATA - > parseGapData ( varlist ) ;
} catch ( . . . ) {
std : : string parseError = " Error parsing gaps " + V ;
result . setError ( parseError . c_str ( ) ) ;
}
return result ;
}
static void configHandleGapDestroy ( void * * data ) {
if ( * data )
2025-08-14 19:44:56 +05:00
delete sc < CCssGapData * > ( * data ) ;
2024-02-21 12:07:39 +01:00
}
2025-04-24 14:48:08 -04:00
static Hyprlang : : CParseResult configHandleFontWeightSet ( const char * VALUE , void * * data ) {
if ( ! * data )
* data = new CFontWeightConfigValueData ( ) ;
2025-08-14 19:44:56 +05:00
const auto DATA = sc < CFontWeightConfigValueData * > ( * data ) ;
2025-04-24 14:48:08 -04:00
Hyprlang : : CParseResult result ;
try {
DATA - > parseWeight ( VALUE ) ;
} catch ( . . . ) {
std : : string parseError = std : : format ( " {} is not a valid font weight " , VALUE ) ;
result . setError ( parseError . c_str ( ) ) ;
}
return result ;
}
static void configHandleFontWeightDestroy ( void * * data ) {
if ( * data )
2025-08-14 19:44:56 +05:00
delete sc < CFontWeightConfigValueData * > ( * data ) ;
2025-04-24 14:48:08 -04:00
}
2025-01-11 23:58:05 +08:00
static Hyprlang : : CParseResult handleExec ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleExec ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
2024-02-18 15:00:34 +00:00
static Hyprlang : : CParseResult handleRawExec ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleRawExec ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleExecOnce ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleExecOnce ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
2025-01-11 23:58:05 +08:00
static Hyprlang : : CParseResult handleExecRawOnce ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleExecRawOnce ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
2024-09-07 14:54:33 -05:00
static Hyprlang : : CParseResult handleExecShutdown ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleExecShutdown ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
2024-02-18 15:00:34 +00:00
static Hyprlang : : CParseResult handleMonitor ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleMonitor ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleBezier ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleBezier ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleAnimation ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleAnimation ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleBind ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleBind ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleUnbind ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleUnbind ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleWindowRule ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleWindowRule ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleLayerRule ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleLayerRule ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleWindowRuleV2 ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
2025-03-18 01:36:55 +00:00
const auto RESULT = g_pConfigManager - > handleWindowRule ( COMMAND , VALUE ) ;
2024-02-18 15:00:34 +00:00
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleBlurLS ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleBlurLS ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleWorkspaceRules ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleWorkspaceRules ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleSubmap ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleSubmap ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleSource ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleSource ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handleEnv ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleEnv ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
static Hyprlang : : CParseResult handlePlugin ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handlePlugin ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
2025-04-08 19:39:53 +02:00
static Hyprlang : : CParseResult handlePermission ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handlePermission ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
2025-08-28 11:20:29 +02:00
static Hyprlang : : CParseResult handleGesture ( const char * c , const char * v ) {
const std : : string VALUE = v ;
const std : : string COMMAND = c ;
const auto RESULT = g_pConfigManager - > handleGesture ( COMMAND , VALUE ) ;
Hyprlang : : CParseResult result ;
if ( RESULT . has_value ( ) )
result . setError ( RESULT . value ( ) . c_str ( ) ) ;
return result ;
}
2025-02-25 13:49:07 +00:00
void CConfigManager : : registerConfigVar ( const char * name , const Hyprlang : : INT & val ) {
m_configValueNumber + + ;
2025-04-20 20:39:33 +02:00
m_config - > addConfigValue ( name , val ) ;
2025-02-25 13:49:07 +00:00
}
void CConfigManager : : registerConfigVar ( const char * name , const Hyprlang : : FLOAT & val ) {
m_configValueNumber + + ;
2025-04-20 20:39:33 +02:00
m_config - > addConfigValue ( name , val ) ;
2025-02-25 13:49:07 +00:00
}
void CConfigManager : : registerConfigVar ( const char * name , const Hyprlang : : VEC2 & val ) {
m_configValueNumber + + ;
2025-04-20 20:39:33 +02:00
m_config - > addConfigValue ( name , val ) ;
2025-02-25 13:49:07 +00:00
}
void CConfigManager : : registerConfigVar ( const char * name , const Hyprlang : : STRING & val ) {
m_configValueNumber + + ;
2025-04-20 20:39:33 +02:00
m_config - > addConfigValue ( name , val ) ;
2025-02-25 13:49:07 +00:00
}
void CConfigManager : : registerConfigVar ( const char * name , Hyprlang : : CUSTOMTYPE & & val ) {
m_configValueNumber + + ;
2025-04-20 20:39:33 +02:00
m_config - > addConfigValue ( name , std : : move ( val ) ) ;
2025-02-25 13:49:07 +00:00
}
2024-02-18 15:00:34 +00:00
CConfigManager : : CConfigManager ( ) {
const auto ERR = verifyConfigExists ( ) ;
2022-07-14 23:55:24 +03:00
2025-01-19 15:39:19 +01:00
m_configPaths . emplace_back ( getMainConfigPath ( ) ) ;
2025-04-20 20:39:33 +02:00
m_config = makeUnique < Hyprlang : : CConfig > ( m_configPaths . begin ( ) - > c_str ( ) , Hyprlang : : SConfigOptions { . throwAllErrors = true , . allowMissingConfig = true } ) ;
2024-02-18 15:00:34 +00:00
2025-02-25 13:49:07 +00:00
registerConfigVar ( " general:border_size " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " general:no_border_on_floating " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " general:gaps_in " , Hyprlang : : CConfigCustomValueType { configHandleGapSet , configHandleGapDestroy , " 5 " } ) ;
registerConfigVar ( " general:gaps_out " , Hyprlang : : CConfigCustomValueType { configHandleGapSet , configHandleGapDestroy , " 20 " } ) ;
2025-06-04 02:48:56 +08:00
registerConfigVar ( " general:float_gaps " , Hyprlang : : CConfigCustomValueType { configHandleGapSet , configHandleGapDestroy , " 0 " } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " general:gaps_workspaces " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " general:no_focus_fallback " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " general:resize_on_border " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " general:extend_border_grab_area " , Hyprlang : : INT { 15 } ) ;
registerConfigVar ( " general:hover_icon_on_border " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " general:layout " , { " dwindle " } ) ;
registerConfigVar ( " general:allow_tearing " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " general:resize_corner " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " general:snap:enabled " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " general:snap:window_gap " , Hyprlang : : INT { 10 } ) ;
registerConfigVar ( " general:snap:monitor_gap " , Hyprlang : : INT { 10 } ) ;
registerConfigVar ( " general:snap:border_overlap " , Hyprlang : : INT { 0 } ) ;
2025-05-28 21:20:03 +08:00
registerConfigVar ( " general:snap:respect_gaps " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " general:col.active_border " , Hyprlang : : CConfigCustomValueType { & configHandleGradientSet , configHandleGradientDestroy , " 0xffffffff " } ) ;
registerConfigVar ( " general:col.inactive_border " , Hyprlang : : CConfigCustomValueType { & configHandleGradientSet , configHandleGradientDestroy , " 0xff444444 " } ) ;
registerConfigVar ( " general:col.nogroup_border " , Hyprlang : : CConfigCustomValueType { & configHandleGradientSet , configHandleGradientDestroy , " 0xffffaaff " } ) ;
registerConfigVar ( " general:col.nogroup_border_active " , Hyprlang : : CConfigCustomValueType { & configHandleGradientSet , configHandleGradientDestroy , " 0xffff00ff " } ) ;
2025-11-05 21:06:31 -03:00
registerConfigVar ( " general:modal_parent_blocking " , Hyprlang : : INT { 1 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " misc:disable_hyprland_logo " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:disable_splash_rendering " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:col.splash " , Hyprlang : : INT { 0x55ffffff } ) ;
registerConfigVar ( " misc:splash_font_family " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " misc:font_family " , { " Sans " } ) ;
registerConfigVar ( " misc:force_default_wallpaper " , Hyprlang : : INT { - 1 } ) ;
registerConfigVar ( " misc:vfr " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " misc:vrr " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:mouse_move_enables_dpms " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:key_press_enables_dpms " , Hyprlang : : INT { 0 } ) ;
2025-08-04 16:29:39 -03:00
registerConfigVar ( " misc:name_vk_after_proc " , Hyprlang : : INT { 1 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " misc:always_follow_on_dnd " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " misc:layers_hog_keyboard_focus " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " misc:animate_manual_resizes " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:animate_mouse_windowdragging " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:disable_autoreload " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:enable_swallow " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:swallow_regex " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " misc:swallow_exception_regex " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " misc:focus_on_activate " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:mouse_move_focuses_monitor " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " misc:allow_session_lock_restore " , Hyprlang : : INT { 0 } ) ;
2025-07-14 13:13:54 +02:00
registerConfigVar ( " misc:session_lock_xray " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " misc:close_special_on_empty " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " misc:background_color " , Hyprlang : : INT { 0xff111111 } ) ;
registerConfigVar ( " misc:new_window_takes_over_fullscreen " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:exit_window_retains_fullscreen " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:initial_workspace_tracking " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " misc:middle_click_paste " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " misc:render_unfocused_fps " , Hyprlang : : INT { 15 } ) ;
registerConfigVar ( " misc:disable_xdg_env_checks " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:disable_hyprland_qtutils_check " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " misc:lockdead_screen_delay " , Hyprlang : : INT { 1000 } ) ;
registerConfigVar ( " misc:enable_anr_dialog " , Hyprlang : : INT { 1 } ) ;
2025-10-01 12:19:09 +01:00
registerConfigVar ( " misc:anr_missed_pings " , Hyprlang : : INT { 5 } ) ;
2025-09-08 11:07:04 +02:00
registerConfigVar ( " misc:screencopy_force_8b " , Hyprlang : : INT { 1 } ) ;
2025-09-20 17:42:02 +02:00
registerConfigVar ( " misc:disable_scale_notification " , Hyprlang : : INT { 0 } ) ;
2025-10-13 06:08:40 -06:00
registerConfigVar ( " misc:size_limits_tiled " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " group:insert_after_current " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " group:focus_removed_window " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " group:merge_groups_on_drag " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " group:merge_groups_on_groupbar " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " group:merge_floated_into_tiled_on_groupbar " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " group:auto_group " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " group:drag_into_group " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " group:group_on_movetoworkspace " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " group:groupbar:enabled " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " group:groupbar:font_family " , { STRVAL_EMPTY } ) ;
2025-04-24 14:48:08 -04:00
registerConfigVar ( " group:groupbar:font_weight_active " , Hyprlang : : CConfigCustomValueType { & configHandleFontWeightSet , configHandleFontWeightDestroy , " normal " } ) ;
registerConfigVar ( " group:groupbar:font_weight_inactive " , Hyprlang : : CConfigCustomValueType { & configHandleFontWeightSet , configHandleFontWeightDestroy , " normal " } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " group:groupbar:font_size " , Hyprlang : : INT { 8 } ) ;
registerConfigVar ( " group:groupbar:gradients " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " group:groupbar:height " , Hyprlang : : INT { 14 } ) ;
2025-04-24 14:48:08 -04:00
registerConfigVar ( " group:groupbar:indicator_gap " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " group:groupbar:indicator_height " , Hyprlang : : INT { 3 } ) ;
registerConfigVar ( " group:groupbar:priority " , Hyprlang : : INT { 3 } ) ;
registerConfigVar ( " group:groupbar:render_titles " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " group:groupbar:scrolling " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " group:groupbar:text_color " , Hyprlang : : INT { 0xffffffff } ) ;
2025-06-16 16:40:38 -04:00
registerConfigVar ( " group:groupbar:text_color_inactive " , Hyprlang : : INT { - 1 } ) ;
registerConfigVar ( " group:groupbar:text_color_locked_active " , Hyprlang : : INT { - 1 } ) ;
registerConfigVar ( " group:groupbar:text_color_locked_inactive " , Hyprlang : : INT { - 1 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " group:groupbar:stacked " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " group:groupbar:rounding " , Hyprlang : : INT { 1 } ) ;
2025-08-16 15:14:14 +02:00
registerConfigVar ( " group:groupbar:rounding_power " , { 2.F } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " group:groupbar:gradient_rounding " , Hyprlang : : INT { 2 } ) ;
2025-08-16 15:14:14 +02:00
registerConfigVar ( " group:groupbar:gradient_rounding_power " , { 2.F } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " group:groupbar:round_only_edges " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " group:groupbar:gradient_round_only_edges " , Hyprlang : : INT { 1 } ) ;
2025-03-12 10:09:09 -04:00
registerConfigVar ( " group:groupbar:gaps_out " , Hyprlang : : INT { 2 } ) ;
registerConfigVar ( " group:groupbar:gaps_in " , Hyprlang : : INT { 2 } ) ;
2025-04-02 23:26:46 +03:00
registerConfigVar ( " group:groupbar:keep_upper_gap " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " group:groupbar:text_offset " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " debug:log_damage " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " debug:overlay " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " debug:damage_blink " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " debug:pass " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " debug:disable_logs " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " debug:disable_time " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " debug:enable_stdout_logs " , Hyprlang : : INT { 0 } ) ;
2025-08-14 19:44:56 +05:00
registerConfigVar ( " debug:damage_tracking " , { sc < Hyprlang : : INT > ( DAMAGE_TRACKING_FULL ) } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " debug:manual_crash " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " debug:suppress_errors " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " debug:error_limit " , Hyprlang : : INT { 5 } ) ;
registerConfigVar ( " debug:error_position " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " debug:disable_scale_checks " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " debug:colored_stdout_logs " , Hyprlang : : INT { 1 } ) ;
2025-02-26 17:56:37 +03:00
registerConfigVar ( " debug:full_cm_proto " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " decoration:rounding " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " decoration:rounding_power " , { 2.F } ) ;
registerConfigVar ( " decoration:blur:enabled " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " decoration:blur:size " , Hyprlang : : INT { 8 } ) ;
registerConfigVar ( " decoration:blur:passes " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " decoration:blur:ignore_opacity " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " decoration:blur:new_optimizations " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " decoration:blur:xray " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " decoration:blur:contrast " , { 0.8916F } ) ;
registerConfigVar ( " decoration:blur:brightness " , { 1.0F } ) ;
registerConfigVar ( " decoration:blur:vibrancy " , { 0.1696F } ) ;
registerConfigVar ( " decoration:blur:vibrancy_darkness " , { 0.0F } ) ;
registerConfigVar ( " decoration:blur:noise " , { 0.0117F } ) ;
registerConfigVar ( " decoration:blur:special " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " decoration:blur:popups " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " decoration:blur:popups_ignorealpha " , { 0.2F } ) ;
registerConfigVar ( " decoration:blur:input_methods " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " decoration:blur:input_methods_ignorealpha " , { 0.2F } ) ;
registerConfigVar ( " decoration:active_opacity " , { 1.F } ) ;
registerConfigVar ( " decoration:inactive_opacity " , { 1.F } ) ;
registerConfigVar ( " decoration:fullscreen_opacity " , { 1.F } ) ;
registerConfigVar ( " decoration:shadow:enabled " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " decoration:shadow:range " , Hyprlang : : INT { 4 } ) ;
registerConfigVar ( " decoration:shadow:render_power " , Hyprlang : : INT { 3 } ) ;
registerConfigVar ( " decoration:shadow:ignore_window " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " decoration:shadow:offset " , Hyprlang : : VEC2 { 0 , 0 } ) ;
registerConfigVar ( " decoration:shadow:scale " , { 1.f } ) ;
registerConfigVar ( " decoration:shadow:sharp " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " decoration:shadow:color " , Hyprlang : : INT { 0xee1a1a1a } ) ;
2025-06-16 16:40:38 -04:00
registerConfigVar ( " decoration:shadow:color_inactive " , Hyprlang : : INT { - 1 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " decoration:dim_inactive " , Hyprlang : : INT { 0 } ) ;
2025-08-21 14:59:20 +02:00
registerConfigVar ( " decoration:dim_modal " , Hyprlang : : INT { 1 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " decoration:dim_strength " , { 0.5f } ) ;
registerConfigVar ( " decoration:dim_special " , { 0.2f } ) ;
registerConfigVar ( " decoration:dim_around " , { 0.4f } ) ;
registerConfigVar ( " decoration:screen_shader " , { STRVAL_EMPTY } ) ;
2025-03-24 23:57:23 +00:00
registerConfigVar ( " decoration:border_part_of_window " , Hyprlang : : INT { 1 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " dwindle:pseudotile " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " dwindle:force_split " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " dwindle:permanent_direction_override " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " dwindle:preserve_split " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " dwindle:special_scale_factor " , { 1.f } ) ;
registerConfigVar ( " dwindle:split_width_multiplier " , { 1.0f } ) ;
registerConfigVar ( " dwindle:use_active_for_splits " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " dwindle:default_split_ratio " , { 1.f } ) ;
registerConfigVar ( " dwindle:split_bias " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " dwindle:smart_split " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " dwindle:smart_resizing " , Hyprlang : : INT { 1 } ) ;
2025-05-27 15:33:17 +08:00
registerConfigVar ( " dwindle:precise_mouse_move " , Hyprlang : : INT { 0 } ) ;
2025-06-10 09:20:31 +02:00
registerConfigVar ( " dwindle:single_window_aspect_ratio " , Hyprlang : : VEC2 { 0 , 0 } ) ;
registerConfigVar ( " dwindle:single_window_aspect_ratio_tolerance " , { 0.1f } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " master:special_scale_factor " , { 1.f } ) ;
registerConfigVar ( " master:mfact " , { 0.55f } ) ;
registerConfigVar ( " master:new_status " , { " slave " } ) ;
registerConfigVar ( " master:slave_count_for_center_master " , Hyprlang : : INT { 2 } ) ;
2025-05-01 14:29:06 +03:00
registerConfigVar ( " master:center_master_fallback " , { " left " } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " master:center_ignores_reserved " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " master:new_on_active " , { " none " } ) ;
registerConfigVar ( " master:new_on_top " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " master:orientation " , { " left " } ) ;
registerConfigVar ( " master:inherit_fullscreen " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " master:allow_small_split " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " master:smart_resizing " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " master:drop_at_cursor " , Hyprlang : : INT { 1 } ) ;
2025-03-06 17:06:05 -05:00
registerConfigVar ( " master:always_keep_position " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " animations:enabled " , Hyprlang : : INT { 1 } ) ;
2025-05-05 20:54:27 -05:00
registerConfigVar ( " animations:workspace_wraparound " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " input:follow_mouse " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " input:follow_mouse_threshold " , Hyprlang : : FLOAT { 0 } ) ;
registerConfigVar ( " input:focus_on_close " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:mouse_refocus " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " input:special_fallthrough " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:off_window_axis_events " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " input:sensitivity " , { 0.f } ) ;
registerConfigVar ( " input:accel_profile " , { STRVAL_EMPTY } ) ;
2025-10-10 17:05:51 +02:00
registerConfigVar ( " input:rotation " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " input:kb_file " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " input:kb_layout " , { " us " } ) ;
registerConfigVar ( " input:kb_variant " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " input:kb_options " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " input:kb_rules " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " input:kb_model " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " input:repeat_rate " , Hyprlang : : INT { 25 } ) ;
registerConfigVar ( " input:repeat_delay " , Hyprlang : : INT { 600 } ) ;
registerConfigVar ( " input:natural_scroll " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:numlock_by_default " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:resolve_binds_by_sym " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:force_no_accel " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:float_switch_override_focus " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " input:left_handed " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:scroll_method " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " input:scroll_button " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:scroll_button_lock " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:scroll_factor " , { 1.f } ) ;
registerConfigVar ( " input:scroll_points " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " input:emulate_discrete_scroll " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " input:touchpad:natural_scroll " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:touchpad:disable_while_typing " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " input:touchpad:clickfinger_behavior " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:touchpad:tap_button_map " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " input:touchpad:middle_button_emulation " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:touchpad:tap-to-click " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " input:touchpad:tap-and-drag " , Hyprlang : : INT { 1 } ) ;
2025-07-16 22:39:36 +02:00
registerConfigVar ( " input:touchpad:drag_lock " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " input:touchpad:scroll_factor " , { 1.f } ) ;
2025-03-03 15:56:01 -05:00
registerConfigVar ( " input:touchpad:flip_x " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:touchpad:flip_y " , Hyprlang : : INT { 0 } ) ;
2025-06-06 16:47:15 +02:00
registerConfigVar ( " input:touchpad:drag_3fg " , Hyprlang : : INT { 0 } ) ;
2025-03-06 14:24:36 +03:00
registerConfigVar ( " input:touchdevice:transform " , Hyprlang : : INT { - 1 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " input:touchdevice:output " , { " [[Auto]] " } ) ;
registerConfigVar ( " input:touchdevice:enabled " , Hyprlang : : INT { 1 } ) ;
2025-09-20 12:57:39 -03:00
registerConfigVar ( " input:virtualkeyboard:share_states " , Hyprlang : : INT { 2 } ) ;
2025-08-04 16:29:39 -03:00
registerConfigVar ( " input:virtualkeyboard:release_pressed_on_close " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " input:tablet:transform " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:tablet:output " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " input:tablet:region_position " , Hyprlang : : VEC2 { 0 , 0 } ) ;
registerConfigVar ( " input:tablet:absolute_region_position " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:tablet:region_size " , Hyprlang : : VEC2 { 0 , 0 } ) ;
registerConfigVar ( " input:tablet:relative_input " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:tablet:left_handed " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " input:tablet:active_area_position " , Hyprlang : : VEC2 { 0 , 0 } ) ;
registerConfigVar ( " input:tablet:active_area_size " , Hyprlang : : VEC2 { 0 , 0 } ) ;
registerConfigVar ( " binds:pass_mouse_when_bound " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " binds:scroll_event_delay " , Hyprlang : : INT { 300 } ) ;
registerConfigVar ( " binds:workspace_back_and_forth " , Hyprlang : : INT { 0 } ) ;
2025-03-30 03:11:39 +02:00
registerConfigVar ( " binds:hide_special_on_workspace_change " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " binds:allow_workspace_cycles " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " binds:workspace_center_on " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " binds:focus_preferred_method " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " binds:ignore_group_lock " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " binds:movefocus_cycles_fullscreen " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " binds:movefocus_cycles_groupfirst " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " binds:disable_keybind_grabbing " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " binds:window_direction_monitor_fallback " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " binds:allow_pin_fullscreen " , Hyprlang : : INT { 0 } ) ;
2025-04-12 10:43:13 -04:00
registerConfigVar ( " binds:drag_threshold " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " gestures:workspace_swipe_distance " , Hyprlang : : INT { 300 } ) ;
registerConfigVar ( " gestures:workspace_swipe_invert " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " gestures:workspace_swipe_min_speed_to_force " , Hyprlang : : INT { 30 } ) ;
registerConfigVar ( " gestures:workspace_swipe_cancel_ratio " , { 0.5f } ) ;
registerConfigVar ( " gestures:workspace_swipe_create_new " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " gestures:workspace_swipe_direction_lock " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " gestures:workspace_swipe_direction_lock_threshold " , Hyprlang : : INT { 10 } ) ;
registerConfigVar ( " gestures:workspace_swipe_forever " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " gestures:workspace_swipe_use_r " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " gestures:workspace_swipe_touch " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " gestures:workspace_swipe_touch_invert " , Hyprlang : : INT { 0 } ) ;
2025-08-28 11:20:29 +02:00
registerConfigVar ( " gestures:close_max_timeout " , Hyprlang : : INT { 1000 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " xwayland:enabled " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " xwayland:use_nearest_neighbor " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " xwayland:force_zero_scaling " , Hyprlang : : INT { 0 } ) ;
2025-03-20 01:06:30 +03:00
registerConfigVar ( " xwayland:create_abstract_socket " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " opengl:nvidia_anti_flicker " , Hyprlang : : INT { 1 } ) ;
2025-07-20 10:40:21 +00:00
registerConfigVar ( " cursor:invisible " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " cursor:no_hardware_cursors " , Hyprlang : : INT { 2 } ) ;
registerConfigVar ( " cursor:no_break_fs_vrr " , Hyprlang : : INT { 2 } ) ;
registerConfigVar ( " cursor:min_refresh_rate " , Hyprlang : : INT { 24 } ) ;
registerConfigVar ( " cursor:hotspot_padding " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " cursor:inactive_timeout " , { 0.f } ) ;
registerConfigVar ( " cursor:no_warps " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " cursor:persistent_warps " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " cursor:warp_on_change_workspace " , Hyprlang : : INT { 0 } ) ;
2025-04-10 14:54:24 +02:00
registerConfigVar ( " cursor:warp_on_toggle_special " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " cursor:default_monitor " , { STRVAL_EMPTY } ) ;
registerConfigVar ( " cursor:zoom_factor " , { 1.f } ) ;
registerConfigVar ( " cursor:zoom_rigid " , Hyprlang : : INT { 0 } ) ;
2025-10-15 14:08:34 +02:00
registerConfigVar ( " cursor:zoom_disable_aa " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " cursor:enable_hyprcursor " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " cursor:sync_gsettings_theme " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " cursor:hide_on_key_press " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " cursor:hide_on_touch " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " cursor:use_cpu_buffer " , Hyprlang : : INT { 2 } ) ;
registerConfigVar ( " cursor:warp_back_after_non_mouse_input " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " autogenerated " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " group:col.border_active " , Hyprlang : : CConfigCustomValueType { & configHandleGradientSet , configHandleGradientDestroy , " 0x66ffff00 " } ) ;
registerConfigVar ( " group:col.border_inactive " , Hyprlang : : CConfigCustomValueType { & configHandleGradientSet , configHandleGradientDestroy , " 0x66777700 " } ) ;
registerConfigVar ( " group:col.border_locked_active " , Hyprlang : : CConfigCustomValueType { & configHandleGradientSet , configHandleGradientDestroy , " 0x66ff5500 " } ) ;
registerConfigVar ( " group:col.border_locked_inactive " , Hyprlang : : CConfigCustomValueType { & configHandleGradientSet , configHandleGradientDestroy , " 0x66775500 " } ) ;
registerConfigVar ( " group:groupbar:col.active " , Hyprlang : : CConfigCustomValueType { & configHandleGradientSet , configHandleGradientDestroy , " 0x66ffff00 " } ) ;
registerConfigVar ( " group:groupbar:col.inactive " , Hyprlang : : CConfigCustomValueType { & configHandleGradientSet , configHandleGradientDestroy , " 0x66777700 " } ) ;
registerConfigVar ( " group:groupbar:col.locked_active " , Hyprlang : : CConfigCustomValueType { & configHandleGradientSet , configHandleGradientDestroy , " 0x66ff5500 " } ) ;
registerConfigVar ( " group:groupbar:col.locked_inactive " , Hyprlang : : CConfigCustomValueType { & configHandleGradientSet , configHandleGradientDestroy , " 0x66775500 " } ) ;
registerConfigVar ( " render:direct_scanout " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " render:expand_undersized_textures " , Hyprlang : : INT { 1 } ) ;
registerConfigVar ( " render:xp_mode " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " render:ctm_animation " , Hyprlang : : INT { 2 } ) ;
2025-03-22 20:34:01 +03:00
registerConfigVar ( " render:cm_fs_passthrough " , Hyprlang : : INT { 2 } ) ;
2025-03-18 11:30:01 +00:00
registerConfigVar ( " render:cm_enabled " , Hyprlang : : INT { 1 } ) ;
2025-04-29 23:09:14 +03:00
registerConfigVar ( " render:send_content_type " , Hyprlang : : INT { 1 } ) ;
2025-06-23 15:33:09 +03:00
registerConfigVar ( " render:cm_auto_hdr " , Hyprlang : : INT { 1 } ) ;
2025-07-09 16:13:57 +02:00
registerConfigVar ( " render:new_render_scheduling " , Hyprlang : : INT { 0 } ) ;
2025-10-02 13:05:54 +03:00
registerConfigVar ( " render:non_shader_cm " , Hyprlang : : INT { 2 } ) ;
2025-10-29 08:53:42 -04:00
registerConfigVar ( " render:cm_sdr_eotf " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " ecosystem:no_update_news " , Hyprlang : : INT { 0 } ) ;
registerConfigVar ( " ecosystem:no_donation_nag " , Hyprlang : : INT { 0 } ) ;
2025-04-08 19:39:53 +02:00
registerConfigVar ( " ecosystem:enforce_permissions " , Hyprlang : : INT { 0 } ) ;
2025-02-25 13:49:07 +00:00
registerConfigVar ( " experimental:xx_color_management_v4 " , Hyprlang : : INT { 0 } ) ;
2025-01-07 21:32:50 +03:00
2024-02-18 15:00:34 +00:00
// devices
2025-04-20 20:39:33 +02:00
m_config - > addSpecialCategory ( " device " , { " name " } ) ;
m_config - > addSpecialConfigValue ( " device " , " sensitivity " , { 0.F } ) ;
m_config - > addSpecialConfigValue ( " device " , " accel_profile " , { STRVAL_EMPTY } ) ;
2025-10-10 17:05:51 +02:00
m_config - > addSpecialConfigValue ( " device " , " rotation " , Hyprlang : : INT { 0 } ) ;
2025-04-20 20:39:33 +02:00
m_config - > addSpecialConfigValue ( " device " , " kb_file " , { STRVAL_EMPTY } ) ;
m_config - > addSpecialConfigValue ( " device " , " kb_layout " , { " us " } ) ;
m_config - > addSpecialConfigValue ( " device " , " kb_variant " , { STRVAL_EMPTY } ) ;
m_config - > addSpecialConfigValue ( " device " , " kb_options " , { STRVAL_EMPTY } ) ;
m_config - > addSpecialConfigValue ( " device " , " kb_rules " , { STRVAL_EMPTY } ) ;
m_config - > addSpecialConfigValue ( " device " , " kb_model " , { STRVAL_EMPTY } ) ;
m_config - > addSpecialConfigValue ( " device " , " repeat_rate " , Hyprlang : : INT { 25 } ) ;
m_config - > addSpecialConfigValue ( " device " , " repeat_delay " , Hyprlang : : INT { 600 } ) ;
m_config - > addSpecialConfigValue ( " device " , " natural_scroll " , Hyprlang : : INT { 0 } ) ;
m_config - > addSpecialConfigValue ( " device " , " tap_button_map " , { STRVAL_EMPTY } ) ;
m_config - > addSpecialConfigValue ( " device " , " numlock_by_default " , Hyprlang : : INT { 0 } ) ;
m_config - > addSpecialConfigValue ( " device " , " resolve_binds_by_sym " , Hyprlang : : INT { 0 } ) ;
m_config - > addSpecialConfigValue ( " device " , " disable_while_typing " , Hyprlang : : INT { 1 } ) ;
m_config - > addSpecialConfigValue ( " device " , " clickfinger_behavior " , Hyprlang : : INT { 0 } ) ;
m_config - > addSpecialConfigValue ( " device " , " middle_button_emulation " , Hyprlang : : INT { 0 } ) ;
m_config - > addSpecialConfigValue ( " device " , " tap-to-click " , Hyprlang : : INT { 1 } ) ;
m_config - > addSpecialConfigValue ( " device " , " tap-and-drag " , Hyprlang : : INT { 1 } ) ;
2025-07-16 22:39:36 +02:00
m_config - > addSpecialConfigValue ( " device " , " drag_lock " , Hyprlang : : INT { 0 } ) ;
2025-04-20 20:39:33 +02:00
m_config - > addSpecialConfigValue ( " device " , " left_handed " , Hyprlang : : INT { 0 } ) ;
m_config - > addSpecialConfigValue ( " device " , " scroll_method " , { STRVAL_EMPTY } ) ;
m_config - > addSpecialConfigValue ( " device " , " scroll_button " , Hyprlang : : INT { 0 } ) ;
m_config - > addSpecialConfigValue ( " device " , " scroll_button_lock " , Hyprlang : : INT { 0 } ) ;
m_config - > addSpecialConfigValue ( " device " , " scroll_points " , { STRVAL_EMPTY } ) ;
2025-09-02 13:16:43 +02:00
m_config - > addSpecialConfigValue ( " device " , " scroll_factor " , Hyprlang : : FLOAT { - 1 } ) ;
2025-04-20 20:39:33 +02:00
m_config - > addSpecialConfigValue ( " device " , " transform " , Hyprlang : : INT { - 1 } ) ;
m_config - > addSpecialConfigValue ( " device " , " output " , { STRVAL_EMPTY } ) ;
m_config - > addSpecialConfigValue ( " device " , " enabled " , Hyprlang : : INT { 1 } ) ; // only for mice, touchpads, and touchdevices
m_config - > addSpecialConfigValue ( " device " , " region_position " , Hyprlang : : VEC2 { 0 , 0 } ) ; // only for tablets
m_config - > addSpecialConfigValue ( " device " , " absolute_region_position " , Hyprlang : : INT { 0 } ) ; // only for tablets
m_config - > addSpecialConfigValue ( " device " , " region_size " , Hyprlang : : VEC2 { 0 , 0 } ) ; // only for tablets
m_config - > addSpecialConfigValue ( " device " , " relative_input " , Hyprlang : : INT { 0 } ) ; // only for tablets
m_config - > addSpecialConfigValue ( " device " , " active_area_position " , Hyprlang : : VEC2 { 0 , 0 } ) ; // only for tablets
m_config - > addSpecialConfigValue ( " device " , " active_area_size " , Hyprlang : : VEC2 { 0 , 0 } ) ; // only for tablets
m_config - > addSpecialConfigValue ( " device " , " flip_x " , Hyprlang : : INT { 0 } ) ; // only for touchpads
m_config - > addSpecialConfigValue ( " device " , " flip_y " , Hyprlang : : INT { 0 } ) ; // only for touchpads
2025-06-06 16:47:15 +02:00
m_config - > addSpecialConfigValue ( " device " , " drag_3fg " , Hyprlang : : INT { 0 } ) ; // only for touchpads
2025-04-20 20:39:33 +02:00
m_config - > addSpecialConfigValue ( " device " , " keybinds " , Hyprlang : : INT { 1 } ) ; // enable/disable keybinds
2025-08-04 16:29:39 -03:00
m_config - > addSpecialConfigValue ( " device " , " share_states " , Hyprlang : : INT { 0 } ) ; // only for virtualkeyboards
m_config - > addSpecialConfigValue ( " device " , " release_pressed_on_close " , Hyprlang : : INT { 0 } ) ; // only for virtualkeyboards
2024-02-18 15:00:34 +00:00
2025-06-05 17:56:46 +03:00
m_config - > addSpecialCategory ( " monitorv2 " , { . key = " output " } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " disabled " , Hyprlang : : INT { 0 } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " mode " , { " preferred " } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " position " , { " auto " } ) ;
2025-06-26 13:28:21 +03:00
m_config - > addSpecialConfigValue ( " monitorv2 " , " scale " , { " auto " } ) ;
2025-06-05 17:56:46 +03:00
m_config - > addSpecialConfigValue ( " monitorv2 " , " addreserved " , { STRVAL_EMPTY } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " mirror " , { STRVAL_EMPTY } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " bitdepth " , { STRVAL_EMPTY } ) ; // TODO use correct type
m_config - > addSpecialConfigValue ( " monitorv2 " , " cm " , { " auto " } ) ;
2025-10-29 08:53:42 -04:00
m_config - > addSpecialConfigValue ( " monitorv2 " , " sdr_eotf " , Hyprlang : : INT { 0 } ) ;
2025-06-05 17:56:46 +03:00
m_config - > addSpecialConfigValue ( " monitorv2 " , " sdrbrightness " , Hyprlang : : FLOAT { 1.0 } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " sdrsaturation " , Hyprlang : : FLOAT { 1.0 } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " vrr " , Hyprlang : : INT { 0 } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " transform " , { STRVAL_EMPTY } ) ; // TODO use correct type
2025-06-15 13:15:18 +03:00
m_config - > addSpecialConfigValue ( " monitorv2 " , " supports_wide_color " , Hyprlang : : INT { 0 } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " supports_hdr " , Hyprlang : : INT { 0 } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " sdr_min_luminance " , Hyprlang : : FLOAT { 0.2 } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " sdr_max_luminance " , Hyprlang : : INT { 80 } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " min_luminance " , Hyprlang : : FLOAT { - 1.0 } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " max_luminance " , Hyprlang : : INT { - 1 } ) ;
m_config - > addSpecialConfigValue ( " monitorv2 " , " max_avg_luminance " , Hyprlang : : INT { - 1 } ) ;
2025-06-05 17:56:46 +03:00
2024-02-18 15:00:34 +00:00
// keywords
2025-04-20 20:39:33 +02:00
m_config - > registerHandler ( & : : handleExec , " exec " , { false } ) ;
m_config - > registerHandler ( & : : handleRawExec , " execr " , { false } ) ;
m_config - > registerHandler ( & : : handleExecOnce , " exec-once " , { false } ) ;
m_config - > registerHandler ( & : : handleExecRawOnce , " execr-once " , { false } ) ;
m_config - > registerHandler ( & : : handleExecShutdown , " exec-shutdown " , { false } ) ;
m_config - > registerHandler ( & : : handleMonitor , " monitor " , { false } ) ;
m_config - > registerHandler ( & : : handleBind , " bind " , { true } ) ;
m_config - > registerHandler ( & : : handleUnbind , " unbind " , { false } ) ;
m_config - > registerHandler ( & : : handleWorkspaceRules , " workspace " , { false } ) ;
m_config - > registerHandler ( & : : handleWindowRule , " windowrule " , { false } ) ;
m_config - > registerHandler ( & : : handleLayerRule , " layerrule " , { false } ) ;
m_config - > registerHandler ( & : : handleWindowRuleV2 , " windowrulev2 " , { false } ) ;
m_config - > registerHandler ( & : : handleBezier , " bezier " , { false } ) ;
m_config - > registerHandler ( & : : handleAnimation , " animation " , { false } ) ;
m_config - > registerHandler ( & : : handleSource , " source " , { false } ) ;
m_config - > registerHandler ( & : : handleSubmap , " submap " , { false } ) ;
m_config - > registerHandler ( & : : handleBlurLS , " blurls " , { false } ) ;
m_config - > registerHandler ( & : : handlePlugin , " plugin " , { false } ) ;
m_config - > registerHandler ( & : : handlePermission , " permission " , { false } ) ;
2025-08-28 11:20:29 +02:00
m_config - > registerHandler ( & : : handleGesture , " gesture " , { false } ) ;
2025-04-20 20:39:33 +02:00
m_config - > registerHandler ( & : : handleEnv , " env " , { true } ) ;
2024-02-18 15:00:34 +00:00
// pluginza
2025-04-20 20:39:33 +02:00
m_config - > addSpecialCategory ( " plugin " , { nullptr , true } ) ;
2024-02-18 15:00:34 +00:00
2025-04-20 20:39:33 +02:00
m_config - > commence ( ) ;
2024-02-18 15:00:34 +00:00
resetHLConfig ( ) ;
2022-07-01 15:57:56 +02:00
2025-02-25 13:49:07 +00:00
if ( CONFIG_OPTIONS . size ( ) ! = m_configValueNumber - 1 /* autogenerated is special */ )
Debug : : log ( LOG , " Warning: config descriptions have {} entries, but there are {} config values. This should fail tests!! " , CONFIG_OPTIONS . size ( ) , m_configValueNumber ) ;
2025-04-22 15:23:29 +02:00
if ( ! g_pCompositor - > m_onlyConfigVerification ) {
2025-01-24 20:30:12 +00:00
Debug : : log (
INFO ,
" !!!!HEY YOU, YES YOU!!!!: further logs to stdout / logfile are disabled by default. BEFORE SENDING THIS LOG, ENABLE THEM. Use debug:disable_logs = false to do so: "
2025-06-20 01:45:06 +03:00
" https://wiki.hypr.land/Configuring/Variables/#debug " ) ;
2025-01-24 20:30:12 +00:00
}
2024-03-23 21:10:54 +00:00
2025-08-14 19:44:56 +05:00
Debug : : m_disableLogs = rc < int64_t * const * > ( m_config - > getConfigValuePtr ( " debug:disable_logs " ) - > getDataStaticPtr ( ) ) ;
Debug : : m_disableTime = rc < int64_t * const * > ( m_config - > getConfigValuePtr ( " debug:disable_time " ) - > getDataStaticPtr ( ) ) ;
2023-03-05 14:54:26 +00:00
2025-01-24 20:30:12 +00:00
if ( g_pEventLoopManager & & ERR . has_value ( ) )
g_pEventLoopManager - > doLater ( [ ERR ] { g_pHyprError - > queueCreate ( ERR . value ( ) , CHyprColor { 1.0 , 0.1 , 0.1 , 1.0 } ) ; } ) ;
2023-03-05 14:54:26 +00:00
}
2024-07-16 22:23:37 +03:00
std : : optional < std : : string > CConfigManager : : generateConfig ( std : : string configPath ) {
std : : string parentPath = std : : filesystem : : path ( configPath ) . parent_path ( ) ;
2023-12-04 01:35:24 +00:00
2025-08-12 15:11:21 -04:00
if ( ! parentPath . empty ( ) ) {
std : : error_code ec ;
bool created = std : : filesystem : : create_directories ( parentPath , ec ) ;
if ( ec ) {
Debug : : log ( ERR , " Couldn't create config home directory ({}): {} " , ec . message ( ) , parentPath ) ;
return " Config could not be generated. " ;
}
if ( created )
Debug : : log ( WARN , " Creating config home directory " ) ;
2024-07-16 22:23:37 +03:00
}
2023-12-04 01:35:24 +00:00
2024-07-16 22:23:37 +03:00
Debug : : log ( WARN , " No config file found; attempting to generate. " ) ;
std : : ofstream ofs ;
ofs . open ( configPath , std : : ios : : trunc ) ;
2025-06-02 22:36:44 +05:00
ofs < < AUTOGENERATED_PREFIX < < EXAMPLE_CONFIG ;
2024-07-16 22:23:37 +03:00
ofs . close ( ) ;
2024-07-05 22:58:47 +02:00
2025-08-12 15:11:21 -04:00
if ( ofs . fail ( ) )
2024-07-16 22:23:37 +03:00
return " Config could not be generated. " ;
2024-07-05 22:58:47 +02:00
2024-07-16 22:23:37 +03:00
return configPath ;
2023-07-07 13:19:35 -04:00
}
std : : string CConfigManager : : getMainConfigPath ( ) {
2025-01-02 18:29:10 +01:00
static std : : string CONFIG_PATH = [ this ] ( ) - > std : : string {
2025-05-05 23:44:49 +02:00
if ( ! g_pCompositor - > m_explicitConfigPath . empty ( ) )
return g_pCompositor - > m_explicitConfigPath ;
2025-01-02 18:29:10 +01:00
if ( const auto CFG_ENV = getenv ( " HYPRLAND_CONFIG " ) ; CFG_ENV )
return CFG_ENV ;
const auto PATHS = Hyprutils : : Path : : findConfig ( ISDEBUG ? " hyprlandd " : " hyprland " ) ;
if ( PATHS . first . has_value ( ) ) {
return PATHS . first . value ( ) ;
} else if ( PATHS . second . has_value ( ) ) {
const auto CONFIGPATH = Hyprutils : : Path : : fullConfigPath ( PATHS . second . value ( ) , ISDEBUG ? " hyprlandd " : " hyprland " ) ;
return generateConfig ( CONFIGPATH ) . value ( ) ;
} else
throw std : : runtime_error ( " Neither HOME nor XDG_CONFIG_HOME are set in the environment. Could not find config in XDG_CONFIG_DIRS or /etc/xdg. " ) ;
} ( ) ;
return CONFIG_PATH ;
2024-07-16 22:23:37 +03:00
}
std : : optional < std : : string > CConfigManager : : verifyConfigExists ( ) {
std : : string mainConfigPath = getMainConfigPath ( ) ;
if ( ! std : : filesystem : : exists ( mainConfigPath ) )
return " broken config dir? " ;
return { } ;
2023-07-07 13:19:35 -04:00
}
2024-12-16 19:05:24 +01:00
std : : string CConfigManager : : getConfigString ( ) {
2024-05-25 20:46:07 +00:00
std : : string configString ;
std : : string currFileContent ;
2025-01-19 15:39:19 +01:00
for ( const auto & path : m_configPaths ) {
2024-05-25 20:46:07 +00:00
std : : ifstream configFile ( path ) ;
configString + = ( " \n \n Config File: " + path + " : " ) ;
if ( ! configFile . is_open ( ) ) {
Debug : : log ( LOG , " Config file not readable/found! " ) ;
configString + = " Read Failed \n " ;
continue ;
}
configString + = " Read Succeeded \n " ;
currFileContent . assign ( std : : istreambuf_iterator < char > ( configFile ) , std : : istreambuf_iterator < char > ( ) ) ;
configString . append ( currFileContent ) ;
}
return configString ;
}
2024-03-20 21:55:13 -04:00
std : : string CConfigManager : : getErrors ( ) {
2025-04-20 20:39:33 +02:00
return m_configErrors ;
2024-03-20 21:55:13 -04:00
}
2024-02-18 15:00:34 +00:00
void CConfigManager : : reload ( ) {
2024-02-20 03:24:10 +00:00
EMIT_HOOK_EVENT ( " preConfigReload " , nullptr ) ;
2024-02-18 15:00:34 +00:00
setDefaultAnimationVars ( ) ;
resetHLConfig ( ) ;
2025-04-20 20:39:33 +02:00
m_configCurrentPath = getMainConfigPath ( ) ;
const auto ERR = m_config - > parse ( ) ;
2025-06-05 17:56:46 +03:00
const auto monitorError = handleMonitorv2 ( ) ;
m_lastConfigVerificationWasSuccessful = ! ERR . error & & ! monitorError . error ;
postConfigReload ( ERR . error | | ! monitorError . error ? ERR : monitorError ) ;
2022-06-30 21:26:00 +02:00
}
2025-01-24 20:30:12 +00:00
std : : string CConfigManager : : verify ( ) {
setDefaultAnimationVars ( ) ;
resetHLConfig ( ) ;
2025-04-20 20:39:33 +02:00
m_configCurrentPath = getMainConfigPath ( ) ;
const auto ERR = m_config - > parse ( ) ;
m_lastConfigVerificationWasSuccessful = ! ERR . error ;
2025-01-24 20:30:12 +00:00
if ( ERR . error )
return ERR . getError ( ) ;
return " config ok " ;
}
2022-07-28 13:28:43 +02:00
void CConfigManager : : setDefaultAnimationVars ( ) {
2025-04-20 20:39:33 +02:00
m_animationTree . createNode ( " __internal_fadeCTM " ) ;
m_animationTree . createNode ( " global " ) ;
2025-01-07 17:55:14 +00:00
// global
2025-04-20 20:39:33 +02:00
m_animationTree . createNode ( " windows " , " global " ) ;
m_animationTree . createNode ( " layers " , " global " ) ;
m_animationTree . createNode ( " fade " , " global " ) ;
m_animationTree . createNode ( " border " , " global " ) ;
m_animationTree . createNode ( " borderangle " , " global " ) ;
m_animationTree . createNode ( " workspaces " , " global " ) ;
2025-07-01 11:33:48 +02:00
m_animationTree . createNode ( " zoomFactor " , " global " ) ;
2025-08-16 20:02:15 +01:00
m_animationTree . createNode ( " monitorAdded " , " global " ) ;
2025-01-07 17:55:14 +00:00
// layer
2025-04-20 20:39:33 +02:00
m_animationTree . createNode ( " layersIn " , " layers " ) ;
m_animationTree . createNode ( " layersOut " , " layers " ) ;
2025-01-07 17:55:14 +00:00
// windows
2025-04-20 20:39:33 +02:00
m_animationTree . createNode ( " windowsIn " , " windows " ) ;
m_animationTree . createNode ( " windowsOut " , " windows " ) ;
m_animationTree . createNode ( " windowsMove " , " windows " ) ;
2025-01-07 17:55:14 +00:00
// fade
2025-04-20 20:39:33 +02:00
m_animationTree . createNode ( " fadeIn " , " fade " ) ;
m_animationTree . createNode ( " fadeOut " , " fade " ) ;
m_animationTree . createNode ( " fadeSwitch " , " fade " ) ;
m_animationTree . createNode ( " fadeShadow " , " fade " ) ;
m_animationTree . createNode ( " fadeDim " , " fade " ) ;
m_animationTree . createNode ( " fadeLayers " , " fade " ) ;
m_animationTree . createNode ( " fadeLayersIn " , " fadeLayers " ) ;
m_animationTree . createNode ( " fadeLayersOut " , " fadeLayers " ) ;
2025-08-03 13:44:50 +02:00
m_animationTree . createNode ( " fadePopups " , " fade " ) ;
m_animationTree . createNode ( " fadePopupsIn " , " fadePopups " ) ;
m_animationTree . createNode ( " fadePopupsOut " , " fadePopups " ) ;
2025-08-17 08:37:13 +01:00
m_animationTree . createNode ( " fadeDpms " , " fade " ) ;
2025-01-07 17:55:14 +00:00
// workspaces
2025-04-20 20:39:33 +02:00
m_animationTree . createNode ( " workspacesIn " , " workspaces " ) ;
m_animationTree . createNode ( " workspacesOut " , " workspaces " ) ;
m_animationTree . createNode ( " specialWorkspace " , " workspaces " ) ;
m_animationTree . createNode ( " specialWorkspaceIn " , " specialWorkspace " ) ;
m_animationTree . createNode ( " specialWorkspaceOut " , " specialWorkspace " ) ;
2025-01-07 17:55:14 +00:00
// init the root nodes
2025-04-20 20:39:33 +02:00
m_animationTree . setConfigForNode ( " global " , 1 , 8.f , " default " ) ;
m_animationTree . setConfigForNode ( " __internal_fadeCTM " , 1 , 5.f , " linear " ) ;
m_animationTree . setConfigForNode ( " borderangle " , 0 , 1 , " default " ) ;
2022-07-28 13:28:43 +02:00
}
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : resetHLConfig ( ) {
2025-04-20 20:39:33 +02:00
m_monitorRules . clear ( ) ;
m_windowRules . clear ( ) ;
2024-02-18 15:00:34 +00:00
g_pKeybindManager - > clearKeybinds ( ) ;
g_pAnimationManager - > removeAllBeziers ( ) ;
2025-01-07 17:55:14 +00:00
g_pAnimationManager - > addBezierWithName ( " linear " , Vector2D ( 0.0 , 0.0 ) , Vector2D ( 1.0 , 1.0 ) ) ;
2025-08-28 11:20:29 +02:00
g_pTrackpadGestures - > clearGestures ( ) ;
2025-01-07 17:55:14 +00:00
2024-02-18 15:00:34 +00:00
m_mAdditionalReservedAreas . clear ( ) ;
2025-04-20 20:39:33 +02:00
m_blurLSNamespaces . clear ( ) ;
m_workspaceRules . clear ( ) ;
2024-02-18 15:00:34 +00:00
setDefaultAnimationVars ( ) ; // reset anims
2025-04-20 20:39:33 +02:00
m_declaredPlugins . clear ( ) ;
m_layerRules . clear ( ) ;
m_failedPluginConfigValues . clear ( ) ;
m_finalExecRequests . clear ( ) ;
2024-01-02 21:08:30 +05:30
2024-02-18 15:00:34 +00:00
// paths
2025-01-19 15:39:19 +01:00
m_configPaths . clear ( ) ;
2024-02-18 15:00:34 +00:00
std : : string mainConfigPath = getMainConfigPath ( ) ;
Debug : : log ( LOG , " Using config: {} " , mainConfigPath ) ;
2025-01-19 15:39:19 +01:00
m_configPaths . emplace_back ( mainConfigPath ) ;
2022-05-16 09:38:42 +02:00
2024-02-18 15:00:34 +00:00
const auto RET = verifyConfigExists ( ) ;
2022-03-17 15:53:45 +01:00
2024-02-18 15:00:34 +00:00
return RET ;
}
2022-06-30 21:26:00 +02:00
2025-01-29 10:50:39 +00:00
void CConfigManager : : updateWatcher ( ) {
static const auto PDISABLEAUTORELOAD = CConfigValue < Hyprlang : : INT > ( " misc:disable_autoreload " ) ;
g_pConfigWatcher - > setWatchList ( * PDISABLEAUTORELOAD ? std : : vector < std : : string > { } : m_configPaths ) ;
}
2025-06-05 17:56:46 +03:00
std : : optional < std : : string > CConfigManager : : handleMonitorv2 ( const std : : string & output ) {
auto parser = CMonitorRuleParser ( output ) ;
auto VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " disabled " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser & & std : : any_cast < Hyprlang : : INT > ( VAL - > getValue ( ) ) )
parser . setDisabled ( ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " mode " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . parseMode ( std : : any_cast < Hyprlang : : STRING > ( VAL - > getValue ( ) ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " position " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . parsePosition ( std : : any_cast < Hyprlang : : STRING > ( VAL - > getValue ( ) ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " scale " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
2025-06-26 13:28:21 +03:00
parser . parseScale ( std : : any_cast < Hyprlang : : STRING > ( VAL - > getValue ( ) ) ) ;
2025-06-05 17:56:46 +03:00
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " addreserved " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser ) {
const auto ARGS = CVarList ( std : : any_cast < Hyprlang : : STRING > ( VAL - > getValue ( ) ) ) ;
2025-10-16 15:33:06 +02:00
try {
parser . setReserved ( { . top = std : : stoi ( ARGS [ 0 ] ) , . bottom = std : : stoi ( ARGS [ 1 ] ) , . left = std : : stoi ( ARGS [ 2 ] ) , . right = std : : stoi ( ARGS [ 3 ] ) } ) ;
} catch ( . . . ) { return " parse error: invalid reserved area " ; }
2025-06-05 17:56:46 +03:00
}
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " mirror " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . setMirror ( std : : any_cast < Hyprlang : : STRING > ( VAL - > getValue ( ) ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " bitdepth " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . parseBitdepth ( std : : any_cast < Hyprlang : : STRING > ( VAL - > getValue ( ) ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " cm " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . parseCM ( std : : any_cast < Hyprlang : : STRING > ( VAL - > getValue ( ) ) ) ;
2025-10-29 08:53:42 -04:00
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " sdr_eotf " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . rule ( ) . sdrEotf = std : : any_cast < Hyprlang : : INT > ( VAL - > getValue ( ) ) ;
2025-06-05 17:56:46 +03:00
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " sdrbrightness " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . rule ( ) . sdrBrightness = std : : any_cast < Hyprlang : : FLOAT > ( VAL - > getValue ( ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " sdrsaturation " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . rule ( ) . sdrSaturation = std : : any_cast < Hyprlang : : FLOAT > ( VAL - > getValue ( ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " vrr " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . rule ( ) . vrr = std : : any_cast < Hyprlang : : INT > ( VAL - > getValue ( ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " transform " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . parseTransform ( std : : any_cast < Hyprlang : : STRING > ( VAL - > getValue ( ) ) ) ;
2025-06-15 13:15:18 +03:00
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " supports_wide_color " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . rule ( ) . supportsWideColor = std : : any_cast < Hyprlang : : INT > ( VAL - > getValue ( ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " supports_hdr " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . rule ( ) . supportsHDR = std : : any_cast < Hyprlang : : INT > ( VAL - > getValue ( ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " sdr_min_luminance " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . rule ( ) . sdrMinLuminance = std : : any_cast < Hyprlang : : FLOAT > ( VAL - > getValue ( ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " sdr_max_luminance " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . rule ( ) . sdrMaxLuminance = std : : any_cast < Hyprlang : : INT > ( VAL - > getValue ( ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " min_luminance " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . rule ( ) . minLuminance = std : : any_cast < Hyprlang : : FLOAT > ( VAL - > getValue ( ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " max_luminance " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . rule ( ) . maxLuminance = std : : any_cast < Hyprlang : : INT > ( VAL - > getValue ( ) ) ;
VAL = m_config - > getSpecialConfigValuePtr ( " monitorv2 " , " max_avg_luminance " , output . c_str ( ) ) ;
if ( VAL & & VAL - > m_bSetByUser )
parser . rule ( ) . maxAvgLuminance = std : : any_cast < Hyprlang : : INT > ( VAL - > getValue ( ) ) ;
2025-06-05 17:56:46 +03:00
auto newrule = parser . rule ( ) ;
std : : erase_if ( m_monitorRules , [ & ] ( const auto & other ) { return other . name = = newrule . name ; } ) ;
m_monitorRules . push_back ( newrule ) ;
return parser . getError ( ) ;
}
Hyprlang : : CParseResult CConfigManager : : handleMonitorv2 ( ) {
Hyprlang : : CParseResult result ;
for ( const auto & output : m_config - > listKeysForSpecialCategory ( " monitorv2 " ) ) {
const auto error = handleMonitorv2 ( output ) ;
if ( error . has_value ( ) ) {
result . setError ( error . value ( ) . c_str ( ) ) ;
return result ;
}
}
return result ;
}
2024-02-18 15:00:34 +00:00
void CConfigManager : : postConfigReload ( const Hyprlang : : CParseResult & result ) {
2025-01-29 10:50:39 +00:00
updateWatcher ( ) ;
2025-01-19 15:39:19 +01:00
2025-04-22 15:23:29 +02:00
for ( auto const & w : g_pCompositor - > m_windows ) {
2024-02-18 15:00:34 +00:00
w - > uncacheWindowDecos ( ) ;
}
2022-06-30 21:26:00 +02:00
2025-07-01 11:33:48 +02:00
static auto PZOOMFACTOR = CConfigValue < Hyprlang : : FLOAT > ( " cursor:zoom_factor " ) ;
for ( auto const & m : g_pCompositor - > m_monitors ) {
* ( m - > m_cursorZoom ) = * PZOOMFACTOR ;
2025-04-30 23:45:20 +02:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( m - > m_id ) ;
2025-07-01 11:33:48 +02:00
}
2022-06-30 21:26:00 +02:00
2024-02-18 15:00:34 +00:00
// Update the keyboard layout to the cfg'd one if this is not the first launch
2025-04-20 20:39:33 +02:00
if ( ! m_isFirstLaunch ) {
2024-02-18 15:00:34 +00:00
g_pInputManager - > setKeyboardLayout ( ) ;
g_pInputManager - > setPointerConfigs ( ) ;
g_pInputManager - > setTouchDeviceConfigs ( ) ;
g_pInputManager - > setTabletConfigs ( ) ;
2022-06-30 21:26:00 +02:00
2025-05-05 23:44:49 +02:00
g_pHyprOpenGL - > m_reloadScreenShader = true ;
2025-01-14 17:52:19 +01:00
}
2024-02-18 15:00:34 +00:00
// parseError will be displayed next frame
2024-03-20 21:55:13 -04:00
if ( result . error )
2025-04-20 20:39:33 +02:00
m_configErrors = result . getError ( ) ;
2024-03-20 21:55:13 -04:00
else
2025-04-20 20:39:33 +02:00
m_configErrors = " " ;
2024-03-20 21:55:13 -04:00
2025-04-20 20:39:33 +02:00
if ( result . error & & ! std : : any_cast < Hyprlang : : INT > ( m_config - > getConfigValue ( " debug:suppress_errors " ) ) )
2024-12-03 18:58:24 +00:00
g_pHyprError - > queueCreate ( result . getError ( ) , CHyprColor ( 1.0 , 50.0 / 255.0 , 50.0 / 255.0 , 1.0 ) ) ;
2025-04-20 20:39:33 +02:00
else if ( std : : any_cast < Hyprlang : : INT > ( m_config - > getConfigValue ( " autogenerated " ) ) = = 1 )
2024-10-08 09:54:25 +01:00
g_pHyprError - > queueCreate (
2025-01-22 11:16:46 +01:00
" Warning: You're using an autogenerated config! Edit the config file to get rid of this message. (config file: " + getMainConfigPath ( ) +
2024-10-08 09:54:25 +01:00
" ) \n SUPER+Q -> kitty (if it doesn't launch, make sure it's installed or choose a different terminal in the config) \n SUPER+M -> exit Hyprland " ,
2024-12-03 18:58:24 +00:00
CHyprColor ( 1.0 , 1.0 , 70.0 / 255.0 , 1.0 ) ) ;
2024-02-18 15:00:34 +00:00
else
g_pHyprError - > destroy ( ) ;
2022-06-30 21:26:00 +02:00
2024-02-18 15:00:34 +00:00
// Set the modes for all monitors as we configured them
// not on first launch because monitors might not exist yet
// and they'll be taken care of in the newMonitor event
// ignore if nomonitorreload is set
2025-04-20 20:39:33 +02:00
if ( ! m_isFirstLaunch & & ! m_noMonitorReload ) {
2024-02-18 15:00:34 +00:00
// check
performMonitorReload ( ) ;
ensureMonitorStatus ( ) ;
ensureVRR ( ) ;
}
2023-02-27 12:32:38 +00:00
2024-09-05 11:26:46 -05:00
# ifndef NO_XWAYLAND
2025-04-22 15:23:29 +02:00
const auto PENABLEXWAYLAND = std : : any_cast < Hyprlang : : INT > ( m_config - > getConfigValue ( " xwayland:enabled " ) ) ;
g_pCompositor - > m_wantsXwayland = PENABLEXWAYLAND ;
2024-09-05 11:26:46 -05:00
// enable/disable xwayland usage
2025-04-20 20:39:33 +02:00
if ( ! m_isFirstLaunch & &
2025-01-23 21:27:11 +00:00
g_pXWayland /* XWayland has to be initialized by CCompositor::initManagers for this to make sense, and it doesn't have to be (e.g. very early plugin load) */ ) {
2025-01-20 13:40:51 -05:00
bool prevEnabledXwayland = g_pXWayland - > enabled ( ) ;
2025-04-22 15:23:29 +02:00
if ( g_pCompositor - > m_wantsXwayland ! = prevEnabledXwayland )
g_pXWayland = makeUnique < CXWayland > ( g_pCompositor - > m_wantsXwayland ) ;
2024-09-05 11:26:46 -05:00
} else
2025-04-22 15:23:29 +02:00
g_pCompositor - > m_wantsXwayland = PENABLEXWAYLAND ;
2024-09-05 11:26:46 -05:00
# endif
2025-04-22 15:23:29 +02:00
if ( ! m_isFirstLaunch & & ! g_pCompositor - > m_unsafeState )
2024-02-18 15:00:34 +00:00
refreshGroupBarGradients ( ) ;
2023-02-27 12:32:38 +00:00
2024-02-18 15:00:34 +00:00
// Updates dynamic window and workspace rules
2025-07-24 00:36:29 +02:00
for ( auto const & w : g_pCompositor - > getWorkspaces ( ) ) {
2024-04-11 01:26:11 +09:00
if ( w - > inert ( ) )
2024-02-18 15:00:34 +00:00
continue ;
2024-11-22 16:01:02 +00:00
w - > updateWindows ( ) ;
w - > updateWindowData ( ) ;
2022-06-30 21:26:00 +02:00
}
2022-04-18 13:25:27 +02:00
2024-02-18 15:00:34 +00:00
// Update window border colors
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
2022-06-30 21:38:06 +02:00
2024-02-18 15:00:34 +00:00
// update layout
2025-04-20 20:39:33 +02:00
g_pLayoutManager - > switchToLayout ( std : : any_cast < Hyprlang : : STRING > ( m_config - > getConfigValue ( " general:layout " ) ) ) ;
2022-09-30 17:03:06 +01:00
2024-02-18 15:00:34 +00:00
// manual crash
2025-04-20 20:39:33 +02:00
if ( std : : any_cast < Hyprlang : : INT > ( m_config - > getConfigValue ( " debug:manual_crash " ) ) & & ! m_manualCrashInitiated ) {
m_manualCrashInitiated = true ;
2024-12-03 18:58:24 +00:00
g_pHyprNotificationOverlay - > addNotification ( " Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor. " , CHyprColor ( 0 ) , 5000 ,
ICON_INFO ) ;
2025-04-20 20:39:33 +02:00
} else if ( m_manualCrashInitiated & & ! std : : any_cast < Hyprlang : : INT > ( m_config - > getConfigValue ( " debug:manual_crash " ) ) ) {
2024-02-18 15:00:34 +00:00
// cowabunga it is
g_pHyprRenderer - > initiateManualCrash ( ) ;
}
2022-11-26 17:56:43 +00:00
2025-04-21 20:42:02 +02:00
Debug : : m_disableStdout = ! std : : any_cast < Hyprlang : : INT > ( m_config - > getConfigValue ( " debug:enable_stdout_logs " ) ) ;
if ( Debug : : m_disableStdout & & m_isFirstLaunch )
2024-02-18 15:00:34 +00:00
Debug : : log ( LOG , " Disabling stdout logs! Check the log for further logs. " ) ;
2022-12-16 17:17:31 +00:00
2025-08-14 19:44:56 +05:00
Debug : : m_coloredLogs = rc < int64_t * const * > ( m_config - > getConfigValuePtr ( " debug:colored_stdout_logs " ) - > getDataStaticPtr ( ) ) ;
2024-04-29 08:07:35 -07:00
2025-04-22 15:23:29 +02:00
for ( auto const & m : g_pCompositor - > m_monitors ) {
2024-02-18 15:00:34 +00:00
// mark blur dirty
2024-10-19 23:03:29 +01:00
g_pHyprOpenGL - > markBlurDirtyForMonitor ( m ) ;
2022-11-26 17:56:43 +00:00
2024-10-19 23:03:29 +01:00
g_pCompositor - > scheduleFrameForMonitor ( m ) ;
2022-11-26 17:56:43 +00:00
2024-02-18 15:00:34 +00:00
// Force the compositor to fully re-render all monitors
2025-04-30 23:45:20 +02:00
m - > m_forceFullFrames = 2 ;
2024-04-24 17:29:41 +02:00
// also force mirrors, as the aspect ratio could've changed
2025-04-30 23:45:20 +02:00
for ( auto const & mirror : m - > m_mirrors )
mirror - > m_forceFullFrames = 3 ;
2024-02-18 15:00:34 +00:00
}
2022-11-26 17:56:43 +00:00
2024-02-18 15:00:34 +00:00
// Reset no monitor reload
2025-04-20 20:39:33 +02:00
m_noMonitorReload = false ;
2022-11-26 17:56:43 +00:00
2024-02-18 15:00:34 +00:00
// update plugins
handlePluginLoads ( ) ;
2022-11-26 17:56:43 +00:00
2025-01-26 14:40:42 +00:00
// update persistent workspaces
2025-04-20 20:39:33 +02:00
if ( ! m_isFirstLaunch )
2025-01-26 14:40:42 +00:00
ensurePersistentWorkspacesPresent ( ) ;
2024-02-18 15:00:34 +00:00
EMIT_HOOK_EVENT ( " configReloaded " , nullptr ) ;
if ( g_pEventManager )
g_pEventManager - > postEvent ( SHyprIPCEvent { " configreloaded " , " " } ) ;
}
2022-11-26 17:56:43 +00:00
2024-02-18 15:00:34 +00:00
void CConfigManager : : init ( ) {
2022-11-26 17:56:43 +00:00
2025-01-19 15:39:19 +01:00
g_pConfigWatcher - > setOnChange ( [ this ] ( const CConfigWatcher : : SConfigWatchEvent & e ) {
Debug : : log ( LOG , " CConfigManager: file {} modified, reloading " , e . file ) ;
reload ( ) ;
} ) ;
2024-02-18 15:00:34 +00:00
const std : : string CONFIGPATH = getMainConfigPath ( ) ;
reload ( ) ;
2022-11-26 17:56:43 +00:00
2025-04-20 20:39:33 +02:00
m_isFirstLaunch = false ;
2024-02-18 15:00:34 +00:00
}
2022-12-01 13:36:07 +00:00
2024-02-18 15:00:34 +00:00
std : : string CConfigManager : : parseKeyword ( const std : : string & COMMAND , const std : : string & VALUE ) {
2025-06-19 14:58:03 +02:00
const auto RET = m_config - > parseDynamic ( COMMAND . c_str ( ) , VALUE . c_str ( ) ) ;
2024-02-18 15:00:34 +00:00
// invalidate layouts if they changed
2024-02-24 14:06:28 +00:00
if ( COMMAND = = " monitor " | | COMMAND . contains ( " gaps_ " ) | | COMMAND . starts_with ( " dwindle: " ) | | COMMAND . starts_with ( " master: " ) ) {
2025-04-22 15:23:29 +02:00
for ( auto const & m : g_pCompositor - > m_monitors )
2025-04-30 23:45:20 +02:00
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( m - > m_id ) ;
2024-02-18 15:00:34 +00:00
}
2022-12-01 13:36:07 +00:00
2024-02-18 15:00:34 +00:00
// Update window border colors
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
// manual crash
2025-04-20 20:39:33 +02:00
if ( std : : any_cast < Hyprlang : : INT > ( m_config - > getConfigValue ( " debug:manual_crash " ) ) & & ! m_manualCrashInitiated ) {
m_manualCrashInitiated = true ;
2024-02-18 15:00:34 +00:00
if ( g_pHyprNotificationOverlay ) {
2024-12-03 18:58:24 +00:00
g_pHyprNotificationOverlay - > addNotification ( " Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor. " , CHyprColor ( 0 ) , 5000 ,
2024-02-18 15:00:34 +00:00
ICON_INFO ) ;
}
2025-04-20 20:39:33 +02:00
} else if ( m_manualCrashInitiated & & ! std : : any_cast < Hyprlang : : INT > ( m_config - > getConfigValue ( " debug:manual_crash " ) ) ) {
2024-02-18 15:00:34 +00:00
// cowabunga it is
g_pHyprRenderer - > initiateManualCrash ( ) ;
2022-12-01 13:36:07 +00:00
}
2022-03-17 15:53:45 +01:00
2024-02-18 15:00:34 +00:00
return RET . error ? RET . getError ( ) : " " ;
2022-03-17 15:53:45 +01:00
}
2024-02-18 15:00:34 +00:00
Hyprlang : : CConfigValue * CConfigManager : : getConfigValueSafeDevice ( const std : : string & dev , const std : : string & val , const std : : string & fallback ) {
2023-05-09 15:01:45 +02:00
2025-04-20 20:39:33 +02:00
const auto VAL = m_config - > getSpecialConfigValuePtr ( " device " , val . c_str ( ) , dev . c_str ( ) ) ;
2023-05-09 15:01:45 +02:00
2025-09-02 13:16:43 +02:00
if ( ( ! VAL | | ! VAL - > m_bSetByUser ) & & ! fallback . empty ( ) )
2025-04-20 20:39:33 +02:00
return m_config - > getConfigValuePtr ( fallback . c_str ( ) ) ;
2023-05-09 15:01:45 +02:00
2024-02-18 15:00:34 +00:00
return VAL ;
2023-05-09 15:01:45 +02:00
}
2025-09-02 13:16:43 +02:00
bool CConfigManager : : deviceConfigExplicitlySet ( const std : : string & dev , const std : : string & val ) {
const auto VAL = m_config - > getSpecialConfigValuePtr ( " device " , val . c_str ( ) , dev . c_str ( ) ) ;
return VAL & & VAL - > m_bSetByUser ;
}
2024-02-18 15:00:34 +00:00
int CConfigManager : : getDeviceInt ( const std : : string & dev , const std : : string & v , const std : : string & fallback ) {
return std : : any_cast < Hyprlang : : INT > ( getConfigValueSafeDevice ( dev , v , fallback ) - > getValue ( ) ) ;
}
2022-03-17 16:56:33 +01:00
2024-02-18 15:00:34 +00:00
float CConfigManager : : getDeviceFloat ( const std : : string & dev , const std : : string & v , const std : : string & fallback ) {
return std : : any_cast < Hyprlang : : FLOAT > ( getConfigValueSafeDevice ( dev , v , fallback ) - > getValue ( ) ) ;
}
2022-03-17 16:56:33 +01:00
2024-02-18 15:00:34 +00:00
Vector2D CConfigManager : : getDeviceVec ( const std : : string & dev , const std : : string & v , const std : : string & fallback ) {
2024-06-19 16:20:06 +02:00
auto vec = std : : any_cast < Hyprlang : : VEC2 > ( getConfigValueSafeDevice ( dev , v , fallback ) - > getValue ( ) ) ;
return { vec . x , vec . y } ;
2024-02-18 15:00:34 +00:00
}
2023-01-29 16:04:47 +00:00
2024-02-18 15:00:34 +00:00
std : : string CConfigManager : : getDeviceString ( const std : : string & dev , const std : : string & v , const std : : string & fallback ) {
2024-12-07 18:51:18 +01:00
auto VAL = std : : string { std : : any_cast < Hyprlang : : STRING > ( getConfigValueSafeDevice ( dev , v , fallback ) - > getValue ( ) ) } ;
2022-05-29 12:27:45 +02:00
2024-02-18 15:00:34 +00:00
if ( VAL = = STRVAL_EMPTY )
return " " ;
2022-05-29 12:27:45 +02:00
2024-02-18 15:00:34 +00:00
return VAL ;
}
2022-04-27 17:46:07 +02:00
2024-10-26 02:06:13 +01:00
SMonitorRule CConfigManager : : getMonitorRuleFor ( const PHLMONITOR PMONITOR ) {
2024-09-26 11:10:53 +01:00
auto applyWlrOutputConfig = [ PMONITOR ] ( SMonitorRule rule ) - > SMonitorRule {
const auto CONFIG = PROTO : : outputManagement - > getOutputStateFor ( PMONITOR ) ;
if ( ! CONFIG )
return rule ;
2025-04-30 23:45:20 +02:00
Debug : : log ( LOG , " CConfigManager::getMonitorRuleFor: found a wlr_output_manager override for {} " , PMONITOR - > m_name ) ;
2024-09-26 11:10:53 +01:00
Debug : : log ( LOG , " > overriding enabled: {} -> {} " , ! rule . disabled , ! CONFIG - > enabled ) ;
rule . disabled = ! CONFIG - > enabled ;
if ( ( CONFIG - > committedProperties & OUTPUT_HEAD_COMMITTED_MODE ) | | ( CONFIG - > committedProperties & OUTPUT_HEAD_COMMITTED_CUSTOM_MODE ) ) {
Debug : : log ( LOG , " > overriding mode: {:.0f}x{:.0f}@{:.2f}Hz -> {:.0f}x{:.0f}@{:.2f}Hz " , rule . resolution . x , rule . resolution . y , rule . refreshRate , CONFIG - > resolution . x ,
CONFIG - > resolution . y , CONFIG - > refresh / 1000.F ) ;
rule . resolution = CONFIG - > resolution ;
rule . refreshRate = CONFIG - > refresh / 1000.F ;
}
if ( CONFIG - > committedProperties & OUTPUT_HEAD_COMMITTED_POSITION ) {
Debug : : log ( LOG , " > overriding offset: {:.0f}, {:.0f} -> {:.0f}, {:.0f} " , rule . offset . x , rule . offset . y , CONFIG - > position . x , CONFIG - > position . y ) ;
rule . offset = CONFIG - > position ;
}
if ( CONFIG - > committedProperties & OUTPUT_HEAD_COMMITTED_TRANSFORM ) {
2025-08-14 19:44:56 +05:00
Debug : : log ( LOG , " > overriding transform: {} -> {} " , sc < uint8_t > ( rule . transform ) , sc < uint8_t > ( CONFIG - > transform ) ) ;
2024-09-26 11:10:53 +01:00
rule . transform = CONFIG - > transform ;
}
if ( CONFIG - > committedProperties & OUTPUT_HEAD_COMMITTED_SCALE ) {
2025-08-14 19:44:56 +05:00
Debug : : log ( LOG , " > overriding scale: {} -> {} " , sc < uint8_t > ( rule . scale ) , sc < uint8_t > ( CONFIG - > scale ) ) ;
2024-09-26 11:10:53 +01:00
rule . scale = CONFIG - > scale ;
}
if ( CONFIG - > committedProperties & OUTPUT_HEAD_COMMITTED_ADAPTIVE_SYNC ) {
Debug : : log ( LOG , " > overriding vrr: {} -> {} " , rule . vrr . value_or ( 0 ) , CONFIG - > adaptiveSync ) ;
2025-08-14 19:44:56 +05:00
rule . vrr = sc < int > ( CONFIG - > adaptiveSync ) ;
2024-09-26 11:10:53 +01:00
}
return rule ;
} ;
2025-04-20 20:39:33 +02:00
for ( auto const & r : m_monitorRules | std : : views : : reverse ) {
2024-09-26 11:10:53 +01:00
if ( PMONITOR - > matchesStaticSelector ( r . name ) ) {
return applyWlrOutputConfig ( r ) ;
2024-02-18 15:00:34 +00:00
}
}
2022-04-27 17:46:07 +02:00
2025-04-30 23:45:20 +02:00
Debug : : log ( WARN , " No rule found for {}, trying to use the first. " , PMONITOR - > m_name ) ;
2022-04-27 17:46:07 +02:00
2025-04-20 20:39:33 +02:00
for ( auto const & r : m_monitorRules ) {
2024-05-29 05:37:24 +08:00
if ( r . name . empty ( ) ) {
2024-09-26 11:10:53 +01:00
return applyWlrOutputConfig ( r ) ;
2022-04-27 17:46:07 +02:00
}
2024-02-18 15:00:34 +00:00
}
2022-04-17 10:19:46 +02:00
2024-02-18 15:00:34 +00:00
Debug : : log ( WARN , " No rules configured. Using the default hardcoded one. " ) ;
2022-04-17 10:21:54 +02:00
2024-09-26 11:10:53 +01:00
return applyWlrOutputConfig ( SMonitorRule { . autoDir = eAutoDirs : : DIR_AUTO_RIGHT ,
. name = " " ,
. resolution = Vector2D ( 0 , 0 ) ,
. offset = Vector2D ( - INT32_MAX , - INT32_MAX ) ,
. scale = - 1 } ) ; // 0, 0 is preferred and -1, -1 is auto
2024-02-18 15:00:34 +00:00
}
2022-04-17 10:19:46 +02:00
2024-04-05 08:54:30 -07:00
SWorkspaceRule CConfigManager : : getWorkspaceRuleFor ( PHLWORKSPACE pWorkspace ) {
SWorkspaceRule mergedRule { } ;
2025-04-20 20:39:33 +02:00
for ( auto const & rule : m_workspaceRules ) {
2024-04-05 08:54:30 -07:00
if ( ! pWorkspace - > matchesStaticSelector ( rule . workspaceString ) )
continue ;
2024-04-19 18:20:16 -07:00
mergedRule = mergeWorkspaceRules ( mergedRule , rule ) ;
2024-03-30 17:49:53 -07:00
}
2024-04-05 08:54:30 -07:00
return mergedRule ;
2024-02-18 15:00:34 +00:00
}
2022-03-19 21:46:29 +01:00
2024-04-19 18:20:16 -07:00
SWorkspaceRule CConfigManager : : mergeWorkspaceRules ( const SWorkspaceRule & rule1 , const SWorkspaceRule & rule2 ) {
SWorkspaceRule mergedRule = rule1 ;
2024-05-03 18:18:04 -07:00
if ( rule1 . monitor . empty ( ) )
mergedRule . monitor = rule2 . monitor ;
if ( rule1 . workspaceString . empty ( ) )
mergedRule . workspaceString = rule2 . workspaceString ;
if ( rule1 . workspaceName . empty ( ) )
mergedRule . workspaceName = rule2 . workspaceName ;
if ( rule1 . workspaceId = = WORKSPACE_INVALID )
mergedRule . workspaceId = rule2 . workspaceId ;
2024-04-19 18:20:16 -07:00
if ( rule2 . isDefault )
mergedRule . isDefault = true ;
if ( rule2 . isPersistent )
mergedRule . isPersistent = true ;
if ( rule2 . gapsIn . has_value ( ) )
mergedRule . gapsIn = rule2 . gapsIn ;
if ( rule2 . gapsOut . has_value ( ) )
mergedRule . gapsOut = rule2 . gapsOut ;
2025-06-04 02:48:56 +08:00
if ( rule2 . floatGaps )
mergedRule . floatGaps = rule2 . floatGaps ;
2024-04-19 18:20:16 -07:00
if ( rule2 . borderSize . has_value ( ) )
mergedRule . borderSize = rule2 . borderSize ;
2024-07-11 14:10:42 +00:00
if ( rule2 . noBorder . has_value ( ) )
mergedRule . noBorder = rule2 . noBorder ;
if ( rule2 . noRounding . has_value ( ) )
mergedRule . noRounding = rule2 . noRounding ;
2024-04-19 18:20:16 -07:00
if ( rule2 . decorate . has_value ( ) )
mergedRule . decorate = rule2 . decorate ;
2024-07-11 14:10:42 +00:00
if ( rule2 . noShadow . has_value ( ) )
mergedRule . noShadow = rule2 . noShadow ;
2024-04-19 18:20:16 -07:00
if ( rule2 . onCreatedEmptyRunCmd . has_value ( ) )
mergedRule . onCreatedEmptyRunCmd = rule2 . onCreatedEmptyRunCmd ;
if ( rule2 . defaultName . has_value ( ) )
mergedRule . defaultName = rule2 . defaultName ;
if ( ! rule2 . layoutopts . empty ( ) ) {
for ( const auto & layoutopt : rule2 . layoutopts ) {
mergedRule . layoutopts [ layoutopt . first ] = layoutopt . second ;
}
}
return mergedRule ;
}
2024-12-16 19:05:24 +01:00
std : : vector < SP < CWindowRule > > CConfigManager : : getMatchingRules ( PHLWINDOW pWindow , bool dynamic , bool shadowExec ) {
2024-04-27 12:43:12 +01:00
if ( ! valid ( pWindow ) )
2024-12-16 19:05:24 +01:00
return std : : vector < SP < CWindowRule > > ( ) ;
2022-03-17 16:56:33 +01:00
2024-05-16 00:55:55 +01:00
// if the window is unmapped, don't process exec rules yet.
2025-04-28 22:25:22 +02:00
shadowExec = shadowExec | | ! pWindow - > m_isMapped ;
2024-05-16 00:55:55 +01:00
2024-12-16 19:05:24 +01:00
std : : vector < SP < CWindowRule > > returns ;
2022-08-03 21:06:51 +02:00
2025-04-28 22:25:22 +02:00
Debug : : log ( LOG , " Searching for matching rules for {} (title: {}) " , pWindow - > m_class , pWindow - > m_title ) ;
2022-08-03 21:06:51 +02:00
2024-02-18 15:00:34 +00:00
// since some rules will be applied later, we need to store some flags
2025-04-28 22:25:22 +02:00
bool hasFloating = pWindow - > m_isFloating ;
2024-07-31 17:55:52 +00:00
bool hasFullscreen = pWindow - > isFullscreen ( ) ;
2025-06-05 16:17:04 -04:00
bool isGrouped = pWindow - > m_groupData . pNextWindow ;
2022-04-21 22:15:42 +02:00
2024-05-29 05:37:24 +08:00
// local tags for dynamic tag rule match
auto tags = pWindow - > m_tags ;
2025-04-20 20:39:33 +02:00
for ( auto const & rule : m_windowRules ) {
2024-02-18 15:00:34 +00:00
// check if we have a matching rule
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_v2 ) {
2024-02-18 15:00:34 +00:00
try {
2025-04-28 22:25:22 +02:00
if ( rule - > m_value . starts_with ( " tag: " ) & & ! tags . isTagged ( rule - > m_value . substr ( 4 ) ) )
2024-05-29 05:37:24 +08:00
continue ;
2025-04-28 22:25:22 +02:00
if ( rule - > m_value . starts_with ( " title: " ) & & ! rule - > m_v1Regex . passes ( pWindow - > m_title ) )
2024-12-16 19:21:44 +01:00
continue ;
2023-05-01 23:28:27 +02:00
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_v1Regex . passes ( pWindow - > m_class ) )
2024-12-16 19:21:44 +01:00
continue ;
2023-05-01 23:28:27 +02:00
2024-02-18 15:00:34 +00:00
} catch ( . . . ) {
2025-04-28 22:25:22 +02:00
Debug : : log ( ERR , " Regex error at {} " , rule - > m_value ) ;
2024-02-18 15:00:34 +00:00
continue ;
}
2022-09-13 15:25:42 +02:00
} else {
2024-02-18 15:00:34 +00:00
try {
2025-04-28 22:25:22 +02:00
if ( rule - > m_X11 ! = - 1 ) {
if ( pWindow - > m_isX11 ! = rule - > m_X11 )
2024-02-18 15:00:34 +00:00
continue ;
}
2022-07-28 13:28:43 +02:00
2025-04-28 22:25:22 +02:00
if ( rule - > m_floating ! = - 1 ) {
if ( hasFloating ! = rule - > m_floating )
2024-02-18 15:00:34 +00:00
continue ;
}
2022-05-14 15:56:01 +02:00
2025-04-28 22:25:22 +02:00
if ( rule - > m_fullscreen ! = - 1 ) {
if ( hasFullscreen ! = rule - > m_fullscreen )
2024-02-18 15:00:34 +00:00
continue ;
}
2022-05-14 15:56:01 +02:00
2025-04-28 22:25:22 +02:00
if ( rule - > m_pinned ! = - 1 ) {
if ( pWindow - > m_pinned ! = rule - > m_pinned )
2024-02-18 15:00:34 +00:00
continue ;
}
2022-09-25 20:07:48 +02:00
2025-04-28 22:25:22 +02:00
if ( rule - > m_focus ! = - 1 ) {
if ( rule - > m_focus ! = ( g_pCompositor - > m_lastWindow . lock ( ) = = pWindow ) )
2024-02-18 15:00:34 +00:00
continue ;
}
2022-05-14 15:56:01 +02:00
2025-06-05 16:17:04 -04:00
if ( rule - > m_group ! = - 1 ) {
if ( rule - > m_group ! = isGrouped )
continue ;
}
2025-10-13 14:16:48 +02:00
if ( rule - > m_modal ! = - 1 ) {
if ( rule - > m_modal ! = pWindow - > isModal ( ) )
continue ;
}
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_fullscreenState . empty ( ) ) {
const auto ARGS = CVarList ( rule - > m_fullscreenState , 2 , ' ' ) ;
2024-08-24 04:42:14 +09:00
//
std : : optional < eFullscreenMode > internalMode , clientMode ;
if ( ARGS [ 0 ] = = " * " )
2024-08-24 15:24:55 +02:00
internalMode = std : : nullopt ;
2024-08-24 04:42:14 +09:00
else if ( isNumber ( ARGS [ 0 ] ) )
2025-08-14 19:44:56 +05:00
internalMode = sc < eFullscreenMode > ( std : : stoi ( ARGS [ 0 ] ) ) ;
2024-08-24 04:42:14 +09:00
else
throw std : : runtime_error ( " szFullscreenState internal mode not valid " ) ;
if ( ARGS [ 1 ] = = " * " )
2024-08-24 15:24:55 +02:00
clientMode = std : : nullopt ;
2024-08-24 04:42:14 +09:00
else if ( isNumber ( ARGS [ 1 ] ) )
2025-08-14 19:44:56 +05:00
clientMode = sc < eFullscreenMode > ( std : : stoi ( ARGS [ 1 ] ) ) ;
2024-08-24 04:42:14 +09:00
else
throw std : : runtime_error ( " szFullscreenState client mode not valid " ) ;
2025-04-28 22:25:22 +02:00
if ( internalMode . has_value ( ) & & pWindow - > m_fullscreenState . internal ! = internalMode )
2024-08-24 04:42:14 +09:00
continue ;
2025-04-28 22:25:22 +02:00
if ( clientMode . has_value ( ) & & pWindow - > m_fullscreenState . client ! = clientMode )
2024-08-24 04:42:14 +09:00
continue ;
}
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_onWorkspace . empty ( ) ) {
const auto PWORKSPACE = pWindow - > m_workspace ;
if ( ! PWORKSPACE | | ! PWORKSPACE - > matchesStaticSelector ( rule - > m_onWorkspace ) )
2024-02-18 15:00:34 +00:00
continue ;
}
2022-05-14 15:56:01 +02:00
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_contentType . empty ( ) ) {
2025-02-02 22:25:29 +03:00
try {
2025-04-28 22:25:22 +02:00
const auto contentType = NContentType : : fromString ( rule - > m_contentType ) ;
2025-02-02 22:25:29 +03:00
if ( pWindow - > getContentType ( ) ! = contentType )
continue ;
2025-04-28 22:25:22 +02:00
} catch ( std : : exception & e ) { Debug : : log ( ERR , " Rule \" content:{} \" failed with: {} " , rule - > m_contentType , e . what ( ) ) ; }
2025-02-02 22:25:29 +03:00
}
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_xdgTag . empty ( ) ) {
if ( pWindow - > xdgTag ( ) . value_or ( " " ) ! = rule - > m_xdgTag )
2025-04-21 22:22:06 +01:00
continue ;
}
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_workspace . empty ( ) ) {
const auto PWORKSPACE = pWindow - > m_workspace ;
2022-07-28 13:28:43 +02:00
2024-02-18 15:00:34 +00:00
if ( ! PWORKSPACE )
continue ;
2022-05-14 15:56:01 +02:00
2025-04-28 22:25:22 +02:00
if ( rule - > m_workspace . starts_with ( " name: " ) ) {
if ( PWORKSPACE - > m_name ! = rule - > m_workspace . substr ( 5 ) )
2024-02-18 15:00:34 +00:00
continue ;
} else {
// number
2025-04-28 22:25:22 +02:00
if ( ! isNumber ( rule - > m_workspace ) )
2024-02-18 15:00:34 +00:00
throw std : : runtime_error ( " szWorkspace not name: or number " ) ;
2022-08-07 19:28:46 +02:00
2025-04-28 22:25:22 +02:00
const int64_t ID = std : : stoll ( rule - > m_workspace ) ;
2023-09-06 12:58:01 +02:00
2025-04-25 02:37:12 +02:00
if ( PWORKSPACE - > m_id ! = ID )
2024-02-18 15:00:34 +00:00
continue ;
}
}
2024-12-16 19:05:24 +01:00
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_tag . empty ( ) & & ! tags . isTagged ( rule - > m_tag ) )
2024-12-16 19:05:24 +01:00
continue ;
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_class . empty ( ) & & ! rule - > m_classRegex . passes ( pWindow - > m_class ) )
2024-12-16 19:21:44 +01:00
continue ;
2024-12-16 19:05:24 +01:00
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_title . empty ( ) & & ! rule - > m_titleRegex . passes ( pWindow - > m_title ) )
2024-12-16 19:21:44 +01:00
continue ;
2024-12-16 19:05:24 +01:00
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_initialTitle . empty ( ) & & ! rule - > m_initialTitleRegex . passes ( pWindow - > m_initialTitle ) )
2024-12-16 19:21:44 +01:00
continue ;
2024-12-16 19:05:24 +01:00
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_initialClass . empty ( ) & & ! rule - > m_initialClassRegex . passes ( pWindow - > m_initialClass ) )
2024-12-16 19:21:44 +01:00
continue ;
2024-12-16 19:05:24 +01:00
2024-02-18 15:00:34 +00:00
} catch ( std : : exception & e ) {
2025-04-28 22:25:22 +02:00
Debug : : log ( ERR , " Regex error at {} ({}) " , rule - > m_value , e . what ( ) ) ;
2024-02-18 15:00:34 +00:00
continue ;
2023-09-06 12:58:01 +02:00
}
2022-08-07 19:28:46 +02:00
}
2022-05-14 15:56:01 +02:00
2024-02-18 15:00:34 +00:00
// applies. Read the rule and behave accordingly
2025-04-28 22:25:22 +02:00
Debug : : log ( LOG , " Window rule {} -> {} matched {} " , rule - > m_rule , rule - > m_value , pWindow ) ;
2022-08-07 19:28:46 +02:00
2024-12-16 19:05:24 +01:00
returns . emplace_back ( rule ) ;
2022-07-28 13:28:43 +02:00
2024-05-29 05:37:24 +08:00
// apply tag with local tags
2025-04-28 22:25:22 +02:00
if ( rule - > m_ruleType = = CWindowRule : : RULE_TAG ) {
CVarList vars { rule - > m_rule , 0 , ' s ' , true } ;
2024-05-29 05:37:24 +08:00
if ( vars . size ( ) = = 2 & & vars [ 0 ] = = " tag " )
tags . applyTag ( vars [ 1 ] , true ) ;
}
2024-02-18 15:00:34 +00:00
if ( dynamic )
continue ;
2022-08-07 19:28:46 +02:00
2025-04-28 22:25:22 +02:00
if ( rule - > m_rule = = " float " )
2024-02-18 15:00:34 +00:00
hasFloating = true ;
2025-04-28 22:25:22 +02:00
else if ( rule - > m_rule = = " fullscreen " )
2024-02-18 15:00:34 +00:00
hasFullscreen = true ;
2022-08-07 19:28:46 +02:00
}
2025-08-14 19:44:56 +05:00
std : : vector < uint64_t > PIDs = { sc < uint64_t > ( pWindow - > getPID ( ) ) } ;
2024-02-18 15:00:34 +00:00
while ( getPPIDof ( PIDs . back ( ) ) > 10 )
PIDs . push_back ( getPPIDof ( PIDs . back ( ) ) ) ;
2022-07-20 22:33:43 +02:00
2024-02-18 15:00:34 +00:00
bool anyExecFound = false ;
2022-07-20 22:45:06 +02:00
2025-04-20 20:39:33 +02:00
for ( auto const & er : m_execRequestedRules ) {
2024-02-18 15:00:34 +00:00
if ( std : : ranges : : any_of ( PIDs , [ & ] ( const auto & pid ) { return pid = = er . iPid ; } ) ) {
2024-12-16 19:05:24 +01:00
returns . emplace_back ( makeShared < CWindowRule > ( er . szRule , " " , false , true ) ) ;
2024-02-18 15:00:34 +00:00
anyExecFound = true ;
2022-07-20 22:33:43 +02:00
}
}
2022-03-19 17:48:18 +01:00
2024-03-02 18:53:11 +00:00
if ( anyExecFound & & ! shadowExec ) // remove exec rules to unclog searches in the future, why have the garbage here.
2025-04-20 20:39:33 +02:00
std : : erase_if ( m_execRequestedRules , [ & ] ( const SExecRequestedRule & other ) { return std : : ranges : : any_of ( PIDs , [ & ] ( const auto & pid ) { return pid = = other . iPid ; } ) ; } ) ;
2022-09-19 19:04:48 +01:00
2024-02-18 15:00:34 +00:00
return returns ;
}
2022-03-19 17:48:18 +01:00
2024-12-16 19:05:24 +01:00
std : : vector < SP < CLayerRule > > CConfigManager : : getMatchingRules ( PHLLS pLS ) {
std : : vector < SP < CLayerRule > > returns ;
2022-09-21 17:41:19 +01:00
2025-04-24 20:49:49 +02:00
if ( ! pLS - > m_layerSurface | | pLS - > m_fadingOut )
2024-02-18 15:00:34 +00:00
return returns ;
2022-04-21 15:50:52 +02:00
2025-04-20 20:39:33 +02:00
for ( auto const & lr : m_layerRules ) {
2025-04-24 20:49:49 +02:00
if ( lr - > m_targetNamespace . starts_with ( " address:0x " ) ) {
2025-08-14 19:44:56 +05:00
if ( std : : format ( " address:0x{:x} " , rc < uintptr_t > ( pLS . get ( ) ) ) ! = lr - > m_targetNamespace )
2024-02-18 15:00:34 +00:00
continue ;
2025-05-04 00:13:29 +02:00
} else if ( ! lr - > m_targetNamespaceRegex . passes ( pLS - > m_layerSurface - > m_layerNamespace ) )
2024-12-16 19:21:44 +01:00
continue ;
2022-05-12 12:41:28 +02:00
2024-02-18 15:00:34 +00:00
// hit
2024-12-16 19:05:24 +01:00
returns . emplace_back ( lr ) ;
2022-07-08 09:27:17 +02:00
}
2022-04-21 17:06:43 +02:00
2025-05-04 00:13:29 +02:00
if ( shouldBlurLS ( pLS - > m_layerSurface - > m_layerNamespace ) )
returns . emplace_back ( makeShared < CLayerRule > ( pLS - > m_layerSurface - > m_layerNamespace , " blur " ) ) ;
2022-09-06 11:57:11 +02:00
2024-02-18 15:00:34 +00:00
return returns ;
2023-01-25 15:34:13 +00:00
}
2024-02-18 15:00:34 +00:00
void CConfigManager : : dispatchExecOnce ( ) {
2025-04-20 20:39:33 +02:00
if ( m_firstExecDispatched | | m_isFirstLaunch )
2022-09-06 11:57:11 +02:00
return ;
2024-02-18 15:00:34 +00:00
// update dbus env
2025-04-22 15:23:29 +02:00
if ( g_pCompositor - > m_aqBackend - > hasSession ( ) )
2024-02-18 15:00:34 +00:00
handleRawExec ( " " ,
# ifdef USES_SYSTEMD
2024-06-23 12:43:17 +05:30
" systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash "
2024-02-18 15:00:34 +00:00
" dbus-update-activation-environment 2>/dev/null && "
# endif
2024-06-23 12:43:17 +05:30
" dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS " ) ;
2022-11-03 19:52:43 +00:00
2025-04-20 20:39:33 +02:00
m_firstExecDispatched = true ;
m_isLaunchingExecOnce = true ;
2023-09-12 11:54:05 +00:00
2025-04-20 20:39:33 +02:00
for ( auto const & c : m_firstExecRequests ) {
2025-01-11 23:58:05 +08:00
c . withRules ? handleExec ( " " , c . exec ) : handleRawExec ( " " , c . exec ) ;
2024-02-18 15:00:34 +00:00
}
2023-09-12 11:54:05 +00:00
2025-04-20 20:39:33 +02:00
m_firstExecRequests . clear ( ) ; // free some kb of memory :P
m_isLaunchingExecOnce = false ;
2022-05-16 10:09:20 +02:00
2024-02-18 15:00:34 +00:00
// set input, fixes some certain issues
g_pInputManager - > setKeyboardLayout ( ) ;
g_pInputManager - > setPointerConfigs ( ) ;
g_pInputManager - > setTouchDeviceConfigs ( ) ;
g_pInputManager - > setTabletConfigs ( ) ;
2023-09-28 21:48:33 +01:00
2024-02-18 15:00:34 +00:00
// check for user's possible errors with their setup and notify them if needed
g_pCompositor - > performUserChecks ( ) ;
}
2023-09-12 11:54:05 +00:00
2024-09-07 14:54:33 -05:00
void CConfigManager : : dispatchExecShutdown ( ) {
2025-04-20 20:39:33 +02:00
if ( m_finalExecRequests . empty ( ) ) {
2025-04-22 15:23:29 +02:00
g_pCompositor - > m_finalRequests = false ;
2024-09-07 14:54:33 -05:00
return ;
}
2025-04-22 15:23:29 +02:00
g_pCompositor - > m_finalRequests = true ;
2024-09-07 14:54:33 -05:00
2025-04-20 20:39:33 +02:00
for ( auto const & c : m_finalExecRequests ) {
2024-09-07 14:54:33 -05:00
handleExecShutdown ( " " , c ) ;
}
2025-04-20 20:39:33 +02:00
m_finalExecRequests . clear ( ) ;
2024-09-07 14:54:33 -05:00
// Actually exit now
handleExecShutdown ( " " , " hyprctl dispatch exit " ) ;
}
2024-02-18 15:00:34 +00:00
void CConfigManager : : performMonitorReload ( ) {
2025-06-05 17:56:46 +03:00
handleMonitorv2 ( ) ;
2023-09-12 11:54:05 +00:00
2024-02-18 15:00:34 +00:00
bool overAgain = false ;
2023-09-12 11:54:05 +00:00
2025-04-22 15:23:29 +02:00
for ( auto const & m : g_pCompositor - > m_realMonitors ) {
2025-04-30 23:45:20 +02:00
if ( ! m - > m_output | | m - > m_isUnsafeFallback )
2024-02-18 15:00:34 +00:00
continue ;
2022-05-16 10:09:20 +02:00
2024-09-26 11:10:53 +01:00
auto rule = getMonitorRuleFor ( m ) ;
2023-09-28 21:48:33 +01:00
2024-12-28 07:32:04 -06:00
if ( ! m - > applyMonitorRule ( & rule ) ) {
2024-02-18 15:00:34 +00:00
overAgain = true ;
break ;
2022-05-16 10:09:20 +02:00
}
2024-02-18 15:00:34 +00:00
// ensure mirror
m - > setMirror ( rule . mirrorOf ) ;
2025-04-30 23:45:20 +02:00
g_pHyprRenderer - > arrangeLayersForMonitor ( m - > m_id ) ;
2022-05-16 10:09:20 +02:00
}
2024-02-18 15:00:34 +00:00
if ( overAgain )
performMonitorReload ( ) ;
2025-04-20 20:39:33 +02:00
m_wantsMonitorReload = false ;
2024-02-18 15:00:34 +00:00
EMIT_HOOK_EVENT ( " monitorLayoutChanged " , nullptr ) ;
2022-09-12 21:05:52 +02:00
}
2024-02-18 15:00:34 +00:00
void * const * CConfigManager : : getConfigValuePtr ( const std : : string & val ) {
2025-04-20 20:39:33 +02:00
const auto VAL = m_config - > getConfigValuePtr ( val . c_str ( ) ) ;
2024-02-18 15:00:34 +00:00
if ( ! VAL )
return nullptr ;
return VAL - > getDataStaticPtr ( ) ;
}
2023-03-05 13:12:01 +00:00
2024-02-18 15:00:34 +00:00
Hyprlang : : CConfigValue * CConfigManager : : getHyprlangConfigValuePtr ( const std : : string & name , const std : : string & specialCat ) {
if ( ! specialCat . empty ( ) )
2025-04-20 20:39:33 +02:00
return m_config - > getSpecialConfigValuePtr ( specialCat . c_str ( ) , name . c_str ( ) , nullptr ) ;
2023-03-05 13:12:01 +00:00
2025-05-02 17:53:55 +01:00
if ( name . starts_with ( " plugin: " ) )
return m_config - > getSpecialConfigValuePtr ( " plugin " , name . substr ( 7 ) . c_str ( ) , nullptr ) ;
2025-04-20 20:39:33 +02:00
return m_config - > getConfigValuePtr ( name . c_str ( ) ) ;
2024-02-18 15:00:34 +00:00
}
2023-03-05 13:12:01 +00:00
2024-02-18 15:00:34 +00:00
bool CConfigManager : : deviceConfigExists ( const std : : string & dev ) {
auto copy = dev ;
2025-05-30 18:25:59 +05:00
std : : ranges : : replace ( copy , ' ' , ' - ' ) ;
2023-03-05 13:15:12 +00:00
2025-04-20 20:39:33 +02:00
return m_config - > specialCategoryExistsForKey ( " device " , copy . c_str ( ) ) ;
2023-03-05 13:12:01 +00:00
}
2024-02-18 15:00:34 +00:00
bool CConfigManager : : shouldBlurLS ( const std : : string & ns ) {
2025-04-20 20:39:33 +02:00
for ( auto const & bls : m_blurLSNamespaces ) {
2024-02-18 15:00:34 +00:00
if ( bls = = ns ) {
return true ;
}
2023-05-01 07:10:53 -07:00
}
2024-02-18 15:00:34 +00:00
return false ;
2023-05-01 07:10:53 -07:00
}
2024-02-18 15:00:34 +00:00
void CConfigManager : : ensureMonitorStatus ( ) {
2025-04-22 15:23:29 +02:00
for ( auto const & rm : g_pCompositor - > m_realMonitors ) {
2025-04-30 23:45:20 +02:00
if ( ! rm - > m_output | | rm - > m_isUnsafeFallback )
2024-02-18 15:00:34 +00:00
continue ;
2022-04-21 16:56:27 +02:00
2024-09-26 11:10:53 +01:00
auto rule = getMonitorRuleFor ( rm ) ;
2022-11-28 19:05:50 +00:00
2025-04-30 23:45:20 +02:00
if ( rule . disabled = = rm - > m_enabled )
2024-12-28 07:32:04 -06:00
rm - > applyMonitorRule ( & rule ) ;
2022-11-28 19:05:50 +00:00
}
2024-02-18 15:00:34 +00:00
}
2024-10-19 23:03:29 +01:00
void CConfigManager : : ensureVRR ( PHLMONITOR pMonitor ) {
2025-08-14 19:44:56 +05:00
static auto PVRR = rc < Hyprlang : : INT * const * > ( getConfigValuePtr ( " misc:vrr " ) ) ;
2022-04-21 16:56:27 +02:00
2024-10-19 23:03:29 +01:00
static auto ensureVRRForDisplay = [ & ] ( PHLMONITOR m ) - > void {
2025-04-30 23:45:20 +02:00
if ( ! m - > m_output | | m - > m_createdByUser )
2024-02-18 15:00:34 +00:00
return ;
2022-05-25 17:42:38 +02:00
2025-04-30 23:45:20 +02:00
const auto USEVRR = m - > m_activeMonitorRule . vrr . has_value ( ) ? m - > m_activeMonitorRule . vrr . value ( ) : * * PVRR ;
2022-05-26 21:23:13 +02:00
2024-02-18 15:00:34 +00:00
if ( USEVRR = = 0 ) {
2025-04-30 23:45:20 +02:00
if ( m - > m_vrrActive ) {
m - > m_output - > state - > resetExplicitFences ( ) ;
m - > m_output - > state - > setAdaptiveSync ( false ) ;
2022-05-26 21:23:13 +02:00
2025-04-30 23:45:20 +02:00
if ( ! m - > m_state . commit ( ) )
Debug : : log ( ERR , " Couldn't commit output {} in ensureVRR -> false " , m - > m_output - > name ) ;
2023-04-07 21:15:11 +02:00
}
2025-04-30 23:45:20 +02:00
m - > m_vrrActive = false ;
2024-02-18 15:00:34 +00:00
return ;
} else if ( USEVRR = = 1 ) {
2025-04-30 23:45:20 +02:00
if ( ! m - > m_vrrActive ) {
m - > m_output - > state - > resetExplicitFences ( ) ;
m - > m_output - > state - > setAdaptiveSync ( true ) ;
2023-04-04 22:13:31 +01:00
2025-04-30 23:45:20 +02:00
if ( ! m - > m_state . test ( ) ) {
Debug : : log ( LOG , " Pending output {} does not accept VRR. " , m - > m_output - > name ) ;
m - > m_output - > state - > setAdaptiveSync ( false ) ;
2024-02-18 15:00:34 +00:00
}
2022-04-21 16:56:27 +02:00
2025-04-30 23:45:20 +02:00
if ( ! m - > m_state . commit ( ) )
Debug : : log ( ERR , " Couldn't commit output {} in ensureVRR -> true " , m - > m_output - > name ) ;
2024-02-18 15:00:34 +00:00
}
2025-04-30 23:45:20 +02:00
m - > m_vrrActive = true ;
2024-02-18 15:00:34 +00:00
return ;
2025-03-21 16:33:07 +03:00
} else if ( USEVRR = = 2 | | USEVRR = = 3 ) {
2025-04-30 23:45:20 +02:00
const auto PWORKSPACE = m - > m_activeWorkspace ;
2022-05-16 09:38:42 +02:00
2024-02-18 15:00:34 +00:00
if ( ! PWORKSPACE )
return ; // ???
2023-12-20 13:07:12 +01:00
2025-04-25 02:37:12 +02:00
bool wantVRR = PWORKSPACE - > m_hasFullscreenWindow & & ( PWORKSPACE - > m_fullscreenMode & FSMODE_FULLSCREEN ) ;
2025-08-22 11:48:42 +02:00
if ( wantVRR & & PWORKSPACE - > getFullscreenWindow ( ) - > m_windowData . noVRR . valueOrDefault ( ) )
wantVRR = false ;
2025-03-21 16:33:07 +03:00
if ( wantVRR & & USEVRR = = 3 ) {
const auto contentType = PWORKSPACE - > getFullscreenWindow ( ) - > getContentType ( ) ;
wantVRR = contentType = = CONTENT_TYPE_GAME | | contentType = = CONTENT_TYPE_VIDEO ;
}
2022-05-16 09:38:42 +02:00
2025-03-21 16:33:07 +03:00
if ( wantVRR ) {
2024-11-01 07:30:26 -05:00
/* fullscreen */
2025-04-30 23:45:20 +02:00
m - > m_vrrActive = true ;
2024-11-01 07:30:26 -05:00
2025-04-30 23:45:20 +02:00
if ( ! m - > m_output - > state - > state ( ) . adaptiveSync ) {
m - > m_output - > state - > setAdaptiveSync ( true ) ;
2022-05-16 09:38:42 +02:00
2025-04-30 23:45:20 +02:00
if ( ! m - > m_state . test ( ) ) {
Debug : : log ( LOG , " Pending output {} does not accept VRR. " , m - > m_output - > name ) ;
m - > m_output - > state - > setAdaptiveSync ( false ) ;
2025-03-21 16:33:07 +03:00
}
2023-03-05 14:54:26 +00:00
}
2025-03-21 16:33:07 +03:00
} else {
2025-04-30 23:45:20 +02:00
m - > m_vrrActive = false ;
2024-11-01 07:30:26 -05:00
2025-04-30 23:45:20 +02:00
m - > m_output - > state - > setAdaptiveSync ( false ) ;
2023-03-05 14:54:26 +00:00
}
}
2024-02-18 15:00:34 +00:00
} ;
2023-03-05 14:54:26 +00:00
2024-02-18 15:00:34 +00:00
if ( pMonitor ) {
ensureVRRForDisplay ( pMonitor ) ;
return ;
}
2023-12-20 13:07:12 +01:00
2025-04-22 15:23:29 +02:00
for ( auto const & m : g_pCompositor - > m_monitors ) {
2024-10-19 23:03:29 +01:00
ensureVRRForDisplay ( m ) ;
2022-05-16 09:38:42 +02:00
}
}
2025-01-07 17:55:14 +00:00
SP < SAnimationPropertyConfig > CConfigManager : : getAnimationPropertyConfig ( const std : : string & name ) {
2025-04-20 20:39:33 +02:00
return m_animationTree . getConfig ( name ) ;
2024-02-18 15:00:34 +00:00
}
2022-03-17 15:53:45 +01:00
2024-02-18 15:00:34 +00:00
void CConfigManager : : addParseError ( const std : : string & err ) {
2024-12-03 18:58:24 +00:00
g_pHyprError - > queueCreate ( err + " \n Hyprland may not work correctly. " , CHyprColor ( 1.0 , 50.0 / 255.0 , 50.0 / 255.0 , 1.0 ) ) ;
2024-02-18 15:00:34 +00:00
}
2024-10-19 23:03:29 +01:00
PHLMONITOR CConfigManager : : getBoundMonitorForWS ( const std : : string & wsname ) {
2024-02-18 15:00:34 +00:00
auto monitor = getBoundMonitorStringForWS ( wsname ) ;
2025-03-30 03:12:15 +02:00
if ( monitor . starts_with ( " desc: " ) )
return g_pCompositor - > getMonitorFromDesc ( trim ( monitor . substr ( 5 ) ) ) ;
2024-02-18 15:00:34 +00:00
else
return g_pCompositor - > getMonitorFromName ( monitor ) ;
}
std : : string CConfigManager : : getBoundMonitorStringForWS ( const std : : string & wsname ) {
2025-04-20 20:39:33 +02:00
for ( auto const & wr : m_workspaceRules ) {
2024-02-18 15:00:34 +00:00
const auto WSNAME = wr . workspaceName . starts_with ( " name: " ) ? wr . workspaceName . substr ( 5 ) : wr . workspaceName ;
2022-10-25 14:32:25 +01:00
2024-03-19 20:56:20 +00:00
if ( WSNAME = = wsname )
2024-02-18 15:00:34 +00:00
return wr . monitor ;
2022-10-25 14:32:25 +01:00
}
2024-02-18 15:00:34 +00:00
return " " ;
}
2022-03-17 15:53:45 +01:00
2024-12-16 15:58:19 +00:00
const std : : vector < SWorkspaceRule > & CConfigManager : : getAllWorkspaceRules ( ) {
2025-04-20 20:39:33 +02:00
return m_workspaceRules ;
2024-02-18 15:00:34 +00:00
}
2022-03-17 15:53:45 +01:00
2024-02-18 15:00:34 +00:00
void CConfigManager : : addExecRule ( const SExecRequestedRule & rule ) {
2025-04-20 20:39:33 +02:00
m_execRequestedRules . push_back ( rule ) ;
2024-02-18 15:00:34 +00:00
}
2022-04-19 13:42:26 -03:00
2024-02-18 15:00:34 +00:00
void CConfigManager : : handlePluginLoads ( ) {
2025-01-23 21:55:41 +01:00
if ( ! g_pPluginSystem )
2022-03-17 15:53:45 +01:00
return ;
2024-02-18 15:00:34 +00:00
bool pluginsChanged = false ;
2025-04-29 18:59:43 +02:00
g_pPluginSystem - > updateConfigPlugins ( m_declaredPlugins , pluginsChanged ) ;
2022-03-17 15:53:45 +01:00
2024-02-18 15:00:34 +00:00
if ( pluginsChanged ) {
g_pHyprError - > destroy ( ) ;
2025-01-19 15:39:19 +01:00
reload ( ) ;
2024-02-18 15:00:34 +00:00
}
}
2022-03-17 15:53:45 +01:00
2025-01-07 17:55:14 +00:00
const std : : unordered_map < std : : string , SP < SAnimationPropertyConfig > > & CConfigManager : : getAnimationConfig ( ) {
2025-04-20 20:39:33 +02:00
return m_animationTree . getFullConfig ( ) ;
2024-02-18 15:00:34 +00:00
}
2022-03-17 15:53:45 +01:00
2024-02-18 15:00:34 +00:00
void CConfigManager : : addPluginConfigVar ( HANDLE handle , const std : : string & name , const Hyprlang : : CConfigValue & value ) {
if ( ! name . starts_with ( " plugin: " ) )
return ;
2022-09-25 20:07:48 +02:00
2024-02-18 15:00:34 +00:00
std : : string field = name . substr ( 7 ) ;
2022-03-17 16:56:33 +01:00
2025-04-20 20:39:33 +02:00
m_config - > addSpecialConfigValue ( " plugin " , field . c_str ( ) , value ) ;
m_pluginVariables . push_back ( { handle , field } ) ;
2024-02-18 15:00:34 +00:00
}
2023-07-07 13:19:35 -04:00
2024-02-18 15:00:34 +00:00
void CConfigManager : : addPluginKeyword ( HANDLE handle , const std : : string & name , Hyprlang : : PCONFIGHANDLERFUNC fn , Hyprlang : : SHandlerOptions opts ) {
2025-04-20 20:39:33 +02:00
m_pluginKeywords . emplace_back ( SPluginKeyword { handle , name , fn } ) ;
m_config - > registerHandler ( fn , name . c_str ( ) , opts ) ;
2024-02-18 15:00:34 +00:00
}
2023-12-04 01:35:24 +00:00
2024-02-18 15:00:34 +00:00
void CConfigManager : : removePluginConfig ( HANDLE handle ) {
2025-04-20 20:39:33 +02:00
for ( auto const & k : m_pluginKeywords ) {
2024-02-18 15:00:34 +00:00
if ( k . handle ! = handle )
continue ;
2022-05-16 10:09:20 +02:00
2025-04-20 20:39:33 +02:00
m_config - > unregisterHandler ( k . name . c_str ( ) ) ;
2023-07-07 13:19:35 -04:00
}
2022-09-25 20:07:48 +02:00
2025-04-20 20:39:33 +02:00
std : : erase_if ( m_pluginKeywords , [ & ] ( const auto & other ) { return other . handle = = handle ; } ) ;
for ( auto const & [ h , n ] : m_pluginVariables ) {
2024-02-18 15:00:34 +00:00
if ( h ! = handle )
continue ;
2022-04-08 22:07:40 +02:00
2025-04-20 20:39:33 +02:00
m_config - > removeSpecialConfigValue ( " plugin " , n . c_str ( ) ) ;
2024-02-18 15:00:34 +00:00
}
2025-04-20 20:39:33 +02:00
std : : erase_if ( m_pluginVariables , [ handle ] ( const auto & other ) { return other . handle = = handle ; } ) ;
2024-02-18 15:00:34 +00:00
}
2022-04-08 22:07:40 +02:00
2024-02-18 15:00:34 +00:00
std : : string CConfigManager : : getDefaultWorkspaceFor ( const std : : string & name ) {
2025-04-20 20:39:33 +02:00
for ( auto other = m_workspaceRules . begin ( ) ; other ! = m_workspaceRules . end ( ) ; + + other ) {
2024-02-18 15:00:34 +00:00
if ( other - > isDefault ) {
if ( other - > monitor = = name )
return other - > workspaceString ;
2025-03-30 03:12:15 +02:00
if ( other - > monitor . starts_with ( " desc: " ) ) {
auto const monitor = g_pCompositor - > getMonitorFromDesc ( trim ( other - > monitor . substr ( 5 ) ) ) ;
2025-04-30 23:45:20 +02:00
if ( monitor & & monitor - > m_name = = name )
2024-02-18 15:00:34 +00:00
return other - > workspaceString ;
}
2022-04-08 22:07:40 +02:00
}
2022-03-17 15:53:45 +01:00
}
2024-02-18 15:00:34 +00:00
return " " ;
}
2022-03-17 15:53:45 +01:00
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handleRawExec ( const std : : string & command , const std : : string & args ) {
2025-04-20 20:39:33 +02:00
if ( m_isFirstLaunch ) {
m_firstExecRequests . push_back ( { args , false } ) ;
2025-01-11 23:58:05 +08:00
return { } ;
}
g_pKeybindManager - > spawnRaw ( args ) ;
return { } ;
}
std : : optional < std : : string > CConfigManager : : handleExec ( const std : : string & command , const std : : string & args ) {
2025-04-20 20:39:33 +02:00
if ( m_isFirstLaunch ) {
m_firstExecRequests . push_back ( { args , true } ) ;
2024-02-18 15:00:34 +00:00
return { } ;
}
2022-03-17 15:53:45 +01:00
2024-02-18 15:00:34 +00:00
g_pKeybindManager - > spawn ( args ) ;
return { } ;
}
2022-03-17 15:53:45 +01:00
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handleExecOnce ( const std : : string & command , const std : : string & args ) {
2025-04-20 20:39:33 +02:00
if ( m_isFirstLaunch )
m_firstExecRequests . push_back ( { args , true } ) ;
2025-01-11 23:58:05 +08:00
return { } ;
}
std : : optional < std : : string > CConfigManager : : handleExecRawOnce ( const std : : string & command , const std : : string & args ) {
2025-04-20 20:39:33 +02:00
if ( m_isFirstLaunch )
m_firstExecRequests . push_back ( { args , false } ) ;
2022-03-17 15:53:45 +01:00
2024-02-18 15:00:34 +00:00
return { } ;
}
2022-03-17 15:53:45 +01:00
2024-09-07 14:54:33 -05:00
std : : optional < std : : string > CConfigManager : : handleExecShutdown ( const std : : string & command , const std : : string & args ) {
2025-04-22 15:23:29 +02:00
if ( g_pCompositor - > m_finalRequests ) {
2024-09-07 14:54:33 -05:00
g_pKeybindManager - > spawn ( args ) ;
return { } ;
}
2025-04-20 20:39:33 +02:00
m_finalExecRequests . push_back ( args ) ;
2024-09-07 14:54:33 -05:00
return { } ;
}
2024-02-18 15:00:34 +00:00
static bool parseModeLine ( const std : : string & modeline , drmModeModeInfo & mode ) {
auto args = CVarList ( modeline , 0 , ' s ' ) ;
2022-03-19 21:48:24 +01:00
2024-02-18 15:00:34 +00:00
auto keyword = args [ 0 ] ;
2025-05-30 18:25:59 +05:00
std : : ranges : : transform ( keyword , keyword . begin ( ) , : : tolower ) ;
2023-12-30 14:18:53 +00:00
2024-02-18 15:00:34 +00:00
if ( keyword ! = " modeline " )
return false ;
2022-03-20 11:14:24 +01:00
2024-02-18 15:00:34 +00:00
if ( args . size ( ) < 10 ) {
Debug : : log ( ERR , " modeline parse error: expected at least 9 arguments, got {} " , args . size ( ) - 1 ) ;
return false ;
2022-07-19 19:26:53 +02:00
}
2022-03-24 21:05:34 +01:00
2024-02-18 15:00:34 +00:00
int argno = 1 ;
2022-12-01 13:36:07 +00:00
2025-10-16 15:33:06 +02:00
try {
mode . type = DRM_MODE_TYPE_USERDEF ;
mode . clock = std : : stof ( args [ argno + + ] ) * 1000 ;
mode . hdisplay = std : : stoi ( args [ argno + + ] ) ;
mode . hsync_start = std : : stoi ( args [ argno + + ] ) ;
mode . hsync_end = std : : stoi ( args [ argno + + ] ) ;
mode . htotal = std : : stoi ( args [ argno + + ] ) ;
mode . vdisplay = std : : stoi ( args [ argno + + ] ) ;
mode . vsync_start = std : : stoi ( args [ argno + + ] ) ;
mode . vsync_end = std : : stoi ( args [ argno + + ] ) ;
mode . vtotal = std : : stoi ( args [ argno + + ] ) ;
mode . vrefresh = mode . clock * 1000.0 * 1000.0 / mode . htotal / mode . vtotal ;
} catch ( const std : : exception & e ) {
Debug : : log ( ERR , " modeline parse error: invalid numeric value: {} " , e . what ( ) ) ;
return false ;
}
2022-04-19 19:01:23 +02:00
2024-02-18 15:00:34 +00:00
// clang-format off
static std : : unordered_map < std : : string , uint32_t > flagsmap = {
{ " +hsync " , DRM_MODE_FLAG_PHSYNC } ,
{ " -hsync " , DRM_MODE_FLAG_NHSYNC } ,
{ " +vsync " , DRM_MODE_FLAG_PVSYNC } ,
{ " -vsync " , DRM_MODE_FLAG_NVSYNC } ,
{ " Interlace " , DRM_MODE_FLAG_INTERLACE } ,
} ;
// clang-format on
2022-05-26 21:23:13 +02:00
2025-08-14 19:44:56 +05:00
for ( ; argno < sc < int > ( args . size ( ) ) ; argno + + ) {
2024-02-18 15:00:34 +00:00
auto key = args [ argno ] ;
2025-05-30 18:25:59 +05:00
std : : ranges : : transform ( key , key . begin ( ) , : : tolower ) ;
2023-11-26 17:59:49 +00:00
2024-02-18 15:00:34 +00:00
auto it = flagsmap . find ( key ) ;
2023-07-01 16:30:36 +02:00
2024-02-18 15:00:34 +00:00
if ( it ! = flagsmap . end ( ) )
mode . flags | = it - > second ;
else
2024-11-12 02:53:55 +02:00
Debug : : log ( ERR , " Invalid flag {} in modeline " , key ) ;
2023-06-26 11:03:51 +00:00
}
2023-07-01 16:30:36 +02:00
2024-02-18 15:00:34 +00:00
snprintf ( mode . name , sizeof ( mode . name ) , " %dx%d@%d " , mode . hdisplay , mode . vdisplay , mode . vrefresh / 1000 ) ;
2023-07-01 16:30:36 +02:00
2024-02-18 15:00:34 +00:00
return true ;
}
2022-07-16 15:57:31 +02:00
2025-06-05 17:56:46 +03:00
CMonitorRuleParser : : CMonitorRuleParser ( const std : : string & name ) {
m_rule . name = name ;
}
const std : : string & CMonitorRuleParser : : name ( ) {
return m_rule . name ;
}
SMonitorRule & CMonitorRuleParser : : rule ( ) {
return m_rule ;
}
std : : optional < std : : string > CMonitorRuleParser : : getError ( ) {
if ( m_error . empty ( ) )
return { } ;
return m_error ;
}
bool CMonitorRuleParser : : parseMode ( const std : : string & value ) {
if ( value . starts_with ( " pref " ) )
m_rule . resolution = Vector2D ( ) ;
else if ( value . starts_with ( " highrr " ) )
m_rule . resolution = Vector2D ( - 1 , - 1 ) ;
else if ( value . starts_with ( " highres " ) )
m_rule . resolution = Vector2D ( - 1 , - 2 ) ;
2025-07-23 11:10:39 +01:00
else if ( value . starts_with ( " maxwidth " ) )
m_rule . resolution = Vector2D ( - 1 , - 3 ) ;
2025-06-05 17:56:46 +03:00
else if ( parseModeLine ( value , m_rule . drmMode ) ) {
m_rule . resolution = Vector2D ( m_rule . drmMode . hdisplay , m_rule . drmMode . vdisplay ) ;
2025-08-14 19:44:56 +05:00
m_rule . refreshRate = sc < float > ( m_rule . drmMode . vrefresh ) / 1000 ;
2025-06-05 17:56:46 +03:00
} else {
if ( ! value . contains ( " x " ) ) {
m_error + = " invalid resolution " ;
m_rule . resolution = Vector2D ( ) ;
return false ;
} else {
try {
m_rule . resolution . x = stoi ( value . substr ( 0 , value . find_first_of ( ' x ' ) ) ) ;
m_rule . resolution . y = stoi ( value . substr ( value . find_first_of ( ' x ' ) + 1 , value . find_first_of ( ' @ ' ) ) ) ;
if ( value . contains ( " @ " ) )
m_rule . refreshRate = stof ( value . substr ( value . find_first_of ( ' @ ' ) + 1 ) ) ;
} catch ( . . . ) {
m_error + = " invalid resolution " ;
m_rule . resolution = Vector2D ( ) ;
return false ;
}
}
}
return true ;
}
bool CMonitorRuleParser : : parsePosition ( const std : : string & value , bool isFirst ) {
if ( value . starts_with ( " auto " ) ) {
m_rule . offset = Vector2D ( - INT32_MAX , - INT32_MAX ) ;
// If this is the first monitor rule needs to be on the right.
if ( value = = " auto-right " | | value = = " auto " | | isFirst )
m_rule . autoDir = eAutoDirs : : DIR_AUTO_RIGHT ;
else if ( value = = " auto-left " )
m_rule . autoDir = eAutoDirs : : DIR_AUTO_LEFT ;
else if ( value = = " auto-up " )
m_rule . autoDir = eAutoDirs : : DIR_AUTO_UP ;
else if ( value = = " auto-down " )
m_rule . autoDir = eAutoDirs : : DIR_AUTO_DOWN ;
2025-06-06 10:01:19 +03:00
else if ( value = = " auto-center-right " )
m_rule . autoDir = eAutoDirs : : DIR_AUTO_CENTER_RIGHT ;
else if ( value = = " auto-center-left " )
m_rule . autoDir = eAutoDirs : : DIR_AUTO_CENTER_LEFT ;
else if ( value = = " auto-center-up " )
m_rule . autoDir = eAutoDirs : : DIR_AUTO_CENTER_UP ;
else if ( value = = " auto-center-down " )
m_rule . autoDir = eAutoDirs : : DIR_AUTO_CENTER_DOWN ;
2025-06-05 17:56:46 +03:00
else {
Debug : : log ( WARN ,
" Invalid auto direction. Valid options are 'auto', "
2025-06-06 10:01:19 +03:00
" 'auto-up', 'auto-down', 'auto-left', 'auto-right', "
" 'auto-center-up', 'auto-center-down', "
" 'auto-center-left', and 'auto-center-right'. " ) ;
2025-06-05 17:56:46 +03:00
m_error + = " invalid auto direction " ;
return false ;
}
} else {
if ( ! value . contains ( " x " ) ) {
m_error + = " invalid offset " ;
m_rule . offset = Vector2D ( - INT32_MAX , - INT32_MAX ) ;
return false ;
} else {
2025-09-02 13:16:26 +02:00
try {
m_rule . offset . x = stoi ( value . substr ( 0 , value . find_first_of ( ' x ' ) ) ) ;
m_rule . offset . y = stoi ( value . substr ( value . find_first_of ( ' x ' ) + 1 ) ) ;
} catch ( . . . ) {
m_error + = " invalid offset " ;
m_rule . offset = Vector2D ( - INT32_MAX , - INT32_MAX ) ;
return false ;
}
2025-06-05 17:56:46 +03:00
}
}
return true ;
}
bool CMonitorRuleParser : : parseScale ( const std : : string & value ) {
if ( value . starts_with ( " auto " ) )
m_rule . scale = - 1 ;
else {
if ( ! isNumber ( value , true ) ) {
m_error + = " invalid scale " ;
return false ;
} else {
m_rule . scale = stof ( value ) ;
if ( m_rule . scale < 0.25f ) {
m_error + = " invalid scale " ;
m_rule . scale = 1 ;
return false ;
}
}
}
return true ;
}
bool CMonitorRuleParser : : parseTransform ( const std : : string & value ) {
2025-10-16 15:33:06 +02:00
if ( ! isNumber ( value ) ) {
m_error + = " invalid transform " ;
return false ;
}
2025-06-05 17:56:46 +03:00
const auto TSF = std : : stoi ( value ) ;
if ( std : : clamp ( TSF , 0 , 7 ) ! = TSF ) {
Debug : : log ( ERR , " Invalid transform {} in monitor " , TSF ) ;
m_error + = " invalid transform " ;
return false ;
}
2025-08-14 19:44:56 +05:00
m_rule . transform = sc < wl_output_transform > ( TSF ) ;
2025-06-05 17:56:46 +03:00
return true ;
}
bool CMonitorRuleParser : : parseBitdepth ( const std : : string & value ) {
m_rule . enable10bit = value = = " 10 " ;
return true ;
}
bool CMonitorRuleParser : : parseCM ( const std : : string & value ) {
2025-10-24 21:18:39 +02:00
auto parsedCM = NCMType : : fromString ( value ) ;
if ( ! parsedCM . has_value ( ) ) {
2025-06-05 17:56:46 +03:00
m_error + = " invalid cm " ;
return false ;
}
2025-10-24 21:18:39 +02:00
m_rule . cmType = parsedCM . value ( ) ;
2025-06-05 17:56:46 +03:00
return true ;
}
bool CMonitorRuleParser : : parseSDRBrightness ( const std : : string & value ) {
try {
m_rule . sdrBrightness = stof ( value ) ;
} catch ( . . . ) {
m_error + = " invalid sdrbrightness " ;
return false ;
}
return true ;
}
bool CMonitorRuleParser : : parseSDRSaturation ( const std : : string & value ) {
try {
m_rule . sdrSaturation = stof ( value ) ;
} catch ( . . . ) {
m_error + = " invalid sdrsaturation " ;
return false ;
}
return true ;
}
bool CMonitorRuleParser : : parseVRR ( const std : : string & value ) {
if ( ! isNumber ( value ) ) {
m_error + = " invalid vrr " ;
return false ;
}
m_rule . vrr = std : : stoi ( value ) ;
return true ;
}
void CMonitorRuleParser : : setDisabled ( ) {
m_rule . disabled = true ;
}
void CMonitorRuleParser : : setMirror ( const std : : string & value ) {
m_rule . mirrorOf = value ;
}
bool CMonitorRuleParser : : setReserved ( const SMonitorAdditionalReservedArea & value ) {
g_pConfigManager - > m_mAdditionalReservedAreas [ name ( ) ] = value ;
return true ;
}
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handleMonitor ( const std : : string & command , const std : : string & args ) {
2023-04-04 14:49:58 +01:00
2024-02-18 15:00:34 +00:00
// get the monitor config
2025-06-05 17:56:46 +03:00
const auto ARGS = CVarList ( args ) ;
2022-08-01 13:12:50 +02:00
2025-06-05 17:56:46 +03:00
auto parser = CMonitorRuleParser ( ARGS [ 0 ] ) ;
2023-08-01 15:47:56 +02:00
2024-02-18 15:00:34 +00:00
if ( ARGS [ 1 ] = = " disable " | | ARGS [ 1 ] = = " disabled " | | ARGS [ 1 ] = = " addreserved " | | ARGS [ 1 ] = = " transform " ) {
if ( ARGS [ 1 ] = = " disable " | | ARGS [ 1 ] = = " disabled " )
2025-06-05 17:56:46 +03:00
parser . setDisabled ( ) ;
2024-02-18 15:00:34 +00:00
else if ( ARGS [ 1 ] = = " transform " ) {
2025-06-05 17:56:46 +03:00
if ( ! parser . parseTransform ( ARGS [ 2 ] ) )
return parser . getError ( ) ;
2022-09-25 20:07:48 +02:00
2025-06-05 17:56:46 +03:00
const auto TRANSFORM = parser . rule ( ) . transform ;
2023-05-01 07:10:53 -07:00
2024-02-18 15:00:34 +00:00
// overwrite if exists
2025-04-20 20:39:33 +02:00
for ( auto & r : m_monitorRules ) {
2025-06-05 17:56:46 +03:00
if ( r . name = = parser . name ( ) ) {
2024-02-18 15:00:34 +00:00
r . transform = TRANSFORM ;
return { } ;
}
}
2023-07-10 13:54:06 +02:00
2024-02-18 15:00:34 +00:00
return { } ;
} else if ( ARGS [ 1 ] = = " addreserved " ) {
2025-10-16 15:33:06 +02:00
try {
parser . setReserved ( { . top = std : : stoi ( ARGS [ 2 ] ) , . bottom = std : : stoi ( ARGS [ 3 ] ) , . left = std : : stoi ( ARGS [ 4 ] ) , . right = std : : stoi ( ARGS [ 5 ] ) } ) ;
} catch ( . . . ) { return " parse error: invalid reserved area " ; }
2024-02-18 15:00:34 +00:00
return { } ;
} else {
Debug : : log ( ERR , " ConfigManager parseMonitor, curitem bogus??? " ) ;
return " parse error: curitem bogus " ;
2022-05-16 10:09:20 +02:00
}
2022-03-17 15:53:45 +01:00
2025-06-05 17:56:46 +03:00
std : : erase_if ( m_monitorRules , [ & ] ( const auto & other ) { return other . name = = parser . name ( ) ; } ) ;
2024-02-18 15:00:34 +00:00
2025-06-05 17:56:46 +03:00
m_monitorRules . push_back ( parser . rule ( ) ) ;
2022-05-16 10:09:20 +02:00
2024-02-18 15:00:34 +00:00
return { } ;
2022-03-17 15:53:45 +01:00
}
2025-06-05 17:56:46 +03:00
parser . parseMode ( ARGS [ 1 ] ) ;
parser . parsePosition ( ARGS [ 2 ] ) ;
parser . parseScale ( ARGS [ 3 ] ) ;
2022-06-30 21:38:06 +02:00
2024-02-18 15:00:34 +00:00
int argno = 4 ;
2022-06-30 21:26:00 +02:00
2025-05-31 23:49:50 +05:00
while ( ! ARGS [ argno ] . empty ( ) ) {
2024-02-18 15:00:34 +00:00
if ( ARGS [ argno ] = = " mirror " ) {
2025-06-05 17:56:46 +03:00
parser . setMirror ( ARGS [ argno + 1 ] ) ;
2024-02-18 15:00:34 +00:00
argno + + ;
} else if ( ARGS [ argno ] = = " bitdepth " ) {
2025-06-05 17:56:46 +03:00
parser . parseBitdepth ( ARGS [ argno + 1 ] ) ;
2024-02-18 15:00:34 +00:00
argno + + ;
2025-03-14 02:15:18 +03:00
} else if ( ARGS [ argno ] = = " cm " ) {
2025-06-05 17:56:46 +03:00
parser . parseCM ( ARGS [ argno + 1 ] ) ;
2025-03-14 02:15:18 +03:00
argno + + ;
} else if ( ARGS [ argno ] = = " sdrsaturation " ) {
2025-06-05 17:56:46 +03:00
parser . parseSDRSaturation ( ARGS [ argno + 1 ] ) ;
2025-03-14 02:15:18 +03:00
argno + + ;
} else if ( ARGS [ argno ] = = " sdrbrightness " ) {
2025-06-05 17:56:46 +03:00
parser . parseSDRBrightness ( ARGS [ argno + 1 ] ) ;
2025-03-14 02:15:18 +03:00
argno + + ;
2024-02-18 15:00:34 +00:00
} else if ( ARGS [ argno ] = = " transform " ) {
2025-06-05 17:56:46 +03:00
parser . parseTransform ( ARGS [ argno + 1 ] ) ;
2024-02-18 15:00:34 +00:00
argno + + ;
} else if ( ARGS [ argno ] = = " vrr " ) {
2025-06-05 17:56:46 +03:00
parser . parseVRR ( ARGS [ argno + 1 ] ) ;
2024-02-18 15:00:34 +00:00
argno + + ;
} else if ( ARGS [ argno ] = = " workspace " ) {
2025-10-27 21:29:35 +00:00
const auto & [ id , name , isAutoID ] = getWorkspaceIDNameFromString ( ARGS [ argno + 1 ] ) ;
2022-03-17 15:53:45 +01:00
2024-02-18 15:00:34 +00:00
SWorkspaceRule wsRule ;
2025-06-05 17:56:46 +03:00
wsRule . monitor = parser . name ( ) ;
2024-02-18 15:00:34 +00:00
wsRule . workspaceString = ARGS [ argno + 1 ] ;
2025-10-27 21:29:35 +00:00
wsRule . workspaceId = isAutoID ? WORKSPACE_INVALID : id ;
2024-02-18 15:00:34 +00:00
wsRule . workspaceName = name ;
2022-03-17 15:53:45 +01:00
2025-04-20 20:39:33 +02:00
m_workspaceRules . emplace_back ( wsRule ) ;
2024-02-18 15:00:34 +00:00
argno + + ;
} else {
2024-11-12 02:53:55 +02:00
Debug : : log ( ERR , " Config error: invalid monitor syntax at \" {} \" " , ARGS [ argno ] ) ;
2024-02-18 15:00:34 +00:00
return " invalid syntax at \" " + ARGS [ argno ] + " \" " ;
}
2023-09-28 02:49:30 +08:00
2024-02-18 15:00:34 +00:00
argno + + ;
}
2022-05-06 14:30:35 +02:00
2025-06-05 17:56:46 +03:00
auto newrule = parser . rule ( ) ;
2025-04-20 20:39:33 +02:00
std : : erase_if ( m_monitorRules , [ & ] ( const auto & other ) { return other . name = = newrule . name ; } ) ;
2022-05-06 14:30:35 +02:00
2025-04-20 20:39:33 +02:00
m_monitorRules . push_back ( newrule ) ;
2022-03-17 16:56:33 +01:00
2025-06-05 17:56:46 +03:00
return parser . getError ( ) ;
2022-06-30 21:26:00 +02:00
}
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handleBezier ( const std : : string & command , const std : : string & args ) {
const auto ARGS = CVarList ( args ) ;
2022-06-30 21:26:00 +02:00
2024-02-18 15:00:34 +00:00
std : : string bezierName = ARGS [ 0 ] ;
2023-09-28 02:49:30 +08:00
2025-05-31 23:49:50 +05:00
if ( ARGS [ 1 ] . empty ( ) )
2024-02-18 15:00:34 +00:00
return " too few arguments " ;
2025-10-16 15:33:06 +02:00
else if ( ! isNumber ( ARGS [ 1 ] , true ) )
return " invalid point " ;
2024-02-18 15:00:34 +00:00
float p1x = std : : stof ( ARGS [ 1 ] ) ;
2022-06-30 21:26:00 +02:00
2025-05-31 23:49:50 +05:00
if ( ARGS [ 2 ] . empty ( ) )
2024-02-18 15:00:34 +00:00
return " too few arguments " ;
2025-10-16 15:33:06 +02:00
else if ( ! isNumber ( ARGS [ 2 ] , true ) )
return " invalid point " ;
2024-02-18 15:00:34 +00:00
float p1y = std : : stof ( ARGS [ 2 ] ) ;
2022-06-30 21:26:00 +02:00
2025-05-31 23:49:50 +05:00
if ( ARGS [ 3 ] . empty ( ) )
2024-02-18 15:00:34 +00:00
return " too few arguments " ;
2025-10-16 15:33:06 +02:00
else if ( ! isNumber ( ARGS [ 3 ] , true ) )
return " invalid point " ;
2024-02-18 15:00:34 +00:00
float p2x = std : : stof ( ARGS [ 3 ] ) ;
2022-06-30 21:26:00 +02:00
2025-05-31 23:49:50 +05:00
if ( ARGS [ 4 ] . empty ( ) )
2024-02-18 15:00:34 +00:00
return " too few arguments " ;
2025-10-16 15:33:06 +02:00
else if ( ! isNumber ( ARGS [ 4 ] , true ) )
return " invalid point " ;
2024-02-18 15:00:34 +00:00
float p2y = std : : stof ( ARGS [ 4 ] ) ;
2022-04-10 18:25:45 +02:00
2025-05-31 23:49:50 +05:00
if ( ! ARGS [ 5 ] . empty ( ) )
2024-02-18 15:00:34 +00:00
return " too many arguments " ;
2022-04-10 18:25:45 +02:00
2024-02-18 15:00:34 +00:00
g_pAnimationManager - > addBezierWithName ( bezierName , Vector2D ( p1x , p1y ) , Vector2D ( p2x , p2y ) ) ;
2023-09-28 02:49:30 +08:00
2024-02-18 15:00:34 +00:00
return { } ;
2022-04-10 18:25:45 +02:00
}
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handleAnimation ( const std : : string & command , const std : : string & args ) {
const auto ARGS = CVarList ( args ) ;
2022-03-19 17:00:52 +01:00
2024-02-18 15:00:34 +00:00
// Master on/off
2022-03-17 16:56:33 +01:00
2024-02-18 15:00:34 +00:00
// anim name
const auto ANIMNAME = ARGS [ 0 ] ;
2022-03-17 16:56:33 +01:00
2025-04-20 20:39:33 +02:00
if ( ! m_animationTree . nodeExists ( ANIMNAME ) )
2024-02-18 15:00:34 +00:00
return " no such animation " ;
2022-03-24 18:22:01 +01:00
2024-04-20 11:26:48 +00:00
// This helper casts strings like "1", "true", "off", "yes"... to int.
2024-11-20 10:32:50 +00:00
int64_t enabledInt = configStringToInt ( ARGS [ 1 ] ) . value_or ( 0 ) = = 1 ;
2022-03-24 18:22:01 +01:00
2024-04-20 11:26:48 +00:00
// Checking that the int is 1 or 0 because the helper can return integers out of range.
if ( enabledInt ! = 0 & & enabledInt ! = 1 )
2024-02-18 15:00:34 +00:00
return " invalid animation on/off state " ;
2022-03-24 18:22:01 +01:00
2025-01-09 22:08:16 +01:00
if ( ! enabledInt ) {
2025-04-20 20:39:33 +02:00
m_animationTree . setConfigForNode ( ANIMNAME , enabledInt , 1 , " default " ) ;
2025-01-09 22:08:16 +01:00
return { } ;
}
2025-01-20 16:48:04 +00:00
float speed = - 1 ;
2024-04-20 11:26:48 +00:00
2025-01-07 20:27:07 +01:00
// speed
if ( isNumber ( ARGS [ 2 ] , true ) ) {
speed = std : : stof ( ARGS [ 2 ] ) ;
2022-03-24 18:22:01 +01:00
2025-01-07 20:27:07 +01:00
if ( speed < = 0 ) {
speed = 1.f ;
2024-02-18 15:00:34 +00:00
return " invalid speed " ;
}
2025-01-07 20:27:07 +01:00
} else {
speed = 10.f ;
return " invalid speed " ;
}
2022-06-24 16:25:57 +02:00
2025-01-07 20:27:07 +01:00
std : : string bezierName = ARGS [ 3 ] ;
2025-04-20 20:39:33 +02:00
m_animationTree . setConfigForNode ( ANIMNAME , enabledInt , speed , ARGS [ 3 ] , ARGS [ 4 ] ) ;
2023-07-02 13:02:48 +02:00
2025-01-07 20:27:07 +01:00
if ( ! g_pAnimationManager - > bezierExists ( bezierName ) ) {
2025-04-20 20:39:33 +02:00
const auto PANIMNODE = m_animationTree . getConfig ( ANIMNAME ) ;
2025-01-07 20:27:07 +01:00
PANIMNODE - > internalBezier = " default " ;
return " no such bezier " ;
}
2022-06-24 16:25:57 +02:00
2025-05-31 23:49:50 +05:00
if ( ! ARGS [ 4 ] . empty ( ) ) {
2025-01-07 20:27:07 +01:00
auto ERR = g_pAnimationManager - > styleValidInConfigVar ( ANIMNAME , ARGS [ 4 ] ) ;
2022-09-06 11:57:11 +02:00
2025-05-31 23:49:50 +05:00
if ( ! ERR . empty ( ) )
2025-01-07 20:27:07 +01:00
return ERR ;
2024-02-18 15:00:34 +00:00
}
2022-09-06 11:57:11 +02:00
2024-02-18 15:00:34 +00:00
return { } ;
}
2022-09-07 11:24:40 +02:00
2024-03-03 01:17:02 +01:00
SParsedKey parseKey ( const std : : string & key ) {
if ( isNumber ( key ) & & std : : stoi ( key ) > 9 )
return { . keycode = std : : stoi ( key ) } ;
else if ( key . starts_with ( " code: " ) & & isNumber ( key . substr ( 5 ) ) )
return { . keycode = std : : stoi ( key . substr ( 5 ) ) } ;
else if ( key = = " catchall " )
return { . catchAll = true } ;
else
return { . key = key } ;
}
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handleBind ( const std : : string & command , const std : : string & value ) {
// example:
// bind[fl]=SUPER,G,exec,dmenu_run <args>
2023-12-26 23:47:46 +01:00
2024-02-18 15:00:34 +00:00
// flags
2024-06-11 19:49:54 +02:00
bool locked = false ;
bool release = false ;
bool repeat = false ;
bool mouse = false ;
bool nonConsuming = false ;
bool transparent = false ;
bool ignoreMods = false ;
bool multiKey = false ;
2024-11-16 07:21:59 +08:00
bool longPress = false ;
2024-06-11 19:49:54 +02:00
bool hasDescription = false ;
2024-07-24 12:10:36 +00:00
bool dontInhibit = false ;
2025-04-12 10:43:13 -04:00
bool click = false ;
bool drag = false ;
2024-06-11 19:49:54 +02:00
const auto BINDARGS = command . substr ( 4 ) ;
2023-12-26 23:47:46 +01:00
2024-08-26 17:25:39 +02:00
for ( auto const & arg : BINDARGS ) {
2024-02-18 15:00:34 +00:00
if ( arg = = ' l ' ) {
locked = true ;
} else if ( arg = = ' r ' ) {
release = true ;
} else if ( arg = = ' e ' ) {
repeat = true ;
} else if ( arg = = ' m ' ) {
mouse = true ;
} else if ( arg = = ' n ' ) {
nonConsuming = true ;
} else if ( arg = = ' t ' ) {
transparent = true ;
} else if ( arg = = ' i ' ) {
ignoreMods = true ;
2024-05-16 10:48:30 +00:00
} else if ( arg = = ' s ' ) {
multiKey = true ;
2024-11-16 07:21:59 +08:00
} else if ( arg = = ' o ' ) {
longPress = true ;
2024-06-11 19:49:54 +02:00
} else if ( arg = = ' d ' ) {
hasDescription = true ;
2024-07-24 12:10:36 +00:00
} else if ( arg = = ' p ' ) {
dontInhibit = true ;
2025-04-12 10:43:13 -04:00
} else if ( arg = = ' c ' ) {
click = true ;
release = true ;
} else if ( arg = = ' g ' ) {
drag = true ;
release = true ;
2024-02-18 15:00:34 +00:00
} else {
return " bind: invalid flag " ;
}
}
2023-12-26 23:47:46 +01:00
2024-11-16 07:21:59 +08:00
if ( ( longPress | | release ) & & repeat )
return " flags e is mutually exclusive with r and o " ;
2023-12-26 23:47:46 +01:00
2024-02-18 15:00:34 +00:00
if ( mouse & & ( repeat | | release | | locked ) )
return " flag m is exclusive " ;
2022-09-07 11:24:40 +02:00
2025-04-12 10:43:13 -04:00
if ( click & & drag )
return " flags c and g are mutually exclusive " ;
2024-06-11 19:49:54 +02:00
const int numbArgs = hasDescription ? 5 : 4 ;
const auto ARGS = CVarList ( value , numbArgs ) ;
2022-11-15 11:21:26 +01:00
2024-06-11 19:49:54 +02:00
const int DESCR_OFFSET = hasDescription ? 1 : 0 ;
2024-02-18 15:00:34 +00:00
if ( ( ARGS . size ( ) < 3 & & ! mouse ) | | ( ARGS . size ( ) < 3 & & mouse ) )
return " bind: too few args " ;
2025-08-14 19:44:56 +05:00
else if ( ( ARGS . size ( ) > sc < size_t > ( 4 ) + DESCR_OFFSET & & ! mouse ) | | ( ARGS . size ( ) > sc < size_t > ( 3 ) + DESCR_OFFSET & & mouse ) )
2024-02-18 15:00:34 +00:00
return " bind: too many args " ;
2022-11-15 11:21:26 +01:00
2024-05-16 10:48:30 +00:00
std : : set < xkb_keysym_t > KEYSYMS ;
std : : set < xkb_keysym_t > MODS ;
if ( multiKey ) {
2024-12-07 18:51:18 +01:00
for ( const auto & splitKey : CVarList ( ARGS [ 1 ] , 8 , ' & ' ) ) {
2024-05-16 10:48:30 +00:00
KEYSYMS . insert ( xkb_keysym_from_name ( splitKey . c_str ( ) , XKB_KEYSYM_CASE_INSENSITIVE ) ) ;
}
2024-12-07 18:51:18 +01:00
for ( const auto & splitMod : CVarList ( ARGS [ 0 ] , 8 , ' & ' ) ) {
2024-05-16 10:48:30 +00:00
MODS . insert ( xkb_keysym_from_name ( splitMod . c_str ( ) , XKB_KEYSYM_CASE_INSENSITIVE ) ) ;
}
}
2024-02-18 15:00:34 +00:00
const auto MOD = g_pKeybindManager - > stringToModMask ( ARGS [ 0 ] ) ;
const auto MODSTR = ARGS [ 0 ] ;
2023-08-02 13:21:38 +02:00
2024-05-16 10:48:30 +00:00
const auto KEY = multiKey ? " " : ARGS [ 1 ] ;
2023-12-08 16:02:16 +00:00
2024-06-11 19:49:54 +02:00
const auto DESCRIPTION = hasDescription ? ARGS [ 2 ] : " " ;
2023-12-20 23:52:18 +01:00
2024-06-11 19:49:54 +02:00
auto HANDLER = ARGS [ 2 + DESCR_OFFSET ] ;
2023-08-02 13:21:38 +02:00
2024-06-11 19:49:54 +02:00
const auto COMMAND = mouse ? HANDLER : ARGS [ 3 + DESCR_OFFSET ] ;
2023-08-02 13:21:38 +02:00
2024-06-11 23:02:29 +02:00
if ( mouse )
HANDLER = " mouse " ;
2024-02-18 15:00:34 +00:00
// to lower
2025-05-30 18:25:59 +05:00
std : : ranges : : transform ( HANDLER , HANDLER . begin ( ) , : : tolower ) ;
2023-08-02 13:21:38 +02:00
2025-05-02 17:07:20 +02:00
const auto DISPATCHER = g_pKeybindManager - > m_dispatchers . find ( HANDLER ) ;
2023-08-02 13:21:38 +02:00
2025-05-02 17:07:20 +02:00
if ( DISPATCHER = = g_pKeybindManager - > m_dispatchers . end ( ) ) {
2024-11-12 02:53:55 +02:00
Debug : : log ( ERR , " Invalid dispatcher: {} " , HANDLER ) ;
2024-02-18 15:00:34 +00:00
return " Invalid dispatcher, requested \" " + HANDLER + " \" does not exist " ;
}
2022-03-24 18:22:01 +01:00
2025-05-31 23:49:50 +05:00
if ( MOD = = 0 & & ! MODSTR . empty ( ) ) {
2024-11-12 02:53:55 +02:00
Debug : : log ( ERR , " Invalid mod: {} " , MODSTR ) ;
2024-02-18 15:00:34 +00:00
return " Invalid mod, requested mod \" " + MODSTR + " \" is not a valid mod. " ;
}
2022-03-24 18:22:01 +01:00
2025-05-31 23:49:50 +05:00
if ( ( ! KEY . empty ( ) ) | | multiKey ) {
2024-03-03 01:17:02 +01:00
SParsedKey parsedKey = parseKey ( KEY ) ;
2025-10-11 02:40:18 +02:00
if ( parsedKey . catchAll & & m_currentSubmap . name . empty ( ) ) {
2024-03-03 01:17:02 +01:00
Debug : : log ( ERR , " Catchall not allowed outside of submap! " ) ;
return " Invalid catchall, catchall keybinds are only allowed in submaps. " ;
}
2024-11-16 07:21:59 +08:00
g_pKeybindManager - > addKeybind ( SKeybind { parsedKey . key , KEYSYMS , parsedKey . keycode , parsedKey . catchAll , MOD , MODS , HANDLER ,
2025-04-20 20:39:33 +02:00
COMMAND , locked , m_currentSubmap , DESCRIPTION , release , repeat , longPress ,
2025-04-12 10:43:13 -04:00
mouse , nonConsuming , transparent , ignoreMods , multiKey , hasDescription , dontInhibit ,
click , drag } ) ;
2024-02-18 15:00:34 +00:00
}
2023-07-02 13:02:48 +02:00
2024-02-18 15:00:34 +00:00
return { } ;
}
2024-02-18 00:13:38 +00:00
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handleUnbind ( const std : : string & command , const std : : string & value ) {
const auto ARGS = CVarList ( value ) ;
2022-03-24 18:22:01 +01:00
2025-06-28 14:55:13 +02:00
if ( ARGS . size ( ) = = 1 & & ARGS [ 0 ] = = " all " ) {
g_pKeybindManager - > m_keybinds . clear ( ) ;
g_pKeybindManager - > m_activeKeybinds . clear ( ) ;
g_pKeybindManager - > m_lastLongPressKeybind . reset ( ) ;
return { } ;
}
2024-02-18 15:00:34 +00:00
const auto MOD = g_pKeybindManager - > stringToModMask ( ARGS [ 0 ] ) ;
2023-04-18 11:48:56 +01:00
2024-03-03 01:17:02 +01:00
const auto KEY = parseKey ( ARGS [ 1 ] ) ;
2022-11-10 13:39:23 +00:00
2024-02-18 15:00:34 +00:00
g_pKeybindManager - > removeKeybind ( MOD , KEY ) ;
2022-11-10 13:39:23 +00:00
2024-02-18 15:00:34 +00:00
return { } ;
}
2022-11-10 13:39:23 +00:00
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handleWindowRule ( const std : : string & command , const std : : string & value ) {
2025-09-26 00:33:58 +02:00
const auto VARLIST = CVarList ( value , 0 , ' , ' , true ) ;
2023-02-27 12:32:38 +00:00
2025-09-26 00:33:58 +02:00
std : : vector < std : : string_view > tokens ;
std : : unordered_map < std : : string_view , std : : string_view > params ;
2022-08-11 21:16:38 +02:00
2025-09-26 00:33:58 +02:00
bool parsingParams = false ;
2023-09-09 13:25:17 +02:00
2025-09-26 00:33:58 +02:00
for ( const auto & varStr : VARLIST ) {
2025-09-29 20:10:34 +02:00
std : : string_view var = varStr ;
auto sep = var . find ( ' : ' ) ;
std : : string_view key = ( sep ! = std : : string_view : : npos ) ? var . substr ( 0 , sep ) : var ;
bool isParam = ( sep ! = std : : string_view : : npos & & ! ( key . starts_with ( " workspace " ) | | ( key . starts_with ( " monitor " ) ) | | key . ends_with ( " plugin " ) ) ) ;
2023-09-09 13:25:17 +02:00
2025-09-27 01:04:22 +02:00
if ( ! parsingParams ) {
2025-09-29 20:10:34 +02:00
if ( ! isParam ) {
2025-09-27 01:04:22 +02:00
tokens . emplace_back ( var ) ;
continue ;
}
2025-09-29 20:10:34 +02:00
2025-09-26 00:33:58 +02:00
parsingParams = true ;
2025-09-27 01:04:22 +02:00
}
2022-06-30 21:26:00 +02:00
2025-09-27 01:04:22 +02:00
if ( sep = = std : : string_view : : npos )
return std : : format ( " Invalid rule: {}, Invalid parameter: {} " , value , std : : string ( var ) ) ;
2022-07-06 22:12:03 +02:00
2025-09-27 01:04:22 +02:00
auto pos = var . find_first_not_of ( ' ' , sep + 1 ) ;
std : : string_view val = ( pos ! = std : : string_view : : npos ) ? var . substr ( pos ) : std : : string_view { } ;
params [ key ] = val ;
2025-09-26 00:33:58 +02:00
}
2025-02-02 22:25:29 +03:00
2025-09-26 00:33:58 +02:00
auto get = [ & ] ( std : : string_view key ) - > std : : string_view {
if ( auto it = params . find ( key ) ; it ! = params . end ( ) )
return it - > second ;
return { } ;
} ;
2025-04-21 22:22:06 +01:00
2025-09-27 01:04:22 +02:00
auto applyParams = [ & ] ( SP < CWindowRule > rule ) - > bool {
bool set = false ;
2025-09-26 00:33:58 +02:00
if ( auto v = get ( " class " ) ; ! v . empty ( ) ) {
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_class = v , true ) ;
2025-09-26 00:33:58 +02:00
rule - > m_classRegex = { std : : string ( v ) } ;
}
if ( auto v = get ( " title " ) ; ! v . empty ( ) ) {
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_title = v , true ) ;
2025-09-26 00:33:58 +02:00
rule - > m_titleRegex = { std : : string ( v ) } ;
}
if ( auto v = get ( " tag " ) ; ! v . empty ( ) )
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_tag = v , true ) ;
2025-09-26 00:33:58 +02:00
if ( auto v = get ( " initialClass " ) ; ! v . empty ( ) ) {
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_initialClass = v , true ) ;
2025-09-26 00:33:58 +02:00
rule - > m_initialClassRegex = { std : : string ( v ) } ;
}
if ( auto v = get ( " initialTitle " ) ; ! v . empty ( ) ) {
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_initialTitle = v , true ) ;
2025-09-26 00:33:58 +02:00
rule - > m_initialTitleRegex = { std : : string ( v ) } ;
}
2025-09-27 01:04:22 +02:00
2025-09-26 00:33:58 +02:00
if ( auto v = get ( " xwayland " ) ; ! v . empty ( ) )
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_X11 = ( v = = " 1 " ) , true ) ;
2025-09-26 00:33:58 +02:00
if ( auto v = get ( " floating " ) ; ! v . empty ( ) )
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_floating = ( v = = " 1 " ) , true ) ;
2025-09-26 00:33:58 +02:00
if ( auto v = get ( " fullscreen " ) ; ! v . empty ( ) )
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_fullscreen = ( v = = " 1 " ) , true ) ;
2025-09-26 00:33:58 +02:00
if ( auto v = get ( " pinned " ) ; ! v . empty ( ) )
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_pinned = ( v = = " 1 " ) , true ) ;
if ( auto v = get ( " focus " ) ; ! v . empty ( ) )
set | = ( rule - > m_focus = ( v = = " 1 " ) , true ) ;
if ( auto v = get ( " group " ) ; ! v . empty ( ) )
set | = ( rule - > m_group = ( v = = " 1 " ) , true ) ;
2025-10-13 14:16:48 +02:00
if ( auto v = get ( " modal " ) ; ! v . empty ( ) )
set | = ( rule - > m_modal = ( v = = " 1 " ) , true ) ;
2025-09-27 01:04:22 +02:00
2025-09-26 00:33:58 +02:00
if ( auto v = get ( " fullscreenstate " ) ; ! v . empty ( ) )
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_fullscreenState = v , true ) ;
2025-09-26 00:33:58 +02:00
if ( auto v = get ( " workspace " ) ; ! v . empty ( ) )
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_workspace = v , true ) ;
2025-09-26 00:33:58 +02:00
if ( auto v = get ( " onworkspace " ) ; ! v . empty ( ) )
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_onWorkspace = v , true ) ;
2025-09-26 00:33:58 +02:00
if ( auto v = get ( " content " ) ; ! v . empty ( ) )
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_contentType = v , true ) ;
2025-09-26 00:33:58 +02:00
if ( auto v = get ( " xdgTag " ) ; ! v . empty ( ) )
2025-09-27 01:04:22 +02:00
set | = ( rule - > m_xdgTag = v , true ) ;
return set ;
2025-09-26 00:33:58 +02:00
} ;
2025-06-05 16:17:04 -04:00
2025-09-26 00:33:58 +02:00
std : : vector < SP < CWindowRule > > rules ;
for ( auto token : tokens ) {
if ( token . starts_with ( " unset " ) ) {
std : : string ruleName = " " ;
if ( token . size ( ) < = 6 | | token . contains ( " all " ) )
ruleName = " all " ;
else
ruleName = std : : string ( token . substr ( 6 ) ) ;
auto rule = makeShared < CWindowRule > ( ruleName , value , true ) ;
applyParams ( rule ) ;
std : : erase_if ( m_windowRules , [ & ] ( const auto & other ) {
if ( ! other - > m_v2 )
return other - > m_class = = rule - > m_class & & ! rule - > m_class . empty ( ) ;
if ( rule - > m_ruleType ! = other - > m_ruleType & & ruleName ! = " all " )
return false ;
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_tag . empty ( ) & & rule - > m_tag ! = other - > m_tag )
2024-05-29 05:37:24 +08:00
return false ;
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_class . empty ( ) & & rule - > m_class ! = other - > m_class )
2024-02-18 15:00:34 +00:00
return false ;
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_title . empty ( ) & & rule - > m_title ! = other - > m_title )
2024-02-18 15:00:34 +00:00
return false ;
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_initialClass . empty ( ) & & rule - > m_initialClass ! = other - > m_initialClass )
2024-02-18 15:00:34 +00:00
return false ;
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_initialTitle . empty ( ) & & rule - > m_initialTitle ! = other - > m_initialTitle )
2024-02-18 15:00:34 +00:00
return false ;
2025-04-28 22:25:22 +02:00
if ( rule - > m_X11 ! = - 1 & & rule - > m_X11 ! = other - > m_X11 )
2024-02-18 15:00:34 +00:00
return false ;
2025-04-28 22:25:22 +02:00
if ( rule - > m_floating ! = - 1 & & rule - > m_floating ! = other - > m_floating )
2024-02-18 15:00:34 +00:00
return false ;
2025-04-28 22:25:22 +02:00
if ( rule - > m_fullscreen ! = - 1 & & rule - > m_fullscreen ! = other - > m_fullscreen )
2024-02-18 15:00:34 +00:00
return false ;
2025-04-28 22:25:22 +02:00
if ( rule - > m_pinned ! = - 1 & & rule - > m_pinned ! = other - > m_pinned )
2024-02-18 15:00:34 +00:00
return false ;
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_fullscreenState . empty ( ) & & rule - > m_fullscreenState ! = other - > m_fullscreenState )
2024-08-24 04:42:14 +09:00
return false ;
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_workspace . empty ( ) & & rule - > m_workspace ! = other - > m_workspace )
2024-02-18 15:00:34 +00:00
return false ;
2025-04-28 22:25:22 +02:00
if ( rule - > m_focus ! = - 1 & & rule - > m_focus ! = other - > m_focus )
2024-02-18 15:00:34 +00:00
return false ;
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_onWorkspace . empty ( ) & & rule - > m_onWorkspace ! = other - > m_onWorkspace )
2024-02-18 15:00:34 +00:00
return false ;
2025-04-28 22:25:22 +02:00
if ( ! rule - > m_contentType . empty ( ) & & rule - > m_contentType ! = other - > m_contentType )
2025-02-02 22:25:29 +03:00
return false ;
2025-06-05 16:17:04 -04:00
if ( rule - > m_group ! = - 1 & & rule - > m_group ! = other - > m_group )
return false ;
2025-10-13 14:16:48 +02:00
if ( rule - > m_modal ! = - 1 & & rule - > m_modal ! = other - > m_modal )
return false ;
2024-02-18 15:00:34 +00:00
return true ;
2025-09-26 00:33:58 +02:00
} ) ;
} else {
auto rule = makeShared < CWindowRule > ( std : : string ( token ) , value , true ) ;
if ( rule - > m_ruleType = = CWindowRule : : RULE_INVALID ) {
Debug : : log ( ERR , " Invalid rule found: {}, Invalid value: {} " , value , token ) ;
return std : : format ( " Invalid rule found: {}, Invalid value: {} " , value , token ) ;
2024-02-18 15:00:34 +00:00
}
2025-09-27 01:04:22 +02:00
if ( applyParams ( rule ) )
rules . emplace_back ( rule ) ;
else {
Debug : : log ( INFO , " ===== Skipping rule: {}, Invalid parameters " , rule - > m_value ) ;
return std : : format ( " Invalid parameters found in: {} " , value ) ;
}
2025-09-26 00:33:58 +02:00
}
2022-07-27 12:32:00 +02:00
}
2022-07-28 13:28:43 +02:00
2025-09-26 00:33:58 +02:00
if ( rules . empty ( ) & & tokens . empty ( ) )
return " Invalid rule syntax: no rules provided " ;
for ( auto & rule : rules ) {
if ( rule - > m_ruleType = = CWindowRule : : RULE_SIZE | | rule - > m_ruleType = = CWindowRule : : RULE_MAXSIZE | | rule - > m_ruleType = = CWindowRule : : RULE_MINSIZE )
m_windowRules . insert ( m_windowRules . begin ( ) , rule ) ;
else
m_windowRules . emplace_back ( rule ) ;
}
2022-10-28 23:48:48 +01:00
2024-02-18 15:00:34 +00:00
return { } ;
}
2023-03-16 14:03:40 +00:00
2025-03-18 01:36:55 +00:00
std : : optional < std : : string > CConfigManager : : handleLayerRule ( const std : : string & command , const std : : string & value ) {
const auto RULE = trim ( value . substr ( 0 , value . find_first_of ( ' , ' ) ) ) ;
const auto VALUE = trim ( value . substr ( value . find_first_of ( ' , ' ) + 1 ) ) ;
// check rule and value
if ( RULE . empty ( ) | | VALUE . empty ( ) )
return " empty rule? " ;
if ( RULE = = " unset " ) {
2025-04-24 20:49:49 +02:00
std : : erase_if ( m_layerRules , [ & ] ( const auto & other ) { return other - > m_targetNamespace = = VALUE ; } ) ;
2025-03-18 01:36:55 +00:00
return { } ;
}
auto rule = makeShared < CLayerRule > ( RULE , VALUE ) ;
2025-04-24 20:49:49 +02:00
if ( rule - > m_ruleType = = CLayerRule : : RULE_INVALID ) {
2025-03-18 01:36:55 +00:00
Debug : : log ( ERR , " Invalid rule found: {} " , RULE ) ;
return " Invalid rule found: " + RULE ;
}
2025-04-24 20:49:49 +02:00
rule - > m_targetNamespaceRegex = { VALUE } ;
2025-03-18 01:36:55 +00:00
2025-04-20 20:39:33 +02:00
m_layerRules . emplace_back ( rule ) ;
2025-03-18 01:36:55 +00:00
2025-04-22 15:23:29 +02:00
for ( auto const & m : g_pCompositor - > m_monitors )
2025-04-30 23:45:20 +02:00
for ( auto const & lsl : m - > m_layerSurfaceLayers )
2025-03-18 01:36:55 +00:00
for ( auto const & ls : lsl )
ls - > applyRules ( ) ;
return { } ;
}
2024-02-18 15:00:34 +00:00
void CConfigManager : : updateBlurredLS ( const std : : string & name , const bool forceBlur ) {
const bool BYADDRESS = name . starts_with ( " address: " ) ;
std : : string matchName = name ;
2023-08-11 17:37:52 +02:00
2024-12-16 19:05:24 +01:00
if ( BYADDRESS )
2024-02-18 15:00:34 +00:00
matchName = matchName . substr ( 8 ) ;
2022-10-22 21:45:17 +01:00
2025-04-22 15:23:29 +02:00
for ( auto const & m : g_pCompositor - > m_monitors ) {
2025-04-30 23:45:20 +02:00
for ( auto const & lsl : m - > m_layerSurfaceLayers ) {
2024-08-26 17:25:39 +02:00
for ( auto const & ls : lsl ) {
2024-02-18 15:00:34 +00:00
if ( BYADDRESS ) {
2025-08-14 19:44:56 +05:00
if ( std : : format ( " 0x{:x} " , rc < uintptr_t > ( ls . get ( ) ) ) = = matchName )
2025-04-24 20:49:49 +02:00
ls - > m_forceBlur = forceBlur ;
} else if ( ls - > m_namespace = = matchName )
ls - > m_forceBlur = forceBlur ;
2022-10-22 21:45:17 +01:00
}
2024-02-18 15:00:34 +00:00
}
}
}
2022-10-22 21:45:17 +01:00
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handleBlurLS ( const std : : string & command , const std : : string & value ) {
if ( value . starts_with ( " remove, " ) ) {
2024-06-11 17:17:45 +02:00
const auto TOREMOVE = trim ( value . substr ( 7 ) ) ;
2025-04-20 20:39:33 +02:00
if ( std : : erase_if ( m_blurLSNamespaces , [ & ] ( const auto & other ) { return other = = TOREMOVE ; } ) )
2024-02-18 15:00:34 +00:00
updateBlurredLS ( TOREMOVE , false ) ;
return { } ;
}
2023-02-14 17:08:42 +00:00
2025-04-20 20:39:33 +02:00
m_blurLSNamespaces . emplace_back ( value ) ;
2024-02-18 15:00:34 +00:00
updateBlurredLS ( value , true ) ;
2022-10-22 21:45:17 +01:00
2024-02-18 15:00:34 +00:00
return { } ;
}
2022-10-22 21:45:17 +01:00
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handleWorkspaceRules ( const std : : string & command , const std : : string & value ) {
// This can either be the monitor or the workspace identifier
2024-06-23 00:52:42 +03:00
const auto FIRST_DELIM = value . find_first_of ( ' , ' ) ;
2022-10-22 21:45:17 +01:00
2024-06-23 00:52:42 +03:00
auto first_ident = trim ( value . substr ( 0 , FIRST_DELIM ) ) ;
2025-10-27 21:29:35 +00:00
const auto & [ id , name , isAutoID ] = getWorkspaceIDNameFromString ( first_ident ) ;
2023-09-04 18:24:18 +02:00
2024-02-18 15:00:34 +00:00
auto rules = value . substr ( FIRST_DELIM + 1 ) ;
SWorkspaceRule wsRule ;
wsRule . workspaceString = first_ident ;
2024-03-19 20:56:20 +00:00
// if (id == WORKSPACE_INVALID) {
// // it could be the monitor. If so, second value MUST be
// // the workspace.
// const auto WORKSPACE_DELIM = value.find_first_of(',', FIRST_DELIM + 1);
// auto wsIdent = removeBeginEndSpacesTabs(value.substr(FIRST_DELIM + 1, (WORKSPACE_DELIM - FIRST_DELIM - 1)));
// id = getWorkspaceIDFromString(wsIdent, name);
// if (id == WORKSPACE_INVALID) {
// Debug::log(ERR, "Invalid workspace identifier found: {}", wsIdent);
// return "Invalid workspace identifier found: " + wsIdent;
// }
// wsRule.monitor = first_ident;
// wsRule.workspaceString = wsIdent;
// wsRule.isDefault = true; // backwards compat
// rules = value.substr(WORKSPACE_DELIM + 1);
// }
2023-02-14 17:08:42 +00:00
2024-04-06 19:53:32 +05:00
const static std : : string ruleOnCreatedEmpty = " on-created-empty: " ;
2024-08-08 21:01:50 +02:00
const static auto ruleOnCreatedEmptyLen = ruleOnCreatedEmpty . length ( ) ;
2022-10-22 21:45:17 +01:00
2024-11-18 23:53:38 +00:00
# define CHECK_OR_THROW(expr) \
\
auto X = expr ; \
if ( ! X ) { \
return " Failed parsing a workspace rule " ; \
}
auto assignRule = [ & ] ( std : : string rule ) - > std : : optional < std : : string > {
2024-02-18 15:00:34 +00:00
size_t delim = std : : string : : npos ;
2024-02-21 12:07:39 +01:00
if ( ( delim = rule . find ( " gapsin: " ) ) ! = std : : string : : npos ) {
CVarList varlist = CVarList ( rule . substr ( delim + 7 ) , 0 , ' ' ) ;
wsRule . gapsIn = CCssGapData ( ) ;
try {
wsRule . gapsIn - > parseGapData ( varlist ) ;
} catch ( . . . ) { return " Error parsing workspace rule gaps: {} " , rule . substr ( delim + 7 ) ; }
} else if ( ( delim = rule . find ( " gapsout: " ) ) ! = std : : string : : npos ) {
CVarList varlist = CVarList ( rule . substr ( delim + 8 ) , 0 , ' ' ) ;
wsRule . gapsOut = CCssGapData ( ) ;
try {
wsRule . gapsOut - > parseGapData ( varlist ) ;
} catch ( . . . ) { return " Error parsing workspace rule gaps: {} " , rule . substr ( delim + 8 ) ; }
} else if ( ( delim = rule . find ( " bordersize: " ) ) ! = std : : string : : npos )
try {
wsRule . borderSize = std : : stoi ( rule . substr ( delim + 11 ) ) ;
} catch ( . . . ) { return " Error parsing workspace rule bordersize: {} " , rule . substr ( delim + 11 ) ; }
2024-11-18 23:53:38 +00:00
else if ( ( delim = rule . find ( " border: " ) ) ! = std : : string : : npos ) {
CHECK_OR_THROW ( configStringToInt ( rule . substr ( delim + 7 ) ) )
wsRule . noBorder = ! * X ;
} else if ( ( delim = rule . find ( " shadow: " ) ) ! = std : : string : : npos ) {
CHECK_OR_THROW ( configStringToInt ( rule . substr ( delim + 7 ) ) )
wsRule . noShadow = ! * X ;
} else if ( ( delim = rule . find ( " rounding: " ) ) ! = std : : string : : npos ) {
CHECK_OR_THROW ( configStringToInt ( rule . substr ( delim + 9 ) ) )
wsRule . noRounding = ! * X ;
} else if ( ( delim = rule . find ( " decorate: " ) ) ! = std : : string : : npos ) {
CHECK_OR_THROW ( configStringToInt ( rule . substr ( delim + 9 ) ) )
wsRule . decorate = * X ;
} else if ( ( delim = rule . find ( " monitor: " ) ) ! = std : : string : : npos )
2024-02-18 15:00:34 +00:00
wsRule . monitor = rule . substr ( delim + 8 ) ;
2024-11-18 23:53:38 +00:00
else if ( ( delim = rule . find ( " default: " ) ) ! = std : : string : : npos ) {
CHECK_OR_THROW ( configStringToInt ( rule . substr ( delim + 8 ) ) )
wsRule . isDefault = * X ;
} else if ( ( delim = rule . find ( " persistent: " ) ) ! = std : : string : : npos ) {
CHECK_OR_THROW ( configStringToInt ( rule . substr ( delim + 11 ) ) )
wsRule . isPersistent = * X ;
} else if ( ( delim = rule . find ( " defaultName: " ) ) ! = std : : string : : npos )
2025-09-29 20:10:34 +02:00
wsRule . defaultName = trim ( rule . substr ( delim + 12 ) ) ;
2024-11-18 23:53:38 +00:00
else if ( ( delim = rule . find ( ruleOnCreatedEmpty ) ) ! = std : : string : : npos ) {
CHECK_OR_THROW ( cleanCmdForWorkspace ( name , rule . substr ( delim + ruleOnCreatedEmptyLen ) ) )
wsRule . onCreatedEmptyRunCmd = * X ;
} else if ( ( delim = rule . find ( " layoutopt: " ) ) ! = std : : string : : npos ) {
2024-02-18 15:00:34 +00:00
std : : string opt = rule . substr ( delim + 10 ) ;
if ( ! opt . contains ( " : " ) ) {
// invalid
Debug : : log ( ERR , " Invalid workspace rule found: {} " , rule ) ;
return " Invalid workspace rule found: " + rule ;
}
2023-09-04 18:24:18 +02:00
2024-12-07 18:51:18 +01:00
std : : string val = opt . substr ( opt . find ( ' : ' ) + 1 ) ;
opt = opt . substr ( 0 , opt . find ( ' : ' ) ) ;
2023-02-14 17:08:42 +00:00
2024-02-18 15:00:34 +00:00
wsRule . layoutopts [ opt ] = val ;
2022-10-22 21:45:17 +01:00
}
2024-02-18 15:00:34 +00:00
return { } ;
2022-10-28 23:48:48 +01:00
} ;
2024-11-18 23:53:38 +00:00
# undef CHECK_OR_THROW
2024-02-18 15:00:34 +00:00
CVarList rulesList { rules , 0 , ' , ' , true } ;
2024-08-26 20:24:30 +02:00
for ( auto const & r : rulesList ) {
2024-02-18 15:00:34 +00:00
const auto R = assignRule ( r ) ;
if ( R . has_value ( ) )
return R ;
2022-10-28 23:48:48 +01:00
}
2024-02-18 15:00:34 +00:00
wsRule . workspaceName = name ;
2025-10-27 21:29:35 +00:00
wsRule . workspaceId = isAutoID ? WORKSPACE_INVALID : id ;
2022-10-22 21:45:17 +01:00
2025-05-30 18:25:59 +05:00
const auto IT = std : : ranges : : find_if ( m_workspaceRules , [ & ] ( const auto & other ) { return other . workspaceString = = wsRule . workspaceString ; } ) ;
2022-08-09 18:13:13 +02:00
2025-04-20 20:39:33 +02:00
if ( IT = = m_workspaceRules . end ( ) )
m_workspaceRules . emplace_back ( wsRule ) ;
2024-02-18 15:00:34 +00:00
else
2024-04-19 18:20:16 -07:00
* IT = mergeWorkspaceRules ( * IT , wsRule ) ;
2022-12-01 13:36:07 +00:00
2024-02-18 15:00:34 +00:00
return { } ;
2022-08-19 21:01:51 +03:00
}
2022-09-12 21:05:52 +02:00
2025-10-11 02:40:18 +02:00
std : : optional < std : : string > CConfigManager : : handleSubmap ( const std : : string & , const std : : string & submap ) {
const auto SUBMAP = CConstVarList ( submap ) ;
m_currentSubmap . name = ( SUBMAP [ 0 ] = = " reset " ) ? " " : SUBMAP [ 0 ] ;
m_currentSubmap . reset = SUBMAP [ 1 ] ;
2024-02-18 15:00:34 +00:00
return { } ;
2022-12-09 17:17:02 +00:00
}
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handleSource ( const std : : string & command , const std : : string & rawpath ) {
if ( rawpath . length ( ) < 2 ) {
Debug : : log ( ERR , " source= path garbage " ) ;
2024-11-12 02:53:55 +02:00
return " source= path " + rawpath + " bogus! " ;
2024-02-18 15:00:34 +00:00
}
2025-01-28 10:20:54 +01:00
2025-09-29 15:10:15 +03:00
std : : unique_ptr < glob_t , void ( * ) ( glob_t * ) > glob_buf { sc < glob_t * > ( calloc ( 1 , sizeof ( glob_t ) ) ) , // allocate and zero-initialize NOLINT(cppcoreguidelines-no-malloc)
2025-01-28 10:20:54 +01:00
[ ] ( glob_t * g ) {
if ( g ) {
globfree ( g ) ; // free internal resources allocated by glob()
2025-09-29 15:10:15 +03:00
free ( g ) ; // free the memory for the glob_t structure NOLINT(cppcoreguidelines-no-malloc)
2025-01-28 10:20:54 +01:00
}
} } ;
2023-05-08 15:37:59 +02:00
2025-04-20 20:39:33 +02:00
if ( auto r = glob ( absolutePath ( rawpath , m_configCurrentPath ) . c_str ( ) , GLOB_TILDE , nullptr , glob_buf . get ( ) ) ; r ! = 0 ) {
2024-02-18 15:00:34 +00:00
std : : string err = std : : format ( " source= globbing error: {} " , r = = GLOB_NOMATCH ? " found no match " : GLOB_ABORTED ? " read error " : " out of memory " ) ;
Debug : : log ( ERR , " {} " , err ) ;
return err ;
}
2022-11-26 17:56:43 +00:00
2024-03-11 01:39:00 +00:00
std : : string errorsFromParsing ;
2024-02-18 15:00:34 +00:00
for ( size_t i = 0 ; i < glob_buf - > gl_pathc ; i + + ) {
2025-08-12 15:11:21 -04:00
auto value = absolutePath ( glob_buf - > gl_pathv [ i ] , m_configCurrentPath ) ;
2023-05-01 07:10:53 -07:00
2025-08-12 15:11:21 -04:00
std : : error_code ec ;
auto file_status = std : : filesystem : : status ( value , ec ) ;
2023-05-01 07:10:53 -07:00
2025-08-12 15:11:21 -04:00
if ( ec ) {
Debug : : log ( ERR , " source= file from glob result is inaccessible ({}): {} " , ec . message ( ) , value ) ;
return " source= file " + value + " is inaccessible! " ;
2024-02-18 15:00:34 +00:00
}
2025-08-12 15:11:21 -04:00
if ( std : : filesystem : : is_regular_file ( file_status ) ) {
m_configPaths . emplace_back ( value ) ;
auto configCurrentPathBackup = m_configCurrentPath ;
m_configCurrentPath = value ;
const auto THISRESULT = m_config - > parseFile ( value . c_str ( ) ) ;
m_configCurrentPath = configCurrentPathBackup ;
if ( THISRESULT . error & & errorsFromParsing . empty ( ) )
errorsFromParsing + = THISRESULT . getError ( ) ;
} else if ( std : : filesystem : : is_directory ( file_status ) ) {
Debug : : log ( WARN , " source= skipping directory {} " , value ) ;
continue ;
} else {
Debug : : log ( WARN , " source= skipping non-regular-file {} " , value ) ;
continue ;
}
2023-05-01 07:10:53 -07:00
}
2024-03-11 01:39:00 +00:00
if ( errorsFromParsing . empty ( ) )
return { } ;
return errorsFromParsing ;
2022-11-26 17:56:43 +00:00
}
2023-01-25 15:16:28 +00:00
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handleEnv ( const std : : string & command , const std : : string & value ) {
const auto ARGS = CVarList ( value , 2 ) ;
2023-02-27 12:32:38 +00:00
2024-02-18 15:00:34 +00:00
if ( ARGS [ 0 ] . empty ( ) )
return " env empty " ;
2023-02-27 12:32:38 +00:00
2025-08-29 11:16:11 +02:00
if ( ! m_isFirstLaunch ) {
// check if env changed at all. If it didn't, ignore. If it did, update it.
const auto * ENV = getenv ( ARGS [ 0 ] . c_str ( ) ) ;
if ( ENV & & ENV = = ARGS [ 1 ] )
return { } ; // env hasn't changed
}
2024-02-18 15:00:34 +00:00
setenv ( ARGS [ 0 ] . c_str ( ) , ARGS [ 1 ] . c_str ( ) , 1 ) ;
2023-07-10 14:13:23 +02:00
2024-02-18 15:00:34 +00:00
if ( command . back ( ) = = ' d ' ) {
// dbus
const auto CMD =
# ifdef USES_SYSTEMD
" systemctl --user import-environment " + ARGS [ 0 ] +
" && hash dbus-update-activation-environment 2>/dev/null && "
# endif
" dbus-update-activation-environment --systemd " +
ARGS [ 0 ] ;
handleRawExec ( " " , CMD ) ;
2023-07-10 14:13:23 +02:00
}
2023-02-27 12:32:38 +00:00
2024-02-18 15:00:34 +00:00
return { } ;
2023-10-29 16:59:50 +00:00
}
2024-02-18 15:00:34 +00:00
std : : optional < std : : string > CConfigManager : : handlePlugin ( const std : : string & command , const std : : string & path ) {
2025-05-30 18:25:59 +05:00
if ( std : : ranges : : find ( m_declaredPlugins , path ) ! = m_declaredPlugins . end ( ) )
2024-02-18 15:00:34 +00:00
return " plugin ' " + path + " ' declared twice " ;
2023-03-18 16:12:43 +00:00
2025-04-20 20:39:33 +02:00
m_declaredPlugins . push_back ( path ) ;
2024-02-18 15:00:34 +00:00
return { } ;
2024-02-21 12:07:39 +01:00
}
2024-08-17 17:33:16 +01:00
2025-04-08 19:39:53 +02:00
std : : optional < std : : string > CConfigManager : : handlePermission ( const std : : string & command , const std : : string & value ) {
CVarList data ( value ) ;
eDynamicPermissionType type = PERMISSION_TYPE_UNKNOWN ;
eDynamicPermissionAllowMode mode = PERMISSION_RULE_ALLOW_MODE_UNKNOWN ;
if ( data [ 1 ] = = " screencopy " )
type = PERMISSION_TYPE_SCREENCOPY ;
2025-04-27 00:03:32 +01:00
else if ( data [ 1 ] = = " plugin " )
type = PERMISSION_TYPE_PLUGIN ;
2025-05-18 18:13:20 +01:00
else if ( data [ 1 ] = = " keyboard " | | data [ 1 ] = = " keeb " )
type = PERMISSION_TYPE_KEYBOARD ;
2025-04-08 19:39:53 +02:00
if ( data [ 2 ] = = " ask " )
mode = PERMISSION_RULE_ALLOW_MODE_ASK ;
else if ( data [ 2 ] = = " allow " )
mode = PERMISSION_RULE_ALLOW_MODE_ALLOW ;
else if ( data [ 2 ] = = " deny " )
mode = PERMISSION_RULE_ALLOW_MODE_DENY ;
if ( type = = PERMISSION_TYPE_UNKNOWN )
return " unknown permission type " ;
if ( mode = = PERMISSION_RULE_ALLOW_MODE_UNKNOWN )
return " unknown permission allow mode " ;
2025-04-30 00:35:32 +01:00
if ( m_isFirstLaunch )
g_pDynamicPermissionManager - > addConfigPermissionRule ( data [ 0 ] , type , mode ) ;
2025-04-08 19:39:53 +02:00
return { } ;
}
2025-08-28 11:20:29 +02:00
std : : optional < std : : string > CConfigManager : : handleGesture ( const std : : string & command , const std : : string & value ) {
CConstVarList data ( value ) ;
size_t fingerCount = 0 ;
eTrackpadGestureDirection direction = TRACKPAD_GESTURE_DIR_NONE ;
try {
fingerCount = std : : stoul ( std : : string { data [ 0 ] } ) ;
} catch ( . . . ) { return std : : format ( " Invalid value {} for finger count " , data [ 0 ] ) ; }
if ( fingerCount < = 1 | | fingerCount > = 10 )
return std : : format ( " Invalid value {} for finger count " , data [ 0 ] ) ;
direction = g_pTrackpadGestures - > dirForString ( data [ 1 ] ) ;
if ( direction = = TRACKPAD_GESTURE_DIR_NONE )
return std : : format ( " Invalid direction: {} " , data [ 1 ] ) ;
int startDataIdx = 2 ;
uint32_t modMask = 0 ;
float deltaScale = 1.F ;
while ( true ) {
if ( data [ startDataIdx ] . starts_with ( " mod: " ) ) {
modMask = g_pKeybindManager - > stringToModMask ( std : : string { data [ startDataIdx ] . substr ( 4 ) } ) ;
startDataIdx + + ;
continue ;
} else if ( data [ startDataIdx ] . starts_with ( " scale: " ) ) {
try {
deltaScale = std : : clamp ( std : : stof ( std : : string { data [ startDataIdx ] . substr ( 6 ) } ) , 0.1F , 10.F ) ;
startDataIdx + + ;
continue ;
} catch ( . . . ) { return std : : format ( " Invalid delta scale: {} " , std : : string { data [ startDataIdx ] . substr ( 6 ) } ) ; }
}
break ;
}
std : : expected < void , std : : string > result ;
2025-09-26 22:49:07 +09:00
if ( data [ startDataIdx ] = = " dispatcher " )
result = g_pTrackpadGestures - > addGesture ( makeUnique < CDispatcherTrackpadGesture > ( std : : string { data [ startDataIdx + 1 ] } , data . join ( " , " , startDataIdx + 2 ) ) , fingerCount ,
direction , modMask , deltaScale ) ;
else if ( data [ startDataIdx ] = = " workspace " )
2025-08-28 11:20:29 +02:00
result = g_pTrackpadGestures - > addGesture ( makeUnique < CWorkspaceSwipeGesture > ( ) , fingerCount , direction , modMask , deltaScale ) ;
else if ( data [ startDataIdx ] = = " resize " )
result = g_pTrackpadGestures - > addGesture ( makeUnique < CResizeTrackpadGesture > ( ) , fingerCount , direction , modMask , deltaScale ) ;
else if ( data [ startDataIdx ] = = " move " )
result = g_pTrackpadGestures - > addGesture ( makeUnique < CMoveTrackpadGesture > ( ) , fingerCount , direction , modMask , deltaScale ) ;
else if ( data [ startDataIdx ] = = " special " )
result = g_pTrackpadGestures - > addGesture ( makeUnique < CSpecialWorkspaceGesture > ( std : : string { data [ startDataIdx + 1 ] } ) , fingerCount , direction , modMask , deltaScale ) ;
else if ( data [ startDataIdx ] = = " close " )
result = g_pTrackpadGestures - > addGesture ( makeUnique < CCloseTrackpadGesture > ( ) , fingerCount , direction , modMask , deltaScale ) ;
else if ( data [ startDataIdx ] = = " float " )
result = g_pTrackpadGestures - > addGesture ( makeUnique < CFloatTrackpadGesture > ( std : : string { data [ startDataIdx + 1 ] } ) , fingerCount , direction , modMask , deltaScale ) ;
else if ( data [ startDataIdx ] = = " fullscreen " )
result = g_pTrackpadGestures - > addGesture ( makeUnique < CFullscreenTrackpadGesture > ( std : : string { data [ startDataIdx + 1 ] } ) , fingerCount , direction , modMask , deltaScale ) ;
2025-09-08 20:24:45 +01:00
else if ( data [ startDataIdx ] = = " unset " )
result = g_pTrackpadGestures - > removeGesture ( fingerCount , direction , modMask , deltaScale ) ;
2025-08-28 11:20:29 +02:00
else
return std : : format ( " Invalid gesture: {} " , data [ startDataIdx ] ) ;
if ( ! result )
return result . error ( ) ;
return std : : nullopt ;
}
2024-08-17 17:33:16 +01:00
const std : : vector < SConfigOptionDescription > & CConfigManager : : getAllDescriptions ( ) {
return CONFIG_OPTIONS ;
}
2025-02-15 00:21:50 +00:00
bool CConfigManager : : shouldUseSoftwareCursors ( PHLMONITOR pMonitor ) {
2025-07-20 10:40:21 +00:00
static auto PNOHW = CConfigValue < Hyprlang : : INT > ( " cursor:no_hardware_cursors " ) ;
static auto PINVISIBLE = CConfigValue < Hyprlang : : INT > ( " cursor:invisible " ) ;
2024-10-26 02:12:43 +01:00
2025-07-16 11:08:29 +02:00
if ( pMonitor - > m_tearingState . activelyTearing )
return true ;
2025-07-20 10:40:21 +00:00
if ( * PINVISIBLE ! = 0 )
return true ;
2024-10-26 02:12:43 +01:00
switch ( * PNOHW ) {
case 0 : return false ;
case 1 : return true ;
2025-07-16 11:02:20 +02:00
case 2 : return g_pHyprRenderer - > isNvidia ( ) & & g_pHyprRenderer - > isMgpu ( ) ;
2025-01-08 12:29:24 +01:00
default : break ;
2024-10-26 02:12:43 +01:00
}
return true ;
}
2024-08-17 17:33:16 +01:00
std : : string SConfigOptionDescription : : jsonify ( ) const {
auto parseData = [ this ] ( ) - > std : : string {
return std : : visit (
2025-02-25 13:49:07 +00:00
[ this ] ( auto & & val ) {
2025-04-20 20:39:33 +02:00
const auto PTR = g_pConfigManager - > m_config - > getConfigValuePtr ( value . c_str ( ) ) ;
2025-02-25 13:49:07 +00:00
if ( ! PTR ) {
Debug : : log ( ERR , " invalid SConfigOptionDescription: no config option {} exists " , value ) ;
return std : : string { " " } ;
}
const char * const EXPLICIT = PTR - > m_bSetByUser ? " true " : " false " ;
std : : string currentValue = " undefined " ;
const auto CONFIGVALUE = PTR - > getValue ( ) ;
if ( typeid ( Hyprlang : : INT ) = = std : : type_index ( CONFIGVALUE . type ( ) ) )
currentValue = std : : format ( " {} " , std : : any_cast < Hyprlang : : INT > ( CONFIGVALUE ) ) ;
else if ( typeid ( Hyprlang : : FLOAT ) = = std : : type_index ( CONFIGVALUE . type ( ) ) )
currentValue = std : : format ( " {:.2f} " , std : : any_cast < Hyprlang : : FLOAT > ( CONFIGVALUE ) ) ;
else if ( typeid ( Hyprlang : : STRING ) = = std : : type_index ( CONFIGVALUE . type ( ) ) )
currentValue = std : : any_cast < Hyprlang : : STRING > ( CONFIGVALUE ) ;
else if ( typeid ( Hyprlang : : VEC2 ) = = std : : type_index ( CONFIGVALUE . type ( ) ) ) {
const auto V = std : : any_cast < Hyprlang : : VEC2 > ( CONFIGVALUE ) ;
currentValue = std : : format ( " {}, {} " , V . x , V . y ) ;
} else if ( typeid ( void * ) = = std : : type_index ( CONFIGVALUE . type ( ) ) ) {
2025-08-14 19:44:56 +05:00
const auto DATA = sc < ICustomConfigValueData * > ( std : : any_cast < void * > ( CONFIGVALUE ) ) ;
2025-02-25 13:49:07 +00:00
currentValue = DATA - > toString ( ) ;
}
try {
using T = std : : decay_t < decltype ( val ) > ;
if constexpr ( std : : is_same_v < T , SStringData > ) {
return std : : format ( R " #( " value " : " { } " ,
" current " : " {} " ,
" explicit " : { } ) # " ,
val . value , currentValue , EXPLICIT ) ;
} else if constexpr ( std : : is_same_v < T , SRangeData > ) {
return std : : format ( R " #( " value " : {},
2024-08-17 17:33:16 +01:00
" min " : { } ,
2025-02-25 13:49:07 +00:00
" max " : { } ,
" current " : { } ,
" explicit " : { } ) # " ,
val . value , val . min , val . max , currentValue , EXPLICIT ) ;
} else if constexpr ( std : : is_same_v < T , SFloatData > ) {
return std : : format ( R " #( " value " : {},
2024-08-17 17:33:16 +01:00
" min " : { } ,
2025-02-25 13:49:07 +00:00
" max " : { } ,
" current " : { } ,
" explicit " : { } ) # " ,
val . value , val . min , val . max , currentValue , EXPLICIT ) ;
} else if constexpr ( std : : is_same_v < T , SColorData > ) {
2025-08-06 16:28:07 +02:00
return std : : format ( R " #( " value " : " { } " ,
" current " : " {} " ,
2025-02-25 13:49:07 +00:00
" explicit " : { } ) # " ,
val . color . getAsHex ( ) , currentValue , EXPLICIT ) ;
} else if constexpr ( std : : is_same_v < T , SBoolData > ) {
return std : : format ( R " #( " value " : {},
" current " : { } ,
" explicit " : { } ) # " ,
val . value , currentValue , EXPLICIT ) ;
} else if constexpr ( std : : is_same_v < T , SChoiceData > ) {
2025-08-06 16:28:07 +02:00
return std : : format ( R " #( " value " : " { } " ,
2025-02-25 13:49:07 +00:00
" firstIndex " : { } ,
" current " : { } ,
" explicit " : { } ) # " ,
val . choices , val . firstIndex , currentValue , EXPLICIT ) ;
} else if constexpr ( std : : is_same_v < T , SVectorData > ) {
return std : : format ( R " #( " x " : {},
2024-08-17 17:33:16 +01:00
" y " : { } ,
" min_x " : { } ,
" min_y " : { } ,
" max_x " : { } ,
2025-02-25 13:49:07 +00:00
" max_y " : { } ,
" current " : " {} " ,
" explicit " : { } ) # " ,
val . vec . x , val . vec . y , val . min . x , val . min . y , val . max . x , val . max . y , currentValue , EXPLICIT ) ;
} else if constexpr ( std : : is_same_v < T , SGradientData > ) {
return std : : format ( R " #( " value " : " { } " ,
" current " : " {} " ,
" explicit " : { } ) # " ,
val . gradient , currentValue , EXPLICIT ) ;
}
} catch ( std : : bad_any_cast & e ) { Debug : : log ( ERR , " Bad any_cast on value {} in descriptions " , value ) ; }
2024-08-17 17:33:16 +01:00
return std : : string { " " } ;
} ,
data ) ;
} ;
std : : string json = std : : format ( R " #({{
" value " : " {} " ,
" description " : " {} " ,
" type " : { } ,
" flags " : { } ,
" data " : { {
{ }
} }
} } ) # " ,
2025-08-14 19:44:56 +05:00
value , escapeJSONStrings ( description ) , sc < uint16_t > ( type ) , sc < uint32_t > ( flags ) , parseData ( ) ) ;
2024-08-17 17:33:16 +01:00
return json ;
}
2025-01-26 14:40:42 +00:00
void CConfigManager : : ensurePersistentWorkspacesPresent ( ) {
2025-04-20 20:39:33 +02:00
g_pCompositor - > ensurePersistentWorkspacesPresent ( m_workspaceRules ) ;
2025-01-26 14:40:42 +00:00
}
2025-03-07 20:12:02 -05:00
void CConfigManager : : storeFloatingSize ( PHLWINDOW window , const Vector2D & size ) {
2025-05-06 09:53:43 +08:00
Debug : : log ( LOG , " storing floating size {}x{} for window {}::{} " , size . x , size . y , window - > m_initialClass , window - > m_initialTitle ) ;
// true -> use m_initialClass and m_initialTitle
SFloatCache id { window , true } ;
2025-03-07 20:12:02 -05:00
m_mStoredFloatingSizes [ id ] = size ;
}
std : : optional < Vector2D > CConfigManager : : getStoredFloatingSize ( PHLWINDOW window ) {
2025-05-06 09:53:43 +08:00
// At startup, m_initialClass and m_initialTitle are undefined
// and m_class and m_title are just "initial" ones.
// false -> use m_class and m_title
SFloatCache id { window , false } ;
Debug : : log ( LOG , " Hash for window {}::{} = {} " , window - > m_class , window - > m_title , id . hash ) ;
2025-03-07 20:12:02 -05:00
if ( m_mStoredFloatingSizes . contains ( id ) ) {
2025-04-28 22:25:22 +02:00
Debug : : log ( LOG , " got stored size {}x{} for window {}::{} " , m_mStoredFloatingSizes [ id ] . x , m_mStoredFloatingSizes [ id ] . y , window - > m_class , window - > m_title ) ;
2025-03-07 20:12:02 -05:00
return m_mStoredFloatingSizes [ id ] ;
}
return std : : nullopt ;
}