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>
2023-10-23 00:11:03 +02: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 13:54:05 +02:00
# include <glob.h>
2022-03-17 15:53:45 +01:00
# include <algorithm>
# include <fstream>
# include <iostream>
2023-05-01 23:24:51 +02:00
# include <sstream>
2022-03-17 15:53:45 +01:00
2023-03-05 19:39:46 +01:00
extern " C " char * * environ ;
2022-03-17 15:53:45 +01:00
CConfigManager : : CConfigManager ( ) {
2023-10-10 18:42:45 +02:00
configValues [ " general:col.active_border " ] . data = std : : make_shared < CGradientValueData > ( 0xffffffff ) ;
configValues [ " general:col.inactive_border " ] . data = std : : make_shared < CGradientValueData > ( 0xff444444 ) ;
configValues [ " general:col.nogroup_border " ] . data = std : : make_shared < CGradientValueData > ( 0xffffaaff ) ;
configValues [ " general:col.nogroup_border_active " ] . data = std : : make_shared < CGradientValueData > ( 0xffff00ff ) ;
configValues [ " group:col.border_active " ] . data = std : : make_shared < CGradientValueData > ( 0x66ffff00 ) ;
configValues [ " group:col.border_inactive " ] . data = std : : make_shared < CGradientValueData > ( 0x66777700 ) ;
configValues [ " group:col.border_locked_active " ] . data = std : : make_shared < CGradientValueData > ( 0x66ff5500 ) ;
configValues [ " group:col.border_locked_inactive " ] . data = std : : make_shared < CGradientValueData > ( 0x66775500 ) ;
configValues [ " group:groupbar:col.active " ] . data = std : : make_shared < CGradientValueData > ( 0x66ffff00 ) ;
configValues [ " group:groupbar:col.inactive " ] . data = std : : make_shared < CGradientValueData > ( 0x66777700 ) ;
configValues [ " group:groupbar:col.locked_active " ] . data = std : : make_shared < CGradientValueData > ( 0x66ff5500 ) ;
configValues [ " group:groupbar:col.locked_inactive " ] . data = std : : make_shared < CGradientValueData > ( 0x66775500 ) ;
2022-11-26 18:56:43 +01:00
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
2023-07-07 19:19:35 +02:00
configPaths . emplace_back ( getMainConfigPath ( ) ) ;
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 ;
2023-03-05 15:54:26 +01:00
populateEnvironment ( ) ;
}
2023-07-07 19:19:35 +02:00
std : : string CConfigManager : : getConfigDir ( ) {
static const char * xdgConfigHome = getenv ( " XDG_CONFIG_HOME " ) ;
std : : string configPath ;
if ( ! xdgConfigHome )
configPath = getenv ( " HOME " ) + std : : string ( " /.config " ) ;
else
configPath = xdgConfigHome ;
return configPath ;
}
std : : string CConfigManager : : getMainConfigPath ( ) {
if ( ! g_pCompositor - > explicitConfigPath . empty ( ) )
return g_pCompositor - > explicitConfigPath ;
return getConfigDir ( ) + " /hypr/ " + ( ISDEBUG ? " hyprlandd.conf " : " hyprland.conf " ) ;
}
2023-03-05 15:54:26 +01:00
void CConfigManager : : populateEnvironment ( ) {
environmentVariables . clear ( ) ;
for ( char * * env = environ ; * env ; + + env ) {
2023-03-18 15:57:59 +01:00
const std : : string ENVVAR = * env ;
const auto VARIABLE = ENVVAR . substr ( 0 , ENVVAR . find_first_of ( ' = ' ) ) ;
const auto VALUE = ENVVAR . substr ( ENVVAR . find_first_of ( ' = ' ) + 1 ) ;
environmentVariables . emplace_back ( std : : make_pair < > ( VARIABLE , VALUE ) ) ;
2023-03-05 15:54:26 +01:00
}
2023-03-18 15:57:59 +01:00
std : : sort ( environmentVariables . begin ( ) , environmentVariables . end ( ) , [ & ] ( const auto & a , const auto & b ) { return a . first . length ( ) > b . first . length ( ) ; } ) ;
2022-04-18 13:27:54 +02:00
}
void CConfigManager : : setDefaultVars ( ) {
2023-02-27 00:14:19 +01:00
configValues [ " general:max_fps " ] . intValue = 60 ;
configValues [ " general:sensitivity " ] . floatValue = 1.0f ;
configValues [ " general:apply_sens_to_raw " ] . intValue = 0 ;
2022-12-16 18:17:31 +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-12-16 18:17:31 +01:00
configValues [ " general:gaps_in " ] . intValue = 5 ;
configValues [ " general:gaps_out " ] . intValue = 20 ;
2022-11-26 18:56:43 +01:00
( ( CGradientValueData * ) configValues [ " general:col.active_border " ] . data . get ( ) ) - > reset ( 0xffffffff ) ;
( ( CGradientValueData * ) configValues [ " general:col.inactive_border " ] . data . get ( ) ) - > reset ( 0xff444444 ) ;
2023-09-22 01:42:00 +02:00
( ( CGradientValueData * ) configValues [ " general:col.nogroup_border " ] . data . get ( ) ) - > reset ( 0xff444444 ) ;
( ( CGradientValueData * ) configValues [ " general:col.nogroup_border_active " ] . data . get ( ) ) - > reset ( 0xffff00ff ) ;
2022-06-24 23:27:02 +02:00
configValues [ " general:cursor_inactive_timeout " ] . intValue = 0 ;
2022-12-16 18:17:31 +01:00
configValues [ " general:no_cursor_warps " ] . intValue = 0 ;
2023-04-10 15:40:03 +02:00
configValues [ " general:no_focus_fallback " ] . intValue = 0 ;
2023-02-18 23:35:31 +01:00
configValues [ " general:resize_on_border " ] . intValue = 0 ;
configValues [ " general:extend_border_grab_area " ] . intValue = 15 ;
configValues [ " general:hover_icon_on_border " ] . intValue = 1 ;
2023-02-27 00:14:19 +01:00
configValues [ " general:layout " ] . strValue = " dwindle " ;
2023-09-28 22:48:33 +02:00
configValues [ " general:allow_tearing " ] . intValue = 0 ;
2022-09-25 20:07:48 +02:00
2023-10-02 17:27:32 +02:00
configValues [ " misc:disable_hyprland_logo " ] . intValue = 0 ;
configValues [ " misc:disable_splash_rendering " ] . intValue = 0 ;
configValues [ " misc:force_hypr_chan " ] . intValue = 0 ;
2023-10-07 15:08:38 +02:00
configValues [ " misc:force_default_wallpaper " ] . intValue = - 1 ;
2023-10-02 17:27:32 +02:00
configValues [ " misc:vfr " ] . intValue = 1 ;
configValues [ " misc:vrr " ] . intValue = 0 ;
configValues [ " misc:mouse_move_enables_dpms " ] . intValue = 0 ;
configValues [ " misc:key_press_enables_dpms " ] . intValue = 0 ;
configValues [ " misc:always_follow_on_dnd " ] . intValue = 1 ;
configValues [ " misc:layers_hog_keyboard_focus " ] . intValue = 1 ;
configValues [ " misc:animate_manual_resizes " ] . intValue = 0 ;
configValues [ " misc:animate_mouse_windowdragging " ] . intValue = 0 ;
configValues [ " misc:disable_autoreload " ] . intValue = 0 ;
configValues [ " misc:enable_swallow " ] . intValue = 0 ;
configValues [ " misc:swallow_regex " ] . strValue = STRVAL_EMPTY ;
configValues [ " misc:swallow_exception_regex " ] . strValue = STRVAL_EMPTY ;
configValues [ " misc:focus_on_activate " ] . intValue = 0 ;
configValues [ " misc:no_direct_scanout " ] . intValue = 1 ;
configValues [ " misc:hide_cursor_on_touch " ] . intValue = 1 ;
configValues [ " misc:mouse_move_focuses_monitor " ] . intValue = 1 ;
configValues [ " misc:render_ahead_of_time " ] . intValue = 0 ;
configValues [ " misc:render_ahead_safezone " ] . intValue = 1 ;
configValues [ " misc:cursor_zoom_factor " ] . floatValue = 1.f ;
configValues [ " misc:cursor_zoom_rigid " ] . intValue = 0 ;
configValues [ " misc:allow_session_lock_restore " ] . intValue = 0 ;
configValues [ " misc:close_special_on_empty " ] . intValue = 1 ;
configValues [ " misc:background_color " ] . intValue = 0xff111111 ;
configValues [ " misc:new_window_takes_over_fullscreen " ] . intValue = 0 ;
2022-12-16 18:17:31 +01:00
2023-10-10 18:42:45 +02:00
( ( CGradientValueData * ) configValues [ " group:col.border_active " ] . data . get ( ) ) - > reset ( 0x66ffff00 ) ;
( ( CGradientValueData * ) configValues [ " group:col.border_inactive " ] . data . get ( ) ) - > reset ( 0x66777700 ) ;
( ( CGradientValueData * ) configValues [ " group:col.border_locked_active " ] . data . get ( ) ) - > reset ( 0x66ff5500 ) ;
( ( CGradientValueData * ) configValues [ " group:col.border_locked_inactive " ] . data . get ( ) ) - > reset ( 0x66775500 ) ;
configValues [ " group:insert_after_current " ] . intValue = 1 ;
configValues [ " group:focus_removed_window " ] . intValue = 1 ;
configValues [ " group:groupbar:font_size " ] . intValue = 8 ;
configValues [ " group:groupbar:gradients " ] . intValue = 1 ;
configValues [ " group:groupbar:render_titles " ] . intValue = 1 ;
configValues [ " group:groupbar:scrolling " ] . intValue = 1 ;
configValues [ " group:groupbar:text_color " ] . intValue = 0xffffffff ;
( ( CGradientValueData * ) configValues [ " group:groupbar:col.active " ] . data . get ( ) ) - > reset ( 0x66ffff00 ) ;
( ( CGradientValueData * ) configValues [ " group:groupbar:col.inactive " ] . data . get ( ) ) - > reset ( 0x66777700 ) ;
( ( CGradientValueData * ) configValues [ " group:groupbar:col.locked_active " ] . data . get ( ) ) - > reset ( 0x66ff5500 ) ;
( ( CGradientValueData * ) configValues [ " group:groupbar:col.locked_inactive " ] . data . get ( ) ) - > reset ( 0x66775500 ) ;
2023-03-24 20:37:37 +01:00
configValues [ " debug:int " ] . intValue = 0 ;
configValues [ " debug:log_damage " ] . intValue = 0 ;
configValues [ " debug:overlay " ] . intValue = 0 ;
configValues [ " debug:damage_blink " ] . intValue = 0 ;
configValues [ " debug:disable_logs " ] . intValue = 0 ;
configValues [ " debug:disable_time " ] . intValue = 1 ;
configValues [ " debug:enable_stdout_logs " ] . intValue = 0 ;
configValues [ " debug:damage_tracking " ] . intValue = DAMAGE_TRACKING_FULL ;
2023-04-04 15:49:58 +02:00
configValues [ " debug:manual_crash " ] . intValue = 0 ;
2023-08-20 18:17:49 +02:00
configValues [ " debug:suppress_errors " ] . intValue = 0 ;
2023-09-29 17:38:13 +02:00
configValues [ " debug:watchdog_timeout " ] . intValue = 5 ;
2022-05-02 16:54:40 +02:00
2022-12-16 18:17:31 +01:00
configValues [ " decoration:rounding " ] . intValue = 0 ;
2023-08-03 15:11:10 +02:00
configValues [ " decoration:blur:enabled " ] . intValue = 1 ;
configValues [ " decoration:blur:size " ] . intValue = 8 ;
configValues [ " decoration:blur:passes " ] . intValue = 1 ;
configValues [ " decoration:blur:ignore_opacity " ] . intValue = 0 ;
configValues [ " decoration:blur:new_optimizations " ] . intValue = 1 ;
configValues [ " decoration:blur:xray " ] . intValue = 0 ;
configValues [ " decoration:blur:noise " ] . floatValue = 0.0117 ;
configValues [ " decoration:blur:contrast " ] . floatValue = 0.8916 ;
configValues [ " decoration:blur:brightness " ] . floatValue = 0.8172 ;
2023-09-07 00:35:44 +02:00
configValues [ " decoration:blur:special " ] . intValue = 0 ;
2022-12-16 18:17:31 +01:00
configValues [ " decoration:active_opacity " ] . floatValue = 1 ;
configValues [ " decoration:inactive_opacity " ] . floatValue = 1 ;
configValues [ " decoration:fullscreen_opacity " ] . floatValue = 1 ;
configValues [ " decoration:no_blur_on_oversized " ] . intValue = 0 ;
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 ;
configValues [ " decoration:shadow_offset " ] . vecValue = Vector2D ( ) ;
configValues [ " decoration:shadow_scale " ] . floatValue = 1.f ;
configValues [ " decoration:col.shadow " ] . intValue = 0xee1a1a1a ;
configValues [ " decoration:col.shadow_inactive " ] . intValue = INT_MAX ;
configValues [ " decoration:dim_inactive " ] . intValue = 0 ;
configValues [ " decoration:dim_strength " ] . floatValue = 0.5f ;
2022-12-28 15:18:23 +01:00
configValues [ " decoration:dim_special " ] . floatValue = 0.2f ;
2022-12-28 15:39:17 +01:00
configValues [ " decoration:dim_around " ] . floatValue = 0.4f ;
2022-12-16 18:17:31 +01:00
configValues [ " decoration:screen_shader " ] . strValue = STRVAL_EMPTY ;
2023-05-06 02:02:18 +02:00
configValues [ " dwindle:pseudotile " ] . intValue = 0 ;
configValues [ " dwindle:force_split " ] . intValue = 0 ;
configValues [ " dwindle:permanent_direction_override " ] . intValue = 0 ;
configValues [ " dwindle:preserve_split " ] . intValue = 0 ;
configValues [ " dwindle:special_scale_factor " ] . floatValue = 0.8f ;
configValues [ " dwindle:split_width_multiplier " ] . floatValue = 1.0f ;
configValues [ " dwindle:no_gaps_when_only " ] . intValue = 0 ;
configValues [ " dwindle:use_active_for_splits " ] . intValue = 1 ;
configValues [ " dwindle:default_split_ratio " ] . floatValue = 1.f ;
2023-07-11 13:37:25 +02:00
configValues [ " dwindle:smart_split " ] . intValue = 0 ;
2023-07-23 15:50:09 +02:00
configValues [ " dwindle:smart_resizing " ] . 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 ;
2023-03-05 17:29:23 +01:00
configValues [ " master:mfact " ] . floatValue = 0.55f ;
2022-12-16 18:17:31 +01:00
configValues [ " master:new_is_master " ] . intValue = 1 ;
2023-02-27 00:12:14 +01:00
configValues [ " master:always_center_master " ] . intValue = 0 ;
2022-12-16 18:17:31 +01:00
configValues [ " master:new_on_top " ] . intValue = 0 ;
configValues [ " master:no_gaps_when_only " ] . intValue = 0 ;
configValues [ " master:orientation " ] . strValue = " left " ;
configValues [ " master:inherit_fullscreen " ] . intValue = 1 ;
2023-04-13 16:20:58 +02:00
configValues [ " master:allow_small_split " ] . intValue = 0 ;
2023-09-10 23:58:06 +02:00
configValues [ " master:smart_resizing " ] . intValue = 1 ;
2023-10-03 23:16:57 +02:00
configValues [ " master:drop_at_cursor " ] . intValue = 1 ;
2022-12-16 18:17:31 +01:00
2023-02-27 00:14:19 +01:00
configValues [ " animations:enabled " ] . intValue = 1 ;
2022-12-16 18:17:31 +01:00
2023-02-27 00:14:19 +01:00
configValues [ " input:follow_mouse " ] . intValue = 1 ;
2023-04-25 17:00:34 +02:00
configValues [ " input:mouse_refocus " ] . intValue = 1 ;
2022-12-16 18:17:31 +01:00
configValues [ " input:sensitivity " ] . floatValue = 0.f ;
configValues [ " input:accel_profile " ] . strValue = STRVAL_EMPTY ;
configValues [ " input:kb_file " ] . strValue = STRVAL_EMPTY ;
configValues [ " input:kb_layout " ] . strValue = " us " ;
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 ;
configValues [ " input:repeat_rate " ] . intValue = 25 ;
configValues [ " input:repeat_delay " ] . intValue = 600 ;
configValues [ " input:natural_scroll " ] . intValue = 0 ;
configValues [ " input:numlock_by_default " ] . intValue = 0 ;
configValues [ " input:force_no_accel " ] . intValue = 0 ;
configValues [ " input:float_switch_override_focus " ] . intValue = 1 ;
configValues [ " input:left_handed " ] . intValue = 0 ;
configValues [ " input:scroll_method " ] . strValue = STRVAL_EMPTY ;
configValues [ " input:scroll_button " ] . intValue = 0 ;
2023-09-06 14:54:48 +02:00
configValues [ " input:scroll_button_lock " ] . intValue = 0 ;
2022-12-16 18:17:31 +01:00
configValues [ " input:touchpad:natural_scroll " ] . intValue = 0 ;
configValues [ " input:touchpad:disable_while_typing " ] . intValue = 1 ;
configValues [ " input:touchpad:clickfinger_behavior " ] . intValue = 0 ;
2023-02-05 15:17:23 +01:00
configValues [ " input:touchpad:tap_button_map " ] . strValue = STRVAL_EMPTY ;
2022-06-12 07:40:01 +02:00
configValues [ " input:touchpad:middle_button_emulation " ] . intValue = 0 ;
2022-12-16 18:17:31 +01:00
configValues [ " input:touchpad:tap-to-click " ] . intValue = 1 ;
2022-12-22 13:05:26 +01:00
configValues [ " input:touchpad:tap-and-drag " ] . intValue = 1 ;
2022-12-16 18:17:31 +01:00
configValues [ " input:touchpad:drag_lock " ] . intValue = 0 ;
configValues [ " input:touchpad:scroll_factor " ] . floatValue = 1.f ;
configValues [ " input:touchdevice:transform " ] . intValue = 0 ;
configValues [ " input:touchdevice:output " ] . strValue = STRVAL_EMPTY ;
2023-01-15 20:38:58 +01:00
configValues [ " input:tablet:transform " ] . intValue = 0 ;
configValues [ " input:tablet:output " ] . strValue = STRVAL_EMPTY ;
2023-09-27 20:49:30 +02:00
configValues [ " input:tablet:region_position " ] . vecValue = Vector2D ( ) ;
configValues [ " input:tablet:region_size " ] . vecValue = Vector2D ( ) ;
2022-12-16 18:17:31 +01:00
configValues [ " binds:pass_mouse_when_bound " ] . intValue = 0 ;
configValues [ " binds:scroll_event_delay " ] . intValue = 300 ;
2022-08-21 13:58:46 +02:00
configValues [ " binds:workspace_back_and_forth " ] . intValue = 0 ;
2022-12-16 18:17:31 +01:00
configValues [ " binds:allow_workspace_cycles " ] . intValue = 0 ;
2023-10-10 18:34:28 +02:00
configValues [ " binds:workspace_center_on " ] . intValue = 1 ;
2023-01-26 15:36:22 +01:00
configValues [ " binds:focus_preferred_method " ] . intValue = 0 ;
2023-09-11 00:29:10 +02:00
configValues [ " binds:ignore_group_lock " ] . intValue = 0 ;
2022-07-26 14:50:21 +02:00
2023-08-23 22:40:19 +02:00
configValues [ " gestures:workspace_swipe " ] . intValue = 0 ;
configValues [ " gestures:workspace_swipe_fingers " ] . intValue = 3 ;
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 ;
configValues [ " gestures:workspace_swipe_create_new " ] . intValue = 1 ;
configValues [ " gestures:workspace_swipe_direction_lock " ] . intValue = 1 ;
configValues [ " gestures:workspace_swipe_direction_lock_threshold " ] . intValue = 10 ;
configValues [ " gestures:workspace_swipe_forever " ] . intValue = 0 ;
configValues [ " gestures:workspace_swipe_numbered " ] . intValue = 0 ;
configValues [ " gestures:workspace_swipe_use_r " ] . intValue = 0 ;
2022-07-07 11:52:12 +02:00
2023-06-11 21:33:50 +02:00
configValues [ " xwayland:use_nearest_neighbor " ] . intValue = 1 ;
2023-06-11 21:52:13 +02:00
configValues [ " xwayland:force_zero_scaling " ] . intValue = 0 ;
2023-06-11 21:33:50 +02:00
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-12-16 18:17:31 +01:00
cfgValues [ " sensitivity " ] . floatValue = 0.f ;
cfgValues [ " accel_profile " ] . strValue = STRVAL_EMPTY ;
cfgValues [ " kb_file " ] . strValue = STRVAL_EMPTY ;
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 ;
2023-02-05 15:17:23 +01:00
cfgValues [ " tap_button_map " ] . strValue = STRVAL_EMPTY ;
2022-12-16 18:17:31 +01:00
cfgValues [ " numlock_by_default " ] . intValue = 0 ;
cfgValues [ " disable_while_typing " ] . intValue = 1 ;
cfgValues [ " clickfinger_behavior " ] . intValue = 0 ;
2022-06-30 21:26:00 +02:00
cfgValues [ " middle_button_emulation " ] . intValue = 0 ;
2022-12-16 18:17:31 +01:00
cfgValues [ " tap-to-click " ] . intValue = 1 ;
2022-12-22 13:05:26 +01:00
cfgValues [ " tap-and-drag " ] . intValue = 1 ;
2022-12-16 18:17:31 +01:00
cfgValues [ " drag_lock " ] . intValue = 0 ;
cfgValues [ " left_handed " ] . intValue = 0 ;
cfgValues [ " scroll_method " ] . strValue = STRVAL_EMPTY ;
cfgValues [ " scroll_button " ] . intValue = 0 ;
2023-09-06 14:54:48 +02:00
cfgValues [ " scroll_button_lock " ] . intValue = 0 ;
2022-12-21 16:11:39 +01:00
cfgValues [ " transform " ] . intValue = 0 ;
cfgValues [ " output " ] . strValue = STRVAL_EMPTY ;
2023-09-28 22:48:33 +02:00
cfgValues [ " enabled " ] . intValue = 1 ; // only for mice / touchpads
2023-09-27 20:49:30 +02:00
cfgValues [ " region_position " ] . vecValue = Vector2D ( ) ; // only for tablets
cfgValues [ " region_size " ] . vecValue = Vector2D ( ) ; // only for tablets
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 " ) ;
2023-02-01 22:06:01 +01:00
INITANIMCFG ( " borderangle " ) ;
2022-07-28 13:28:43 +02:00
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
2022-12-16 18:17:31 +01:00
animationConfig [ " global " ] = { false , " default " , " " , 8.f , 1 , & animationConfig [ " general " ] , nullptr } ;
2022-07-28 13:28:43 +02:00
CREATEANIMCFG ( " windows " , " global " ) ;
CREATEANIMCFG ( " fade " , " global " ) ;
CREATEANIMCFG ( " border " , " global " ) ;
2023-02-01 22:06:01 +01:00
CREATEANIMCFG ( " borderangle " , " global " ) ;
2022-07-28 13:28:43 +02:00
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 ( ) ;
2023-07-07 19:19:35 +02:00
const std : : string CONFIGPATH = getMainConfigPath ( ) ;
2022-03-19 17:00:52 +01:00
2022-12-18 00:05:15 +01:00
struct stat fileStat ;
int err = stat ( CONFIGPATH . c_str ( ) , & fileStat ) ;
2022-03-19 17:00:52 +01:00
if ( err ! = 0 ) {
2023-09-06 12:51:36 +02:00
Debug : : log ( WARN , " Error at statting config, error {} " , errno ) ;
2022-03-19 17:00:52 +01:00
}
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 ) {
2023-10-15 20:07:23 +02:00
if ( ! configValues . contains ( COMMAND ) ) {
if ( ! COMMAND . starts_with ( " device: " ) /* devices parsed later */ & & ! COMMAND . starts_with ( " plugin: " ) /* plugins parsed later */ ) {
2022-07-12 16:07:51 +02:00
if ( COMMAND [ 0 ] = = ' $ ' ) {
// register a dynamic var
2023-09-06 21:45:37 +02:00
Debug : : log ( LOG , " Registered dynamic var \" {} \" -> {} " , COMMAND , VALUE ) ;
2023-03-18 15:57:59 +01:00
configDynamicVars . emplace_back ( std : : make_pair < > ( COMMAND . substr ( 1 ) , VALUE ) ) ;
std : : sort ( configDynamicVars . begin ( ) , configDynamicVars . end ( ) , [ & ] ( const auto & a , const auto & b ) { return a . first . length ( ) > b . first . length ( ) ; } ) ;
2022-07-12 16:07:51 +02:00
} 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 ;
2023-10-15 20:07:23 +02:00
if ( COMMAND . starts_with ( " device: " ) ) {
2022-12-16 18:17:31 +01:00
const auto DEVICE = COMMAND . substr ( 7 ) . substr ( 0 , COMMAND . find_last_of ( ' : ' ) - 7 ) ;
2022-06-30 21:26:00 +02:00
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 ( ) ) {
2022-12-21 16:11:39 +01:00
if ( it - > second . contains ( " touch_output " ) | | it - > second . contains ( " touch_transform " ) ) {
parseError = " touch_output and touch_transform have been changed to output and transform respectively " ;
return ;
}
2022-06-30 21:26:00 +02:00
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >: No such field. " ;
return ;
}
CONFIGENTRY = & it - > second . at ( CONFIGVAR ) ;
2023-10-15 20:07:23 +02:00
} else if ( COMMAND . starts_with ( " plugin: " ) ) {
2023-02-27 13:32:38 +01:00
for ( auto & [ handle , pMap ] : pluginConfigs ) {
auto it = std : : find_if ( pMap - > begin ( ) , pMap - > end ( ) , [ & ] ( const auto & other ) { return other . first = = COMMAND ; } ) ;
if ( it = = pMap - > end ( ) ) {
2023-03-03 20:32:44 +01:00
continue ; // May be in another plugin
2023-02-27 13:32:38 +01:00
}
CONFIGENTRY = & it - > second ;
}
2023-07-10 14:13:23 +02:00
if ( ! CONFIGENTRY ) {
m_vFailedPluginConfigValues . emplace_back ( std : : make_pair < > ( COMMAND , VALUE ) ) ;
2023-02-27 13:32:38 +01:00
return ; // silent ignore
2023-07-10 14:13:23 +02:00
}
2022-06-30 21:26:00 +02:00
} 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 {
2022-11-13 20:33:13 +01:00
CONFIGENTRY - > intValue = configStringToInt ( VALUE ) ;
} catch ( std : : exception & e ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( WARN , " Error reading value of {} " , COMMAND ) ;
2022-11-13 20:33:13 +01:00
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >. " + e . what ( ) ;
2022-03-17 15:53:45 +01:00
}
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 ( . . . ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( WARN , " Error reading value of {} " , COMMAND ) ;
2022-03-17 15:53:45 +01:00
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 ( . . . ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( WARN , " Error reading value of {} " , COMMAND ) ;
2022-03-17 15:53:45 +01:00
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 {
2023-09-06 21:45:37 +02:00
Debug : : log ( WARN , " Error reading value of {} " , COMMAND ) ;
2022-09-30 18:03:06 +02:00
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >. " ;
}
} catch ( . . . ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( WARN , " Error reading value of {} " , COMMAND ) ;
2022-09-30 18:03:06 +02:00
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >. " ;
}
2022-11-26 18:56:43 +01:00
} else if ( CONFIGENTRY - > data . get ( ) ! = nullptr ) {
switch ( CONFIGENTRY - > data - > getDataType ( ) ) {
case CVD_TYPE_GRADIENT : {
2022-12-16 18:17:31 +01:00
2022-12-18 00:05:15 +01:00
CVarList varlist ( VALUE , 0 , ' ' ) ;
2022-11-26 18:56:43 +01:00
CGradientValueData * data = ( CGradientValueData * ) CONFIGENTRY - > data . get ( ) ;
data - > m_vColors . clear ( ) ;
for ( auto & var : varlist ) {
if ( var . find ( " deg " ) ! = std : : string : : npos ) {
// last arg
try {
data - > m_fAngle = std : : stoi ( var . substr ( 0 , var . find ( " deg " ) ) ) * ( PI / 180.0 ) ; // radians
} catch ( . . . ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( WARN , " Error reading value of {} " , COMMAND ) ;
2022-11-26 18:56:43 +01:00
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >. " ;
}
break ;
}
if ( data - > m_vColors . size ( ) > = 10 ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( WARN , " Error reading value of {} " , COMMAND ) ;
2022-11-26 18:56:43 +01:00
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >. Max colors in a gradient is 10. " ;
break ;
}
try {
2023-01-05 19:25:45 +01:00
data - > m_vColors . push_back ( CColor ( configStringToInt ( var ) ) ) ;
2022-11-26 18:56:43 +01:00
} catch ( std : : exception & e ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( WARN , " Error reading value of {} " , COMMAND ) ;
2022-11-26 18:56:43 +01:00
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >. " + e . what ( ) ;
}
}
if ( data - > m_vColors . size ( ) = = 0 ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( WARN , " Error reading value of {} " , COMMAND ) ;
2022-11-26 18:56:43 +01:00
parseError = " Error setting value < " + VALUE + " > for field < " + COMMAND + " >. No colors provided. " ;
data - > m_vColors . push_back ( 0 ) ; // transparent
}
break ;
}
default : {
2022-11-26 21:46:34 +01:00
UNREACHABLE ( ) ;
2022-11-26 18:56:43 +01:00
}
}
2022-03-17 15:53:45 +01:00
}
2022-12-01 14:36:07 +01:00
if ( COMMAND = = " decoration:screen_shader " ) {
const auto PATH = absolutePath ( VALUE , configCurrentPath ) ;
configPaths . push_back ( PATH ) ;
struct stat fileStat ;
2022-12-16 18:17:31 +01:00
int err = stat ( PATH . c_str ( ) , & fileStat ) ;
2022-12-01 14:36:07 +01:00
if ( err ! = 0 ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( WARN , " Error at ticking config at {}, error {}: {} " , PATH , err , strerror ( err ) ) ;
2022-12-01 14:36:07 +01:00
return ;
}
configModifyTimes [ PATH ] = fileStat . st_mtime ;
}
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-11-10 14:50:16 +01:00
g_pKeybindManager - > spawn ( args ) ;
2022-03-17 15:53:45 +01:00
}
2023-05-09 15:01:45 +02:00
static bool parseModeLine ( const std : : string & modeline , drmModeModeInfo & mode ) {
auto args = CVarList ( modeline , 0 , ' s ' ) ;
auto keyword = args [ 0 ] ;
std : : transform ( keyword . begin ( ) , keyword . end ( ) , keyword . begin ( ) , : : tolower ) ;
if ( keyword ! = " modeline " )
return false ;
if ( args . size ( ) < 10 ) {
2023-09-06 12:51:36 +02:00
Debug : : log ( ERR , " modeline parse error: expected at least 9 arguments, got {} " , args . size ( ) - 1 ) ;
2023-05-09 15:01:45 +02:00
return false ;
}
int argno = 1 ;
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 ;
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 } ,
} ;
for ( ; argno < static_cast < int > ( args . size ( ) ) ; argno + + ) {
auto key = args [ argno ] ;
std : : transform ( key . begin ( ) , key . end ( ) , key . begin ( ) , : : tolower ) ;
auto it = flagsmap . find ( key ) ;
if ( it ! = flagsmap . end ( ) )
mode . flags | = it - > second ;
else
2023-09-06 21:45:37 +02:00
Debug : : log ( ERR , " invalid flag {} in modeline " , it - > first ) ;
2023-05-09 15:01:45 +02:00
}
snprintf ( mode . name , sizeof ( mode . name ) , " %dx%d@%d " , mode . hdisplay , mode . vdisplay , mode . vrefresh / 1000 ) ;
return true ;
}
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-12-18 00:05:15 +01: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 " ) {
2023-01-29 17:04:47 +01:00
const auto TSF = std : : stoi ( ARGS [ 2 ] ) ;
if ( std : : clamp ( TSF , 0 , 7 ) ! = TSF ) {
2023-09-06 12:51:36 +02:00
Debug : : log ( ERR , " invalid transform {} in monitor " , TSF ) ;
2023-01-29 17:04:47 +01:00
parseError = " invalid transform " ;
return ;
}
2023-09-10 14:14:27 +02:00
const auto TRANSFORM = ( wl_output_transform ) TSF ;
2022-05-29 12:27:45 +02:00
// overwrite if exists
for ( auto & r : m_dMonitorRules ) {
if ( r . name = = newrule . name ) {
2023-09-10 14:14:27 +02:00
r . transform = TRANSFORM ;
2022-05-29 12:27:45 +02:00
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-12-16 18:17:31 +01:00
std : : erase_if ( m_dMonitorRules , [ & ] ( 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 ;
}
2023-10-15 20:07:23 +02:00
if ( ARGS [ 1 ] . starts_with ( " pref " ) ) {
2022-07-30 22:54:29 +02:00
newrule . resolution = Vector2D ( ) ;
2023-10-15 20:07:23 +02:00
} else if ( ARGS [ 1 ] . starts_with ( " highrr " ) ) {
2022-12-16 18:17:31 +01:00
newrule . resolution = Vector2D ( - 1 , - 1 ) ;
2023-10-15 20:07:23 +02:00
} else if ( ARGS [ 1 ] . starts_with ( " highres " ) ) {
2022-12-16 18:17:31 +01:00
newrule . resolution = Vector2D ( - 1 , - 2 ) ;
2023-05-09 15:01:45 +02:00
} else if ( parseModeLine ( ARGS [ 1 ] , newrule . drmMode ) ) {
newrule . resolution = Vector2D ( newrule . drmMode . hdisplay , newrule . drmMode . vdisplay ) ;
newrule . refreshRate = newrule . drmMode . vrefresh / 1000 ;
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
2023-10-15 20:07:23 +02:00
if ( ARGS [ 2 ] . starts_with ( " auto " ) ) {
2023-08-16 18:16:36 +02:00
newrule . offset = Vector2D ( - INT32_MAX , - INT32_MAX ) ;
2022-08-04 11:10:26 +02:00
} 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-08-03 21:06:51 +02:00
}
2023-10-15 20:07:23 +02:00
if ( ARGS [ 3 ] . starts_with ( " auto " ) ) {
2022-12-14 18:57:18 +01:00
newrule . scale = - 1 ;
} else {
newrule . scale = stof ( ARGS [ 3 ] ) ;
2022-03-17 16:56:33 +01:00
2022-12-14 18:57:18 +01:00
if ( newrule . scale < 0.25f ) {
2022-12-16 18:17:31 +01:00
parseError = " not a valid scale. " ;
2022-12-14 18:57:18 +01:00
newrule . scale = 1 ;
}
2022-08-03 21:06:51 +02:00
}
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 + + ;
2023-03-18 17:12:43 +01:00
} else if ( ARGS [ argno ] = = " transform " ) {
newrule . transform = ( wl_output_transform ) std : : stoi ( ARGS [ argno + 1 ] ) ;
argno + + ;
2023-08-11 17:37:52 +02:00
} else if ( ARGS [ argno ] = = " vrr " ) {
newrule . vrr = std : : stoi ( ARGS [ argno + 1 ] ) ;
argno + + ;
2023-03-18 17:12:43 +01:00
} else if ( ARGS [ argno ] = = " workspace " ) {
2023-05-01 23:28:27 +02:00
std : : string name = " " ;
int wsId = getWorkspaceIDFromString ( ARGS [ argno + 1 ] , name ) ;
SWorkspaceRule wsRule ;
wsRule . monitor = newrule . name ;
wsRule . workspaceString = ARGS [ argno + 1 ] ;
wsRule . workspaceName = name ;
wsRule . workspaceId = wsId ;
2023-05-05 16:33:31 +02:00
m_dWorkspaceRules . emplace_back ( wsRule ) ;
2023-03-18 17:12:43 +01:00
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-12-16 18:17:31 +01:00
std : : erase_if ( m_dMonitorRules , [ & ] ( 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-12-18 00:05:15 +01: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-12-16 18:17:31 +01:00
void CConfigManager : : setAnimForChildren ( SAnimationPropertyConfig * const ANIM ) {
2022-07-28 13:28:43 +02:00
for ( auto & [ name , anim ] : animationConfig ) {
2023-03-30 00:44:25 +02:00
if ( anim . pParentAnimation = = ANIM & & ! anim . overridden ) {
// if a child isnt overridden, set the values of the parent
2022-07-28 13:28:43 +02:00
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 ;
}
2023-03-30 00:44:25 +02:00
PANIM - > second . overridden = true ;
2023-04-01 20:37:25 +02:00
PANIM - > second . pValues = & PANIM - > second ;
2022-07-28 13:28:43 +02:00
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 " ;
}
2023-09-06 12:58:01 +02:00
if ( PANIM - > second . internalEnabled ) {
// speed
if ( isNumber ( ARGS [ 2 ] , true ) ) {
PANIM - > second . internalSpeed = std : : stof ( ARGS [ 2 ] ) ;
if ( PANIM - > second . internalSpeed < = 0 ) {
parseError = " invalid speed " ;
PANIM - > second . internalSpeed = 1.f ;
}
} else {
PANIM - > second . internalSpeed = 10.f ;
2022-12-16 18:17:31 +01:00
parseError = " invalid speed " ;
2022-08-07 19:28:46 +02:00
}
2022-05-14 15:56:01 +02:00
2023-09-06 12:58:01 +02:00
// curve
PANIM - > second . internalBezier = ARGS [ 3 ] ;
2022-05-14 16:43:30 +02:00
2023-09-06 12:58:01 +02:00
if ( ! g_pAnimationManager - > bezierExists ( ARGS [ 3 ] ) ) {
parseError = " no such bezier " ;
PANIM - > second . internalBezier = " default " ;
}
2022-08-07 19:28:46 +02:00
2023-09-06 12:58:01 +02:00
// style
PANIM - > second . internalStyle = ARGS [ 4 ] ;
2022-07-28 13:28:43 +02:00
2023-09-06 12:58:01 +02:00
if ( ARGS [ 4 ] ! = " " ) {
const auto ERR = g_pAnimationManager - > styleValidInConfigVar ( ANIMNAME , ARGS [ 4 ] ) ;
2022-08-07 19:28:46 +02:00
2023-09-06 12:58:01 +02:00
if ( ERR ! = " " )
parseError = ERR ;
}
2022-08-07 19:28:46 +02:00
}
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
2023-06-14 13:08:56 +02:00
bool locked = false ;
bool release = false ;
bool repeat = false ;
bool mouse = false ;
bool nonConsuming = false ;
2023-08-25 12:35:24 +02:00
bool transparent = false ;
2023-10-17 21:09:54 +02:00
bool ignoreMods = false ;
2023-06-14 13:08:56 +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 ;
2023-06-14 13:08:56 +02:00
} else if ( arg = = ' n ' ) {
nonConsuming = true ;
2023-08-25 12:35:24 +02:00
} else if ( arg = = ' t ' ) {
transparent = true ;
2023-10-17 21:09:54 +02:00
} else if ( arg = = ' i ' ) {
ignoreMods = 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-12-16 18:17:31 +01:00
const auto MOD = g_pKeybindManager - > stringToModMask ( ARGS [ 0 ] ) ;
2022-10-03 15:29:45 +02:00
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-12-18 00:05:15 +01:00
auto HANDLER = ARGS [ 2 ] ;
2022-10-03 15:29:45 +02:00
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-07-08 09:27:17 +02:00
if ( KEY ! = " " ) {
if ( isNumber ( KEY ) & & std : : stoi ( KEY ) > 9 )
2023-10-17 21:09:54 +02:00
g_pKeybindManager - > addKeybind (
SKeybind { " " , std : : stoi ( KEY ) , MOD , HANDLER , COMMAND , locked , m_szCurrentSubmap , release , repeat , mouse , nonConsuming , transparent , ignoreMods } ) ;
2023-10-15 20:07:23 +02:00
else if ( KEY . starts_with ( " code: " ) & & isNumber ( KEY . substr ( 5 ) ) )
2023-08-25 12:35:24 +02:00
g_pKeybindManager - > addKeybind (
2023-10-17 21:09:54 +02:00
SKeybind { " " , std : : stoi ( KEY . substr ( 5 ) ) , MOD , HANDLER , COMMAND , locked , m_szCurrentSubmap , release , repeat , mouse , nonConsuming , transparent , ignoreMods } ) ;
2022-07-08 09:27:17 +02:00
else
2023-10-17 21:09:54 +02:00
g_pKeybindManager - > addKeybind ( SKeybind { KEY , - 1 , MOD , HANDLER , COMMAND , locked , m_szCurrentSubmap , release , repeat , mouse , nonConsuming , transparent , ignoreMods } ) ;
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 ) {
2023-10-15 20:07:23 +02:00
return RULE = = " float " | | RULE = = " tile " | | RULE . starts_with ( " opacity " ) | | RULE . starts_with ( " move " ) | | RULE . starts_with ( " size " ) | | RULE . starts_with ( " minsize " ) | |
RULE . starts_with ( " maxsize " ) | | RULE . starts_with ( " pseudo " ) | | RULE . starts_with ( " monitor " ) | | RULE . starts_with ( " idleinhibit " ) | | RULE = = " nofocus " | | RULE = = " noblur " | |
RULE = = " noshadow " | | RULE = = " nodim " | | RULE = = " noborder " | | RULE = = " opaque " | | RULE = = " forceinput " | | RULE = = " fullscreen " | | RULE = = " nofullscreenrequest " | |
RULE = = " nomaximizerequest " | | RULE = = " fakefullscreen " | | RULE = = " nomaxsize " | | RULE = = " pin " | | RULE = = " noanim " | | RULE = = " dimaround " | | RULE = = " windowdance " | |
RULE = = " maximize " | | RULE = = " keepaspectratio " | | RULE . starts_with ( " animation " ) | | RULE . starts_with ( " rounding " ) | | RULE . starts_with ( " workspace " ) | |
RULE . starts_with ( " bordercolor " ) | | RULE = = " forcergbx " | | RULE = = " noinitialfocus " | | RULE = = " stayfocused " | | RULE . starts_with ( " bordersize " ) | | RULE . starts_with ( " xray " ) | |
2023-10-24 22:28:55 +02:00
RULE . starts_with ( " center " ) | | RULE . starts_with ( " group " ) | | RULE = = " immediate " | | RULE = = " nearestneighbor " ;
2022-09-06 11:57:11 +02:00
}
2023-01-25 16:34:13 +01:00
bool layerRuleValid ( const std : : string & RULE ) {
2023-10-15 20:07:23 +02:00
return RULE = = " noanim " | | RULE = = " blur " | | RULE . starts_with ( " ignorealpha " ) | | RULE . starts_with ( " ignorezero " ) | | RULE . starts_with ( " xray " ) ;
2023-01-25 16:34:13 +01:00
}
2022-09-06 11:57:11 +02:00
void CConfigManager : : handleWindowRule ( const std : : string & command , const std : : string & value ) {
2022-12-16 18:17:31 +01: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 ;
}
2022-11-03 20:52:43 +01:00
if ( RULE = = " unset " ) {
2022-12-16 18:17:31 +01:00
std : : erase_if ( m_dWindowRules , [ & ] ( const SWindowRule & other ) { return other . szValue = = VALUE ; } ) ;
2022-11-03 20:52:43 +01:00
return ;
}
2022-09-06 11:57:11 +02:00
// verify we support a rule
if ( ! windowRuleValid ( RULE ) ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( ERR , " Invalid rule found: {} " , RULE ) ;
2022-09-06 11:57:11 +02:00
parseError = " Invalid rule found: " + RULE ;
return ;
}
2022-03-24 18:22:01 +01:00
2023-10-15 20:07:23 +02:00
if ( RULE . starts_with ( " size " ) | | RULE . starts_with ( " maxsize " ) | | RULE . starts_with ( " minsize " ) )
2023-08-11 16:54:16 +02:00
m_dWindowRules . push_front ( { RULE , VALUE } ) ;
else
m_dWindowRules . push_back ( { RULE , VALUE } ) ;
2022-09-06 11:57:11 +02:00
}
2023-01-25 16:34:13 +01:00
void CConfigManager : : handleLayerRule ( const std : : string & command , const std : : string & value ) {
const auto RULE = removeBeginEndSpacesTabs ( value . substr ( 0 , value . find_first_of ( ' , ' ) ) ) ;
const auto VALUE = removeBeginEndSpacesTabs ( value . substr ( value . find_first_of ( ' , ' ) + 1 ) ) ;
// check rule and value
2023-03-18 00:16:13 +01:00
if ( RULE = = " " | | VALUE = = " " )
2023-01-25 16:34:13 +01:00
return ;
if ( RULE = = " unset " ) {
std : : erase_if ( m_dLayerRules , [ & ] ( const SLayerRule & other ) { return other . targetNamespace = = VALUE ; } ) ;
return ;
}
if ( ! layerRuleValid ( RULE ) ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( ERR , " Invalid rule found: {} " , RULE ) ;
2023-01-25 16:34:13 +01:00
parseError = " Invalid rule found: " + RULE ;
return ;
}
m_dLayerRules . push_back ( { VALUE , RULE } ) ;
2023-03-18 00:16:13 +01:00
for ( auto & m : g_pCompositor - > m_vMonitors )
for ( auto & lsl : m - > m_aLayerSurfaceLayers )
for ( auto & ls : lsl )
ls - > applyRules ( ) ;
2023-01-25 16:34:13 +01:00
}
2022-09-06 11:57:11 +02:00
void CConfigManager : : handleWindowRuleV2 ( const std : : string & command , const std : : string & value ) {
2023-09-24 14:35:36 +02:00
const auto RULE = removeBeginEndSpacesTabs ( value . substr ( 0 , value . find_first_of ( ' , ' ) ) ) ;
2022-12-16 18:17:31 +01:00
const auto VALUE = value . substr ( value . find_first_of ( ' , ' ) + 1 ) ;
2022-09-06 11:57:11 +02:00
2022-11-03 20:52:43 +01:00
if ( ! windowRuleValid ( RULE ) & & RULE ! = " unset " ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( ERR , " Invalid rulev2 found: {} " , RULE ) ;
2022-09-06 11:57:11 +02:00
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 ;
2022-12-16 18:17:31 +01:00
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
2022-12-16 18:17:31 +01:00
const auto TITLEPOS = VALUE . find ( " title: " ) ;
const auto CLASSPOS = VALUE . find ( " class: " ) ;
const auto X11POS = VALUE . find ( " xwayland: " ) ;
const auto FLOATPOS = VALUE . find ( " floating: " ) ;
2022-11-15 11:21:26 +01:00
const auto FULLSCREENPOS = VALUE . find ( " fullscreen: " ) ;
2022-12-16 18:17:31 +01:00
const auto PINNEDPOS = VALUE . find ( " pinned: " ) ;
2023-08-02 13:21:38 +02:00
const auto WORKSPACEPOS = VALUE . find ( " workspace: " ) ;
2022-09-06 11:57:11 +02:00
2022-12-16 18:17:31 +01:00
if ( TITLEPOS = = std : : string : : npos & & CLASSPOS = = std : : string : : npos & & X11POS = = std : : string : : npos & & FLOATPOS = = std : : string : : npos & & FULLSCREENPOS = = std : : string : : npos & &
2023-08-02 13:21:38 +02:00
PINNEDPOS = = std : : string : : npos & & WORKSPACEPOS = = std : : string : : npos ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( ERR , " Invalid rulev2 syntax: {} " , VALUE ) ;
2022-09-06 11:57:11 +02:00
parseError = " Invalid rulev2 syntax: " + VALUE ;
return ;
}
auto extract = [ & ] ( size_t pos ) - > std : : string {
std : : string result ;
result = VALUE . substr ( pos ) ;
size_t min = 999999 ;
2022-12-16 18:17:31 +01:00
if ( TITLEPOS > pos & & TITLEPOS < min )
min = TITLEPOS ;
if ( CLASSPOS > pos & & CLASSPOS < min )
min = CLASSPOS ;
if ( X11POS > pos & & X11POS < min )
min = X11POS ;
if ( FLOATPOS > pos & & FLOATPOS < min )
min = FLOATPOS ;
if ( FULLSCREENPOS > pos & & FULLSCREENPOS < min )
min = FULLSCREENPOS ;
if ( PINNEDPOS > pos & & PINNEDPOS < min )
min = PINNEDPOS ;
2023-08-02 13:21:38 +02:00
if ( WORKSPACEPOS > pos & & WORKSPACEPOS < min )
min = PINNEDPOS ;
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 ;
} ;
2023-08-02 13:21:38 +02:00
if ( CLASSPOS ! = std : : string : : npos )
2022-09-06 11:57:11 +02:00
rule . szClass = extract ( CLASSPOS + 6 ) ;
2023-08-02 13:21:38 +02:00
if ( TITLEPOS ! = std : : string : : npos )
2022-09-06 11:57:11 +02:00
rule . szTitle = extract ( TITLEPOS + 6 ) ;
2023-08-02 13:21:38 +02:00
if ( X11POS ! = std : : string : : npos )
2022-09-07 11:24:40 +02:00
rule . bX11 = extract ( X11POS + 9 ) = = " 1 " ? 1 : 0 ;
2023-08-02 13:21:38 +02:00
if ( FLOATPOS ! = std : : string : : npos )
2022-09-07 11:24:40 +02:00
rule . bFloating = extract ( FLOATPOS + 9 ) = = " 1 " ? 1 : 0 ;
2023-08-02 13:21:38 +02:00
if ( FULLSCREENPOS ! = std : : string : : npos )
2022-11-15 11:21:26 +01:00
rule . bFullscreen = extract ( FULLSCREENPOS + 11 ) = = " 1 " ? 1 : 0 ;
2023-08-02 13:21:38 +02:00
if ( PINNEDPOS ! = std : : string : : npos )
2022-11-15 11:21:26 +01:00
rule . bPinned = extract ( PINNEDPOS + 7 ) = = " 1 " ? 1 : 0 ;
2023-08-02 13:21:38 +02:00
if ( WORKSPACEPOS ! = std : : string : : npos )
rule . szWorkspace = extract ( WORKSPACEPOS + 10 ) ;
2022-11-15 11:21:26 +01:00
2022-11-03 20:52:43 +01:00
if ( RULE = = " unset " ) {
std : : erase_if ( m_dWindowRules , [ & ] ( const SWindowRule & other ) {
if ( ! other . v2 ) {
return other . szClass = = rule . szClass & & ! rule . szClass . empty ( ) ;
} else {
2023-08-02 13:21:38 +02:00
if ( ! rule . szClass . empty ( ) & & rule . szClass ! = other . szClass )
2022-11-03 20:52:43 +01:00
return false ;
2023-08-02 13:21:38 +02:00
if ( ! rule . szTitle . empty ( ) & & rule . szTitle ! = other . szTitle )
2022-11-03 20:52:43 +01:00
return false ;
2023-08-02 13:21:38 +02:00
if ( rule . bX11 ! = - 1 & & rule . bX11 ! = other . bX11 )
2022-11-03 20:52:43 +01:00
return false ;
2023-08-02 13:21:38 +02:00
if ( rule . bFloating ! = - 1 & & rule . bFloating ! = other . bFloating )
2022-11-03 20:52:43 +01:00
return false ;
2023-08-02 13:21:38 +02:00
if ( rule . bFullscreen ! = - 1 & & rule . bFullscreen ! = other . bFullscreen )
2022-11-15 11:21:26 +01:00
return false ;
2023-08-02 13:21:38 +02:00
if ( rule . bPinned ! = - 1 & & rule . bPinned ! = other . bPinned )
return false ;
if ( ! rule . szWorkspace . empty ( ) & & rule . szWorkspace ! = other . szWorkspace )
2022-11-15 11:21:26 +01:00
return false ;
2022-11-03 20:52:43 +01:00
return true ;
}
} ) ;
return ;
}
2023-10-15 20:07:23 +02:00
if ( RULE . starts_with ( " size " ) | | RULE . starts_with ( " maxsize " ) | | RULE . starts_with ( " minsize " ) )
2023-08-11 16:54:16 +02:00
m_dWindowRules . push_front ( rule ) ;
else
m_dWindowRules . push_back ( rule ) ;
2022-03-24 18:22:01 +01:00
}
2023-02-05 23:46:20 +01:00
void CConfigManager : : updateBlurredLS ( const std : : string & name , const bool forceBlur ) {
2023-10-15 20:07:23 +02:00
const bool BYADDRESS = name . starts_with ( " address: " ) ;
2023-02-25 18:39:26 +01:00
std : : string matchName = name ;
if ( BYADDRESS ) {
2023-03-09 15:24:06 +01:00
matchName = matchName . substr ( 8 ) ;
2023-02-25 18:39:26 +01:00
}
2023-02-05 23:46:20 +01:00
for ( auto & m : g_pCompositor - > m_vMonitors ) {
for ( auto & lsl : m - > m_aLayerSurfaceLayers ) {
for ( auto & ls : lsl ) {
2023-02-25 18:39:26 +01:00
if ( BYADDRESS ) {
2023-09-20 09:26:20 +02:00
if ( std : : format ( " 0x{:x} " , ( uintptr_t ) ls . get ( ) ) = = matchName )
2023-02-25 18:39:26 +01:00
ls - > forceBlur = forceBlur ;
} else if ( ls - > szNamespace = = matchName )
2023-02-05 23:46:20 +01:00
ls - > forceBlur = forceBlur ;
}
}
}
}
2022-07-06 22:12:03 +02:00
void CConfigManager : : handleBlurLS ( const std : : string & command , const std : : string & value ) {
2023-10-15 20:07:23 +02:00
if ( value . starts_with ( " remove, " ) ) {
2022-10-03 15:29:45 +02:00
const auto TOREMOVE = removeBeginEndSpacesTabs ( value . substr ( 7 ) ) ;
2023-02-05 23:46:20 +01:00
if ( std : : erase_if ( m_dBlurLSNamespaces , [ & ] ( const auto & other ) { return other = = TOREMOVE ; } ) )
updateBlurredLS ( TOREMOVE , false ) ;
2022-07-15 13:29:56 +02:00
return ;
}
2022-07-06 22:12:03 +02:00
m_dBlurLSNamespaces . emplace_back ( value ) ;
2023-02-05 23:46:20 +01:00
updateBlurredLS ( value , true ) ;
2022-07-06 22:12:03 +02:00
}
2023-05-01 23:28:27 +02:00
void CConfigManager : : handleWorkspaceRules ( const std : : string & command , const std : : string & value ) {
// This can either be the monitor or the workspace identifier
const auto FIRST_DELIM = value . find_first_of ( ' , ' ) ;
std : : string name = " " ;
auto first_ident = removeBeginEndSpacesTabs ( value . substr ( 0 , FIRST_DELIM ) ) ;
int id = getWorkspaceIDFromString ( first_ident , name ) ;
auto rules = value . substr ( FIRST_DELIM + 1 ) ;
SWorkspaceRule wsRule ;
wsRule . workspaceString = first_ident ;
if ( id = = INT_MAX ) {
// 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 = = INT_MAX ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( ERR , " Invalid workspace identifier found: {} " , wsIdent ) ;
2023-05-01 23:28:27 +02:00
parseError = " Invalid workspace identifier found: " + wsIdent ;
return ;
}
wsRule . monitor = first_ident ;
wsRule . workspaceString = wsIdent ;
2023-05-05 16:33:31 +02:00
wsRule . isDefault = true ; // backwards compat
2023-05-01 23:28:27 +02:00
rules = value . substr ( WORKSPACE_DELIM + 1 ) ;
}
2023-10-23 00:11:03 +02:00
const static std : : string ruleOnCreatedEmtpy = " on-created-empty: " ;
const static int ruleOnCreatedEmtpyLen = ruleOnCreatedEmtpy . length ( ) ;
auto assignRule = [ & ] ( std : : string rule ) {
2023-05-01 23:28:27 +02:00
size_t delim = std : : string : : npos ;
if ( ( delim = rule . find ( " gapsin: " ) ) ! = std : : string : : npos )
wsRule . gapsIn = std : : stoi ( rule . substr ( delim + 7 ) ) ;
else if ( ( delim = rule . find ( " gapsout: " ) ) ! = std : : string : : npos )
wsRule . gapsOut = std : : stoi ( rule . substr ( delim + 8 ) ) ;
else if ( ( delim = rule . find ( " bordersize: " ) ) ! = std : : string : : npos )
wsRule . borderSize = std : : stoi ( rule . substr ( delim + 11 ) ) ;
else if ( ( delim = rule . find ( " border: " ) ) ! = std : : string : : npos )
wsRule . border = configStringToInt ( rule . substr ( delim + 7 ) ) ;
2023-08-12 23:37:55 +02:00
else if ( ( delim = rule . find ( " shadow: " ) ) ! = std : : string : : npos )
2023-08-16 18:16:36 +02:00
wsRule . shadow = configStringToInt ( rule . substr ( delim + 7 ) ) ;
2023-05-01 23:28:27 +02:00
else if ( ( delim = rule . find ( " rounding: " ) ) ! = std : : string : : npos )
wsRule . rounding = configStringToInt ( rule . substr ( delim + 9 ) ) ;
else if ( ( delim = rule . find ( " decorate: " ) ) ! = std : : string : : npos )
wsRule . decorate = configStringToInt ( rule . substr ( delim + 9 ) ) ;
else if ( ( delim = rule . find ( " monitor: " ) ) ! = std : : string : : npos )
wsRule . monitor = rule . substr ( delim + 8 ) ;
2023-05-05 16:33:31 +02:00
else if ( ( delim = rule . find ( " default: " ) ) ! = std : : string : : npos )
2023-05-06 02:08:59 +02:00
wsRule . isDefault = configStringToInt ( rule . substr ( delim + 8 ) ) ;
2023-10-09 21:28:22 +02:00
else if ( ( delim = rule . find ( " persistent: " ) ) ! = std : : string : : npos )
wsRule . isPersistent = configStringToInt ( rule . substr ( delim + 11 ) ) ;
2023-10-23 00:11:03 +02:00
else if ( ( delim = rule . find ( ruleOnCreatedEmtpy ) ) ! = std : : string : : npos )
wsRule . onCreatedEmptyRunCmd = cleanCmdForWorkspace ( name , rule . substr ( delim + ruleOnCreatedEmtpyLen ) ) ;
2023-05-01 23:28:27 +02:00
} ;
size_t pos = 0 ;
std : : string rule ;
while ( ( pos = rules . find ( ' , ' ) ) ! = std : : string : : npos ) {
rule = rules . substr ( 0 , pos ) ;
assignRule ( rule ) ;
rules . erase ( 0 , pos + 1 ) ;
}
assignRule ( rules ) ; // match remaining rule
2022-03-20 16:01:47 +01:00
2023-05-05 16:33:31 +02:00
wsRule . workspaceId = id ;
wsRule . workspaceName = name ;
2023-05-12 02:15:32 +02:00
const auto IT = std : : find_if ( m_dWorkspaceRules . begin ( ) , m_dWorkspaceRules . end ( ) , [ & ] ( const auto & other ) { return other . workspaceString = = wsRule . workspaceString ; } ) ;
if ( IT = = m_dWorkspaceRules . end ( ) )
m_dWorkspaceRules . emplace_back ( wsRule ) ;
else
* IT = wsRule ;
2022-03-20 16:01:47 +01:00
}
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 ;
}
2023-09-12 13:54:05 +02:00
std : : unique_ptr < glob_t , void ( * ) ( glob_t * ) > glob_buf { new glob_t , [ ] ( glob_t * g ) { globfree ( g ) ; } } ;
memset ( glob_buf . get ( ) , 0 , sizeof ( glob_t ) ) ;
2022-07-06 15:05:23 +02:00
2023-09-14 13:07:31 +02:00
if ( auto r = glob ( absolutePath ( rawpath , configCurrentPath ) . c_str ( ) , GLOB_TILDE , nullptr , glob_buf . get ( ) ) ; r ! = 0 ) {
parseError = std : : format ( " source= globbing error: {} " , r = = GLOB_NOMATCH ? " found no match " : GLOB_ABORTED ? " read error " : " out of memory " ) ;
2023-09-20 09:26:20 +02:00
Debug : : log ( ERR , " {} " , parseError ) ;
2022-05-16 10:09:20 +02:00
return ;
}
2023-09-12 13:54:05 +02:00
for ( size_t i = 0 ; i < glob_buf - > gl_pathc ; i + + ) {
auto value = absolutePath ( glob_buf - > gl_pathv [ i ] , configCurrentPath ) ;
2022-05-16 10:09:20 +02:00
2023-09-12 13:54:05 +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 ) ;
2022-05-16 10:09:20 +02:00
2023-09-12 13:54:05 +02:00
struct stat fileStat ;
int err = stat ( value . c_str ( ) , & fileStat ) ;
if ( err ! = 0 ) {
Debug : : log ( WARN , " Error at ticking config at {}, error {}: {} " , value , err , strerror ( err ) ) ;
return ;
}
configModifyTimes [ value ] = fileStat . st_mtime ;
std : : ifstream ifs ;
ifs . open ( value ) ;
2022-05-16 10:09:20 +02:00
2023-09-12 13:54:05 +02:00
std : : string line = " " ;
int linenum = 1 ;
if ( ifs . is_open ( ) ) {
2023-09-25 00:11:34 +02:00
auto configCurrentPathBackup = configCurrentPath ;
2023-09-28 22:48:33 +02:00
2023-09-12 13:54:05 +02:00
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 , " {} " , line . c_str ( ) ) ;
parseError + = " Config error at line " + std : : to_string ( linenum ) + " ( " + configCurrentPath + " ): Line parsing error. " ;
}
2023-10-15 20:07:23 +02:00
if ( parseError ! = " " & & ! parseError . starts_with ( " Config error at line " ) ) {
2023-09-12 13:54:05 +02:00
parseError = " Config error at line " + std : : to_string ( linenum ) + " ( " + configCurrentPath + " ): " + parseError ;
}
+ + linenum ;
2022-05-16 10:09:20 +02:00
}
2023-09-12 13:54:05 +02:00
ifs . close ( ) ;
2023-09-28 22:48:33 +02:00
2023-09-25 00:11:34 +02:00
configCurrentPath = configCurrentPathBackup ;
2022-05-16 10:09:20 +02:00
}
}
}
2022-09-12 21:05:52 +02:00
void CConfigManager : : handleBindWS ( const std : : string & command , const std : : string & value ) {
2023-05-05 16:41:25 +02:00
parseError = " bindws has been deprecated in favor of workspace rules, see the wiki -> workspace rules " ;
2022-09-12 21:05:52 +02:00
}
2023-03-05 14:12:01 +01:00
void CConfigManager : : handleEnv ( const std : : string & command , const std : : string & value ) {
if ( ! isFirstLaunch )
return ;
const auto ARGS = CVarList ( value , 2 ) ;
if ( ARGS [ 0 ] . empty ( ) ) {
parseError = " env empty " ;
return ;
}
setenv ( ARGS [ 0 ] . c_str ( ) , ARGS [ 1 ] . c_str ( ) , 1 ) ;
2023-03-05 14:15:12 +01:00
if ( command . back ( ) = = ' d ' ) {
// dbus
2023-04-15 21:03:09 +02:00
const auto CMD =
# ifdef USES_SYSTEMD
" systemctl --user import-environment " + ARGS [ 0 ] +
2023-03-05 14:15:12 +01:00
" && hash dbus-update-activation-environment 2>/dev/null && "
2023-04-15 21:03:09 +02:00
# endif
2023-03-05 14:15:12 +01:00
" dbus-update-activation-environment --systemd " +
ARGS [ 0 ] ;
2023-09-06 21:45:37 +02:00
handleRawExec ( " " , CMD ) ;
2023-03-05 14:15:12 +01:00
}
2023-03-05 14:12:01 +01:00
}
2023-05-01 16:10:53 +02:00
void CConfigManager : : handlePlugin ( const std : : string & command , const std : : string & path ) {
if ( std : : find ( m_vDeclaredPlugins . begin ( ) , m_vDeclaredPlugins . end ( ) , path ) ! = m_vDeclaredPlugins . end ( ) ) {
parseError = " plugin ' " + path + " ' declared twice " ;
return ;
}
m_vDeclaredPlugins . push_back ( path ) ;
}
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-12-16 18:17:31 +01:00
parseError = " " ;
2022-05-25 17:42:38 +02:00
currentCategory = " " ;
}
2022-04-21 16:56:27 +02:00
2022-11-28 20:05:50 +01:00
int needsLayoutRecalc = COMMAND = = " monitor " ; // 0 - no, 1 - yes, 2 - maybe
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-12-16 18:17:31 +01:00
} else if ( COMMAND = = " monitor " )
handleMonitor ( COMMAND , VALUE ) ;
2023-10-15 20:07:23 +02:00
else if ( COMMAND . starts_with ( " bind " ) )
2022-12-16 18:17:31 +01:00
handleBind ( COMMAND , VALUE ) ;
else if ( COMMAND = = " unbind " )
handleUnbind ( COMMAND , VALUE ) ;
else if ( COMMAND = = " workspace " )
2023-05-01 23:28:27 +02:00
handleWorkspaceRules ( COMMAND , VALUE ) ;
2022-12-16 18:17:31 +01:00
else if ( COMMAND = = " windowrule " )
handleWindowRule ( COMMAND , VALUE ) ;
else if ( COMMAND = = " windowrulev2 " )
handleWindowRuleV2 ( COMMAND , VALUE ) ;
2023-01-25 16:34:13 +01:00
else if ( COMMAND = = " layerrule " )
handleLayerRule ( COMMAND , VALUE ) ;
2022-12-16 18:17:31 +01:00
else if ( COMMAND = = " bezier " )
handleBezier ( COMMAND , VALUE ) ;
else if ( COMMAND = = " animation " )
handleAnimation ( COMMAND , VALUE ) ;
else if ( COMMAND = = " source " )
handleSource ( COMMAND , VALUE ) ;
else if ( COMMAND = = " submap " )
handleSubmap ( COMMAND , VALUE ) ;
else if ( COMMAND = = " blurls " )
handleBlurLS ( COMMAND , VALUE ) ;
else if ( COMMAND = = " wsbind " )
handleBindWS ( COMMAND , VALUE ) ;
2023-10-15 20:07:23 +02:00
else if ( COMMAND . starts_with ( " env " ) )
2023-03-05 14:12:01 +01:00
handleEnv ( COMMAND , VALUE ) ;
2023-10-15 20:07:23 +02:00
else if ( COMMAND . starts_with ( " plugin " ) )
2023-05-01 16:10:53 +02:00
handlePlugin ( COMMAND , VALUE ) ;
2022-11-28 20:05:50 +01:00
else {
2022-05-14 15:56:01 +02:00
configSetValueSafe ( currentCategory + ( currentCategory = = " " ? " " : " : " ) + COMMAND , VALUE ) ;
2022-11-28 20:05:50 +01:00
needsLayoutRecalc = 2 ;
}
2022-04-21 16:56:27 +02:00
if ( dynamic ) {
std : : string retval = parseError ;
2022-12-16 18:17:31 +01:00
parseError = " " ;
2022-05-25 17:42:38 +02:00
2022-11-28 20:05:50 +01:00
// invalidate layouts if they changed
if ( needsLayoutRecalc ) {
2023-10-15 20:07:23 +02:00
if ( needsLayoutRecalc = = 1 | | COMMAND . contains ( " gaps_ " ) | | COMMAND . starts_with ( " dwindle: " ) | | COMMAND . starts_with ( " master: " ) ) {
2022-11-28 20:05:50 +01: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
2023-04-04 23:13:31 +02:00
// manual crash
if ( configValues [ " debug:manual_crash " ] . intValue & & ! m_bManualCrashInitiated ) {
m_bManualCrashInitiated = true ;
2023-04-07 21:15:11 +02:00
if ( g_pHyprNotificationOverlay ) {
g_pHyprNotificationOverlay - > addNotification ( " Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor. " , CColor ( 0 ) , 5000 ,
ICON_INFO ) ;
}
2023-04-04 23:13:31 +02:00
} else if ( m_bManualCrashInitiated & & ! configValues [ " debug:manual_crash " ] . intValue ) {
// cowabunga it is
g_pHyprRenderer - > initiateManualCrash ( ) ;
}
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 ) ;
2023-03-05 15:54:26 +01:00
bool found = false ;
2022-12-16 18:17:31 +01:00
for ( auto & [ var , value ] : configDynamicVars ) {
2023-10-15 20:07:23 +02:00
if ( STRAFTERDOLLAR . starts_with ( var ) ) {
2022-05-16 09:38:42 +02:00
line . replace ( dollarPlace , var . length ( ) + 1 , value ) ;
2023-03-05 15:54:26 +01:00
found = true ;
2022-05-16 09:38:42 +02:00
break ;
}
}
2023-03-05 15:54:26 +01:00
if ( ! found ) {
// maybe env?
for ( auto & [ var , value ] : environmentVariables ) {
2023-10-15 20:07:23 +02:00
if ( STRAFTERDOLLAR . starts_with ( var ) ) {
2023-03-05 15:54:26 +01:00
line . replace ( dollarPlace , var . length ( ) + 1 , value ) ;
break ;
}
}
}
2022-05-16 09:38:42 +02:00
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 ;
2022-11-06 15:28:15 +01:00
while ( ( startPos = line . find ( " ## " , startPos ) ) ! = std : : string : : npos & & startPos < line . length ( ) - 1 & & startPos > 0 ) {
2022-10-25 15:32:25 +02:00
line . replace ( startPos , 2 , " # " ) ;
startPos + + ;
}
2022-03-17 15:53:45 +01:00
2023-02-04 16:21:57 +01:00
line = removeBeginEndSpacesTabs ( line ) ;
2022-03-17 15:53:45 +01:00
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 ) ;
2022-12-16 18:17:31 +01:00
} else {
2022-04-19 18:42:26 +02:00
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 ) ) ;
2022-12-16 18:17:31 +01:00
const auto VALUE = removeBeginEndSpacesTabs ( line . substr ( EQUALSPLACE + 1 ) ) ;
2022-04-18 13:25:27 +02:00
//
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! " ) ;
2022-12-16 18:17:31 +01:00
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 ( ) ;
2023-05-05 16:33:31 +02:00
m_dWorkspaceRules . clear ( ) ;
2022-07-28 13:28:43 +02:00
setDefaultAnimationVars ( ) ; // reset anims
2023-05-01 16:10:53 +02:00
m_vDeclaredPlugins . clear ( ) ;
2023-05-04 19:28:45 +02:00
m_dLayerRules . clear ( ) ;
2023-07-10 14:13:23 +02:00
m_vFailedPluginConfigValues . clear ( ) ;
2022-03-17 16:56:33 +01:00
2022-05-16 10:09:20 +02:00
// paths
configPaths . clear ( ) ;
2023-07-07 19:19:35 +02:00
std : : string mainConfigPath = getMainConfigPath ( ) ;
2023-09-06 21:45:37 +02:00
Debug : : log ( LOG , " Using config: {} " , mainConfigPath ) ;
2023-07-07 19:19:35 +02:00
configPaths . push_back ( mainConfigPath ) ;
std : : string configPath = mainConfigPath . substr ( 0 , mainConfigPath . find_last_of ( ' / ' ) ) ;
// find_last_of never returns npos since main_config at least has /hypr/
if ( ! std : : filesystem : : is_directory ( configPath ) ) {
Debug : : log ( WARN , " Creating config home directory " ) ;
try {
std : : filesystem : : create_directories ( configPath ) ;
} catch ( . . . ) {
parseError = " Broken config file! (Could not create config directory) " ;
return ;
}
2022-07-14 22:55:24 +02:00
}
2022-05-16 10:09:20 +02:00
2023-07-07 19:19:35 +02:00
if ( ! std : : filesystem : : exists ( mainConfigPath ) ) {
Debug : : log ( WARN , " No config file found; attempting to generate. " ) ;
std : : ofstream ofs ;
ofs . open ( mainConfigPath , std : : ios : : trunc ) ;
ofs < < AUTOCONFIG ;
ofs . close ( ) ;
}
2022-09-25 20:07:48 +02:00
2022-03-17 15:53:45 +01:00
std : : ifstream ifs ;
2023-07-07 19:19:35 +02:00
ifs . open ( mainConfigPath ) ;
2022-03-17 15:53:45 +01:00
if ( ! ifs . good ( ) ) {
2023-07-07 19:19:35 +02:00
Debug : : log ( WARN , " Config reading error. Attempting to generate, backing up old one if exists " ) ;
2022-03-17 15:53:45 +01:00
2023-07-07 19:19:35 +02:00
ifs . close ( ) ;
2022-06-15 08:29:51 +02:00
2023-07-07 19:19:35 +02:00
if ( std : : filesystem : : exists ( mainConfigPath ) )
std : : filesystem : : rename ( mainConfigPath , mainConfigPath + " .backup " ) ;
2022-04-08 22:07:40 +02:00
2023-07-07 19:19:35 +02:00
// Create default config
std : : ofstream ofs ;
ofs . open ( mainConfigPath , std : : ios : : trunc ) ;
2022-04-08 22:07:40 +02:00
ofs < < AUTOCONFIG ;
ofs . close ( ) ;
2023-07-07 19:19:35 +02:00
// Try to re-open
ifs . open ( mainConfigPath ) ;
2022-04-08 22:07:40 +02:00
if ( ! ifs . good ( ) ) {
parseError = " Broken config file! (Could not open) " ;
return ;
}
2022-03-17 15:53:45 +01:00
}
2022-12-16 18:17:31 +01:00
std : : string line = " " ;
int linenum = 1 ;
2022-03-17 15:53:45 +01:00
if ( ifs . is_open ( ) ) {
while ( std : : getline ( ifs , line ) ) {
// Read line by line.
try {
2023-07-10 13:10:30 +02:00
configCurrentPath = mainConfigPath ;
2022-03-17 15:53:45 +01:00
parseLine ( line ) ;
} catch ( . . . ) {
Debug : : log ( ERR , " Error reading line from config. Line: " ) ;
2023-09-06 21:45:37 +02:00
Debug : : log ( NONE , " {} " , line ) ;
2022-03-17 15:53:45 +01:00
2023-07-07 19:19:35 +02:00
parseError + = " Config error at line " + std : : to_string ( linenum ) + " ( " + mainConfigPath + " ): Line parsing error. " ;
2022-03-17 15:53:45 +01:00
}
2023-10-15 20:07:23 +02:00
if ( parseError ! = " " & & ! parseError . starts_with ( " Config error at line " ) ) {
2023-07-07 19:19:35 +02:00
parseError = " Config error at line " + std : : to_string ( linenum ) + " ( " + mainConfigPath + " ): " + 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-12-21 16:11:39 +01:00
g_pInputManager - > setTabletConfigs ( ) ;
2022-07-19 19:26:53 +02:00
}
2022-03-24 21:05:34 +01:00
2022-12-01 14:36:07 +01:00
if ( ! isFirstLaunch )
g_pHyprOpenGL - > m_bReloadScreenShader = true ;
2022-04-08 21:40:41 +02:00
// parseError will be displayed next frame
2023-08-20 18:17:49 +02:00
if ( parseError ! = " " & & ! configValues [ " debug:suppress_errors " ] . intValue )
2023-01-05 19:25:45 +01:00
g_pHyprError - > queueCreate ( parseError + " \n Hyprland may not work correctly. " , CColor ( 1.0 , 50.0 / 255.0 , 50.0 / 255.0 , 1.0 ) ) ;
2022-04-08 22:07:40 +02:00
else if ( configValues [ " autogenerated " ] . intValue = = 1 )
2023-07-07 19:19:35 +02:00
g_pHyprError - > queueCreate ( " Warning: You're using an autogenerated config! (config file: " + mainConfigPath + " ) \n SUPER+Q -> kitty \n SUPER+M -> exit Hyprland " ,
2023-01-05 19:25:45 +01:00
CColor ( 1.0 , 1.0 , 70.0 / 255.0 , 1.0 ) ) ;
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-07-27 12:32:00 +02:00
// check
2022-12-02 19:45:45 +01:00
performMonitorReload ( ) ;
2023-04-03 23:52:09 +02:00
ensureMonitorStatus ( ) ;
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
2023-08-17 10:13:19 +02:00
// Updates dynamic window and workspace rules
2023-06-26 13:03:51 +02:00
for ( auto & w : g_pCompositor - > m_vWindows ) {
if ( ! w - > m_bIsMapped )
continue ;
2023-07-01 16:30:36 +02:00
2023-06-26 13:03:51 +02:00
w - > updateDynamicRules ( ) ;
2023-08-17 10:13:19 +02:00
w - > updateSpecialRenderData ( ) ;
2023-06-26 13:03:51 +02:00
}
2023-07-01 16:30:36 +02:00
2023-06-28 11:40:16 +02:00
// Update window border colors
g_pCompositor - > updateAllWindowsAnimatedDecorationValues ( ) ;
2023-07-01 16:30:36 +02:00
2022-07-16 15:57:31 +02:00
// update layout
g_pLayoutManager - > switchToLayout ( configValues [ " general:layout " ] . strValue ) ;
2023-04-04 15:49:58 +02:00
// manual crash
if ( configValues [ " debug:manual_crash " ] . intValue & & ! m_bManualCrashInitiated ) {
m_bManualCrashInitiated = true ;
g_pHyprNotificationOverlay - > addNotification ( " Manual crash has been set up. Set debug:manual_crash back to 0 in order to crash the compositor. " , CColor ( 0 ) , 5000 , ICON_INFO ) ;
} else if ( m_bManualCrashInitiated & & ! configValues [ " debug:manual_crash " ] . intValue ) {
// cowabunga it is
g_pHyprRenderer - > initiateManualCrash ( ) ;
}
2023-03-24 20:37:37 +01:00
Debug : : disableStdout = ! configValues [ " debug:enable_stdout_logs " ] . intValue ;
2023-05-03 17:08:01 +02:00
if ( Debug : : disableStdout & & isFirstLaunch )
Debug : : log ( LOG , " Disabling stdout logs! Check the log for further logs. " ) ;
2023-03-24 20:37:37 +01:00
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 ( ) ) ;
2023-08-01 15:47:56 +02:00
g_pCompositor - > scheduleFrameForMonitor ( 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 ;
2023-05-01 16:10:53 +02:00
// update plugins
handlePluginLoads ( ) ;
2023-07-10 13:54:06 +02:00
EMIT_HOOK_EVENT ( " configReloaded " , nullptr ) ;
2022-03-17 15:53:45 +01:00
}
void CConfigManager : : tick ( ) {
2023-07-07 19:19:35 +02:00
std : : string CONFIGPATH = getMainConfigPath ( ) ;
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 ;
2022-12-16 18:17:31 +01:00
int err = stat ( cf . c_str ( ) , & fileStat ) ;
2022-05-16 10:09:20 +02:00
if ( err ! = 0 ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( WARN , " Error at ticking config at {}, error {}: {} " , cf , err , strerror ( err ) ) ;
2023-04-12 23:00:39 +02:00
continue ;
2022-05-16 10:09:20 +02:00
}
// check if we need to reload cfg
if ( fileStat . st_mtime ! = configModifyTimes [ cf ] | | m_bForceReload ) {
2022-12-16 18:17:31 +01:00
parse = true ;
2022-05-16 10:09:20 +02:00
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 ( ) ;
}
}
2022-12-16 18:17:31 +01:00
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 ) ;
2022-12-18 00:05:15 +01:00
SConfigValue copy = configValues [ val ] ;
2022-03-17 15:53:45 +01:00
return copy ;
}
2023-09-06 16:14:18 +02:00
SConfigValue CConfigManager : : getConfigValueSafeDevice ( const std : : string & dev , const std : : string & val , const std : : string & fallback ) {
2022-06-30 21:26:00 +02:00
std : : lock_guard < std : : mutex > lg ( configmtx ) ;
2022-12-18 00:05:15 +01:00
const auto it = deviceConfigs . find ( dev ) ;
2022-06-30 21:26:00 +02:00
if ( it = = deviceConfigs . end ( ) ) {
2023-09-06 19:16:46 +02:00
if ( fallback . empty ( ) ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( ERR , " getConfigValueSafeDevice: No device config for {} found??? " , dev ) ;
2023-09-06 19:16:46 +02:00
return SConfigValue ( ) ;
}
return configValues [ fallback ] ;
2022-06-30 21:26:00 +02:00
}
2023-09-06 16:14:18 +02:00
const SConfigValue DEVICECONFIG = it - > second [ val ] ;
2022-06-30 21:26:00 +02:00
2023-09-06 16:14:18 +02:00
if ( ! DEVICECONFIG . set & & ! fallback . empty ( ) ) {
return configValues [ fallback ] ;
2022-06-30 21:38:06 +02:00
}
2023-09-06 16:14:18 +02:00
return DEVICECONFIG ;
2022-06-30 21:26:00 +02:00
}
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 ;
}
2023-09-27 20:49:30 +02:00
Vector2D CConfigManager : : getVec ( const std : : string & v ) {
return getConfigValueSafe ( v ) . vecValue ;
}
2022-06-30 21:26:00 +02:00
std : : string CConfigManager : : getString ( const std : : string & v ) {
2022-12-16 18:17:31 +01:00
auto VAL = getConfigValueSafe ( v ) . strValue ;
2022-05-06 14:30:35 +02:00
if ( VAL = = STRVAL_EMPTY )
return " " ;
return VAL ;
2022-03-17 15:53:45 +01:00
}
2022-03-17 16:56:33 +01:00
2023-09-06 16:14:18 +02:00
int CConfigManager : : getDeviceInt ( const std : : string & dev , const std : : string & v , const std : : string & fallback ) {
return getConfigValueSafeDevice ( dev , v , fallback ) . intValue ;
2022-06-30 21:26:00 +02:00
}
2023-09-06 16:14:18 +02:00
float CConfigManager : : getDeviceFloat ( const std : : string & dev , const std : : string & v , const std : : string & fallback ) {
return getConfigValueSafeDevice ( dev , v , fallback ) . floatValue ;
2022-06-30 21:26:00 +02:00
}
2023-09-27 20:49:30 +02:00
Vector2D CConfigManager : : getDeviceVec ( const std : : string & dev , const std : : string & v , const std : : string & fallback ) {
return getConfigValueSafeDevice ( dev , v , fallback ) . vecValue ;
}
2023-09-06 16:14:18 +02:00
std : : string CConfigManager : : getDeviceString ( const std : : string & dev , const std : : string & v , const std : : string & fallback ) {
auto VAL = getConfigValueSafeDevice ( dev , v , fallback ) . strValue ;
2022-06-30 21:26:00 +02:00
if ( VAL = = STRVAL_EMPTY )
return " " ;
return VAL ;
}
2022-12-16 18:17:31 +01:00
void CConfigManager : : setInt ( const std : : string & v , int val ) {
2022-04-10 18:25:45 +02:00
configValues [ v ] . intValue = val ;
}
2022-12-16 18:17:31 +01:00
void CConfigManager : : setFloat ( const std : : string & v , float val ) {
2022-04-10 18:25:45 +02:00
configValues [ v ] . floatValue = val ;
}
2023-09-27 20:49:30 +02:00
void CConfigManager : : setVec ( const std : : string & v , Vector2D val ) {
configValues [ v ] . vecValue = val ;
}
2022-12-16 18:17:31 +01:00
void CConfigManager : : setString ( const std : : string & v , const std : : string & val ) {
2022-04-10 18:25:45 +02:00
configValues [ v ] . strValue = val ;
}
2022-12-16 18:17:31 +01:00
SMonitorRule CConfigManager : : getMonitorRuleFor ( const std : : string & name , const std : : string & displayName ) {
2022-03-17 16:56:33 +01:00
SMonitorRule * found = nullptr ;
for ( auto & r : m_dMonitorRules ) {
2022-12-16 18:17:31 +01:00
if ( r . name = = name | |
2023-10-15 20:07:23 +02:00
( r . name . starts_with ( " desc: " ) & &
2022-12-16 18:17:31 +01:00
( 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 ;
2023-09-06 21:45:37 +02:00
Debug : : log ( WARN , " No rule found for {}, trying to use the first. " , name ) ;
2022-03-19 17:00:52 +01:00
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. " ) ;
2023-08-16 18:16:36 +02:00
return SMonitorRule { . name = " " , . resolution = Vector2D ( 0 , 0 ) , . offset = Vector2D ( - INT32_MAX , - INT32_MAX ) , . scale = - 1 } ; // 0, 0 is preferred and -1, -1 is auto
2022-03-24 18:22:01 +01:00
}
2023-05-01 23:28:27 +02:00
SWorkspaceRule CConfigManager : : getWorkspaceRuleFor ( CWorkspace * pWorkspace ) {
2023-10-05 02:31:13 +02:00
const auto WORKSPACEIDSTR = std : : to_string ( pWorkspace - > m_iID ) ;
const auto IT = std : : find_if ( m_dWorkspaceRules . begin ( ) , m_dWorkspaceRules . end ( ) , [ & ] ( const auto & other ) {
2023-10-19 17:04:48 +02:00
return other . workspaceName = = pWorkspace - > m_szName /* name matches */
| | ( pWorkspace - > m_bIsSpecialWorkspace & & other . workspaceName . starts_with ( " special: " ) & &
other . workspaceName . substr ( 8 ) = = pWorkspace - > m_szName ) /* special and special:name */
| | ( pWorkspace - > m_iID > 0 & & WORKSPACEIDSTR = = other . workspaceName ) ; /* id matches and workspace is numerical */
2023-10-05 02:31:13 +02:00
} ) ;
2023-05-05 16:33:31 +02:00
if ( IT = = m_dWorkspaceRules . end ( ) )
2023-05-01 23:28:27 +02:00
return SWorkspaceRule { } ;
2023-05-05 16:33:31 +02:00
return * IT ;
2023-05-01 23:28:27 +02:00
}
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 ;
2022-12-18 00:05:15 +01:00
std : : string title = g_pXWaylandManager - > getTitle ( pWindow ) ;
std : : string appidclass = g_pXWaylandManager - > getAppIDClass ( pWindow ) ;
2022-03-24 18:22:01 +01:00
2023-09-06 21:45:37 +02:00
Debug : : log ( LOG , " Searching for matching rules for {} (title: {}) " , appidclass , title ) ;
2022-06-24 16:25:57 +02:00
2023-07-02 13:02:48 +02:00
// since some rules will be applied later, we need to store some flags
bool hasFloating = pWindow - > m_bIsFloating ;
bool hasFullscreen = pWindow - > m_bIsFullscreen ;
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 {
2023-10-15 20:07:23 +02:00
if ( rule . szValue . starts_with ( " title: " ) ) {
2022-09-06 11:57:11 +02:00
// 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 ( . . . ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( ERR , " Regex error at {} " , rule . szValue ) ;
2022-09-06 11:57:11 +02:00
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 ) {
2023-07-02 13:02:48 +02:00
if ( hasFloating ! = rule . bFloating )
2022-09-07 11:24:40 +02:00
continue ;
}
2022-11-15 11:21:26 +01:00
if ( rule . bFullscreen ! = - 1 ) {
2023-07-02 13:02:48 +02:00
if ( hasFullscreen ! = rule . bFullscreen )
2022-11-15 11:21:26 +01:00
continue ;
}
if ( rule . bPinned ! = - 1 ) {
if ( pWindow - > m_bPinned ! = rule . bPinned )
continue ;
}
2023-08-02 13:21:38 +02:00
if ( ! rule . szWorkspace . empty ( ) ) {
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( pWindow - > m_iWorkspaceID ) ;
if ( ! PWORKSPACE )
continue ;
2023-10-15 20:07:23 +02:00
if ( rule . szWorkspace . starts_with ( " name: " ) ) {
2023-08-02 13:21:38 +02:00
if ( PWORKSPACE - > m_szName ! = rule . szWorkspace . substr ( 5 ) )
continue ;
} else {
// number
if ( ! isNumber ( rule . szWorkspace ) )
throw std : : runtime_error ( " szWorkspace not name: or number " ) ;
const int64_t ID = std : : stoll ( rule . szWorkspace ) ;
if ( PWORKSPACE - > m_iID ! = ID )
continue ;
}
}
} catch ( std : : exception & e ) {
2023-09-06 21:45:37 +02:00
Debug : : log ( ERR , " Regex error at {} ({}) " , rule . szValue , e . what ( ) ) ;
2022-09-06 11:57:11 +02:00
continue ;
2022-06-24 16:25:57 +02:00
}
2022-03-24 18:22:01 +01:00
}
// applies. Read the rule and behave accordingly
2023-09-20 17:25:03 +02:00
Debug : : log ( LOG , " Window rule {} -> {} matched {} " , rule . szRule , rule . szValue , pWindow ) ;
2022-03-24 18:22:01 +01:00
returns . push_back ( rule ) ;
2023-07-02 13:02:48 +02:00
if ( rule . szRule = = " float " )
hasFloating = true ;
else if ( rule . szRule = = " fullscreen " )
hasFullscreen = true ;
2022-03-24 18:22:01 +01:00
}
2023-04-18 12:48:56 +02:00
std : : vector < uint64_t > PIDs = { ( uint64_t ) pWindow - > getPID ( ) } ;
while ( getPPIDof ( PIDs . back ( ) ) > 10 )
PIDs . push_back ( getPPIDof ( PIDs . back ( ) ) ) ;
bool anyExecFound = false ;
2022-11-10 14:39:23 +01:00
for ( auto & er : execRequestedRules ) {
2023-04-18 12:48:56 +02:00
if ( std : : ranges : : any_of ( PIDs , [ & ] ( const auto & pid ) { return pid = = er . iPid ; } ) ) {
2022-11-10 14:39:23 +01:00
returns . push_back ( { er . szRule , " execRule " } ) ;
anyExecFound = true ;
}
}
if ( anyExecFound ) // remove exec rules to unclog searches in the future, why have the garbage here.
2023-04-18 12:48:56 +02:00
execRequestedRules . erase ( std : : remove_if ( execRequestedRules . begin ( ) , execRequestedRules . end ( ) ,
[ & ] ( const SExecRequestedRule & other ) { return std : : ranges : : any_of ( PIDs , [ & ] ( const auto & pid ) { return pid = = other . iPid ; } ) ; } ) ) ;
2022-11-10 14:39:23 +01:00
2022-03-24 18:22:01 +01:00
return returns ;
2022-04-12 20:02:57 +02:00
}
2023-01-25 16:34:13 +01:00
std : : vector < SLayerRule > CConfigManager : : getMatchingRules ( SLayerSurface * pLS ) {
std : : vector < SLayerRule > returns ;
2023-03-18 16:02:00 +01:00
if ( ! pLS - > layerSurface | | pLS - > fadingOut )
return returns ;
2023-01-25 16:34:13 +01:00
for ( auto & lr : m_dLayerRules ) {
2023-10-15 20:07:23 +02:00
if ( lr . targetNamespace . starts_with ( " address:0x " ) ) {
2023-09-20 09:26:20 +02:00
if ( std : : format ( " address:0x{:x} " , ( uintptr_t ) pLS ) ! = lr . targetNamespace )
2023-03-18 00:33:03 +01:00
continue ;
} else {
std : : regex NSCHECK ( lr . targetNamespace ) ;
2023-01-25 16:34:13 +01:00
2023-03-18 00:33:03 +01:00
if ( ! pLS - > layerSurface - > _namespace | | ! std : : regex_search ( pLS - > layerSurface - > _namespace , NSCHECK ) )
continue ;
}
2023-01-25 16:34:13 +01:00
// hit
returns . push_back ( lr ) ;
}
2023-03-18 00:36:36 +01:00
if ( pLS - > layerSurface - > _namespace & & shouldBlurLS ( pLS - > layerSurface - > _namespace ) )
returns . push_back ( { pLS - > layerSurface - > _namespace , " blur " } ) ;
2023-01-25 16:34:13 +01:00
return returns ;
}
2022-04-12 20:02:57 +02:00
void CConfigManager : : dispatchExecOnce ( ) {
if ( firstExecDispatched | | isFirstLaunch )
return ;
2023-03-05 13:52:57 +01:00
// update dbus env
2023-03-24 04:21:38 +01:00
if ( g_pCompositor - > m_sWLRSession )
handleRawExec (
" " ,
2023-04-15 21:03:09 +02:00
# ifdef USES_SYSTEMD
2023-03-24 04:21:38 +01:00
" systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP && hash dbus-update-activation-environment 2>/dev/null && "
2023-04-15 21:03:09 +02:00
# endif
2023-03-24 04:21:38 +01:00
" dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE " ) ;
2023-03-05 13:52:57 +01:00
2022-04-12 20:02:57 +02:00
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-12-21 16:11:39 +01:00
g_pInputManager - > setTabletConfigs ( ) ;
2022-07-22 12:37:44 +02:00
2023-03-20 16:02:47 +01:00
// check for user's possible errors with their setup and notify them if needed
g_pCompositor - > performUserChecks ( ) ;
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 ) {
2023-03-15 16:11:41 +01:00
if ( ! m - > output )
continue ;
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
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
2022-11-19 14:01:32 +01:00
// ensure mirror
m - > setMirror ( rule . mirrorOf ) ;
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 ;
2023-07-18 15:30:28 +02:00
EMIT_HOOK_EVENT ( " monitorLayoutChanged " , nullptr ) ;
2022-04-21 22:15:42 +02:00
}
2022-04-23 14:16:02 +02:00
2022-12-16 18:17:31 +01:00
SConfigValue * CConfigManager : : getConfigValuePtr ( const std : : string & val ) {
2022-04-23 14:16:02 +02:00
return & configValues [ val ] ;
2022-05-16 23:52:48 +02:00
}
2022-06-30 21:26:00 +02:00
2022-12-16 18:17:31 +01:00
SConfigValue * CConfigManager : : getConfigValuePtrSafe ( const std : : string & val ) {
2023-09-09 13:25:17 +02:00
if ( val . starts_with ( " device: " ) ) {
const auto DEVICE = val . substr ( 7 , val . find_last_of ( ' : ' ) - 7 ) ;
const auto CONFIGVAR = val . substr ( val . find_last_of ( ' : ' ) + 1 ) ;
const auto DEVICECONF = deviceConfigs . find ( DEVICE ) ;
if ( DEVICECONF = = deviceConfigs . end ( ) )
return nullptr ;
const auto IT = DEVICECONF - > second . find ( CONFIGVAR ) ;
if ( IT = = DEVICECONF - > second . end ( ) )
return nullptr ;
2022-08-11 21:16:38 +02:00
2023-09-09 13:25:17 +02:00
return & IT - > second ;
} else if ( val . starts_with ( " plugin: " ) ) {
2023-02-27 13:32:38 +01:00
for ( auto & [ pl , pMap ] : pluginConfigs ) {
2023-09-09 13:25:17 +02:00
const auto IT = pMap - > find ( val ) ;
2023-02-27 13:32:38 +01:00
2023-09-09 13:25:17 +02:00
if ( IT ! = pMap - > end ( ) )
return & IT - > second ;
2023-02-27 13:32:38 +01:00
}
2022-08-11 21:16:38 +02:00
return nullptr ;
2023-02-27 13:32:38 +01:00
}
2022-08-11 21:16:38 +02:00
2023-09-09 13:25:17 +02:00
const auto IT = configValues . find ( val ) ;
if ( IT = = configValues . end ( ) )
return nullptr ;
2022-08-11 21:16:38 +02:00
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 ( ) , ' ' , ' - ' ) ;
2023-10-15 20:07:23 +02:00
return deviceConfigs . contains ( copy ) ;
2022-06-30 21:26:00 +02:00
}
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
2023-04-03 23:52:09 +02:00
void CConfigManager : : ensureMonitorStatus ( ) {
2022-07-27 12:32:00 +02:00
for ( auto & rm : g_pCompositor - > m_vRealMonitors ) {
2023-03-16 15:03:40 +01:00
if ( ! rm - > output )
continue ;
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-12-16 18:17:31 +01: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-29 00:48:48 +02:00
void CConfigManager : : ensureVRR ( CMonitor * pMonitor ) {
2023-02-14 18:08:42 +01:00
static auto * const PVRR = & getConfigValuePtr ( " misc:vrr " ) - > intValue ;
2022-10-29 00:48:48 +02:00
2023-02-14 18:08:42 +01:00
static auto ensureVRRForDisplay = [ & ] ( CMonitor * m ) - > void {
2023-03-16 15:03:40 +01:00
if ( ! m - > output )
return ;
2023-08-11 17:37:52 +02:00
const auto USEVRR = m - > activeMonitorRule . vrr . has_value ( ) ? m - > activeMonitorRule . vrr . value ( ) : * PVRR ;
if ( USEVRR = = 0 ) {
2023-02-14 18:08:42 +01:00
if ( m - > vrrActive ) {
2022-10-22 22:45:17 +02:00
wlr_output_enable_adaptive_sync ( m - > output , 0 ) ;
2023-09-04 18:24:18 +02:00
if ( ! wlr_output_commit ( m - > output ) )
2023-09-06 12:51:36 +02:00
Debug : : log ( ERR , " Couldn't commit output {} in ensureVRR -> false " , m - > output - > name ) ;
2022-10-22 22:45:17 +02:00
}
2023-02-14 18:08:42 +01:00
m - > vrrActive = false ;
return ;
2023-08-11 17:37:52 +02:00
} else if ( USEVRR = = 1 ) {
2023-02-14 18:08:42 +01:00
if ( ! m - > vrrActive ) {
wlr_output_enable_adaptive_sync ( m - > output , 1 ) ;
2022-10-22 22:45:17 +02:00
2023-02-14 18:08:42 +01:00
if ( ! wlr_output_test ( m - > output ) ) {
2023-09-06 12:51:36 +02:00
Debug : : log ( LOG , " Pending output {} does not accept VRR. " , m - > output - > name ) ;
2023-02-14 18:08:42 +01:00
wlr_output_enable_adaptive_sync ( m - > output , 0 ) ;
}
2023-09-04 18:24:18 +02:00
if ( ! wlr_output_commit ( m - > output ) )
2023-09-06 12:51:36 +02:00
Debug : : log ( ERR , " Couldn't commit output {} in ensureVRR -> true " , m - > output - > name ) ;
2023-02-14 18:08:42 +01:00
}
m - > vrrActive = true ;
return ;
2023-08-11 17:37:52 +02:00
} else if ( USEVRR = = 2 ) {
2023-02-14 18:08:42 +01:00
/* fullscreen */
2022-10-22 22:45:17 +02:00
m - > vrrActive = true ;
2023-02-14 18:08:42 +01:00
const auto PWORKSPACE = g_pCompositor - > getWorkspaceByID ( m - > activeWorkspace ) ;
2022-10-22 22:45:17 +02:00
2023-02-14 18:08:42 +01:00
if ( ! PWORKSPACE )
return ; // ???
2022-10-22 22:45:17 +02:00
2023-09-04 18:24:18 +02:00
const auto WORKSPACEFULL = PWORKSPACE - > m_bHasFullscreenWindow & & PWORKSPACE - > m_efFullscreenMode = = FULLSCREEN_FULL ;
if ( WORKSPACEFULL & & m - > output - > adaptive_sync_status = = WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED ) {
2023-02-14 18:08:42 +01:00
wlr_output_enable_adaptive_sync ( m - > output , 1 ) ;
if ( ! wlr_output_test ( m - > output ) ) {
2023-09-06 12:51:36 +02:00
Debug : : log ( LOG , " Pending output {} does not accept VRR. " , m - > output - > name ) ;
2023-02-14 18:08:42 +01:00
wlr_output_enable_adaptive_sync ( m - > output , 0 ) ;
}
2022-10-22 22:45:17 +02:00
2023-09-04 18:24:18 +02:00
if ( ! wlr_output_commit ( m - > output ) )
2023-09-06 12:51:36 +02:00
Debug : : log ( ERR , " Couldn't commit output {} in ensureVRR -> true " , m - > output - > name ) ;
2023-09-04 18:24:18 +02:00
} else if ( ! WORKSPACEFULL & & m - > output - > adaptive_sync_status = = WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ) {
2023-02-14 18:08:42 +01:00
wlr_output_enable_adaptive_sync ( m - > output , 0 ) ;
2023-09-04 18:24:18 +02:00
if ( ! wlr_output_commit ( m - > output ) )
2023-09-06 12:51:36 +02:00
Debug : : log ( ERR , " Couldn't commit output {} in ensureVRR -> false " , m - > output - > name ) ;
2023-02-14 18:08:42 +01:00
}
2022-10-22 22:45:17 +02:00
}
2022-10-29 00:48:48 +02:00
} ;
if ( pMonitor ) {
ensureVRRForDisplay ( pMonitor ) ;
return ;
}
for ( auto & m : g_pCompositor - > m_vMonitors ) {
ensureVRRForDisplay ( m . get ( ) ) ;
2022-10-22 22:45:17 +02:00
}
}
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-12-01 14:36:07 +01:00
2023-01-05 23:30:13 +01:00
g_pHyprError - > queueCreate ( parseError + " \n Hyprland may not work correctly. " , CColor ( 1.0 , 50.0 / 255.0 , 50.0 / 255.0 , 1.0 ) ) ;
2022-08-19 20:01:51 +02:00
}
2022-09-12 21:05:52 +02:00
2022-12-16 18:17:31 +01:00
CMonitor * CConfigManager : : getBoundMonitorForWS ( const std : : string & wsname ) {
2023-07-09 23:10:35 +02:00
auto monitor = getBoundMonitorStringForWS ( wsname ) ;
if ( monitor . substr ( 0 , 5 ) = = " desc: " )
return g_pCompositor - > getMonitorFromDesc ( monitor . substr ( 5 ) ) ;
else
return g_pCompositor - > getMonitorFromName ( monitor ) ;
2022-09-12 21:05:52 +02:00
}
2022-11-10 14:39:23 +01:00
2022-12-16 18:17:31 +01:00
std : : string CConfigManager : : getBoundMonitorStringForWS ( const std : : string & wsname ) {
2023-05-05 16:41:25 +02:00
for ( auto & wr : m_dWorkspaceRules ) {
2023-10-15 20:07:23 +02:00
const auto WSNAME = wr . workspaceName . starts_with ( " name: " ) ? wr . workspaceName . substr ( 5 ) : wr . workspaceName ;
2022-12-09 18:17:02 +01:00
if ( WSNAME = = wsname ) {
2023-05-05 16:41:25 +02:00
return wr . monitor ;
2022-12-09 18:17:02 +01:00
}
}
return " " ;
}
2023-05-08 15:37:59 +02:00
const std : : deque < SWorkspaceRule > & CConfigManager : : getAllWorkspaceRules ( ) {
return m_dWorkspaceRules ;
}
2022-12-16 18:17:31 +01:00
void CConfigManager : : addExecRule ( const SExecRequestedRule & rule ) {
2022-11-10 14:39:23 +01:00
execRequestedRules . push_back ( rule ) ;
}
2022-11-26 18:56:43 +01:00
2023-05-01 16:10:53 +02:00
void CConfigManager : : handlePluginLoads ( ) {
if ( g_pPluginSystem = = nullptr )
return ;
bool pluginsChanged = false ;
auto failedPlugins = g_pPluginSystem - > updateConfigPlugins ( m_vDeclaredPlugins , pluginsChanged ) ;
if ( ! failedPlugins . empty ( ) ) {
std : : stringstream error ;
error < < " Failed to load the following plugins: " ;
for ( auto path : failedPlugins ) {
error < < " \n " < < path ;
}
g_pHyprError - > queueCreate ( error . str ( ) , CColor ( 1.0 , 50.0 / 255.0 , 50.0 / 255.0 , 1.0 ) ) ;
}
if ( pluginsChanged ) {
g_pHyprError - > destroy ( ) ;
m_bForceReload = true ;
tick ( ) ;
}
}
2022-11-26 18:56:43 +01:00
ICustomConfigValueData : : ~ ICustomConfigValueData ( ) {
; // empty
}
2023-01-25 16:16:28 +01:00
std : : unordered_map < std : : string , SAnimationPropertyConfig > CConfigManager : : getAnimationConfig ( ) {
return animationConfig ;
}
2023-02-27 13:32:38 +01:00
void CConfigManager : : addPluginConfigVar ( HANDLE handle , const std : : string & name , const SConfigValue & value ) {
auto CONFIGMAPIT = std : : find_if ( pluginConfigs . begin ( ) , pluginConfigs . end ( ) , [ & ] ( const auto & other ) { return other . first = = handle ; } ) ;
if ( CONFIGMAPIT = = pluginConfigs . end ( ) ) {
pluginConfigs . emplace (
std : : pair < HANDLE , std : : unique_ptr < std : : unordered_map < std : : string , SConfigValue > > > ( handle , std : : make_unique < std : : unordered_map < std : : string , SConfigValue > > ( ) ) ) ;
CONFIGMAPIT = std : : find_if ( pluginConfigs . begin ( ) , pluginConfigs . end ( ) , [ & ] ( const auto & other ) { return other . first = = handle ; } ) ;
}
( * CONFIGMAPIT - > second ) [ name ] = value ;
2023-07-10 14:13:23 +02:00
if ( const auto IT = std : : find_if ( m_vFailedPluginConfigValues . begin ( ) , m_vFailedPluginConfigValues . end ( ) , [ & ] ( const auto & other ) { return other . first = = name ; } ) ;
IT ! = m_vFailedPluginConfigValues . end ( ) ) {
configSetValueSafe ( IT - > first , IT - > second ) ;
}
2023-02-27 13:32:38 +01:00
}
void CConfigManager : : removePluginConfig ( HANDLE handle ) {
std : : erase_if ( pluginConfigs , [ & ] ( const auto & other ) { return other . first = = handle ; } ) ;
2023-02-28 21:50:10 +01:00
}
2023-03-18 17:12:43 +01:00
std : : string CConfigManager : : getDefaultWorkspaceFor ( const std : : string & name ) {
2023-07-10 07:53:03 +02:00
for ( auto other = m_dWorkspaceRules . begin ( ) ; other ! = m_dWorkspaceRules . end ( ) ; + + other ) {
2023-07-11 11:29:19 +02:00
if ( other - > isDefault ) {
if ( other - > monitor = = name )
return other - > workspaceString ;
if ( other - > monitor . substr ( 0 , 5 ) = = " desc: " ) {
auto monitor = g_pCompositor - > getMonitorFromDesc ( other - > monitor . substr ( 5 ) ) ;
if ( monitor & & monitor - > szName = = name )
return other - > workspaceString ;
}
}
2023-07-10 07:53:03 +02:00
}
return " " ;
2023-04-10 15:40:03 +02:00
}