@@ -89,15 +89,17 @@ private void LoadGlobals()
8989 currentText : $ "Current: { OnOffText ( SafeRead ( GameModeMonitor . ReadCurrent ) ) } ",
9090 defaultText : "Default: Enabled" ,
9191 onLabel : "Enabled" , offLabel : "Disabled" ,
92- pref : g . GameMode , groupName : "gm" ) ) ;
92+ pref : g . GameMode , groupName : "gm" ,
93+ onPrefChanged : OnRowPrefChanged ) ) ;
9394
9495 GlobalToggleRows . Add ( new GlobalToggleRow (
9596 name : "Game DVR background recording" ,
9697 description : "Always-on game capture. Costs CPU/GPU during gameplay; off is gaming-recommended." ,
9798 currentText : $ "Current: { OnOffText ( SafeRead ( GameDvrMonitor . ReadCurrent ) ) } ",
9899 defaultText : "Default: Enabled" ,
99100 onLabel : "Enabled" , offLabel : "Disabled" ,
100- pref : g . GameDvr , groupName : "dvr" ) ) ;
101+ pref : g . GameDvr , groupName : "dvr" ,
102+ onPrefChanged : OnRowPrefChanged ) ) ;
101103
102104 GlobalToggleRows . Add ( new GlobalToggleRow (
103105 name : "Hardware-accelerated GPU Scheduling (HAGS)" ,
@@ -106,7 +108,8 @@ private void LoadGlobals()
106108 defaultText : "Default: Enabled (Win11)" ,
107109 onLabel : "Enabled" , offLabel : "Disabled" ,
108110 requiresReboot : true ,
109- pref : g . Hags , groupName : "hags" ) ) ;
111+ pref : g . Hags , groupName : "hags" ,
112+ onPrefChanged : OnRowPrefChanged ) ) ;
110113
111114 GlobalToggleRows . Add ( new GlobalToggleRow (
112115 name : "Memory Integrity / VBS (Core Isolation)" ,
@@ -115,7 +118,8 @@ private void LoadGlobals()
115118 defaultText : "Default: Enabled (Win11)" ,
116119 onLabel : "Enabled" , offLabel : "Disabled" ,
117120 requiresReboot : true ,
118- pref : g . MemoryIntegrity , groupName : "memint" ) ) ;
121+ pref : g . MemoryIntegrity , groupName : "memint" ,
122+ onPrefChanged : OnRowPrefChanged ) ) ;
119123
120124 GlobalToggleRows . Add ( new GlobalToggleRow (
121125 name : "System Responsiveness" ,
@@ -124,15 +128,17 @@ private void LoadGlobals()
124128 defaultText : "Default: 20 Gaming: 10" ,
125129 onLabel : "Gaming" , offLabel : "Default" ,
126130 requiresReboot : true ,
127- pref : g . SystemResponsiveness , groupName : "sysresp" ) ) ;
131+ pref : g . SystemResponsiveness , groupName : "sysresp" ,
132+ onPrefChanged : OnRowPrefChanged ) ) ;
128133
129134 GlobalToggleRows . Add ( new GlobalToggleRow (
130135 name : "Network Throttling" ,
131136 description : "Multimedia packet pacing. Disabling reduces network jitter for online games." ,
132137 currentText : $ "Current: { GamingDefaultText ( SafeRead ( NetworkThrottlingMonitor . ReadCurrent ) ) } ",
133138 defaultText : "Default: 10 Gaming: Disabled" ,
134139 onLabel : "Gaming" , offLabel : "Default" ,
135- pref : g . NetworkThrottling , groupName : "netthr" ) ) ;
140+ pref : g . NetworkThrottling , groupName : "netthr" ,
141+ onPrefChanged : OnRowPrefChanged ) ) ;
136142
137143 GlobalToggleRows . Add ( new GlobalToggleRow (
138144 name : "USB Selective Suspend (global)" ,
@@ -141,39 +147,44 @@ private void LoadGlobals()
141147 defaultText : "Default: Enabled Gaming: Disabled" ,
142148 onLabel : "Gaming" , offLabel : "Default" ,
143149 requiresReboot : true ,
144- pref : g . UsbSelectiveSuspend , groupName : "usbsus" ) ) ;
150+ pref : g . UsbSelectiveSuspend , groupName : "usbsus" ,
151+ onPrefChanged : OnRowPrefChanged ) ) ;
145152
146153 GlobalToggleRows . Add ( new GlobalToggleRow (
147154 name : "Games multimedia task profile" ,
148155 description : "Priority + scheduling values for processes registered with the Games multimedia class." ,
149156 currentText : $ "Current: { GamingDefaultText ( SafeRead ( GamesTaskProfileMonitor . ReadCurrent ) ) } ",
150157 defaultText : "Default: standard Gaming: boosted" ,
151158 onLabel : "Gaming" , offLabel : "Default" ,
152- pref : g . GamesTaskProfile , groupName : "gtask" ) ) ;
159+ pref : g . GamesTaskProfile , groupName : "gtask" ,
160+ onPrefChanged : OnRowPrefChanged ) ) ;
153161
154162 GlobalToggleRows . Add ( new GlobalToggleRow (
155163 name : "Mouse \" Enhance pointer precision\" " ,
156164 description : "Acceleration curve applied to mouse movement. Most gamers want this off for consistent aim." ,
157165 currentText : $ "Current: { OnOffText ( SafeRead ( MousePrecisionMonitor . ReadCurrent ) ) } ",
158166 defaultText : "Default: Enabled" ,
159167 onLabel : "Enabled" , offLabel : "Disabled" ,
160- pref : g . MousePrecision , groupName : "mp" ) ) ;
168+ pref : g . MousePrecision , groupName : "mp" ,
169+ onPrefChanged : OnRowPrefChanged ) ) ;
161170
162171 GlobalToggleRows . Add ( new GlobalToggleRow (
163172 name : "Fullscreen optimizations (global)" ,
164173 description : "Borderless-windowed compositing layer. Generally fine; some titles prefer it off." ,
165174 currentText : $ "Current: { OnOffText ( SafeRead ( FullscreenOptimizationsMonitor . ReadCurrent ) ) } ",
166175 defaultText : "Default: Enabled" ,
167176 onLabel : "Enabled" , offLabel : "Disabled" ,
168- pref : g . FullscreenOptimizations , groupName : "fso" ) ) ;
177+ pref : g . FullscreenOptimizations , groupName : "fso" ,
178+ onPrefChanged : OnRowPrefChanged ) ) ;
169179
170180 GlobalToggleRows . Add ( new GlobalToggleRow (
171181 name : "Variable Refresh Rate (DirectX)" ,
172182 description : "G-Sync / FreeSync compatibility flag (Settings → Display → Graphics). Not the same as Dynamic Refresh Rate (DRR) in Advanced Display." ,
173183 currentText : $ "Current: { OnOffText ( SafeRead ( VrrMonitor . ReadCurrent ) ) } ",
174184 defaultText : "Default: not set" ,
175185 onLabel : "Enabled" , offLabel : "Disabled" ,
176- pref : g . Vrr , groupName : "vrr" ) ) ;
186+ pref : g . Vrr , groupName : "vrr" ,
187+ onPrefChanged : OnRowPrefChanged ) ) ;
177188
178189 var planNames = PowerPlanMonitor . ListAvailablePlans ( ) ;
179190 var active = SafeRunGuid ( PowerPlanMonitor . GetActivePlan ) ;
@@ -393,12 +404,36 @@ private void PersistFormToConfig()
393404 foreach ( var row in DisplayRows ) row . WriteTo ( _config ) ;
394405 }
395406
396- private void CancelButton_Click ( object sender , RoutedEventArgs e ) => Close ( ) ;
407+ private bool _suppressSaveOnClose = false ;
408+
409+ private void OnWindowClosing ( object ? sender , CancelEventArgs e )
410+ {
411+ if ( _suppressSaveOnClose ) return ;
412+ try
413+ {
414+ PersistFormToConfig ( ) ;
415+ _store . Save ( _config ) ;
416+ }
417+ catch { }
418+ }
419+
420+ private void OnRowPrefChanged ( string settingName , string field , string before , string after )
421+ {
422+ try { _store . Save ( _config ) ; } catch { }
423+ ChangeLogger . LogPreferenceChange ( settingName , field , before , after ) ;
424+ }
425+
426+ private void CancelButton_Click ( object sender , RoutedEventArgs e )
427+ {
428+ _suppressSaveOnClose = true ;
429+ Close ( ) ;
430+ }
397431}
398432
399433public sealed class GlobalToggleRow : INotifyPropertyChanged
400434{
401435 private readonly ToggleSettingPref _pref ;
436+ private readonly Action < string , string , string , string > ? _onPrefChanged ;
402437 public string Name { get ; }
403438 public string Description { get ; }
404439 public string CurrentText { get ; }
@@ -409,23 +444,54 @@ public sealed class GlobalToggleRow : INotifyPropertyChanged
409444 public bool RequiresReboot { get ; }
410445 public Visibility RebootBadgeVisibility => RequiresReboot ? Visibility . Visible : Visibility . Collapsed ;
411446
412- public bool Monitor { get => _pref . Monitor ; set { _pref . Monitor = value ; OnPropertyChanged ( ) ; } }
447+ public bool Monitor
448+ {
449+ get => _pref . Monitor ;
450+ set
451+ {
452+ if ( _pref . Monitor == value ) return ;
453+ var before = _pref . Monitor ;
454+ _pref . Monitor = value ;
455+ OnPropertyChanged ( ) ;
456+ _onPrefChanged ? . Invoke ( Name , "Monitor" , before . ToString ( ) , value . ToString ( ) ) ;
457+ }
458+ }
413459 public bool DesiredOn
414460 {
415461 get => _pref . DesiredOn ;
416- set { if ( _pref . DesiredOn != value ) { _pref . DesiredOn = value ; OnPropertyChanged ( ) ; OnPropertyChanged ( nameof ( DesiredOff ) ) ; } }
462+ set
463+ {
464+ if ( _pref . DesiredOn == value ) return ;
465+ var before = _pref . DesiredOn ;
466+ _pref . DesiredOn = value ;
467+ OnPropertyChanged ( ) ;
468+ OnPropertyChanged ( nameof ( DesiredOff ) ) ;
469+ _onPrefChanged ? . Invoke ( Name , "Want" , before ? OnLabel : OffLabel , value ? OnLabel : OffLabel ) ;
470+ }
417471 }
418472 public bool DesiredOff
419473 {
420474 get => ! _pref . DesiredOn ;
421- set { if ( value && _pref . DesiredOn ) { _pref . DesiredOn = false ; OnPropertyChanged ( ) ; OnPropertyChanged ( nameof ( DesiredOn ) ) ; } }
475+ set { if ( value && _pref . DesiredOn ) DesiredOn = false ; }
476+ }
477+ public bool AutoApply
478+ {
479+ get => _pref . AutoApply ;
480+ set
481+ {
482+ if ( _pref . AutoApply == value ) return ;
483+ var before = _pref . AutoApply ;
484+ _pref . AutoApply = value ;
485+ OnPropertyChanged ( ) ;
486+ _onPrefChanged ? . Invoke ( Name , "AutoApply" , before . ToString ( ) , value . ToString ( ) ) ;
487+ }
422488 }
423- public bool AutoApply { get => _pref . AutoApply ; set { _pref . AutoApply = value ; OnPropertyChanged ( ) ; } }
424489
425490 public GlobalToggleRow ( string name , string description , string currentText , string defaultText ,
426491 string onLabel , string offLabel ,
427492 ToggleSettingPref pref , string groupName ,
428- bool requiresReboot = false )
493+ bool requiresReboot = false ,
494+ Action < string , string , string , string > ? onPrefChanged = null )
429495 {
430496 Name = name ;
431497 Description = description ;
@@ -436,6 +502,7 @@ public GlobalToggleRow(string name, string description, string currentText, stri
436502 _pref = pref ;
437503 GroupName = groupName ;
438504 RequiresReboot = requiresReboot ;
505+ _onPrefChanged = onPrefChanged ;
439506 }
440507
441508 public void WriteBack ( ) { /* mutations are direct; nothing to do */ }
0 commit comments