diff --git a/FluentTerminal.App.Services/Implementation/DefaultValueProvider.cs b/FluentTerminal.App.Services/Implementation/DefaultValueProvider.cs index 08d73aa..ef13842 100644 --- a/FluentTerminal.App.Services/Implementation/DefaultValueProvider.cs +++ b/FluentTerminal.App.Services/Implementation/DefaultValueProvider.cs @@ -23,7 +23,8 @@ namespace FluentTerminal.App.Services.Implementation AlwaysShowTabs = false, AlwaysUseWinPty = true, ShowNewOutputIndicator = false, - EnableTrayIcon = true + EnableTrayIcon = true, + ShowCustomTitleInTitlebar = true }; } diff --git a/FluentTerminal.App.ViewModels/MainViewModel.cs b/FluentTerminal.App.ViewModels/MainViewModel.cs index 3c948f8..e6d065c 100644 --- a/FluentTerminal.App.ViewModels/MainViewModel.cs +++ b/FluentTerminal.App.ViewModels/MainViewModel.cs @@ -25,6 +25,7 @@ namespace FluentTerminal.App.ViewModels private double _backgroundOpacity; private TerminalViewModel _selectedTerminal; private TabsPosition _tabsPosition; + private string _windowTitle; public MainViewModel(ISettingsService settingsService, ITrayProcessCommunicationService trayProcessCommunicationService, IDialogService dialogService, IKeyboardCommandService keyboardCommandService, IApplicationView applicationView, IDispatcherTimer dispatcherTimer, IClipboardService clipboardService) @@ -117,6 +118,18 @@ namespace FluentTerminal.App.ViewModels public RelayCommand AddTerminalCommand { get; } + public string WindowTitle + { + get => _windowTitle; + set + { + if (Set(ref _windowTitle, value)) + { + ApplicationView.Title = value; + } + } + } + public bool ShowTabsOnTop { get => TabsPosition == TabsPosition.Top && (Terminals.Count > 1 || _applicationSettings.AlwaysShowTabs); @@ -154,6 +167,14 @@ namespace FluentTerminal.App.ViewModels if (SelectedTerminal != null) { SelectedTerminal.IsSelected = true; + if (_applicationSettings.ShowCustomTitleInTitlebar) + { + WindowTitle = SelectedTerminal.TabTitle; + } + else + { + WindowTitle = SelectedTerminal.ShellTitle; + } } } } @@ -212,17 +233,47 @@ namespace FluentTerminal.App.ViewModels var terminal = new TerminalViewModel(_settingsService, _trayProcessCommunicationService, _dialogService, _keyboardCommandService, _applicationSettings, profile, ApplicationView, _dispatcherTimer, _clipboardService); terminal.Closed += OnTerminalClosed; + terminal.ShellTitleChanged += Terminal_ShellTitleChanged; + terminal.CustomTitleChanged += Terminal_CustomTitleChanged; Terminals.Add(terminal); SelectedTerminal = terminal; }); } + private void Terminal_CustomTitleChanged(object sender, string e) + { + if (sender is TerminalViewModel terminal) + { + if (terminal.IsSelected && _applicationSettings.ShowCustomTitleInTitlebar) + { + if (string.IsNullOrWhiteSpace(e)) + { + WindowTitle = terminal.ShellTitle; + } + else + { + WindowTitle = e; + } + } + } + } + + private void Terminal_ShellTitleChanged(object sender, string e) + { + if (sender is TerminalViewModel terminal && terminal.IsSelected && !_applicationSettings.ShowCustomTitleInTitlebar) + { + WindowTitle = e; + } + } + public async Task CloseAllTerminals() { foreach (var terminal in Terminals) { terminal.Closed -= OnTerminalClosed; + terminal.ShellTitleChanged -= Terminal_ShellTitleChanged; + terminal.CustomTitleChanged -= Terminal_CustomTitleChanged; await terminal.Close(); } } @@ -250,6 +301,15 @@ namespace FluentTerminal.App.ViewModels TabsPosition = e.TabsPosition; RaisePropertyChanged(nameof(ShowTabsOnTop)); RaisePropertyChanged(nameof(ShowTabsOnBottom)); + + if (e.ShowCustomTitleInTitlebar) + { + WindowTitle = SelectedTerminal?.TabTitle; + } + else + { + WindowTitle = SelectedTerminal?.ShellTitle; + } }); } diff --git a/FluentTerminal.App.ViewModels/Settings/GeneralPageViewModel.cs b/FluentTerminal.App.ViewModels/Settings/GeneralPageViewModel.cs index 69b5d61..ad67182 100644 --- a/FluentTerminal.App.ViewModels/Settings/GeneralPageViewModel.cs +++ b/FluentTerminal.App.ViewModels/Settings/GeneralPageViewModel.cs @@ -68,6 +68,20 @@ namespace FluentTerminal.App.ViewModels.Settings } } + public bool ShowCustomTitleInTitlebar + { + get => _applicationSettings.ShowCustomTitleInTitlebar; + set + { + if (_applicationSettings.ShowCustomTitleInTitlebar != value) + { + _applicationSettings.ShowCustomTitleInTitlebar = value; + _settingsService.SaveApplicationSettings(_applicationSettings); + RaisePropertyChanged(); + } + } + } + public bool EnableTrayIcon { get => _applicationSettings.EnableTrayIcon; @@ -281,6 +295,7 @@ namespace FluentTerminal.App.ViewModels.Settings AlwaysUseWinPty = defaults.AlwaysUseWinPty; ShowNewOutputIndicator = defaults.ShowNewOutputIndicator; EnableTrayIcon = defaults.EnableTrayIcon; + ShowCustomTitleInTitlebar = defaults.ShowCustomTitleInTitlebar; } } diff --git a/FluentTerminal.App.ViewModels/TerminalViewModel.cs b/FluentTerminal.App.ViewModels/TerminalViewModel.cs index 04c26af..50c0f69 100644 --- a/FluentTerminal.App.ViewModels/TerminalViewModel.cs +++ b/FluentTerminal.App.ViewModels/TerminalViewModel.cs @@ -79,6 +79,8 @@ namespace FluentTerminal.App.ViewModels public event EventHandler OptionsChanged; public event EventHandler SearchStarted; public event EventHandler ThemeChanged; + public event EventHandler ShellTitleChanged; + public event EventHandler CustomTitleChanged; public ApplicationSettings ApplicationSettings { get; private set; } @@ -116,7 +118,6 @@ namespace FluentTerminal.App.ViewModels { if (IsSelected) { - ApplicationView.Title = ShellTitle ?? string.Empty; HasNewOutput = false; } RaisePropertyChanged(nameof(IsUnderlined)); @@ -201,9 +202,9 @@ namespace FluentTerminal.App.ViewModels get => _tabTitle; set { - if (Set(ref _tabTitle, value) && IsSelected) + if (Set(ref _tabTitle, value)) { - ApplicationView.Title = value; + CustomTitleChanged?.Invoke(this, value); } } } @@ -390,6 +391,7 @@ namespace FluentTerminal.App.ViewModels private void Terminal_TitleChanged(object sender, string e) { ShellTitle = e; + ShellTitleChanged?.Invoke(this, e); } private async Task TryClose() diff --git a/FluentTerminal.App/Adapters/ApplicationViewAdapter.cs b/FluentTerminal.App/Adapters/ApplicationViewAdapter.cs index de4f319..79d6f22 100644 --- a/FluentTerminal.App/Adapters/ApplicationViewAdapter.cs +++ b/FluentTerminal.App/Adapters/ApplicationViewAdapter.cs @@ -39,7 +39,7 @@ namespace FluentTerminal.App.Adapters public string Title { get => _applicationView.Title; - set => _applicationView.Title = value; + set => _applicationView.Title = value ?? string.Empty; } public bool IsApiContractPresent(string api, ushort version) diff --git a/FluentTerminal.App/Views/MainPage.xaml b/FluentTerminal.App/Views/MainPage.xaml index 31a3eb4..1f07512 100644 --- a/FluentTerminal.App/Views/MainPage.xaml +++ b/FluentTerminal.App/Views/MainPage.xaml @@ -173,7 +173,7 @@ diff --git a/FluentTerminal.App/Views/SettingsPages/GeneralSettings.xaml b/FluentTerminal.App/Views/SettingsPages/GeneralSettings.xaml index d4f8ee9..7649ac1 100644 --- a/FluentTerminal.App/Views/SettingsPages/GeneralSettings.xaml +++ b/FluentTerminal.App/Views/SettingsPages/GeneralSettings.xaml @@ -84,6 +84,11 @@ Header="Always show tabs" IsOn="{x:Bind ViewModel.AlwaysShowTabs, Mode=TwoWay}" /> + +