2022-03-17 15:53:45 +01:00
# include "ConfigManager.hpp"
2022-03-19 17:48:18 +01:00
# include "../managers/KeybindManager.hpp"
2022-03-17 15:53:45 +01:00
# include <string.h>
# include <sys/stat.h>
# include <sys/types.h>
# include <unistd.h>
# include <algorithm>
# include <fstream>
# include <iostream>
CConfigManager : : CConfigManager ( ) {
2022-04-18 13:27:54 +02:00
setDefaultVars ( ) ;
2022-07-28 13:28:43 +02:00
setDefaultAnimationVars ( ) ;
2022-07-14 22:55:24 +02:00
std : : string CONFIGPATH ;
if ( g_pCompositor - > explicitConfigPath = = " " ) {
static const char * const ENVHOME = getenv ( " HOME " ) ;
CONFIGPATH = ENVHOME + ( ISDEBUG ? ( std : : string ) " /.config/hypr/hyprlandd.conf " : ( std : : string ) " /.config/hypr/hyprland.conf " ) ;
} else {
CONFIGPATH = g_pCompositor - > explicitConfigPath ;
}
2022-05-16 10:09:20 +02:00
configPaths . emplace_back ( CONFIGPATH ) ;
2022-07-01 15:57:56 +02:00
Debug : : disableLogs = & configValues [ " debug:disable_logs " ] . intValue ;
2022-07-18 11:46:42 +02:00
Debug : : disableTime = & configValues [ " debug:disable_time " ] . intValue ;
2022-04-18 13:27:54 +02:00
}
void CConfigManager : : setDefaultVars ( ) {
2022-06-25 23:57:23 +02:00
configValues [ " general:max_fps " ] . intValue = 60 ;
configValues [ " general:sensitivity " ] . floatValue = 1.0f ;
2022-06-22 13:01:59 +02:00
configValues [ " general:apply_sens_to_raw " ] . intValue = 0 ;
2022-03-20 19:58:12 +01:00
configValues [ " general:main_mod " ] . strValue = " SUPER " ; // exposed to the user for easier configuring
configValues [ " general:main_mod_internal " ] . intValue = g_pKeybindManager - > stringToModMask ( " SUPER " ) ; // actually used and automatically calculated
2022-03-17 15:53:45 +01:00
2022-06-25 23:57:23 +02:00
configValues [ " general:damage_tracking " ] . strValue = " full " ;
configValues [ " general:damage_tracking_internal " ] . intValue = DAMAGE_TRACKING_FULL ;
2022-04-14 16:43:29 +02:00
2022-03-17 15:53:45 +01:00
configValues [ " general:border_size " ] . intValue = 1 ;
2022-06-21 22:54:41 +02:00
configValues [ " general:no_border_on_floating " ] . intValue = 0 ;
2022-03-17 15:53:45 +01:00
configValues [ " general:gaps_in " ] . intValue = 5 ;
configValues [ " general:gaps_out " ] . intValue = 20 ;
2022-03-19 16:13:19 +01:00
configValues [ " general:col.active_border " ] . intValue = 0xffffffff ;
configValues [ " general:col.inactive_border " ] . intValue = 0xff444444 ;
2022-06-24 23:27:02 +02:00
configValues [ " general:cursor_inactive_timeout " ] . intValue = 0 ;
2022-08-01 18:50:16 +02:00
configValues [ " general:no_cursor_warps " ] . intValue = 0 ;
2022-07-16 15:57:31 +02:00
configValues [ " general:layout " ] . strValue = " dwindle " ;
2022-09-25 20:07:48 +02:00
2022-07-10 15:41:26 +02:00
configValues [ " misc:disable_hyprland_logo " ] . intValue = 0 ;
configValues [ " misc:disable_splash_rendering " ] . intValue = 0 ;
2022-07-12 15:41:28 +02:00
configValues [ " misc:no_vfr " ] . intValue = 1 ;
2022-07-30 22:26:46 +02:00
configValues [ " misc:damage_entire_on_snapshot " ] . intValue = 0 ;
2022-07-31 15:46:42 +02:00
configValues [ " misc:mouse_move_enables_dpms " ] . intValue = 0 ;
2022-08-06 22:26:32 +02:00
configValues [ " misc:always_follow_on_dnd " ] . intValue = 1 ;
2022-08-11 21:52:38 +02:00
configValues [ " misc:layers_hog_keyboard_focus " ] . intValue = 1 ;
2022-08-16 21:56:54 +02:00
configValues [ " misc:animate_manual_resizes " ] . intValue = 0 ;
2022-09-10 17:28:41 +02:00
configValues [ " misc:disable_autoreload " ] . intValue = 0 ;
2022-10-01 20:19:15 +02:00
configValues [ " misc:enable_swallow " ] . intValue = 0 ;
configValues [ " misc:swallow_regex " ] . strValue = STRVAL_EMPTY ;
2022-10-25 19:53:18 +02:00
configValues [ " misc:focus_on_activate " ] . intValue = 0 ;
2022-03-23 22:01:59 +01:00
2022-05-02 16:54:40 +02:00
configValues [ " debug:int " ] . intValue = 0 ;
2022-05-05 15:09:26 +02:00
configValues [ " debug:log_damage " ] . intValue = 0 ;
2022-05-28 17:32:19 +02:00
configValues [ " debug:overlay " ] . intValue = 0 ;
2022-06-29 11:44:00 +02:00
configValues [ " debug:damage_blink " ] . intValue = 0 ;
2022-07-01 15:57:56 +02:00
configValues [ " debug:disable_logs " ] . intValue = 0 ;
2022-07-18 11:46:42 +02:00
configValues [ " debug:disable_time " ] . intValue = 1 ;
2022-05-02 16:54:40 +02:00
2022-08-31 11:17:04 +02:00
configValues [ " decoration:rounding " ] . intValue = 0 ;
2022-04-09 16:51:08 +02:00
configValues [ " decoration:blur " ] . intValue = 1 ;
configValues [ " decoration:blur_size " ] . intValue = 8 ;
2022-04-09 17:06:09 +02:00
configValues [ " decoration:blur_passes " ] . intValue = 1 ;
2022-05-28 18:57:32 +02:00
configValues [ " decoration:blur_ignore_opacity " ] . intValue = 0 ;
2022-08-02 15:26:44 +02:00
configValues [ " decoration:blur_new_optimizations " ] . intValue = 0 ;
2022-04-17 21:44:06 +02:00
configValues [ " decoration:active_opacity " ] . floatValue = 1 ;
configValues [ " decoration:inactive_opacity " ] . floatValue = 1 ;
2022-05-16 23:52:48 +02:00
configValues [ " decoration:fullscreen_opacity " ] . floatValue = 1 ;
2022-06-26 20:09:42 +02:00
configValues [ " decoration:multisample_edges " ] . intValue = 1 ;
2022-07-15 19:21:13 +02:00
configValues [ " decoration:no_blur_on_oversized " ] . intValue = 0 ;
2022-06-25 20:28:40 +02:00
configValues [ " decoration:drop_shadow " ] . intValue = 1 ;
configValues [ " decoration:shadow_range " ] . intValue = 4 ;
configValues [ " decoration:shadow_render_power " ] . intValue = 3 ;
configValues [ " decoration:shadow_ignore_window " ] . intValue = 1 ;
2022-09-30 18:03:06 +02:00
configValues [ " decoration:shadow_offset " ] . vecValue = Vector2D ( ) ;
2022-06-25 20:28:40 +02:00
configValues [ " decoration:col.shadow " ] . intValue = 0xee1a1a1a ;
2022-07-16 12:44:45 +02:00
configValues [ " decoration:col.shadow_inactive " ] . intValue = INT_MAX ;
2022-08-30 12:46:17 +02:00
configValues [ " decoration:dim_inactive " ] . intValue = 0 ;
configValues [ " decoration:dim_strength " ] . floatValue = 0.5f ;
2022-04-05 15:50:47 +02:00
2022-04-02 20:04:32 +02:00
configValues [ " dwindle:pseudotile " ] . intValue = 0 ;
2022-04-12 16:44:18 +02:00
configValues [ " dwindle:col.group_border " ] . intValue = 0x66777700 ;
configValues [ " dwindle:col.group_border_active " ] . intValue = 0x66ffff00 ;
2022-05-08 15:36:17 +02:00
configValues [ " dwindle:force_split " ] . intValue = 0 ;
2022-05-16 17:27:55 +02:00
configValues [ " dwindle:preserve_split " ] . intValue = 0 ;
2022-06-03 19:03:33 +02:00
configValues [ " dwindle:special_scale_factor " ] . floatValue = 0.8f ;
2022-06-20 15:37:27 +02:00
configValues [ " dwindle:split_width_multiplier " ] . floatValue = 1.0f ;
2022-08-01 12:51:52 +02:00
configValues [ " dwindle:no_gaps_when_only " ] . intValue = 0 ;
2022-08-19 22:03:35 +02:00
configValues [ " dwindle:use_active_for_splits " ] . intValue = 1 ;
2022-04-02 20:04:32 +02:00
2022-07-16 15:57:31 +02:00
configValues [ " master:special_scale_factor " ] . floatValue = 0.8f ;
configValues [ " master:new_is_master " ] . intValue = 1 ;
2022-07-16 23:24:42 +02:00
configValues [ " master:new_on_top " ] . intValue = 0 ;
2022-08-01 12:57:37 +02:00
configValues [ " master:no_gaps_when_only " ] . intValue = 0 ;
2022-07-16 15:57:31 +02:00
2022-03-23 22:01:59 +01:00
configValues [ " animations:enabled " ] . intValue = 1 ;
configValues [ " animations:speed " ] . floatValue = 7.f ;
2022-04-23 21:47:16 +02:00
configValues [ " animations:curve " ] . strValue = " default " ;
2022-05-14 16:43:30 +02:00
configValues [ " animations:windows_style " ] . strValue = STRVAL_EMPTY ;
2022-04-23 21:47:16 +02:00
configValues [ " animations:windows_curve " ] . strValue = " [[f]] " ;
2022-03-31 17:53:28 +02:00
configValues [ " animations:windows_speed " ] . floatValue = 0.f ;
2022-03-23 22:01:59 +01:00
configValues [ " animations:windows " ] . intValue = 1 ;
2022-05-14 16:43:30 +02:00
configValues [ " animations:borders_style " ] . strValue = STRVAL_EMPTY ;
2022-04-23 21:47:16 +02:00
configValues [ " animations:borders_curve " ] . strValue = " [[f]] " ;
2022-03-31 17:53:28 +02:00
configValues [ " animations:borders_speed " ] . floatValue = 0.f ;
2022-03-23 22:01:59 +01:00
configValues [ " animations:borders " ] . intValue = 1 ;
2022-05-14 16:43:30 +02:00
configValues [ " animations:fadein_style " ] . strValue = STRVAL_EMPTY ;
2022-04-23 21:47:16 +02:00
configValues [ " animations:fadein_curve " ] . strValue = " [[f]] " ;
2022-03-31 17:53:28 +02:00
configValues [ " animations:fadein_speed " ] . floatValue = 0.f ;
2022-03-23 22:01:59 +01:00
configValues [ " animations:fadein " ] . intValue = 1 ;
2022-05-14 16:43:30 +02:00
configValues [ " animations:workspaces_style " ] . strValue = STRVAL_EMPTY ;
2022-05-12 11:27:31 +02:00
configValues [ " animations:workspaces_curve " ] . strValue = " [[f]] " ;
configValues [ " animations:workspaces_speed " ] . floatValue = 0.f ;
configValues [ " animations:workspaces " ] . intValue = 1 ;
2022-03-24 21:05:34 +01:00
2022-07-19 19:26:53 +02:00
configValues [ " input:sensitivity " ] . floatValue = 0.f ;
2022-10-05 22:21:22 +02:00
configValues [ " input:accel_profile " ] . strValue = STRVAL_EMPTY ;
2022-08-19 20:01:51 +02:00
configValues [ " input:kb_file " ] . strValue = STRVAL_EMPTY ;
2022-06-25 23:57:23 +02:00
configValues [ " input:kb_layout " ] . strValue = " us " ;
2022-05-06 14:30:35 +02:00
configValues [ " input:kb_variant " ] . strValue = STRVAL_EMPTY ;
configValues [ " input:kb_options " ] . strValue = STRVAL_EMPTY ;
configValues [ " input:kb_rules " ] . strValue = STRVAL_EMPTY ;
configValues [ " input:kb_model " ] . strValue = STRVAL_EMPTY ;
2022-04-19 18:51:53 +02:00
configValues [ " input:repeat_rate " ] . intValue = 25 ;
configValues [ " input:repeat_delay " ] . intValue = 600 ;
2022-05-06 19:34:48 +02:00
configValues [ " input:natural_scroll " ] . intValue = 0 ;
2022-06-02 19:47:11 +02:00
configValues [ " input:numlock_by_default " ] . intValue = 0 ;
2022-06-06 12:08:33 +02:00
configValues [ " input:force_no_accel " ] . intValue = 0 ;
2022-08-22 18:22:26 +02:00
configValues [ " input:float_switch_override_focus " ] . intValue = 1 ;
2022-10-04 22:46:41 +02:00
configValues [ " input:left_handed " ] . intValue = 0 ;
2022-10-05 22:21:22 +02:00
configValues [ " input:scroll_method " ] . strValue = STRVAL_EMPTY ;
2022-06-11 17:24:00 +02:00
configValues [ " input:touchpad:natural_scroll " ] . intValue = 0 ;
2022-04-19 18:51:53 +02:00
configValues [ " input:touchpad:disable_while_typing " ] . intValue = 1 ;
2022-06-12 07:40:01 +02:00
configValues [ " input:touchpad:clickfinger_behavior " ] . intValue = 0 ;
configValues [ " input:touchpad:middle_button_emulation " ] . intValue = 0 ;
configValues [ " input:touchpad:tap-to-click " ] . intValue = 1 ;
2022-07-12 13:11:54 +02:00
configValues [ " input:touchpad:drag_lock " ] . intValue = 0 ;
2022-10-06 21:20:10 +02:00
configValues [ " input:touchpad:scroll_factor " ] . floatValue = 1.f ;
2022-10-08 19:55:07 +02:00
configValues [ " input:touchdevice:transform " ] . intValue = 0 ;
2022-10-14 13:38:44 +02:00
configValues [ " input:touchdevice:output " ] . strValue = STRVAL_EMPTY ;
2022-04-08 22:07:40 +02:00
2022-09-22 17:33:45 +02:00
configValues [ " binds:pass_mouse_when_bound " ] . intValue = 0 ;
2022-07-26 23:34:03 +02:00
configValues [ " binds:scroll_event_delay " ] . intValue = 300 ;
2022-08-21 13:58:46 +02:00
configValues [ " binds:workspace_back_and_forth " ] . intValue = 0 ;
configValues [ " binds:allow_workspace_cycles " ] . intValue = 0 ;
2022-07-26 14:50:21 +02:00
2022-07-07 11:52:12 +02:00
configValues [ " gestures:workspace_swipe " ] . intValue = 0 ;
2022-07-19 18:35:24 +02:00
configValues [ " gestures:workspace_swipe_fingers " ] . intValue = 3 ;
2022-07-07 11:52:12 +02:00
configValues [ " gestures:workspace_swipe_distance " ] . intValue = 300 ;
configValues [ " gestures:workspace_swipe_invert " ] . intValue = 1 ;
configValues [ " gestures:workspace_swipe_min_speed_to_force " ] . intValue = 30 ;
configValues [ " gestures:workspace_swipe_cancel_ratio " ] . floatValue = 0.5f ;
2022-10-20 15:54:32 +02:00
configValues [ " gestures:workspace_swipe_create_new " ] . intValue = 1 ;
2022-07-07 11:52:12 +02:00
2022-04-13 20:19:40 +02:00
configValues [ " input:follow_mouse " ] . intValue = 1 ;
2022-04-08 22:07:40 +02:00
configValues [ " autogenerated " ] . intValue = 0 ;
2022-03-17 17:08:54 +01:00
}
2022-03-17 15:53:45 +01:00
2022-06-30 21:26:00 +02:00
void CConfigManager : : setDeviceDefaultVars ( const std : : string & dev ) {
auto & cfgValues = deviceConfigs [ dev ] ;
2022-07-19 19:26:53 +02:00
cfgValues [ " sensitivity " ] . floatValue = 0.f ;
2022-10-05 22:21:22 +02:00
cfgValues [ " accel_profile " ] . strValue = STRVAL_EMPTY ;
2022-08-19 20:01:51 +02:00
cfgValues [ " kb_file " ] . strValue = STRVAL_EMPTY ;
2022-06-30 21:26:00 +02:00
cfgValues [ " kb_layout " ] . strValue = " us " ;
cfgValues [ " kb_variant " ] . strValue = STRVAL_EMPTY ;
cfgValues [ " kb_options " ] . strValue = STRVAL_EMPTY ;
cfgValues [ " kb_rules " ] . strValue = STRVAL_EMPTY ;
cfgValues [ " kb_model " ] . strValue = STRVAL_EMPTY ;
cfgValues [ " repeat_rate " ] . intValue = 25 ;
cfgValues [ " repeat_delay " ] . intValue = 600 ;
cfgValues [ " natural_scroll " ] . intValue = 0 ;
cfgValues [ " numlock_by_default " ] . intValue = 0 ;
cfgValues [ " disable_while_typing " ] . intValue = 1 ;
cfgValues [ " clickfinger_behavior " ] . intValue = 0 ;
cfgValues [ " middle_button_emulation " ] . intValue = 0 ;
cfgValues [ " tap-to-click " ] . intValue = 1 ;
2022-07-12 13:11:54 +02:00
cfgValues [ " drag_lock " ] . intValue = 0 ;
2022-10-04 22:46:41 +02:00
cfgValues [ " left_handed " ] . intValue = 0 ;
2022-10-05 22:21:22 +02:00
cfgValues [ " scroll_method " ] . strValue = STRVAL_EMPTY ;
2022-10-14 13:23:11 +02:00
cfgValues [ " touch_transform " ] . intValue = 0 ;
2022-10-14 13:38:44 +02:00
cfgValues [ " touch_output " ] . strValue = STRVAL_EMPTY ;
2022-10-27 13:58:10 +02:00
cfgValues [ " enabled " ] . intValue = 1 ; // only for mice / touchpads
2022-06-30 21:26:00 +02:00
}
2022-07-28 13:28:43 +02:00
void CConfigManager : : setDefaultAnimationVars ( ) {
if ( isFirstLaunch ) {
INITANIMCFG ( " global " ) ;
INITANIMCFG ( " windows " ) ;
INITANIMCFG ( " fade " ) ;
INITANIMCFG ( " border " ) ;
INITANIMCFG ( " workspaces " ) ;
// windows
INITANIMCFG ( " windowsIn " ) ;
INITANIMCFG ( " windowsOut " ) ;
INITANIMCFG ( " windowsMove " ) ;
// fade
INITANIMCFG ( " fadeIn " ) ;
INITANIMCFG ( " fadeOut " ) ;
INITANIMCFG ( " fadeSwitch " ) ;
INITANIMCFG ( " fadeShadow " ) ;
2022-08-30 12:46:17 +02:00
INITANIMCFG ( " fadeDim " ) ;
2022-07-28 13:28:43 +02:00
// border
// workspaces
2022-08-26 11:26:23 +02:00
INITANIMCFG ( " specialWorkspace " ) ;
2022-07-28 13:28:43 +02:00
}
2022-09-25 20:07:48 +02:00
2022-07-28 13:28:43 +02:00
// init the values
animationConfig [ " global " ] = {
false ,
" default " ,
" " ,
8.f ,
1 ,
& animationConfig [ " general " ] ,
nullptr
} ;
CREATEANIMCFG ( " windows " , " global " ) ;
CREATEANIMCFG ( " fade " , " global " ) ;
CREATEANIMCFG ( " border " , " global " ) ;
CREATEANIMCFG ( " workspaces " , " global " ) ;
CREATEANIMCFG ( " windowsIn " , " windows " ) ;
CREATEANIMCFG ( " windowsOut " , " windows " ) ;
CREATEANIMCFG ( " windowsMove " , " windows " ) ;
CREATEANIMCFG ( " fadeIn " , " fade " ) ;
CREATEANIMCFG ( " fadeOut " , " fade " ) ;
CREATEANIMCFG ( " fadeSwitch " , " fade " ) ;
CREATEANIMCFG ( " fadeShadow " , " fade " ) ;
2022-08-30 12:46:17 +02:00
CREATEANIMCFG ( " fadeDim " , " fade " ) ;
2022-08-26 11:26:23 +02:00
CREATEANIMCFG ( " specialWorkspace " , " workspaces " ) ;
2022-07-28 13:28:43 +02:00
}
2022-03-17 17:08:54 +01:00
void CConfigManager : : init ( ) {
2022-09-25 20:07:48 +02:00
2022-03-17 15:53:45 +01:00
loadConfigLoadVars ( ) ;
2022-03-19 17:00:52 +01:00
const char * const ENVHOME = getenv ( " HOME " ) ;
const std : : string CONFIGPATH = ENVHOME + ( ISDEBUG ? ( std : : string ) " /.config/hypr/hyprlandd.conf " : ( std : : string ) " /.config/hypr/hyprland.conf " ) ;
struct stat fileStat ;
int err = stat ( CONFIGPATH . c_str ( ) , & fileStat ) ;
if ( err ! = 0 ) {
Debug : : log ( WARN , " Error at statting config, error %i " , errno ) ;
}
2022-05-16 10:09:20 +02:00
configModifyTimes [ CONFIGPATH ] = fileStat . st_mtime ;
2022-03-19 17:00:52 +01:00
2022-03-17 15:53:45 +01:00
isFirstLaunch = false ;
}
void CConfigManager : : configSetValueSafe ( const std : : string & COMMAND , const std : : string & VALUE ) {
if ( configValues . find ( COMMAND ) = = configValues . end ( ) ) {
2022-07-12 16:07:51 +02:00
if ( COMMAND . find ( " device: " ) ! = 0 /* devices parsed later */ ) {
if ( COMMAND [ 0 ] = = ' $ ' ) {
// register a dynamic var
Debug : : log ( LOG , " Registered dynamic var \" %s \" -> %s " , COMMAND . c_str ( ) , VALUE . c_str ( ) ) ;
configDynamicVars [ COMMAND . substr ( 1 ) ] = VALUE ;
} else {
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >: No such field. " ;
}
2022-05-16 09:38:42 +02:00
2022-06-30 21:26:00 +02:00
return ;
}
2022-03-17 15:53:45 +01:00
}
2022-06-30 21:26:00 +02:00
SConfigValue * CONFIGENTRY = nullptr ;
if ( COMMAND . find ( " device: " ) = = 0 ) {
const auto DEVICE = COMMAND . substr ( 7 ) . substr ( 0 , COMMAND . find_last_of ( ' : ' ) - 7 ) ;
const auto CONFIGVAR = COMMAND . substr ( COMMAND . find_last_of ( ' : ' ) + 1 ) ;
if ( ! deviceConfigExists ( DEVICE ) )
setDeviceDefaultVars ( DEVICE ) ;
auto it = deviceConfigs . find ( DEVICE ) ;
if ( it - > second . find ( CONFIGVAR ) = = it - > second . end ( ) ) {
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >: No such field. " ;
return ;
}
CONFIGENTRY = & it - > second . at ( CONFIGVAR ) ;
} else {
CONFIGENTRY = & configValues . at ( COMMAND ) ;
}
2022-04-18 13:25:27 +02:00
2022-06-30 21:38:06 +02:00
CONFIGENTRY - > set = true ;
2022-09-30 18:03:06 +02:00
if ( CONFIGENTRY - > intValue ! = - INT64_MAX ) {
2022-03-17 15:53:45 +01:00
try {
if ( VALUE . find ( " 0x " ) = = 0 ) {
// Values with 0x are hex
const auto VALUEWITHOUTHEX = VALUE . substr ( 2 ) ;
2022-06-30 21:26:00 +02:00
CONFIGENTRY - > intValue = stol ( VALUEWITHOUTHEX , nullptr , 16 ) ;
2022-10-16 23:23:10 +02:00
} else if ( VALUE . find ( " rgba( " ) = = 0 & & VALUE . find ( " ) " ) = = VALUE . length ( ) - 1 ) {
const auto VALUEWITHOUTFUNC = VALUE . substr ( 5 , VALUE . length ( ) - 6 ) ;
if ( removeBeginEndSpacesTabs ( VALUEWITHOUTFUNC ) . length ( ) ! = 8 ) {
Debug : : log ( WARN , " invalid length %i for rgba " , VALUEWITHOUTFUNC . length ( ) ) ;
parseError = " rgba() expects length of 8 characters (4 bytes) " ;
return ;
}
const auto RGBA = std : : stol ( VALUEWITHOUTFUNC , nullptr , 16 ) ;
// now we need to RGBA -> ARGB. The config holds ARGB only.
CONFIGENTRY - > intValue = ( RGBA > > 8 ) + 0x1000000 * ( RGBA & 0xFF ) ;
} else if ( VALUE . find ( " rgb( " ) = = 0 & & VALUE . find ( " ) " ) = = VALUE . length ( ) - 1 ) {
const auto VALUEWITHOUTFUNC = VALUE . substr ( 4 , VALUE . length ( ) - 5 ) ;
if ( removeBeginEndSpacesTabs ( VALUEWITHOUTFUNC ) . length ( ) ! = 6 ) {
Debug : : log ( WARN , " invalid length %i for rgb " , VALUEWITHOUTFUNC . length ( ) ) ;
parseError = " rgb() expects length of 6 characters (3 bytes) " ;
return ;
}
const auto RGB = std : : stol ( VALUEWITHOUTFUNC , nullptr , 16 ) ;
CONFIGENTRY - > intValue = RGB + 0xFF000000 ; // 0xFF for opaque
2022-07-12 10:28:42 +02:00
} else if ( VALUE . find ( " true " ) = = 0 | | VALUE . find ( " on " ) = = 0 | | VALUE . find ( " yes " ) = = 0 ) {
CONFIGENTRY - > intValue = 1 ;
} else if ( VALUE . find ( " false " ) = = 0 | | VALUE . find ( " off " ) = = 0 | | VALUE . find ( " no " ) = = 0 ) {
CONFIGENTRY - > intValue = 0 ;
}
else
2022-06-30 21:26:00 +02:00
CONFIGENTRY - > intValue = stol ( VALUE ) ;
2022-03-17 15:53:45 +01:00
} catch ( . . . ) {
Debug : : log ( WARN , " Error reading value of %s " , COMMAND . c_str ( ) ) ;
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >. " ;
}
2022-09-30 18:03:06 +02:00
} else if ( CONFIGENTRY - > floatValue ! = - __FLT_MAX__ ) {
2022-03-17 15:53:45 +01:00
try {
2022-06-30 21:26:00 +02:00
CONFIGENTRY - > floatValue = stof ( VALUE ) ;
2022-03-17 15:53:45 +01:00
} catch ( . . . ) {
Debug : : log ( WARN , " Error reading value of %s " , COMMAND . c_str ( ) ) ;
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >. " ;
}
2022-06-30 21:26:00 +02:00
} else if ( CONFIGENTRY - > strValue ! = " " ) {
2022-03-17 15:53:45 +01:00
try {
2022-06-30 21:26:00 +02:00
CONFIGENTRY - > strValue = VALUE ;
2022-03-17 15:53:45 +01:00
} catch ( . . . ) {
Debug : : log ( WARN , " Error reading value of %s " , COMMAND . c_str ( ) ) ;
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >. " ;
}
2022-09-30 18:03:06 +02:00
} else if ( CONFIGENTRY - > vecValue ! = Vector2D ( - __FLT_MAX__ , - __FLT_MAX__ ) ) {
try {
if ( const auto SPACEPOS = VALUE . find ( ' ' ) ; SPACEPOS ! = std : : string : : npos ) {
const auto X = VALUE . substr ( 0 , SPACEPOS ) ;
const auto Y = VALUE . substr ( SPACEPOS + 1 ) ;
if ( isNumber ( X , true ) & & isNumber ( Y , true ) ) {
CONFIGENTRY - > vecValue = Vector2D ( std : : stof ( X ) , std : : stof ( Y ) ) ;
}
} else {
Debug : : log ( WARN , " Error reading value of %s " , COMMAND . c_str ( ) ) ;
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >. " ;
}
} catch ( . . . ) {
Debug : : log ( WARN , " Error reading value of %s " , COMMAND . c_str ( ) ) ;
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >. " ;
}
2022-03-17 15:53:45 +01:00
}
}
void CConfigManager : : handleRawExec ( const std : : string & command , const std : : string & args ) {
// Exec in the background dont wait for it.
2022-06-09 15:03:34 +02:00
std : : string toExec = args ;
if ( g_pXWaylandManager - > m_sWLRXWayland )
toExec = std : : string ( " WAYLAND_DISPLAY= " ) + std : : string ( g_pCompositor - > m_szWLDisplaySocket ) + " DISPLAY= " + std : : string ( g_pXWaylandManager - > m_sWLRXWayland - > display_name ) + " " + toExec ;
else
toExec = std : : string ( " WAYLAND_DISPLAY= " ) + std : : string ( g_pCompositor - > m_szWLDisplaySocket ) + " " + toExec ;
Debug : : log ( LOG , " Config executing %s " , toExec . c_str ( ) ) ;
2022-06-16 21:19:36 +02:00
2022-06-15 19:06:51 +02:00
int socket [ 2 ] ;
2022-06-16 21:19:36 +02:00
if ( pipe ( socket ) ! = 0 ) {
Debug : : log ( LOG , " Unable to create pipe for fork " ) ;
}
2022-06-15 19:06:51 +02:00
2022-06-16 21:19:36 +02:00
pid_t child , grandchild ;
2022-06-15 19:06:51 +02:00
child = fork ( ) ;
2022-06-16 21:19:36 +02:00
if ( child < 0 ) {
2022-06-15 19:06:51 +02:00
close ( socket [ 0 ] ) ;
close ( socket [ 1 ] ) ;
Debug : : log ( LOG , " Fail to create the first fork " ) ;
return ;
}
2022-06-16 21:19:36 +02:00
if ( child = = 0 ) {
2022-06-15 19:06:51 +02:00
// run in child
grandchild = fork ( ) ;
2022-10-06 20:02:03 +02:00
sigset_t set ;
sigemptyset ( & set ) ;
sigprocmask ( SIG_SETMASK , & set , NULL ) ;
2022-06-16 21:19:36 +02:00
if ( grandchild = = 0 ) {
2022-06-15 19:06:51 +02:00
// run in grandchild
close ( socket [ 0 ] ) ;
close ( socket [ 1 ] ) ;
execl ( " /bin/sh " , " /bin/sh " , " -c " , args . c_str ( ) , nullptr ) ;
// exit grandchild
_exit ( 0 ) ;
}
close ( socket [ 0 ] ) ;
2022-06-16 21:19:36 +02:00
write ( socket [ 1 ] , & grandchild , sizeof ( grandchild ) ) ;
2022-06-15 19:06:51 +02:00
close ( socket [ 1 ] ) ;
// exit child
2022-03-17 15:53:45 +01:00
_exit ( 0 ) ;
}
2022-06-15 19:06:51 +02:00
// run in parent
close ( socket [ 1 ] ) ;
2022-06-16 21:19:36 +02:00
read ( socket [ 0 ] , & grandchild , sizeof ( grandchild ) ) ;
2022-06-15 19:06:51 +02:00
close ( socket [ 0 ] ) ;
// clear child and leave child to init
waitpid ( child , NULL , 0 ) ;
2022-06-16 21:19:36 +02:00
if ( child < 0 ) {
2022-06-15 19:06:51 +02:00
Debug : : log ( LOG , " Fail to create the second fork " ) ;
return ;
}
2022-06-16 21:19:36 +02:00
Debug : : log ( LOG , " Process created with pid %d " , grandchild ) ;
2022-03-17 15:53:45 +01:00
}
2022-03-17 16:56:33 +01:00
void CConfigManager : : handleMonitor ( const std : : string & command , const std : : string & args ) {
// get the monitor config
SMonitorRule newrule ;
2022-10-03 15:29:45 +02:00
const auto ARGS = CVarList ( args ) ;
2022-03-17 16:56:33 +01:00
2022-10-03 15:29:45 +02:00
newrule . name = ARGS [ 0 ] ;
2022-03-17 16:56:33 +01:00
2022-10-03 15:29:45 +02:00
if ( ARGS [ 1 ] = = " disable " | | ARGS [ 1 ] = = " disabled " | | ARGS [ 1 ] = = " addreserved " | | ARGS [ 1 ] = = " transform " ) {
if ( ARGS [ 1 ] = = " disable " | | ARGS [ 1 ] = = " disabled " )
2022-04-27 17:46:07 +02:00
newrule . disabled = true ;
2022-10-03 15:29:45 +02:00
else if ( ARGS [ 1 ] = = " transform " ) {
wl_output_transform transform = ( wl_output_transform ) std : : stoi ( ARGS [ 2 ] ) ;
2022-05-29 12:27:45 +02:00
// overwrite if exists
for ( auto & r : m_dMonitorRules ) {
if ( r . name = = newrule . name ) {
r . transform = transform ;
return ;
}
}
return ;
2022-10-03 15:29:45 +02:00
} else if ( ARGS [ 1 ] = = " addreserved " ) {
int top = std : : stoi ( ARGS [ 2 ] ) ;
2022-04-27 17:46:07 +02:00
2022-10-03 15:29:45 +02:00
int bottom = std : : stoi ( ARGS [ 3 ] ) ;
2022-04-27 17:46:07 +02:00
2022-10-03 15:29:45 +02:00
int left = std : : stoi ( ARGS [ 4 ] ) ;
2022-04-27 17:46:07 +02:00
2022-10-03 15:29:45 +02:00
int right = std : : stoi ( ARGS [ 5 ] ) ;
2022-04-27 17:46:07 +02:00
m_mAdditionalReservedAreas [ newrule . name ] = { top , bottom , left , right } ;
return ; // this is not a rule, ignore
} else {
Debug : : log ( ERR , " ConfigManager parseMonitor, curitem bogus??? " ) ;
return ;
}
2022-04-17 10:19:46 +02:00
2022-09-25 20:07:48 +02:00
if ( std : : find_if ( m_dMonitorRules . begin ( ) , m_dMonitorRules . end ( ) , [ & ] ( const auto & other ) { return other . name = = newrule . name ; } ) ! = m_dMonitorRules . end ( ) )
2022-08-03 17:19:32 +02:00
m_dMonitorRules . erase ( std : : remove_if ( m_dMonitorRules . begin ( ) , m_dMonitorRules . end ( ) , [ & ] ( const auto & other ) { return other . name = = newrule . name ; } ) ) ;
2022-04-21 17:33:24 +02:00
2022-04-17 10:19:46 +02:00
m_dMonitorRules . push_back ( newrule ) ;
2022-04-17 10:21:54 +02:00
2022-04-17 10:19:46 +02:00
return ;
}
2022-10-03 15:29:45 +02:00
if ( ARGS [ 1 ] . find ( " pref " ) = = 0 ) {
2022-07-30 22:54:29 +02:00
newrule . resolution = Vector2D ( ) ;
2022-10-03 15:29:45 +02:00
} else if ( ARGS [ 1 ] . find ( " highrr " ) = = 0 ) {
2022-09-21 22:29:52 +02:00
newrule . resolution = Vector2D ( - 1 , - 1 ) ;
2022-10-03 15:29:45 +02:00
} else if ( ARGS [ 1 ] . find ( " highres " ) = = 0 ) {
2022-09-22 00:22:39 +02:00
newrule . resolution = Vector2D ( - 1 , - 2 ) ;
2022-07-30 22:54:29 +02:00
} else {
2022-10-03 15:29:45 +02:00
newrule . resolution . x = stoi ( ARGS [ 1 ] . substr ( 0 , ARGS [ 1 ] . find_first_of ( ' x ' ) ) ) ;
newrule . resolution . y = stoi ( ARGS [ 1 ] . substr ( ARGS [ 1 ] . find_first_of ( ' x ' ) + 1 , ARGS [ 1 ] . find_first_of ( ' @ ' ) ) ) ;
2022-03-19 21:46:29 +01:00
2022-10-03 15:29:45 +02:00
if ( ARGS [ 1 ] . contains ( " @ " ) )
newrule . refreshRate = stof ( ARGS [ 1 ] . substr ( ARGS [ 1 ] . find_first_of ( ' @ ' ) + 1 ) ) ;
2022-08-03 21:06:51 +02:00
}
2022-03-17 16:56:33 +01:00
2022-10-03 15:29:45 +02:00
if ( ARGS [ 2 ] . find ( " auto " ) = = 0 ) {
2022-08-04 11:10:26 +02:00
newrule . offset = Vector2D ( - 1 , - 1 ) ;
} else {
2022-10-03 15:29:45 +02:00
newrule . offset . x = stoi ( ARGS [ 2 ] . substr ( 0 , ARGS [ 2 ] . find_first_of ( ' x ' ) ) ) ;
newrule . offset . y = stoi ( ARGS [ 2 ] . substr ( ARGS [ 2 ] . find_first_of ( ' x ' ) + 1 ) ) ;
2022-03-17 16:56:33 +01:00
2022-08-04 11:10:26 +02:00
if ( newrule . offset . x < 0 | | newrule . offset . y < 0 ) {
parseError = " invalid offset. Offset cannot be negative. " ;
newrule . offset = Vector2D ( ) ;
}
2022-08-03 21:06:51 +02:00
}
2022-10-03 15:29:45 +02:00
newrule . scale = stof ( ARGS [ 3 ] ) ;
2022-03-17 16:56:33 +01:00
2022-08-03 21:06:51 +02:00
if ( newrule . scale < 0.25f ) {
parseError = " not a valid scale. " ;
newrule . scale = 1 ;
}
2022-10-03 15:29:45 +02:00
int argno = 4 ;
2022-04-21 22:15:42 +02:00
2022-10-03 15:29:45 +02:00
while ( ARGS [ argno ] ! = " " ) {
if ( ARGS [ argno ] = = " mirror " ) {
newrule . mirrorOf = ARGS [ argno + 1 ] ;
argno + + ;
2022-10-27 14:26:47 +02:00
} else if ( ARGS [ argno ] = = " bitdepth " ) {
newrule . enable10bit = ARGS [ argno + 1 ] = = " 10 " ;
argno + + ;
2022-09-13 15:25:42 +02:00
} else {
Debug : : log ( ERR , " Config error: invalid monitor syntax " ) ;
2022-10-03 15:29:45 +02:00
parseError = " invalid syntax at \" " + ARGS [ argno ] + " \" " ;
2022-09-13 15:25:42 +02:00
return ;
}
2022-10-03 15:29:45 +02:00
argno + + ;
2022-04-21 22:15:42 +02:00
}
2022-08-03 17:19:32 +02:00
if ( std : : find_if ( m_dMonitorRules . begin ( ) , m_dMonitorRules . end ( ) , [ & ] ( const auto & other ) { return other . name = = newrule . name ; } ) ! = m_dMonitorRules . end ( ) )
m_dMonitorRules . erase ( std : : remove_if ( m_dMonitorRules . begin ( ) , m_dMonitorRules . end ( ) , [ & ] ( const auto & other ) { return other . name = = newrule . name ; } ) ) ;
2022-04-21 17:33:24 +02:00
2022-03-17 16:56:33 +01:00
m_dMonitorRules . push_back ( newrule ) ;
}
2022-04-23 21:47:16 +02:00
void CConfigManager : : handleBezier ( const std : : string & command , const std : : string & args ) {
2022-10-03 15:29:45 +02:00
const auto ARGS = CVarList ( args ) ;
2022-04-23 21:47:16 +02:00
2022-10-03 15:29:45 +02:00
std : : string bezierName = ARGS [ 0 ] ;
2022-04-23 21:47:16 +02:00
2022-10-03 15:29:45 +02:00
if ( ARGS [ 1 ] = = " " )
2022-08-09 18:15:37 +02:00
parseError = " too few arguments " ;
2022-10-03 15:29:45 +02:00
float p1x = std : : stof ( ARGS [ 1 ] ) ;
if ( ARGS [ 2 ] = = " " )
2022-08-09 18:15:37 +02:00
parseError = " too few arguments " ;
2022-10-03 15:29:45 +02:00
float p1y = std : : stof ( ARGS [ 2 ] ) ;
if ( ARGS [ 3 ] = = " " )
2022-08-09 18:15:37 +02:00
parseError = " too few arguments " ;
2022-10-03 15:29:45 +02:00
float p2x = std : : stof ( ARGS [ 3 ] ) ;
if ( ARGS [ 4 ] = = " " )
2022-08-09 18:15:37 +02:00
parseError = " too few arguments " ;
2022-10-03 15:29:45 +02:00
float p2y = std : : stof ( ARGS [ 4 ] ) ;
if ( ARGS [ 5 ] ! = " " )
2022-08-09 18:15:37 +02:00
parseError = " too many arguments " ;
2022-04-23 21:47:16 +02:00
g_pAnimationManager - > addBezierWithName ( bezierName , Vector2D ( p1x , p1y ) , Vector2D ( p2x , p2y ) ) ;
}
2022-07-28 13:28:43 +02:00
void CConfigManager : : setAnimForChildren ( SAnimationPropertyConfig * const ANIM ) {
for ( auto & [ name , anim ] : animationConfig ) {
if ( anim . pParentAnimation = = ANIM & & ! anim . overriden ) {
// if a child isnt overriden, set the values of the parent
anim . pValues = ANIM - > pValues ;
setAnimForChildren ( & anim ) ;
}
}
} ;
2022-05-14 15:56:01 +02:00
void CConfigManager : : handleAnimation ( const std : : string & command , const std : : string & args ) {
2022-10-03 15:29:45 +02:00
const auto ARGS = CVarList ( args ) ;
2022-05-14 15:56:01 +02:00
// Master on/off
// anim name
2022-10-03 15:29:45 +02:00
const auto ANIMNAME = ARGS [ 0 ] ;
2022-09-25 20:07:48 +02:00
2022-07-28 13:28:43 +02:00
const auto PANIM = animationConfig . find ( ANIMNAME ) ;
2022-05-14 15:56:01 +02:00
2022-07-28 13:28:43 +02:00
if ( PANIM = = animationConfig . end ( ) ) {
parseError = " no such animation " ;
2022-05-14 15:56:01 +02:00
return ;
}
2022-07-28 13:28:43 +02:00
PANIM - > second . overriden = true ;
PANIM - > second . pValues = & PANIM - > second ;
2022-05-14 15:56:01 +02:00
// on/off
2022-10-03 15:29:45 +02:00
PANIM - > second . internalEnabled = ARGS [ 1 ] = = " 1 " ;
2022-05-14 15:56:01 +02:00
2022-10-03 15:29:45 +02:00
if ( ARGS [ 1 ] ! = " 0 " & & ARGS [ 1 ] ! = " 1 " ) {
2022-08-07 19:28:46 +02:00
parseError = " invalid animation on/off state " ;
}
2022-07-28 13:28:43 +02:00
// speed
2022-10-03 15:29:45 +02:00
if ( isNumber ( ARGS [ 2 ] , true ) ) {
PANIM - > second . internalSpeed = std : : stof ( ARGS [ 2 ] ) ;
2022-08-07 19:28:46 +02:00
if ( PANIM - > second . internalSpeed < = 0 ) {
parseError = " invalid speed " ;
PANIM - > second . internalSpeed = 1.f ;
}
2022-07-28 13:28:43 +02:00
} else {
PANIM - > second . internalSpeed = 10.f ;
2022-08-07 19:28:46 +02:00
parseError = " invalid speed " ;
2022-07-28 13:28:43 +02:00
}
2022-05-14 15:56:01 +02:00
// curve
2022-10-03 15:29:45 +02:00
PANIM - > second . internalBezier = ARGS [ 3 ] ;
2022-05-14 16:43:30 +02:00
2022-10-03 15:29:45 +02:00
if ( ! g_pAnimationManager - > bezierExists ( ARGS [ 3 ] ) ) {
2022-08-07 19:28:46 +02:00
parseError = " no such bezier " ;
PANIM - > second . internalBezier = " default " ;
}
2022-05-14 16:43:30 +02:00
// style
2022-10-03 15:29:45 +02:00
PANIM - > second . internalStyle = ARGS [ 4 ] ;
2022-07-28 13:28:43 +02:00
2022-10-03 15:29:45 +02:00
if ( ARGS [ 4 ] ! = " " ) {
const auto ERR = g_pAnimationManager - > styleValidInConfigVar ( ANIMNAME , ARGS [ 4 ] ) ;
2022-08-07 19:28:46 +02:00
if ( ERR ! = " " )
parseError = ERR ;
}
2022-07-28 13:28:43 +02:00
// now, check for children, recursively
setAnimForChildren ( & PANIM - > second ) ;
2022-05-14 15:56:01 +02:00
}
2022-07-20 22:33:43 +02:00
void CConfigManager : : handleBind ( const std : : string & command , const std : : string & value ) {
2022-03-19 17:48:18 +01:00
// example:
2022-07-20 22:33:43 +02:00
// bind[fl]=SUPER,G,exec,dmenu_run <args>
// flags
bool locked = false ;
2022-07-20 22:45:06 +02:00
bool release = false ;
2022-07-25 14:42:49 +02:00
bool repeat = false ;
2022-09-19 20:04:48 +02:00
bool mouse = false ;
2022-10-03 15:29:45 +02:00
const auto BINDARGS = command . substr ( 4 ) ;
2022-07-20 22:45:06 +02:00
2022-10-03 15:29:45 +02:00
for ( auto & arg : BINDARGS ) {
2022-07-20 22:33:43 +02:00
if ( arg = = ' l ' ) {
locked = true ;
2022-07-20 22:45:06 +02:00
} else if ( arg = = ' r ' ) {
release = true ;
2022-07-25 14:42:49 +02:00
} else if ( arg = = ' e ' ) {
repeat = true ;
2022-09-19 20:04:48 +02:00
} else if ( arg = = ' m ' ) {
mouse = true ;
2022-07-20 22:33:43 +02:00
} else {
parseError = " bind: invalid flag " ;
return ;
}
}
2022-03-19 17:48:18 +01:00
2022-07-26 17:04:26 +02:00
if ( release & & repeat ) {
parseError = " flags r and e are mutually exclusive " ;
return ;
}
2022-09-19 20:04:48 +02:00
if ( mouse & & ( repeat | | release | | locked ) ) {
parseError = " flag m is exclusive " ;
return ;
}
2022-10-03 17:38:05 +02:00
const auto ARGS = CVarList ( value , 4 ) ;
2022-03-19 17:48:18 +01:00
2022-10-03 22:01:08 +02:00
if ( ( ARGS . size ( ) < 3 & & ! mouse ) | | ( ARGS . size ( ) < 3 & & mouse ) ) {
2022-10-03 15:29:45 +02:00
parseError = " bind: too few args " ;
return ;
} else if ( ( ARGS . size ( ) > 4 & & ! mouse ) | | ( ARGS . size ( ) > 3 & & mouse ) ) {
parseError = " bind: too many args " ;
return ;
}
2022-03-19 17:48:18 +01:00
2022-10-03 15:29:45 +02:00
const auto MOD = g_pKeybindManager - > stringToModMask ( ARGS [ 0 ] ) ;
const auto MODSTR = ARGS [ 0 ] ;
2022-03-19 17:48:18 +01:00
2022-10-03 15:29:45 +02:00
const auto KEY = ARGS [ 1 ] ;
2022-03-19 17:48:18 +01:00
2022-10-03 15:29:45 +02:00
auto HANDLER = ARGS [ 2 ] ;
const auto COMMAND = mouse ? HANDLER : ARGS [ 3 ] ;
2022-09-19 20:04:48 +02:00
if ( mouse )
HANDLER = " mouse " ;
2022-03-19 17:48:18 +01:00
2022-09-21 18:41:19 +02:00
// to lower
std : : transform ( HANDLER . begin ( ) , HANDLER . end ( ) , HANDLER . begin ( ) , : : tolower ) ;
2022-04-21 15:50:52 +02:00
const auto DISPATCHER = g_pKeybindManager - > m_mDispatchers . find ( HANDLER ) ;
if ( DISPATCHER = = g_pKeybindManager - > m_mDispatchers . end ( ) ) {
Debug : : log ( ERR , " Invalid dispatcher! " ) ;
parseError = " Invalid dispatcher, requested \" " + HANDLER + " \" does not exist " ;
return ;
}
2022-05-12 12:41:28 +02:00
if ( MOD = = 0 & & MODSTR ! = " " ) {
Debug : : log ( ERR , " Invalid mod! " ) ;
parseError = " Invalid mod, requested mod \" " + MODSTR + " \" is not a valid mod. " ;
return ;
}
2022-08-21 17:01:32 +02:00
if ( KEY = = " exclam " | | KEY = = " asciicircum " | | KEY = = " at " ) { // just some
parseError = " Your config contains (probably) wrong keys. The SHIFT keysym behavior has changed after v0.10.3beta. Please consult the wiki (Advanced configuring -> binds) " ;
return ;
}
2022-07-08 09:27:17 +02:00
if ( KEY ! = " " ) {
if ( isNumber ( KEY ) & & std : : stoi ( KEY ) > 9 )
2022-09-19 20:04:48 +02:00
g_pKeybindManager - > addKeybind ( SKeybind { " " , std : : stoi ( KEY ) , MOD , HANDLER , COMMAND , locked , m_szCurrentSubmap , release , repeat , mouse } ) ;
2022-07-08 09:27:17 +02:00
else
2022-09-19 20:04:48 +02:00
g_pKeybindManager - > addKeybind ( SKeybind { KEY , - 1 , MOD , HANDLER , COMMAND , locked , m_szCurrentSubmap , release , repeat , mouse } ) ;
2022-07-08 09:27:17 +02:00
}
2022-03-19 17:48:18 +01:00
}
2022-04-21 17:06:43 +02:00
void CConfigManager : : handleUnbind ( const std : : string & command , const std : : string & value ) {
2022-10-03 15:29:45 +02:00
const auto ARGS = CVarList ( value ) ;
2022-04-21 17:06:43 +02:00
2022-10-03 15:29:45 +02:00
const auto MOD = g_pKeybindManager - > stringToModMask ( ARGS [ 0 ] ) ;
2022-04-21 17:06:43 +02:00
2022-10-03 15:29:45 +02:00
const auto KEY = ARGS [ 1 ] ;
2022-04-21 17:06:43 +02:00
g_pKeybindManager - > removeKeybind ( MOD , KEY ) ;
}
2022-09-06 11:57:11 +02:00
bool windowRuleValid ( const std : : string & RULE ) {
2022-09-25 20:07:48 +02:00
return ! ( RULE ! = " float "
2022-03-24 18:22:01 +01:00
& & RULE ! = " tile "
2022-04-22 14:37:38 +02:00
& & RULE . find ( " opacity " ) ! = 0
2022-03-24 18:22:01 +01:00
& & RULE . find ( " move " ) ! = 0
& & RULE . find ( " size " ) ! = 0
2022-10-06 10:09:58 +02:00
& & RULE . find ( " minsize " ) ! = 0
2022-10-15 17:04:57 +02:00
& & RULE . find ( " maxsize " ) ! = 0
2022-04-02 20:04:32 +02:00
& & RULE . find ( " pseudo " ) ! = 0
2022-04-21 17:17:47 +02:00
& & RULE . find ( " monitor " ) ! = 0
2022-06-24 22:28:54 +02:00
& & RULE ! = " nofocus "
& & RULE ! = " noblur "
2022-10-20 21:36:27 +02:00
& & RULE ! = " noshadow "
& & RULE ! = " noborder "
2022-07-16 16:27:17 +02:00
& & RULE ! = " center "
2022-08-02 00:08:31 +02:00
& & RULE ! = " opaque "
2022-08-27 13:01:55 +02:00
& & RULE ! = " forceinput "
2022-06-26 12:12:29 +02:00
& & RULE ! = " fullscreen "
2022-09-10 13:11:02 +02:00
& & RULE ! = " pin "
2022-10-06 10:16:40 +02:00
& & RULE ! = " noanim "
2022-10-20 23:38:49 +02:00
& & RULE ! = " windowdance "
2022-05-15 14:18:31 +02:00
& & RULE . find ( " animation " ) ! = 0
2022-05-28 17:48:01 +02:00
& & RULE . find ( " rounding " ) ! = 0
2022-09-06 11:57:11 +02:00
& & RULE . find ( " workspace " ) ! = 0 ) ;
}
void CConfigManager : : handleWindowRule ( const std : : string & command , const std : : string & value ) {
2022-10-03 15:29:45 +02:00
const auto RULE = removeBeginEndSpacesTabs ( value . substr ( 0 , value . find_first_of ( " , " ) ) ) ;
const auto VALUE = removeBeginEndSpacesTabs ( value . substr ( value . find_first_of ( " , " ) + 1 ) ) ;
2022-09-06 11:57:11 +02:00
// check rule and value
if ( RULE = = " " | | VALUE = = " " ) {
return ;
}
// verify we support a rule
if ( ! windowRuleValid ( RULE ) ) {
Debug : : log ( ERR , " Invalid rule found: %s " , RULE . c_str ( ) ) ;
parseError = " Invalid rule found: " + RULE ;
return ;
}
2022-03-24 18:22:01 +01:00
m_dWindowRules . push_back ( { RULE , VALUE } ) ;
2022-09-06 11:57:11 +02:00
}
void CConfigManager : : handleWindowRuleV2 ( const std : : string & command , const std : : string & value ) {
const auto RULE = value . substr ( 0 , value . find_first_of ( " , " ) ) ;
const auto VALUE = value . substr ( value . find_first_of ( " , " ) + 1 ) ;
if ( ! windowRuleValid ( RULE ) ) {
Debug : : log ( ERR , " Invalid rulev2 found: %s " , RULE . c_str ( ) ) ;
parseError = " Invalid rulev2 found: " + RULE ;
return ;
}
2022-03-24 18:22:01 +01:00
2022-09-06 11:57:11 +02:00
// now we estract shit from the value
SWindowRule rule ;
rule . v2 = true ;
rule . szRule = RULE ;
2022-09-07 11:24:40 +02:00
rule . szValue = VALUE ;
2022-09-06 11:57:11 +02:00
const auto TITLEPOS = VALUE . find ( " title: " ) ;
const auto CLASSPOS = VALUE . find ( " class: " ) ;
2022-09-07 11:24:40 +02:00
const auto X11POS = VALUE . find ( " xwayland: " ) ;
const auto FLOATPOS = VALUE . find ( " floating: " ) ;
2022-09-06 11:57:11 +02:00
2022-09-07 11:24:40 +02:00
if ( TITLEPOS = = std : : string : : npos & & CLASSPOS = = std : : string : : npos & & X11POS = = std : : string : : npos & & FLOATPOS = = std : : string : : npos ) {
2022-09-06 11:57:11 +02:00
Debug : : log ( ERR , " Invalid rulev2 syntax: %s " , VALUE . c_str ( ) ) ;
parseError = " Invalid rulev2 syntax: " + VALUE ;
return ;
}
auto extract = [ & ] ( size_t pos ) - > std : : string {
std : : string result ;
result = VALUE . substr ( pos ) ;
size_t min = 999999 ;
if ( TITLEPOS > pos & & TITLEPOS < min ) min = TITLEPOS ;
if ( CLASSPOS > pos & & CLASSPOS < min ) min = CLASSPOS ;
2022-09-07 11:24:40 +02:00
if ( X11POS > pos & & X11POS < min ) min = X11POS ;
if ( FLOATPOS > pos & & FLOATPOS < min ) min = FLOATPOS ;
2022-09-06 11:57:11 +02:00
result = result . substr ( 0 , min - pos ) ;
2022-10-03 15:29:45 +02:00
result = removeBeginEndSpacesTabs ( result ) ;
2022-09-06 11:57:11 +02:00
if ( result . back ( ) = = ' , ' )
result . pop_back ( ) ;
return result ;
} ;
if ( CLASSPOS ! = std : : string : : npos ) {
rule . szClass = extract ( CLASSPOS + 6 ) ;
}
if ( TITLEPOS ! = std : : string : : npos ) {
rule . szTitle = extract ( TITLEPOS + 6 ) ;
}
2022-09-07 11:24:40 +02:00
if ( X11POS ! = std : : string : : npos ) {
rule . bX11 = extract ( X11POS + 9 ) = = " 1 " ? 1 : 0 ;
}
if ( FLOATPOS ! = std : : string : : npos ) {
rule . bFloating = extract ( FLOATPOS + 9 ) = = " 1 " ? 1 : 0 ;
}
2022-09-06 11:57:11 +02:00
m_dWindowRules . push_back ( rule ) ;
2022-03-24 18:22:01 +01:00
}
2022-07-06 22:12:03 +02:00
void CConfigManager : : handleBlurLS ( const std : : string & command , const std : : string & value ) {
2022-07-15 13:29:56 +02:00
if ( value . find ( " remove, " ) = = 0 ) {
2022-10-03 15:29:45 +02:00
const auto TOREMOVE = removeBeginEndSpacesTabs ( value . substr ( 7 ) ) ;
2022-07-15 13:29:56 +02:00
m_dBlurLSNamespaces . erase ( std : : remove ( m_dBlurLSNamespaces . begin ( ) , m_dBlurLSNamespaces . end ( ) , TOREMOVE ) ) ;
return ;
}
2022-07-06 22:12:03 +02:00
m_dBlurLSNamespaces . emplace_back ( value ) ;
}
2022-03-20 16:01:47 +01:00
void CConfigManager : : handleDefaultWorkspace ( const std : : string & command , const std : : string & value ) {
2022-10-03 15:29:45 +02:00
const auto ARGS = CVarList ( value ) ;
2022-03-20 16:01:47 +01:00
for ( auto & mr : m_dMonitorRules ) {
2022-10-03 15:29:45 +02:00
if ( mr . name = = ARGS [ 0 ] ) {
mr . defaultWorkspace = ARGS [ 1 ] ;
2022-03-20 16:01:47 +01:00
break ;
}
}
}
2022-06-22 20:23:20 +02:00
void CConfigManager : : handleSubmap ( const std : : string & command , const std : : string & submap ) {
2022-09-25 20:07:48 +02:00
if ( submap = = " reset " )
2022-06-22 20:23:20 +02:00
m_szCurrentSubmap = " " ;
else
m_szCurrentSubmap = submap ;
}
2022-05-16 10:09:20 +02:00
void CConfigManager : : handleSource ( const std : : string & command , const std : : string & rawpath ) {
2022-08-19 20:01:51 +02:00
if ( rawpath . length ( ) < 2 ) {
2022-07-06 15:05:23 +02:00
Debug : : log ( ERR , " source= path garbage " ) ;
2022-08-19 20:01:51 +02:00
parseError = " source path " + rawpath + " bogus! " ;
2022-07-06 15:05:23 +02:00
return ;
}
2022-08-19 22:18:09 +02:00
auto value = absolutePath ( rawpath , configCurrentPath ) ;
2022-05-16 10:09:20 +02:00
if ( ! std : : filesystem : : exists ( value ) ) {
Debug : : log ( ERR , " source= file doesnt exist " ) ;
parseError = " source file " + value + " doesn't exist! " ;
return ;
}
configPaths . push_back ( value ) ;
struct stat fileStat ;
int err = stat ( value . c_str ( ) , & fileStat ) ;
if ( err ! = 0 ) {
Debug : : log ( WARN , " Error at ticking config at %s, error %i: %s " , value . c_str ( ) , err , strerror ( err ) ) ;
return ;
}
configModifyTimes [ value ] = fileStat . st_mtime ;
std : : ifstream ifs ;
ifs . open ( value ) ;
std : : string line = " " ;
int linenum = 1 ;
if ( ifs . is_open ( ) ) {
while ( std : : getline ( ifs , line ) ) {
// Read line by line.
try {
configCurrentPath = value ;
parseLine ( line ) ;
} catch ( . . . ) {
Debug : : log ( ERR , " Error reading line from config. Line: " ) ;
Debug : : log ( NONE , " %s " , line . c_str ( ) ) ;
parseError + = " Config error at line " + std : : to_string ( linenum ) + " ( " + configCurrentPath + " ): Line parsing error. " ;
}
if ( parseError ! = " " & & parseError . find ( " Config error at line " ) ! = 0 ) {
parseError = " Config error at line " + std : : to_string ( linenum ) + " ( " + configCurrentPath + " ): " + parseError ;
}
+ + linenum ;
}
ifs . close ( ) ;
}
}
2022-09-12 21:05:52 +02:00
void CConfigManager : : handleBindWS ( const std : : string & command , const std : : string & value ) {
2022-10-03 15:29:45 +02:00
const auto ARGS = CVarList ( value ) ;
2022-09-12 21:05:52 +02:00
2022-10-03 15:29:45 +02:00
const auto FOUND = std : : find_if ( boundWorkspaces . begin ( ) , boundWorkspaces . end ( ) , [ & ] ( const auto & other ) { return other . first = = ARGS [ 0 ] ; } ) ;
2022-09-24 14:42:18 +02:00
if ( FOUND ! = boundWorkspaces . end ( ) ) {
2022-10-03 15:29:45 +02:00
FOUND - > second = ARGS [ 1 ] ;
2022-09-24 14:42:18 +02:00
return ;
}
2022-10-03 15:29:45 +02:00
boundWorkspaces . push_back ( { ARGS [ 0 ] , ARGS [ 1 ] } ) ;
2022-09-12 21:05:52 +02:00
}
2022-04-21 16:56:27 +02:00
std : : string CConfigManager : : parseKeyword ( const std : : string & COMMAND , const std : : string & VALUE , bool dynamic ) {
2022-05-25 17:42:38 +02:00
if ( dynamic ) {
2022-04-21 16:56:27 +02:00
parseError = " " ;
2022-05-25 17:42:38 +02:00
currentCategory = " " ;
}
2022-04-21 16:56:27 +02:00
if ( COMMAND = = " exec " ) {
if ( isFirstLaunch ) {
firstExecRequests . push_back ( VALUE ) ;
} else {
handleRawExec ( COMMAND , VALUE ) ;
}
} else if ( COMMAND = = " exec-once " ) {
if ( isFirstLaunch ) {
firstExecRequests . push_back ( VALUE ) ;
}
}
2022-05-14 15:56:01 +02:00
else if ( COMMAND = = " monitor " ) handleMonitor ( COMMAND , VALUE ) ;
2022-07-20 22:33:43 +02:00
else if ( COMMAND . find ( " bind " ) = = 0 ) handleBind ( COMMAND , VALUE ) ;
2022-05-14 15:56:01 +02:00
else if ( COMMAND = = " unbind " ) handleUnbind ( COMMAND , VALUE ) ;
else if ( COMMAND = = " workspace " ) handleDefaultWorkspace ( COMMAND , VALUE ) ;
else if ( COMMAND = = " windowrule " ) handleWindowRule ( COMMAND , VALUE ) ;
2022-09-06 11:57:11 +02:00
else if ( COMMAND = = " windowrulev2 " ) handleWindowRuleV2 ( COMMAND , VALUE ) ;
2022-05-14 15:56:01 +02:00
else if ( COMMAND = = " bezier " ) handleBezier ( COMMAND , VALUE ) ;
else if ( COMMAND = = " animation " ) handleAnimation ( COMMAND , VALUE ) ;
2022-05-16 10:09:20 +02:00
else if ( COMMAND = = " source " ) handleSource ( COMMAND , VALUE ) ;
2022-06-22 20:23:20 +02:00
else if ( COMMAND = = " submap " ) handleSubmap ( COMMAND , VALUE ) ;
2022-07-06 22:12:03 +02:00
else if ( COMMAND = = " blurls " ) handleBlurLS ( COMMAND , VALUE ) ;
2022-09-12 21:05:52 +02:00
else if ( COMMAND = = " wsbind " ) handleBindWS ( COMMAND , VALUE ) ;
2022-05-14 15:56:01 +02:00
else
configSetValueSafe ( currentCategory + ( currentCategory = = " " ? " " : " : " ) + COMMAND , VALUE ) ;
2022-04-21 16:56:27 +02:00
if ( dynamic ) {
std : : string retval = parseError ;
parseError = " " ;
2022-05-25 17:42:38 +02:00
// invalidate layouts jic
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors )
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( m - > ID ) ;
2022-05-26 21:23:13 +02:00
// Update window border colors
2022-07-12 13:40:55 +02:00
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
2022-05-26 21:23:13 +02:00
2022-04-21 16:56:27 +02:00
return retval ;
}
return parseError ;
}
2022-05-16 09:38:42 +02:00
void CConfigManager : : applyUserDefinedVars ( std : : string & line , const size_t equalsPlace ) {
auto dollarPlace = line . find_first_of ( ' $ ' , equalsPlace ) ;
while ( dollarPlace ! = std : : string : : npos ) {
const auto STRAFTERDOLLAR = line . substr ( dollarPlace + 1 ) ;
for ( auto & [ var , value ] : configDynamicVars ) {
if ( STRAFTERDOLLAR . find ( var ) = = 0 ) {
line . replace ( dollarPlace , var . length ( ) + 1 , value ) ;
break ;
}
}
dollarPlace = line . find_first_of ( ' $ ' , dollarPlace + 1 ) ;
}
}
2022-03-17 15:53:45 +01:00
void CConfigManager : : parseLine ( std : : string & line ) {
// first check if its not a comment
2022-10-25 15:32:25 +02:00
if ( line [ 0 ] = = ' # ' )
2022-03-17 15:53:45 +01:00
return ;
2022-10-25 15:32:25 +02:00
// now, cut the comment off. ## is an escape.
for ( long unsigned int i = 1 ; i < line . length ( ) ; + + i ) {
if ( line [ i ] = = ' # ' ) {
if ( i + 1 < line . length ( ) & & line [ i + 1 ] ! = ' # ' ) {
line = line . substr ( 0 , i ) ;
break ; // no need to parse more
}
i + + ;
}
}
size_t startPos = 0 ;
while ( ( startPos = line . find ( " ## " , startPos ) ) ! = std : : string : : npos ) {
line . replace ( startPos , 2 , " # " ) ;
startPos + + ;
}
2022-03-17 15:53:45 +01:00
// remove shit at the beginning
while ( line [ 0 ] = = ' ' | | line [ 0 ] = = ' \t ' ) {
line = line . substr ( 1 ) ;
}
2022-07-06 16:50:11 +02:00
if ( line . contains ( " { " ) ) {
2022-03-17 15:53:45 +01:00
auto cat = line . substr ( 0 , line . find ( " { " ) ) ;
transform ( cat . begin ( ) , cat . end ( ) , cat . begin ( ) , : : tolower ) ;
2022-08-20 18:47:48 +02:00
std : : replace ( cat . begin ( ) , cat . end ( ) , ' ' , ' - ' ) ;
2022-04-19 18:42:26 +02:00
if ( currentCategory . length ( ) ! = 0 ) {
currentCategory . push_back ( ' : ' ) ;
currentCategory . append ( cat ) ;
}
else {
currentCategory = cat ;
}
2022-03-17 15:53:45 +01:00
return ;
}
2022-07-06 16:50:11 +02:00
if ( line . contains ( " } " ) & & currentCategory ! = " " ) {
2022-08-27 23:12:01 +02:00
const auto LASTSEP = currentCategory . find_last_of ( ' : ' ) ;
2022-08-28 10:25:48 +02:00
if ( LASTSEP = = std : : string : : npos | | currentCategory . contains ( " device " ) )
2022-08-27 23:12:01 +02:00
currentCategory = " " ;
2022-09-25 20:07:48 +02:00
else
2022-08-27 23:12:01 +02:00
currentCategory = currentCategory . substr ( 0 , LASTSEP ) ;
2022-09-25 20:07:48 +02:00
2022-03-17 15:53:45 +01:00
return ;
}
// And parse
// check if command
const auto EQUALSPLACE = line . find_first_of ( ' = ' ) ;
2022-05-16 09:38:42 +02:00
// apply vars
applyUserDefinedVars ( line , EQUALSPLACE ) ;
2022-03-17 15:53:45 +01:00
if ( EQUALSPLACE = = std : : string : : npos )
return ;
2022-04-18 13:25:27 +02:00
const auto COMMAND = removeBeginEndSpacesTabs ( line . substr ( 0 , EQUALSPLACE ) ) ;
const auto VALUE = removeBeginEndSpacesTabs ( line . substr ( EQUALSPLACE + 1 ) ) ;
//
2022-03-17 15:53:45 +01:00
2022-04-21 16:56:27 +02:00
parseKeyword ( COMMAND , VALUE ) ;
2022-03-17 15:53:45 +01:00
}
void CConfigManager : : loadConfigLoadVars ( ) {
Debug : : log ( LOG , " Reloading the config! " ) ;
parseError = " " ; // reset the error
currentCategory = " " ; // reset the category
2022-09-25 20:07:48 +02:00
2022-04-18 13:27:54 +02:00
// reset all vars before loading
setDefaultVars ( ) ;
2022-03-17 16:56:33 +01:00
m_dMonitorRules . clear ( ) ;
2022-03-24 18:22:01 +01:00
m_dWindowRules . clear ( ) ;
2022-03-19 21:48:24 +01:00
g_pKeybindManager - > clearKeybinds ( ) ;
2022-04-23 21:47:16 +02:00
g_pAnimationManager - > removeAllBeziers ( ) ;
2022-04-27 17:46:07 +02:00
m_mAdditionalReservedAreas . clear ( ) ;
2022-05-16 09:38:42 +02:00
configDynamicVars . clear ( ) ;
2022-06-30 21:26:00 +02:00
deviceConfigs . clear ( ) ;
2022-07-06 22:12:03 +02:00
m_dBlurLSNamespaces . clear ( ) ;
2022-09-12 21:05:52 +02:00
boundWorkspaces . clear ( ) ;
2022-07-28 13:28:43 +02:00
setDefaultAnimationVars ( ) ; // reset anims
2022-03-17 16:56:33 +01:00
2022-05-16 10:09:20 +02:00
// paths
configPaths . clear ( ) ;
2022-07-14 22:55:24 +02:00
std : : string CONFIGPATH ;
2022-05-16 10:09:20 +02:00
static const char * const ENVHOME = getenv ( " HOME " ) ;
2022-06-15 08:29:51 +02:00
const std : : string CONFIGPARENTPATH = ENVHOME + ( std : : string ) " /.config/hypr/ " ;
2022-03-17 15:53:45 +01:00
2022-07-14 22:55:24 +02:00
if ( g_pCompositor - > explicitConfigPath = = " " ) {
CONFIGPATH = CONFIGPARENTPATH + ( ISDEBUG ? " hyprlandd.conf " : " hyprland.conf " ) ;
} else {
CONFIGPATH = g_pCompositor - > explicitConfigPath ;
}
2022-05-16 10:09:20 +02:00
2022-07-14 22:55:24 +02:00
configPaths . push_back ( CONFIGPATH ) ;
2022-09-25 20:07:48 +02:00
2022-03-17 15:53:45 +01:00
std : : ifstream ifs ;
2022-04-08 22:07:40 +02:00
ifs . open ( CONFIGPATH ) ;
2022-03-17 15:53:45 +01:00
if ( ! ifs . good ( ) ) {
2022-07-14 22:55:24 +02:00
if ( g_pCompositor - > explicitConfigPath = = " " ) {
Debug : : log ( WARN , " Config reading error. (No file? Attempting to generate, backing up old one if exists) " ) ;
try {
std : : filesystem : : rename ( CONFIGPATH , CONFIGPATH + " .backup " ) ;
} catch ( . . . ) { /* Probably doesn't exist */ }
2022-03-17 15:53:45 +01:00
2022-07-14 22:55:24 +02:00
try {
if ( ! std : : filesystem : : is_directory ( CONFIGPARENTPATH ) )
std : : filesystem : : create_directories ( CONFIGPARENTPATH ) ;
}
catch ( . . . ) {
parseError = " Broken config file! (Could not create directory) " ;
return ;
}
2022-06-15 08:29:51 +02:00
}
2022-04-08 22:07:40 +02:00
std : : ofstream ofs ;
ofs . open ( CONFIGPATH , std : : ios : : trunc ) ;
ofs < < AUTOCONFIG ;
ofs . close ( ) ;
ifs . open ( CONFIGPATH ) ;
if ( ! ifs . good ( ) ) {
parseError = " Broken config file! (Could not open) " ;
return ;
}
2022-03-17 15:53:45 +01:00
}
std : : string line = " " ;
int linenum = 1 ;
if ( ifs . is_open ( ) ) {
while ( std : : getline ( ifs , line ) ) {
// Read line by line.
try {
2022-05-16 10:09:20 +02:00
configCurrentPath = " ~/.config/hypr/hyprland.conf " ;
2022-03-17 15:53:45 +01:00
parseLine ( line ) ;
} catch ( . . . ) {
Debug : : log ( ERR , " Error reading line from config. Line: " ) ;
Debug : : log ( NONE , " %s " , line . c_str ( ) ) ;
2022-05-16 10:09:20 +02:00
parseError + = " Config error at line " + std : : to_string ( linenum ) + " ( " + configCurrentPath + " ): Line parsing error. " ;
2022-03-17 15:53:45 +01:00
}
if ( parseError ! = " " & & parseError . find ( " Config error at line " ) ! = 0 ) {
2022-05-16 10:09:20 +02:00
parseError = " Config error at line " + std : : to_string ( linenum ) + " ( " + configCurrentPath + " ): " + parseError ;
2022-03-17 15:53:45 +01:00
}
+ + linenum ;
}
ifs . close ( ) ;
}
2022-03-19 21:48:24 +01:00
2022-06-30 15:44:26 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors )
g_pLayoutManager - > getCurrentLayout ( ) - > recalculateMonitor ( m - > ID ) ;
2022-03-20 11:14:24 +01:00
2022-04-10 16:19:49 +02:00
// Update the keyboard layout to the cfg'd one if this is not the first launch
2022-07-19 19:26:53 +02:00
if ( ! isFirstLaunch ) {
2022-04-10 16:19:49 +02:00
g_pInputManager - > setKeyboardLayout ( ) ;
2022-10-05 22:21:22 +02:00
g_pInputManager - > setPointerConfigs ( ) ;
2022-10-07 16:03:52 +02:00
g_pInputManager - > setTouchDeviceConfigs ( ) ;
2022-07-19 19:26:53 +02:00
}
2022-03-24 21:05:34 +01:00
2022-04-14 16:43:29 +02:00
// Calculate the internal vars
2022-03-20 11:14:24 +01:00
configValues [ " general:main_mod_internal " ] . intValue = g_pKeybindManager - > stringToModMask ( configValues [ " general:main_mod " ] . strValue ) ;
2022-04-14 16:43:29 +02:00
const auto DAMAGETRACKINGMODE = g_pHyprRenderer - > damageTrackingModeFromStr ( configValues [ " general:damage_tracking " ] . strValue ) ;
if ( DAMAGETRACKINGMODE ! = DAMAGE_TRACKING_INVALID )
configValues [ " general:damage_tracking_internal " ] . intValue = DAMAGETRACKINGMODE ;
else {
parseError = " invalid value for general:damage_tracking, supported: full, monitor, none " ;
configValues [ " general:damage_tracking_internal " ] . intValue = DAMAGE_TRACKING_NONE ;
}
2022-04-08 21:40:41 +02:00
// parseError will be displayed next frame
if ( parseError ! = " " )
g_pHyprError - > queueCreate ( parseError + " \n Hyprland may not work correctly. " , CColor ( 255 , 50 , 50 , 255 ) ) ;
2022-04-08 22:07:40 +02:00
else if ( configValues [ " autogenerated " ] . intValue = = 1 )
2022-08-16 15:59:18 +02:00
g_pHyprError - > queueCreate ( " Warning: You're using an autogenerated config! (config file: " + CONFIGPATH + " ) \n SUPER+Q -> kitty \n SUPER+M -> exit Hyprland " , CColor ( 255 , 255 , 70 , 255 ) ) ;
2022-04-08 21:40:41 +02:00
else
g_pHyprError - > destroy ( ) ;
2022-04-19 19:01:23 +02: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
2022-08-14 23:26:18 +02:00
// ignore if nomonitorreload is set
if ( ! isFirstLaunch & & ! m_bNoMonitorReload ) {
2022-04-19 19:01:23 +02:00
m_bWantsMonitorReload = true ;
2022-07-27 12:32:00 +02:00
// check
ensureDPMS ( ) ;
2022-10-22 22:45:17 +02:00
ensureVRR ( ) ;
2022-04-19 19:01:23 +02:00
}
2022-05-26 21:23:13 +02:00
// Update window border colors
2022-07-12 13:40:55 +02:00
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
2022-06-26 22:47:13 +02:00
2022-07-16 15:57:31 +02:00
// update layout
g_pLayoutManager - > switchToLayout ( configValues [ " general:layout " ] . strValue ) ;
2022-09-06 17:26:18 +02:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
2022-09-06 18:12:25 +02:00
// mark blur dirty
2022-08-01 13:12:50 +02:00
g_pHyprOpenGL - > markBlurDirtyForMonitor ( m . get ( ) ) ;
2022-09-06 18:12:25 +02:00
// Force the compositor to fully re-render all monitors
m - > forceFullFrames = 2 ;
2022-09-06 17:26:18 +02:00
}
2022-09-25 20:07:48 +02:00
2022-08-14 23:26:18 +02:00
// Reset no monitor reload
m_bNoMonitorReload = false ;
2022-03-17 15:53:45 +01:00
}
void CConfigManager : : tick ( ) {
2022-05-16 10:09:20 +02:00
static const char * const ENVHOME = getenv ( " HOME " ) ;
2022-03-17 15:53:45 +01:00
2022-03-19 16:13:19 +01:00
const std : : string CONFIGPATH = ENVHOME + ( ISDEBUG ? ( std : : string ) " /.config/hypr/hyprlandd.conf " : ( std : : string ) " /.config/hypr/hyprland.conf " ) ;
2022-03-17 15:53:45 +01:00
2022-04-08 22:07:40 +02:00
if ( ! std : : filesystem : : exists ( CONFIGPATH ) ) {
2022-05-17 13:16:37 +02:00
Debug : : log ( ERR , " Config doesn't exist?? " ) ;
2022-04-08 22:07:40 +02:00
return ;
}
2022-05-16 10:09:20 +02:00
bool parse = false ;
for ( auto & cf : configPaths ) {
struct stat fileStat ;
int err = stat ( cf . c_str ( ) , & fileStat ) ;
if ( err ! = 0 ) {
Debug : : log ( WARN , " Error at ticking config at %s, error %i: %s " , cf . c_str ( ) , err , strerror ( err ) ) ;
return ;
}
// check if we need to reload cfg
if ( fileStat . st_mtime ! = configModifyTimes [ cf ] | | m_bForceReload ) {
parse = true ;
configModifyTimes [ cf ] = fileStat . st_mtime ;
}
2022-03-17 15:53:45 +01:00
}
2022-05-16 10:09:20 +02:00
if ( parse ) {
2022-05-08 15:28:45 +02:00
m_bForceReload = false ;
2022-05-16 10:09:20 +02:00
2022-03-17 15:53:45 +01:00
loadConfigLoadVars ( ) ;
}
}
std : : mutex configmtx ;
2022-06-30 21:26:00 +02:00
SConfigValue CConfigManager : : getConfigValueSafe ( const std : : string & val ) {
2022-03-17 15:53:45 +01:00
std : : lock_guard < std : : mutex > lg ( configmtx ) ;
SConfigValue copy = configValues [ val ] ;
return copy ;
}
2022-06-30 21:26:00 +02:00
SConfigValue CConfigManager : : getConfigValueSafeDevice ( const std : : string & dev , const std : : string & val ) {
std : : lock_guard < std : : mutex > lg ( configmtx ) ;
2022-08-20 18:47:48 +02:00
auto devcopy = dev ;
std : : replace ( devcopy . begin ( ) , devcopy . end ( ) , ' ' , ' - ' ) ;
const auto it = deviceConfigs . find ( devcopy ) ;
2022-06-30 21:26:00 +02:00
if ( it = = deviceConfigs . end ( ) ) {
2022-08-20 18:47:48 +02:00
Debug : : log ( ERR , " getConfigValueSafeDevice: No device config for %s found??? " , devcopy . c_str ( ) ) ;
2022-06-30 21:26:00 +02:00
return SConfigValue ( ) ;
}
SConfigValue copy = it - > second [ val ] ;
2022-06-30 21:38:06 +02:00
// fallback if not set explicitly
if ( ! copy . set ) {
for ( auto & cv : configValues ) {
2022-07-28 21:38:30 +02:00
auto foundIt = cv . first . find ( val ) ;
if ( foundIt = = std : : string : : npos )
continue ;
2022-08-20 18:47:48 +02:00
if ( cv . first = = " input: " + val | | cv . first = = " input:touchpad: " + cv . first ) {
2022-06-30 21:38:06 +02:00
copy = cv . second ;
}
}
}
2022-06-30 21:26:00 +02:00
return copy ;
}
int CConfigManager : : getInt ( const std : : string & v ) {
2022-03-17 15:53:45 +01:00
return getConfigValueSafe ( v ) . intValue ;
}
2022-06-30 21:26:00 +02:00
float CConfigManager : : getFloat ( const std : : string & v ) {
2022-03-17 15:53:45 +01:00
return getConfigValueSafe ( v ) . floatValue ;
}
2022-06-30 21:26:00 +02:00
std : : string CConfigManager : : getString ( const std : : string & v ) {
2022-05-06 14:30:35 +02:00
const auto VAL = getConfigValueSafe ( v ) . strValue ;
if ( VAL = = STRVAL_EMPTY )
return " " ;
return VAL ;
2022-03-17 15:53:45 +01:00
}
2022-03-17 16:56:33 +01:00
2022-06-30 21:26:00 +02:00
int CConfigManager : : getDeviceInt ( const std : : string & dev , const std : : string & v ) {
return getConfigValueSafeDevice ( dev , v ) . intValue ;
}
float CConfigManager : : getDeviceFloat ( const std : : string & dev , const std : : string & v ) {
return getConfigValueSafeDevice ( dev , v ) . floatValue ;
}
std : : string CConfigManager : : getDeviceString ( const std : : string & dev , const std : : string & v ) {
const auto VAL = getConfigValueSafeDevice ( dev , v ) . strValue ;
if ( VAL = = STRVAL_EMPTY )
return " " ;
return VAL ;
}
2022-04-10 18:25:45 +02:00
void CConfigManager : : setInt ( std : : string v , int val ) {
configValues [ v ] . intValue = val ;
}
void CConfigManager : : setFloat ( std : : string v , float val ) {
configValues [ v ] . floatValue = val ;
}
void CConfigManager : : setString ( std : : string v , std : : string val ) {
configValues [ v ] . strValue = val ;
}
2022-10-05 11:22:33 +02:00
SMonitorRule CConfigManager : : getMonitorRuleFor ( std : : string name , std : : string displayName ) {
2022-03-17 16:56:33 +01:00
SMonitorRule * found = nullptr ;
for ( auto & r : m_dMonitorRules ) {
2022-10-05 18:38:36 +02:00
if ( r . name = = name | | ( r . name . find ( " desc: " ) = = 0 & & ( r . name . substr ( 5 ) = = displayName | | r . name . substr ( 5 ) = = removeBeginEndSpacesTabs ( displayName . substr ( 0 , displayName . find_first_of ( ' ( ' ) ) ) ) ) ) {
2022-03-17 16:56:33 +01:00
found = & r ;
break ;
}
}
if ( found )
return * found ;
2022-03-19 17:00:52 +01:00
Debug : : log ( WARN , " No rule found for %s, trying to use the first. " , name . c_str ( ) ) ;
2022-03-17 16:56:33 +01:00
for ( auto & r : m_dMonitorRules ) {
2022-10-05 18:38:36 +02:00
if ( r . name = = " " ) {
2022-03-17 16:56:33 +01:00
found = & r ;
break ;
}
}
if ( found )
return * found ;
2022-03-19 17:00:52 +01:00
Debug : : log ( WARN , " No rules configured. Using the default hardcoded one. " ) ;
2022-08-12 22:26:35 +02:00
return SMonitorRule { . name = " " , . resolution = Vector2D ( 0 , 0 ) , . offset = Vector2D ( - 1 , - 1 ) , . scale = 1 } ; // 0, 0 is preferred and -1, -1 is auto
2022-03-24 18:22:01 +01:00
}
std : : vector < SWindowRule > CConfigManager : : getMatchingRules ( CWindow * pWindow ) {
if ( ! g_pCompositor - > windowValidMapped ( pWindow ) )
return std : : vector < SWindowRule > ( ) ;
std : : vector < SWindowRule > returns ;
std : : string title = g_pXWaylandManager - > getTitle ( pWindow ) ;
std : : string appidclass = g_pXWaylandManager - > getAppIDClass ( pWindow ) ;
2022-06-24 16:25:57 +02:00
Debug : : log ( LOG , " Searching for matching rules for %s (title: %s) " , appidclass . c_str ( ) , title . c_str ( ) ) ;
2022-03-24 18:22:01 +01:00
for ( auto & rule : m_dWindowRules ) {
// check if we have a matching rule
2022-09-06 11:57:11 +02:00
if ( ! rule . v2 ) {
try {
if ( rule . szValue . find ( " title: " ) = = 0 ) {
// we have a title rule.
std : : regex RULECHECK ( rule . szValue . substr ( 6 ) ) ;
2022-06-24 16:25:57 +02:00
2022-09-06 11:57:11 +02:00
if ( ! std : : regex_search ( title , RULECHECK ) )
continue ;
} else {
std : : regex classCheck ( rule . szValue ) ;
2022-03-24 18:22:01 +01:00
2022-09-06 11:57:11 +02:00
if ( ! std : : regex_search ( appidclass , classCheck ) )
continue ;
}
} catch ( . . . ) {
Debug : : log ( ERR , " Regex error at %s " , rule . szValue . c_str ( ) ) ;
continue ;
}
} else {
try {
if ( rule . szClass ! = " " ) {
std : : regex RULECHECK ( rule . szClass ) ;
if ( ! std : : regex_search ( appidclass , RULECHECK ) )
continue ;
}
if ( rule . szTitle ! = " " ) {
std : : regex RULECHECK ( rule . szTitle ) ;
if ( ! std : : regex_search ( title , RULECHECK ) )
continue ;
}
2022-09-07 11:24:40 +02:00
if ( rule . bX11 ! = - 1 ) {
if ( pWindow - > m_bIsX11 ! = rule . bX11 )
continue ;
}
if ( rule . bFloating ! = - 1 ) {
if ( pWindow - > m_bIsFloating ! = rule . bFloating )
continue ;
}
2022-09-06 11:57:11 +02:00
} catch ( . . . ) {
Debug : : log ( ERR , " Regex error at %s " , rule . szValue . c_str ( ) ) ;
continue ;
2022-06-24 16:25:57 +02:00
}
2022-03-24 18:22:01 +01:00
}
// applies. Read the rule and behave accordingly
Debug : : log ( LOG , " Window rule %s -> %s matched %x [%s] " , rule . szRule . c_str ( ) , rule . szValue . c_str ( ) , pWindow , pWindow - > m_szTitle . c_str ( ) ) ;
returns . push_back ( rule ) ;
}
return returns ;
2022-04-12 20:02:57 +02:00
}
void CConfigManager : : dispatchExecOnce ( ) {
if ( firstExecDispatched | | isFirstLaunch )
return ;
firstExecDispatched = true ;
for ( auto & c : firstExecRequests ) {
handleRawExec ( " " , c ) ;
}
firstExecRequests . clear ( ) ; // free some kb of memory :P
2022-07-21 20:30:48 +02:00
// set input, fixes some certain issues
g_pInputManager - > setKeyboardLayout ( ) ;
2022-10-05 22:21:22 +02:00
g_pInputManager - > setPointerConfigs ( ) ;
2022-10-07 16:03:52 +02:00
g_pInputManager - > setTouchDeviceConfigs ( ) ;
2022-07-22 12:37:44 +02:00
// set ws names again
for ( auto & ws : g_pCompositor - > m_vWorkspaces ) {
wlr_ext_workspace_handle_v1_set_name ( ws - > m_pWlrHandle , ws - > m_szName . c_str ( ) ) ;
}
2022-04-19 19:01:23 +02:00
}
void CConfigManager : : performMonitorReload ( ) {
2022-06-30 23:55:28 +02:00
bool overAgain = false ;
2022-08-03 17:29:05 +02:00
for ( auto & m : g_pCompositor - > m_vRealMonitors ) {
2022-10-05 11:22:33 +02:00
auto rule = getMonitorRuleFor ( m - > szName , m - > output - > description ? m - > output - > description : " " ) ;
2022-09-13 15:25:42 +02:00
// ensure mirror
m - > setMirror ( rule . mirrorOf ) ;
2022-06-30 23:55:28 +02:00
if ( ! g_pHyprRenderer - > applyMonitorRule ( m . get ( ) , & rule ) ) {
overAgain = true ;
break ;
}
2022-09-08 14:11:32 +02:00
g_pHyprRenderer - > arrangeLayersForMonitor ( m - > ID ) ;
2022-04-19 19:01:23 +02:00
}
2022-06-30 23:55:28 +02:00
if ( overAgain )
performMonitorReload ( ) ;
2022-04-19 19:01:23 +02:00
m_bWantsMonitorReload = false ;
2022-04-21 22:15:42 +02:00
}
2022-04-23 14:16:02 +02:00
SConfigValue * CConfigManager : : getConfigValuePtr ( std : : string val ) {
return & configValues [ val ] ;
2022-05-16 23:52:48 +02:00
}
2022-06-30 21:26:00 +02:00
2022-08-11 21:16:38 +02:00
SConfigValue * CConfigManager : : getConfigValuePtrSafe ( std : : string val ) {
const auto IT = configValues . find ( val ) ;
if ( IT = = configValues . end ( ) )
return nullptr ;
return & ( IT - > second ) ;
}
2022-06-30 21:26:00 +02:00
bool CConfigManager : : deviceConfigExists ( const std : : string & dev ) {
2022-08-20 18:47:48 +02:00
auto copy = dev ;
std : : replace ( copy . begin ( ) , copy . end ( ) , ' ' , ' - ' ) ;
const auto it = deviceConfigs . find ( copy ) ;
2022-06-30 21:26:00 +02:00
return it ! = deviceConfigs . end ( ) ;
}
2022-07-06 22:12:03 +02:00
bool CConfigManager : : shouldBlurLS ( const std : : string & ns ) {
for ( auto & bls : m_dBlurLSNamespaces ) {
if ( bls = = ns ) {
return true ;
}
}
return false ;
}
2022-07-27 12:32:00 +02:00
void CConfigManager : : ensureDPMS ( ) {
for ( auto & rm : g_pCompositor - > m_vRealMonitors ) {
2022-10-05 11:22:33 +02:00
auto rule = getMonitorRuleFor ( rm - > szName , rm - > output - > description ? rm - > output - > description : " " ) ;
2022-07-27 12:32:00 +02:00
if ( rule . disabled = = rm - > m_bEnabled ) {
2022-08-03 21:19:12 +02:00
rm - > m_pThisWrap = & rm ;
2022-07-27 12:32:00 +02:00
g_pHyprRenderer - > applyMonitorRule ( rm . get ( ) , & rule ) ;
}
}
}
2022-07-28 13:28:43 +02:00
2022-10-22 22:45:17 +02:00
void CConfigManager : : ensureVRR ( ) {
static auto * const PNOVRR = & getConfigValuePtr ( " misc:no_vfr " ) - > intValue ;
for ( auto & m : g_pCompositor - > m_vMonitors ) {
if ( ! * PNOVRR & & ! m - > vrrActive ) {
// Adaptive sync (VRR)
wlr_output_enable_adaptive_sync ( m - > output , 1 ) ;
if ( ! wlr_output_test ( m - > output ) ) {
Debug : : log ( LOG , " Pending output %s does not accept VRR. " , m - > output - > name ) ;
wlr_output_enable_adaptive_sync ( m - > output , 0 ) ;
}
if ( ! wlr_output_commit ( m - > output ) ) {
Debug : : log ( ERR , " Couldn't commit output %s in ensureVRR -> true " , m - > output - > name ) ;
}
m - > vrrActive = true ;
Debug : : log ( LOG , " VRR ensured on %s -> true " , m - > output - > name ) ;
} else if ( * PNOVRR & & m - > vrrActive ) {
wlr_output_enable_adaptive_sync ( m - > output , 0 ) ;
if ( ! wlr_output_commit ( m - > output ) ) {
Debug : : log ( ERR , " Couldn't commit output %s in ensureVRR -> false " , m - > output - > name ) ;
}
m - > vrrActive = false ;
Debug : : log ( LOG , " VRR ensured on %s -> false " , m - > output - > name ) ;
}
}
}
2022-07-28 13:28:43 +02:00
SAnimationPropertyConfig * CConfigManager : : getAnimationPropertyConfig ( const std : : string & name ) {
return & animationConfig [ name ] ;
}
2022-08-09 18:13:13 +02:00
void CConfigManager : : addParseError ( const std : : string & err ) {
if ( parseError = = " " )
parseError = err ;
2022-08-19 20:01:51 +02:00
}
2022-09-12 21:05:52 +02:00
CMonitor * CConfigManager : : getBoundMonitorForWS ( std : : string wsname ) {
for ( auto & [ ws , mon ] : boundWorkspaces ) {
const auto WSNAME = ws . find ( " name: " ) = = 0 ? ws . substr ( 5 ) : ws ;
if ( WSNAME = = wsname ) {
return g_pCompositor - > getMonitorFromString ( mon ) ;
}
}
return nullptr ;
}