diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md
index 4bad687..71c31c0 100644
--- a/CHANGELOG.en-US.md
+++ b/CHANGELOG.en-US.md
@@ -3,6 +3,8 @@
English (US) release notes, mirroring CHANGELOG.md (Brazilian Portuguese). Before publishing a version, add a `## [VERSION]` section to **both** files: the workflow publishes the section matching the tag from each one and fails if either is missing.
## [Unreleased]
+### Fixes
+- FPS counter: the style saved in Settings now applies as soon as the session starts. Before, the counter only showed up after cycling the "FPS counter" row in the session menu. (#139)
## [1.6.0-beta.7]
### Heads-up: beta version, not the stable one
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4bd76a5..e78b566 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,8 @@
Notas em português do Brasil; a versão em inglês (Estados Unidos) fica em `CHANGELOG.en-US.md`. Antes de publicar uma versão, adicione uma seção `## [VERSÃO]` com o changelog daquela versão **nos dois arquivos**. O workflow publica as duas seções correspondentes à tag na mesma release e falha se faltar alguma.
## [Unreleased]
+### Correções
+- Contador de FPS: o estilo salvo em Ajustes agora vale assim que a sessão começa. Antes, o contador só aparecia depois de alternar a linha "Contador de FPS" no menu da sessão. (#139)
## [1.6.0-beta.7]
### Atenção: versão beta, não é a estável
diff --git a/docs/TESTING.md b/docs/TESTING.md
index 9531d2e..3e0b8cd 100644
--- a/docs/TESTING.md
+++ b/docs/TESTING.md
@@ -393,3 +393,4 @@ Pré-requisito: RivaTuner Statistics Server instalado, com "Show On-Screen Displ
- [ ] Com o RTSS fechado, ligar Compacto abre o RTSS e o contador aparece.
- [ ] Voltar ao PC: o nosso some e o do Afterburner volta.
- [ ] A escolha e o layout ficam salvos para a próxima sessão.
+- [ ] Com Compacto (ou outro estilo nosso) já salvo em Ajustes, iniciar a sessão: o contador aparece e o do Afterburner some sem precisar mexer na linha do menu.
diff --git a/src/ConsoleMode/Models/Models.cs b/src/ConsoleMode/Models/Models.cs
index 16726e3..6fbd8de 100644
--- a/src/ConsoleMode/Models/Models.cs
+++ b/src/ConsoleMode/Models/Models.cs
@@ -87,6 +87,19 @@ public sealed class AppConfig
/// Turning the TV on / to the PC's input when console mode starts (issue #75).
public TvControlConfig Tv { get; set; } = new();
+ ///
+ /// A copy with other monitor fields and every other setting as it is here. A copy, not a field-by-field
+ /// rebuild: a setting added later is carried along without anyone having to remember it.
+ ///
+ public AppConfig WithMonitors(string focusMonitor, List hideMonitors, Dictionary monitorModes)
+ {
+ var copy = (AppConfig)MemberwiseClone();
+ copy.FocusMonitor = focusMonitor;
+ copy.HideMonitors = hideMonitors;
+ copy.MonitorModes = monitorModes;
+ return copy;
+ }
+
[JsonIgnore]
public string SetupKey =>
$"{FocusMonitor}|{(MonitorModes.TryGetValue(FocusMonitor, out var mode) ? mode.Key : "current")}";
diff --git a/src/ConsoleMode/Services/ConsoleEngine.cs b/src/ConsoleMode/Services/ConsoleEngine.cs
index f55ea61..f90e0fd 100644
--- a/src/ConsoleMode/Services/ConsoleEngine.cs
+++ b/src/ConsoleMode/Services/ConsoleEngine.cs
@@ -407,40 +407,7 @@ private AppConfig ResolveMonitorNames(AppConfig config)
foreach (var (key, mode) in config.MonitorModes)
modes[Monitors.ResolveName(key)] = mode;
- return new AppConfig
- {
- Version = config.Version,
- AppLanguage = config.AppLanguage,
- FocusMonitor = focus,
- HideMonitors = hide,
- HideStrategy = config.HideStrategy,
- FullscreenMode = config.FullscreenMode,
- PlaynitePath = config.PlaynitePath,
- AudioDeviceId = config.AudioDeviceId,
- AudioDeviceName = config.AudioDeviceName,
- AudioAutoSwitch = config.AudioAutoSwitch,
- FpsLimit = config.FpsLimit,
- MonitorModes = modes,
- HdrEnable = config.HdrEnable,
- VrrEnable = config.VrrEnable,
- UiMode = config.UiMode,
- TourDone = config.TourDone,
- ConfirmedSetup = config.ConfirmedSetup,
- CheckUpdates = config.CheckUpdates,
- BetaUpdates = config.BetaUpdates,
- HomeShortcut = config.HomeShortcut,
- MenuShortcut = config.MenuShortcut,
- ExitShortcut = config.ExitShortcut,
- ShortcutsOnboardingDone = config.ShortcutsOnboardingDone,
- HomeButtonShortPress = config.HomeButtonShortPress,
- CloseSteamOnRestore = config.CloseSteamOnRestore,
- AutoStartOnController = config.AutoStartOnController,
- InterfaceSounds = config.InterfaceSounds,
- ConsoleBackground = config.ConsoleBackground,
- ConsoleBackgroundImage = config.ConsoleBackgroundImage,
- SkippedUpdateVersion = config.SkippedUpdateVersion,
- Tv = config.Tv
- };
+ return config.WithMonitors(focus, hide, modes);
}
private void MoveToFocus(string monitorName, nint[] handles, ScreenRect? rect)
diff --git a/tests/ConsoleMode.Tests/AppConfigTests.cs b/tests/ConsoleMode.Tests/AppConfigTests.cs
new file mode 100644
index 0000000..8345f17
--- /dev/null
+++ b/tests/ConsoleMode.Tests/AppConfigTests.cs
@@ -0,0 +1,61 @@
+using System.Reflection;
+using ConsoleMode.Models;
+using ConsoleMode.Services;
+
+namespace ConsoleMode.Tests;
+
+public class AppConfigTests
+{
+ [Fact]
+ public void Copy_for_a_session_swaps_only_the_monitor_fields()
+ {
+ var config = new AppConfig { FocusMonitor = "id-tv", HideMonitors = ["id-desk"] };
+ var hide = new List { @"\\.\DISPLAY1" };
+ var modes = new Dictionary();
+
+ var copy = config.WithMonitors(@"\\.\DISPLAY2", hide, modes);
+
+ Assert.Equal(@"\\.\DISPLAY2", copy.FocusMonitor);
+ Assert.Same(hide, copy.HideMonitors);
+ Assert.Same(modes, copy.MonitorModes);
+ Assert.Equal("id-tv", config.FocusMonitor);
+ Assert.Equal(["id-desk"], config.HideMonitors);
+ }
+
+ // The session used to get a field-by-field copy that forgot the FPS counter: the saved style
+ // was never applied when console mode started.
+ [Fact]
+ public void Copy_for_a_session_keeps_the_fps_counter()
+ {
+ var layout = new FpsOverlayLayout { SingleLine = true };
+ var config = new AppConfig { FpsOverlay = RtssOverlay.Compact, FpsOverlayLayout = layout };
+
+ var copy = config.WithMonitors("", [], []);
+
+ Assert.Equal(RtssOverlay.Compact, copy.FpsOverlay);
+ Assert.Same(layout, copy.FpsOverlayLayout);
+ }
+
+ [Fact]
+ public void Copy_for_a_session_keeps_every_other_setting()
+ {
+ string[] swapped = [nameof(AppConfig.FocusMonitor), nameof(AppConfig.HideMonitors), nameof(AppConfig.MonitorModes), nameof(AppConfig.SetupKey)];
+ var config = new AppConfig();
+ var properties = typeof(AppConfig).GetProperties(BindingFlags.Public | BindingFlags.Instance)
+ .Where(p => p.CanWrite && !swapped.Contains(p.Name))
+ .ToList();
+ foreach (var property in properties)
+ {
+ // A value that differs from the default, so a property left behind shows up.
+ if (property.PropertyType == typeof(string)) property.SetValue(config, "changed-" + property.Name);
+ else if (property.PropertyType == typeof(bool)) property.SetValue(config, !(bool)property.GetValue(config)!);
+ else if (property.PropertyType == typeof(int)) property.SetValue(config, (int)property.GetValue(config)! + 7);
+ else property.SetValue(config, Activator.CreateInstance(property.PropertyType));
+ }
+
+ var copy = config.WithMonitors("", [], []);
+
+ foreach (var property in properties)
+ Assert.Equal(property.GetValue(config), property.GetValue(copy));
+ }
+}