Add a Compatibility and Terminal page to the Settings UI (#17895)

## Summary of the Pull Request
Adds a global Compatibility page to the settings UI. This page exposes
several existing settings and introduces a few new settings:
- compatibility.allowHeadless
- compatibility.isolatedMode
- compatibility.textMeasurement
- debugFeatures

This also adds a Terminal subpage for profiles in the settings UI. This
page includes:
- suppressApplicationTitle
- compatibility.input.forceVT
- compatibility.allowDECRQCRA
- answerbackMessage

Several smaller changes were accomplished as a part of this PR:
- `experimental.input.forceVT` was renamed to
`compatibility.input.forceVT`
- introduced the `compatibility.allowDECRQCRA` setting
- updated the schema for these new settings and
`compatibility.allowHeadless` (which was missing)
- add `Feature_DebugModeUI` feature flag to control if debug features
should be shown in the SUI

Verified accessible via Accessibility Insights

A part of #10000
Closes #16672
This commit is contained in:
Carlos Zamora 2024-10-10 16:54:31 -07:00 committed by GitHub
parent 0b4d3d5f89
commit 18d86bca09
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 572 additions and 86 deletions

View File

@ -2355,11 +2355,21 @@
"description": "When set to true, the terminal will focus the pane on mouse hover.",
"type": "boolean"
},
"compatibility.allowHeadless": {
"default": false,
"description": "When set to true, Windows Terminal will run in the background. This allows globalSummon and quakeMode actions to work even when no windows are open.",
"type": "boolean"
},
"compatibility.isolatedMode": {
"default": false,
"description": "When set to true, Terminal windows will not be able to interact with each other (including global hotkeys, tab drag/drop, running commandlines in existing windows, etc.). This is a compatibility escape hatch for users who are running into certain windowing issues.",
"type": "boolean"
},
"compatibility.allowDECRQCRA": {
"default": false,
"description": "When set to true, the terminal will support the DECRQCRA (Request Checksum of Rectangular Area) escape sequence.",
"type": "boolean"
},
"copyFormatting": {
"default": true,
"description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. An array of specific formats can also be used. Supported array values include `html` and `rtf`. Plain text is always copied.",

View File

@ -21,6 +21,7 @@ namespace Microsoft.Terminal.Core
String WordDelimiters;
Boolean ForceVTInput;
Boolean AllowVtChecksumReport;
Boolean TrimBlockSelection;
Boolean DetectURLs;

View File

@ -90,6 +90,11 @@ void Terminal::UpdateSettings(ICoreSettings settings)
_autoMarkPrompts = settings.AutoMarkPrompts();
_rainbowSuggestions = settings.RainbowSuggestions();
if (_stateMachine)
{
SetVtChecksumReportSupport(settings.AllowVtChecksumReport());
}
_getTerminalInput().ForceDisableWin32InputMode(settings.ForceVTInput());
if (settings.TabColor() == nullptr)
@ -212,6 +217,12 @@ void Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle)
engine.Dispatch().SetCursorStyle(cursorStyle);
}
void Terminal::SetVtChecksumReportSupport(const bool enabled)
{
auto& engine = reinterpret_cast<OutputStateMachineEngine&>(_stateMachine->Engine());
engine.Dispatch().SetVtChecksumReportSupport(enabled);
}
bool Terminal::IsXtermBracketedPasteModeEnabled() const noexcept
{
return _systemMode.test(Mode::BracketedPaste);

View File

@ -94,6 +94,7 @@ public:
void UpdateAppearance(const winrt::Microsoft::Terminal::Core::ICoreAppearance& appearance);
void SetFontInfo(const FontInfo& fontInfo);
void SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle);
void SetVtChecksumReportSupport(const bool enabled);
bool IsXtermBracketedPasteModeEnabled() const noexcept;
std::wstring_view GetWorkingDirectory() noexcept;

View File

@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "Compatibility.h"
#include "EnumEntry.h"
#include "Compatibility.g.cpp"
#include "CompatibilityViewModel.g.cpp"
using namespace winrt::Windows::UI::Xaml::Navigation;
using namespace winrt::Microsoft::Terminal::Settings::Model;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
CompatibilityViewModel::CompatibilityViewModel(Model::GlobalAppSettings globalSettings) :
_GlobalSettings{ globalSettings }
{
INITIALIZE_BINDABLE_ENUM_SETTING(TextMeasurement, TextMeasurement, winrt::Microsoft::Terminal::Control::TextMeasurement, L"Globals_TextMeasurement_", L"Text");
}
bool CompatibilityViewModel::DebugFeaturesAvailable() const noexcept
{
return Feature_DebugModeUI::IsEnabled();
}
Compatibility::Compatibility()
{
InitializeComponent();
}
void Compatibility::OnNavigatedTo(const NavigationEventArgs& e)
{
_ViewModel = e.Parameter().as<Editor::CompatibilityViewModel>();
}
}

View File

@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "Compatibility.g.h"
#include "CompatibilityViewModel.g.h"
#include "ViewModelHelpers.h"
#include "Utils.h"
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
struct CompatibilityViewModel : CompatibilityViewModelT<CompatibilityViewModel>, ViewModelHelper<CompatibilityViewModel>
{
public:
CompatibilityViewModel(Model::GlobalAppSettings globalSettings);
bool DebugFeaturesAvailable() const noexcept;
// DON'T YOU DARE ADD A `WINRT_CALLBACK(PropertyChanged` TO A CLASS DERIVED FROM ViewModelHelper. Do this instead:
using ViewModelHelper<CompatibilityViewModel>::PropertyChanged;
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, AllowHeadless);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, IsolatedMode);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, DebugFeaturesEnabled);
GETSET_BINDABLE_ENUM_SETTING(TextMeasurement, winrt::Microsoft::Terminal::Control::TextMeasurement, _GlobalSettings.TextMeasurement);
private:
Model::GlobalAppSettings _GlobalSettings;
};
struct Compatibility : public HasScrollViewer<Compatibility>, CompatibilityT<Compatibility>
{
Compatibility();
void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
til::property_changed_event PropertyChanged;
WINRT_OBSERVABLE_PROPERTY(Editor::CompatibilityViewModel, ViewModel, PropertyChanged.raise, nullptr);
};
}
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
{
BASIC_FACTORY(Compatibility);
BASIC_FACTORY(CompatibilityViewModel);
}

View File

@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "EnumEntry.idl";
#include "ViewModelHelpers.idl.h"
namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass CompatibilityViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
CompatibilityViewModel(Microsoft.Terminal.Settings.Model.GlobalAppSettings globalSettings);
Boolean DebugFeaturesAvailable { get; };
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, AllowHeadless);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, IsolatedMode);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, DebugFeaturesEnabled);
IInspectable CurrentTextMeasurement;
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> TextMeasurementList { get; };
}
[default_interface] runtimeclass Compatibility : Windows.UI.Xaml.Controls.Page
{
Compatibility();
CompatibilityViewModel ViewModel { get; };
}
}

View File

@ -0,0 +1,56 @@
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<Page x:Class="Microsoft.Terminal.Settings.Editor.Compatibility"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="CommonResources.xaml" />
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:Key="EnumComboBoxTemplate"
x:DataType="local:EnumEntry">
<TextBlock Text="{x:Bind EnumName}" />
</DataTemplate>
</ResourceDictionary>
</Page.Resources>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Allow Headless -->
<local:SettingContainer x:Uid="Globals_AllowHeadless">
<ToggleSwitch IsOn="{x:Bind ViewModel.AllowHeadless, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Isolated Mode -->
<local:SettingContainer x:Uid="Globals_IsolatedMode">
<ToggleSwitch IsOn="{x:Bind ViewModel.IsolatedMode, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Text Measurement -->
<local:SettingContainer x:Uid="Globals_TextMeasurement">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.TextMeasurementList}"
SelectedItem="{x:Bind ViewModel.CurrentTextMeasurement, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}" />
</local:SettingContainer>
<!-- Debug Features -->
<local:SettingContainer x:Uid="Globals_DebugFeaturesEnabled"
Visibility="{x:Bind ViewModel.DebugFeaturesAvailable}">
<ToggleSwitch IsOn="{x:Bind ViewModel.DebugFeaturesEnabled, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
</StackPanel>
</Page>

View File

@ -6,6 +6,7 @@
#include "MainPage.g.cpp"
#include "Launch.h"
#include "Interaction.h"
#include "Compatibility.h"
#include "Rendering.h"
#include "RenderingViewModel.h"
#include "Actions.h"
@ -39,6 +40,7 @@ using namespace winrt::Windows::Foundation::Collections;
static const std::wstring_view launchTag{ L"Launch_Nav" };
static const std::wstring_view interactionTag{ L"Interaction_Nav" };
static const std::wstring_view renderingTag{ L"Rendering_Nav" };
static const std::wstring_view compatibilityTag{ L"Compatibility_Nav" };
static const std::wstring_view actionsTag{ L"Actions_Nav" };
static const std::wstring_view globalProfileTag{ L"GlobalProfile_Nav" };
static const std::wstring_view addProfileTag{ L"AddProfile" };
@ -339,6 +341,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_breadcrumbs.Append(crumb);
SettingsMainPage_ScrollViewer().ScrollToVerticalOffset(0);
}
else if (currentPage == ProfileSubPage::Terminal)
{
contentFrame().Navigate(xaml_typename<Editor::Profiles_Terminal>(), profile);
const auto crumb = winrt::make<Breadcrumb>(breadcrumbTag, RS_(L"Profile_Terminal/Header"), BreadcrumbSubPage::Profile_Terminal);
_breadcrumbs.Append(crumb);
SettingsMainPage_ScrollViewer().ScrollToVerticalOffset(0);
}
else if (currentPage == ProfileSubPage::Advanced)
{
contentFrame().Navigate(xaml_typename<Editor::Profiles_Advanced>(), profile);
@ -372,6 +381,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
const auto crumb = winrt::make<Breadcrumb>(box_value(clickedItemTag), RS_(L"Nav_Rendering/Content"), BreadcrumbSubPage::None);
_breadcrumbs.Append(crumb);
}
else if (clickedItemTag == compatibilityTag)
{
contentFrame().Navigate(xaml_typename<Editor::Compatibility>(), winrt::make<CompatibilityViewModel>(_settingsClone.GlobalSettings()));
const auto crumb = winrt::make<Breadcrumb>(box_value(clickedItemTag), RS_(L"Nav_Compatibility/Content"), BreadcrumbSubPage::None);
_breadcrumbs.Append(crumb);
}
else if (clickedItemTag == actionsTag)
{
contentFrame().Navigate(xaml_typename<Editor::Actions>(), winrt::make<ActionsViewModel>(_settingsClone));
@ -395,6 +410,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
profileVM.CurrentPage(ProfileSubPage::Appearance);
}
else if (subPage == BreadcrumbSubPage::Profile_Terminal)
{
profileVM.CurrentPage(ProfileSubPage::Terminal);
}
else if (subPage == BreadcrumbSubPage::Profile_Advanced)
{
profileVM.CurrentPage(ProfileSubPage::Advanced);
@ -452,6 +471,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
profile.CurrentPage(ProfileSubPage::Appearance);
}
else if (subPage == BreadcrumbSubPage::Profile_Terminal)
{
profile.CurrentPage(ProfileSubPage::Terminal);
}
else if (subPage == BreadcrumbSubPage::Profile_Advanced)
{
profile.CurrentPage(ProfileSubPage::Advanced);

View File

@ -17,6 +17,7 @@ namespace Microsoft.Terminal.Settings.Editor
{
None = 0,
Profile_Appearance,
Profile_Terminal,
Profile_Advanced,
ColorSchemes_Edit
};

View File

@ -135,6 +135,13 @@
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
<muxc:NavigationViewItem x:Uid="Nav_Compatibility"
Tag="Compatibility_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xEC7A;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
<muxc:NavigationViewItem x:Uid="Nav_Actions"
Tag="Actions_Nav">
<muxc:NavigationViewItem.Icon>

View File

@ -64,6 +64,9 @@
<ClInclude Include="Interaction.h">
<DependentUpon>Interaction.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="Compatibility.h">
<DependentUpon>Compatibility.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="KeyChordListener.h">
<DependentUpon>KeyChordListener.xaml</DependentUpon>
</ClInclude>
@ -118,6 +121,10 @@
<DependentUpon>Profiles_Appearance.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="Profiles_Terminal.h">
<DependentUpon>Profiles_Terminal.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="Appearances.h">
<DependentUpon>Appearances.xaml</DependentUpon>
<SubType>Code</SubType>
@ -154,6 +161,9 @@
<Page Include="Interaction.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="Compatibility.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="KeyChordListener.xaml">
<SubType>Designer</SubType>
</Page>
@ -172,6 +182,9 @@
<Page Include="Profiles_Appearance.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="Profiles_Terminal.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="Appearances.xaml">
<SubType>Designer</SubType>
</Page>
@ -204,6 +217,9 @@
<ClCompile Include="Interaction.cpp">
<DependentUpon>Interaction.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="Compatibility.cpp">
<DependentUpon>Compatibility.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="KeyChordListener.cpp">
<DependentUpon>KeyChordListener.xaml</DependentUpon>
</ClCompile>
@ -261,6 +277,10 @@
<DependentUpon>Profiles_Appearance.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="Profiles_Terminal.cpp">
<DependentUpon>Profiles_Terminal.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="Appearances.cpp">
<DependentUpon>Appearances.xaml</DependentUpon>
<SubType>Code</SubType>
@ -311,6 +331,10 @@
<DependentUpon>Interaction.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="Compatibility.idl">
<DependentUpon>Compatibility.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="Rendering.idl">
<DependentUpon>Rendering.xaml</DependentUpon>
<SubType>Code</SubType>
@ -338,6 +362,10 @@
<DependentUpon>Profiles_Appearance.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="Profiles_Terminal.idl">
<DependentUpon>Profiles_Terminal.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="Appearances.idl">
<DependentUpon>Appearances.xaml</DependentUpon>
<SubType>Code</SubType>

View File

@ -120,6 +120,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
OBSERVABLE_PROJECTED_SETTING(_profile, ShowMarks);
OBSERVABLE_PROJECTED_SETTING(_profile, AutoMarkPrompts);
OBSERVABLE_PROJECTED_SETTING(_profile, RepositionCursorWithMouse);
OBSERVABLE_PROJECTED_SETTING(_profile, ForceVTInput);
OBSERVABLE_PROJECTED_SETTING(_profile, AllowVtChecksumReport);
OBSERVABLE_PROJECTED_SETTING(_profile, AnswerbackMessage);
OBSERVABLE_PROJECTED_SETTING(_profile, RainbowSuggestions);
WINRT_PROPERTY(bool, IsBaseLayer, false);

View File

@ -29,7 +29,8 @@ namespace Microsoft.Terminal.Settings.Editor
{
Base = 0,
Appearance = 1,
Advanced = 2
Terminal = 2,
Advanced = 3
};
runtimeclass ProfileViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
@ -111,6 +112,9 @@ namespace Microsoft.Terminal.Settings.Editor
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, ShowMarks);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AutoMarkPrompts);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, RepositionCursorWithMouse);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, ForceVTInput);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AllowVtChecksumReport);
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, AnswerbackMessage);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, RainbowSuggestions);
}
}

View File

@ -37,15 +37,6 @@
Visibility="{x:Bind Profile.IsBaseLayer}" />
<StackPanel Grid.Row="1"
Style="{StaticResource SettingsStackStyle}">
<!-- Suppress Application Title -->
<local:SettingContainer x:Uid="Profile_SuppressApplicationTitle"
ClearSettingValue="{x:Bind Profile.ClearSuppressApplicationTitle}"
HasSettingValue="{x:Bind Profile.HasSuppressApplicationTitle, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.SuppressApplicationTitleOverrideSource, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind Profile.SuppressApplicationTitle, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Antialiasing Mode -->
<local:SettingContainer x:Uid="Profile_AntialiasingMode"
ClearSettingValue="{x:Bind Profile.ClearAntialiasingMode}"

View File

@ -24,6 +24,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
Automation::AutomationProperties::SetName(DeleteButton(), RS_(L"Profile_DeleteButton/Text"));
AppearanceNavigator().Content(box_value(RS_(L"Profile_Appearance/Header")));
TerminalNavigator().Content(box_value(RS_(L"Profile_Terminal/Header")));
AdvancedNavigator().Content(box_value(RS_(L"Profile_Advanced/Header")));
}
@ -66,6 +67,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_Profile.CurrentPage(ProfileSubPage::Appearance);
}
void Profiles_Base::Terminal_Click(const IInspectable& /*sender*/, const RoutedEventArgs& /*args*/)
{
_Profile.CurrentPage(ProfileSubPage::Terminal);
}
void Profiles_Base::Advanced_Click(const IInspectable& /*sender*/, const RoutedEventArgs& /*args*/)
{
_Profile.CurrentPage(ProfileSubPage::Advanced);

View File

@ -21,6 +21,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
safe_void_coroutine Icon_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
safe_void_coroutine Commandline_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void Appearance_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void Terminal_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void Advanced_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void DeleteConfirmation_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);

View File

@ -159,16 +159,13 @@
<Button x:Name="AppearanceNavigator"
Click="Appearance_Click"
Style="{StaticResource NavigatorButtonStyle}">
Appearance
</Button>
Style="{StaticResource NavigatorButtonStyle}" />
<Button x:Name="TerminalNavigator"
Click="Terminal_Click"
Style="{StaticResource NavigatorButtonStyle}" />
<Button x:Name="AdvancedNavigator"
Click="Advanced_Click"
Style="{StaticResource NavigatorButtonStyle}">
<TextBlock HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="Advanced" />
</Button>
Style="{StaticResource NavigatorButtonStyle}" />
<!-- Delete Button -->
<Border MaxWidth="{StaticResource StandardControlMaxWidth}">
<Button x:Name="DeleteButton"

View File

@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "Profiles_Terminal.h"
#include "Profiles_Terminal.g.cpp"
#include "ProfileViewModel.h"
#include "EnumEntry.h"
#include <LibraryResources.h>
#include "..\WinRTUtils\inc\Utils.h"
using namespace winrt::Windows::UI::Xaml::Navigation;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
Profiles_Terminal::Profiles_Terminal()
{
InitializeComponent();
}
void Profiles_Terminal::OnNavigatedTo(const NavigationEventArgs& e)
{
_Profile = e.Parameter().as<Editor::ProfileViewModel>();
}
void Profiles_Terminal::OnNavigatedFrom(const NavigationEventArgs& /*e*/)
{
_ViewModelChangedRevoker.revoke();
}
}

View File

@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "Profiles_Terminal.g.h"
#include "ViewModelHelpers.h"
#include "Utils.h"
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
struct Profiles_Terminal : public HasScrollViewer<Profiles_Terminal>, Profiles_TerminalT<Profiles_Terminal>
{
public:
Profiles_Terminal();
void OnNavigatedTo(const Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
void OnNavigatedFrom(const Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
til::property_changed_event PropertyChanged;
WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);
private:
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _ViewModelChangedRevoker;
};
};
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
{
BASIC_FACTORY(Profiles_Terminal);
}

View File

@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "ProfileViewModel.idl";
namespace Microsoft.Terminal.Settings.Editor
{
[default_interface] runtimeclass Profiles_Terminal : Windows.UI.Xaml.Controls.Page, Windows.UI.Xaml.Data.INotifyPropertyChanged
{
Profiles_Terminal();
ProfileViewModel Profile { get; };
}
}

View File

@ -0,0 +1,75 @@
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<Page x:Class="Microsoft.Terminal.Settings.Editor.Profiles_Terminal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="using:Microsoft.Terminal.Settings.Model"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="CommonResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock x:Uid="Profile_BaseLayerDisclaimer"
Grid.Row="0"
Margin="{StaticResource StandardIndentMargin}"
Style="{StaticResource DisclaimerStyle}"
Visibility="{x:Bind Profile.IsBaseLayer}" />
<StackPanel Grid.Row="1"
Style="{StaticResource SettingsStackStyle}">
<!-- Suppress Application Title -->
<local:SettingContainer x:Uid="Profile_SuppressApplicationTitle"
ClearSettingValue="{x:Bind Profile.ClearSuppressApplicationTitle}"
HasSettingValue="{x:Bind Profile.HasSuppressApplicationTitle, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.SuppressApplicationTitleOverrideSource, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind Profile.SuppressApplicationTitle, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Force VT Input -->
<local:SettingContainer x:Uid="Profile_ForceVTInput"
ClearSettingValue="{x:Bind Profile.ClearForceVTInput}"
HasSettingValue="{x:Bind Profile.HasForceVTInput, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.ForceVTInputOverrideSource, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind Profile.ForceVTInput, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Allow VT Checksum Report -->
<local:SettingContainer x:Uid="Profile_AllowVtChecksumReport"
ClearSettingValue="{x:Bind Profile.ClearAllowVtChecksumReport}"
HasSettingValue="{x:Bind Profile.HasAllowVtChecksumReport, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.AllowVtChecksumReportOverrideSource, Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind Profile.AllowVtChecksumReport, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Answerback Message -->
<local:SettingContainer x:Uid="Profile_AnswerbackMessage"
ClearSettingValue="{x:Bind Profile.ClearAnswerbackMessage}"
CurrentValue="{x:Bind Profile.AnswerbackMessage, Mode=OneWay}"
HasSettingValue="{x:Bind Profile.HasAnswerbackMessage, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.AnswerbackMessageOverrideSource, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyle}">
<TextBox Style="{StaticResource TextBoxSettingStyle}"
Text="{x:Bind Profile.AnswerbackMessage, Mode=TwoWay}" />
</local:SettingContainer>
</StackPanel>
</Grid>
</Page>

View File

@ -41,13 +41,5 @@
<ToggleSwitch IsOn="{x:Bind ViewModel.SoftwareRendering, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<local:SettingContainer x:Uid="Globals_TextMeasurement">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.TextMeasurementList}"
SelectedItem="{x:Bind ViewModel.CurrentTextMeasurement, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}" />
</local:SettingContainer>
</StackPanel>
</Page>

View File

@ -17,6 +17,5 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_settings{ std::move(settings) }
{
INITIALIZE_BINDABLE_ENUM_SETTING(GraphicsAPI, GraphicsAPI, winrt::Microsoft::Terminal::Control::GraphicsAPI, L"Globals_GraphicsAPI_", L"Text");
INITIALIZE_BINDABLE_ENUM_SETTING(TextMeasurement, TextMeasurement, winrt::Microsoft::Terminal::Control::TextMeasurement, L"Globals_TextMeasurement_", L"Text");
}
}

View File

@ -16,7 +16,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
GETSET_BINDABLE_ENUM_SETTING(GraphicsAPI, winrt::Microsoft::Terminal::Control::GraphicsAPI, _settings.GlobalSettings().GraphicsAPI);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_settings.GlobalSettings(), DisablePartialInvalidation);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_settings.GlobalSettings(), SoftwareRendering);
GETSET_BINDABLE_ENUM_SETTING(TextMeasurement, winrt::Microsoft::Terminal::Control::TextMeasurement, _settings.GlobalSettings().TextMeasurement);
private:
Model::CascadiaSettings _settings{ nullptr };

View File

@ -15,7 +15,5 @@ namespace Microsoft.Terminal.Settings.Editor
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> GraphicsAPIList { get; };
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, DisablePartialInvalidation);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, SoftwareRendering);
IInspectable CurrentTextMeasurement;
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> TextMeasurementList { get; };
}
}

View File

@ -560,10 +560,42 @@
<value>Always on top</value>
<comment>Header for a control to toggle if the app will always be presented on top of other windows, or is treated normally (when disabled).</comment>
</data>
<data name="Profile_ForceVTInput.Header" xml:space="preserve">
<value>Use the legacy input encoding</value>
<comment>Header for a control to toggle legacy input encoding for the terminal.</comment>
</data>
<data name="Profile_AllowVtChecksumReport.Header" xml:space="preserve">
<value>Allow DECRQCRA (Request Checksum of Rectangular Area)</value>
<comment>{Locked="DECRQCRA"}{Locked="Request Checksum of Rectangular Area"}Header for a control to toggle support for the DECRQCRA control sequence.</comment>
</data>
<data name="Globals_AllowHeadless.Header" xml:space="preserve">
<value>Allow Windows Terminal to run in the background</value>
<comment>Header for a control to toggle support for Windows Terminal to run in the background.</comment>
</data>
<data name="Globals_IsolatedMode.Header" xml:space="preserve">
<value>Force each window to run in its own process</value>
<comment>Header for a control to toggle making each window be its own process.</comment>
</data>
<data name="Globals_DebugFeaturesEnabled.Header" xml:space="preserve">
<value>Enable debugging features</value>
<comment>Header for a control to toggle debug features.</comment>
</data>
<data name="Globals_AlwaysOnTop.HelpText" xml:space="preserve">
<value>Terminal will always be the topmost window on the desktop.</value>
<comment>A description for what the "always on top" setting does. Presented near "Globals_AlwaysOnTop.Header".</comment>
</data>
<data name="Profile_ForceVTInput.HelpText" xml:space="preserve">
<value>Certain keyboard input in some applications may stop working properly when this setting is enabled.</value>
<comment>Additional description for what the "force vt input" setting does. Presented near "Globals_ForceVTInput.Header".</comment>
</data>
<data name="Globals_AllowHeadless.HelpText" xml:space="preserve">
<value>This allows actions such as Global Summon and Quake Mode actions to work even when no windows are open.</value>
<comment>Additional description for what the "allow headless" setting does. Presented near "Globals_AllowHeadless.Header".</comment>
</data>
<data name="Globals_IsolatedMode.HelpText" xml:space="preserve">
<value>Certain features will not work properly, including—but not limited to—global hotkeys, tab drag and drop, and wt.exe window targeting.</value>
<comment>{Locked="wt.exe"} Additional description for what the "isolated mode" setting does. Presented near "Globals_IsolatedMode.Header".</comment>
</data>
<data name="Globals_TabWidthMode.Header" xml:space="preserve">
<value>Tab width mode</value>
<comment>Header for a control to choose how wide the tabs are.</comment>
@ -632,6 +664,10 @@
<value>Interaction</value>
<comment>Header for the "interaction" menu item. This navigates to a page that lets you see and modify settings related to the user's mouse and touch interactions with the app.</comment>
</data>
<data name="Nav_Compatibility.Content" xml:space="preserve">
<value>Compatibility</value>
<comment>Header for the "compatibility" menu item. This navigates to a page that lets you see and modify settings related to compatibility with command line scenarios.</comment>
</data>
<data name="Nav_Launch.Content" xml:space="preserve">
<value>Startup</value>
<comment>Header for the "startup" menu item. This navigates to a page that lets you see and modify settings related to the app's launch experience (i.e. screen position, mode, etc.)</comment>
@ -668,6 +704,10 @@
<value>Advanced</value>
<comment>Header for a sub-page of profile settings focused on more advanced scenarios.</comment>
</data>
<data name="Profile_Terminal.Header" xml:space="preserve">
<value>Terminal Emulation</value>
<comment>Header for a sub-page of profile settings focused on customizing the capabilities of the terminal.</comment>
</data>
<data name="Profile_AltGrAliasing.Header" xml:space="preserve">
<value>AltGr aliasing</value>
<comment>Header for a control to toggle whether the app treats ctrl+alt as the AltGr (also known as the Alt Graph) modifier key found on keyboards. {Locked="AltGr"}</comment>
@ -1889,6 +1929,18 @@
<value>Non-monospace fonts:</value>
<comment>This is a label that is followed by a list of proportional fonts.</comment>
</data>
<data name="Profile_AnswerbackMessage.Header" xml:space="preserve">
<value>ENQ (Request Terminal Status) response</value>
<comment>{Locked=ENQ}{Locked="Request Terminal Status"} Header for a control to determine the response to the ENQ escape sequence. This is represented using a text box.</comment>
</data>
<data name="Profile_AnswerbackMessage.HelpText" xml:space="preserve">
<value>The response that is sent when an ENQ control sequence is received.</value>
<comment>{Locked=ENQ} A description for what the "ENQ response" setting does. Presented near "Profile_AnswerbackMessage".</comment>
</data>
<data name="Globals_DebugFeaturesEnabled.HelpText" xml:space="preserve">
<value>Useful for troubleshooting or developing Terminal.</value>
<comment>Additional description for what the "debug features enabled" setting does. Presented near "Globals_DebugFeaturesEnabled.Header".</comment>
</data>
<data name="Profile_RainbowSuggestions.Header" xml:space="preserve">
<value>Experimental: Display suggested input in rainbow colors</value>
<comment>This is a label for a setting that, when enabled, applies a rainbow coloring to the preview text from the suggestions UI.</comment>

View File

@ -524,6 +524,15 @@ bool SettingsLoader::FixupUserSettings()
fixedUp = true;
}
// Terminal 1.23: Migrate the global
// `experimental.input.forceVT` to being a per-profile setting.
if (userSettings.globals->LegacyForceVTInput())
{
// migrate the user's opt-out to the profiles.defaults
userSettings.baseLayerProfile->ForceVTInput(true);
fixedUp = true;
}
return fixedUp;
}

View File

@ -23,6 +23,7 @@ static constexpr std::string_view ThemeKey{ "theme" };
static constexpr std::string_view DefaultProfileKey{ "defaultProfile" };
static constexpr std::string_view LegacyUseTabSwitcherModeKey{ "useTabSwitcher" };
static constexpr std::string_view LegacyReloadEnvironmentVariablesKey{ "compatibility.reloadEnvironmentVariables" };
static constexpr std::string_view LegacyForceVTInputKey{ "experimental.input.forceVT" };
static constexpr std::string_view LegacyInputServiceWarningKey{ "inputServiceWarning" };
static constexpr std::string_view LegacyWarnAboutLargePasteKey{ "largePasteWarning" };
static constexpr std::string_view LegacyWarnAboutMultiLinePasteKey{ "multiLinePasteWarning" };
@ -171,6 +172,12 @@ void GlobalAppSettings::LayerJson(const Json::Value& json, const OriginTag origi
_logSettingSet(LegacyReloadEnvironmentVariablesKey);
}
JsonUtils::GetValueForKey(json, LegacyForceVTInputKey, _legacyForceVTInput);
if (json[LegacyForceVTInputKey.data()])
{
_logSettingSet(LegacyForceVTInputKey);
}
// Remove settings included in userDefaults
static constexpr std::array<std::pair<std::string_view, std::string_view>, 2> userDefaultSettings{ { { "copyOnSelect", "false" },
{ "copyFormatting", "false" } } };

View File

@ -71,6 +71,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
const Windows::Foundation::Collections::IMapView<winrt::hstring, Model::ColorScheme>& schemes);
bool LegacyReloadEnvironmentVariables() const noexcept { return _legacyReloadEnvironmentVariables; }
bool LegacyForceVTInput() const noexcept { return _legacyForceVTInput; }
void LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const;
@ -91,6 +92,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
winrt::guid _defaultProfile{};
bool _fixupsAppliedDuringLoad{ false };
bool _legacyReloadEnvironmentVariables{ true };
bool _legacyForceVTInput{ false };
winrt::com_ptr<implementation::ActionMap> _actionMap{ winrt::make_self<implementation::ActionMap>() };
std::set<std::string> _changeLog;

View File

@ -82,7 +82,6 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_SETTING(Boolean, SoftwareRendering);
INHERITABLE_SETTING(Microsoft.Terminal.Control.TextMeasurement, TextMeasurement);
INHERITABLE_SETTING(Boolean, UseBackgroundImageForWindow);
INHERITABLE_SETTING(Boolean, ForceVTInput);
INHERITABLE_SETTING(Boolean, DebugFeaturesEnabled);
INHERITABLE_SETTING(Boolean, StartOnUserLogin);
INHERITABLE_SETTING(Boolean, AlwaysOnTop);

View File

@ -30,7 +30,6 @@ Author(s):
X(winrt::Microsoft::Terminal::Control::TextMeasurement, TextMeasurement, "compatibility.textMeasurement") \
X(winrt::Microsoft::Terminal::Control::DefaultInputScope, DefaultInputScope, "defaultInputScope") \
X(bool, UseBackgroundImageForWindow, "experimental.useBackgroundImageForWindow", false) \
X(bool, ForceVTInput, "experimental.input.forceVT", false) \
X(bool, TrimBlockSelection, "trimBlockSelection", true) \
X(bool, DetectURLs, "experimental.detectURLs", true) \
X(bool, AlwaysShowTabs, "alwaysShowTabs", true) \
@ -100,7 +99,10 @@ Author(s):
X(bool, ShowMarks, "showMarksOnScrollbar", false) \
X(bool, RepositionCursorWithMouse, "experimental.repositionCursorWithMouse", false) \
X(bool, ReloadEnvironmentVariables, "compatibility.reloadEnvironmentVariables", true) \
X(bool, RainbowSuggestions, "experimental.rainbowSuggestions", false)
X(bool, RainbowSuggestions, "experimental.rainbowSuggestions", false) \
X(bool, ForceVTInput, "compatibility.input.forceVT", false) \
X(bool, AllowVtChecksumReport, "compatibility.allowDECRQCRA", false) \
X(bool, AllowKeypadMode, "compatibility.allowDECNKM", false)
// Intentionally omitted Profile settings:
// * Name

View File

@ -89,6 +89,8 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_PROFILE_SETTING(Boolean, ReloadEnvironmentVariables);
INHERITABLE_PROFILE_SETTING(Boolean, RainbowSuggestions);
INHERITABLE_PROFILE_SETTING(Boolean, ForceVTInput);
INHERITABLE_PROFILE_SETTING(Boolean, AllowVtChecksumReport);
INHERITABLE_PROFILE_SETTING(Boolean, AllowKeypadMode);
}
}

View File

@ -347,6 +347,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
_RepositionCursorWithMouse = profile.RepositionCursorWithMouse();
_ReloadEnvironmentVariables = profile.ReloadEnvironmentVariables();
_RainbowSuggestions = profile.RainbowSuggestions();
_ForceVTInput = profile.ForceVTInput();
_AllowVtChecksumReport = profile.AllowVtChecksumReport();
}
// Method Description:
@ -370,7 +372,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
_TextMeasurement = globalSettings.TextMeasurement();
_DefaultInputScope = globalSettings.DefaultInputScope();
_UseBackgroundImageForWindow = globalSettings.UseBackgroundImageForWindow();
_ForceVTInput = globalSettings.ForceVTInput();
_TrimBlockSelection = globalSettings.TrimBlockSelection();
_DetectURLs = globalSettings.DetectURLs();
_EnableUnfocusedAcrylic = globalSettings.EnableUnfocusedAcrylic();

View File

@ -94,6 +94,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::TerminalSettings, bool, CopyOnSelect, false);
INHERITABLE_SETTING(Model::TerminalSettings, Microsoft::Terminal::Control::CopyFormat, CopyFormatting, 0);
INHERITABLE_SETTING(Model::TerminalSettings, bool, FocusFollowMouse, false);
INHERITABLE_SETTING(Model::TerminalSettings, bool, AllowVtChecksumReport, false);
INHERITABLE_SETTING(Model::TerminalSettings, bool, TrimBlockSelection, true);
INHERITABLE_SETTING(Model::TerminalSettings, bool, DetectURLs, true);

View File

@ -124,8 +124,6 @@ namespace SettingsModelUnitTests
"trimPaste": true,
"experimental.input.forceVT": false,
"warning.confirmCloseAllTabs" : true,
"warning.inputService" : true,
"warning.largePaste" : true,

View File

@ -51,7 +51,8 @@
X(bool, DetectURLs, true) \
X(bool, AutoMarkPrompts) \
X(bool, RepositionCursorWithMouse, false) \
X(bool, RainbowSuggestions)
X(bool, RainbowSuggestions) \
X(bool, AllowVtChecksumReport)
// --------------------------- Control Settings ---------------------------
// All of these settings are defined in IControlSettings.

View File

@ -179,4 +179,11 @@
</alwaysEnabledBrandingTokens>
</feature>
<feature>
<name>Feature_DebugModeUI</name>
<description>Enables UI access to the debug mode setting</description>
<stage>AlwaysEnabled</stage>
<alwaysDisabledReleaseTokens/>
</feature>
</featureStaging>

View File

@ -130,6 +130,7 @@ public:
virtual void ScreenAlignmentPattern() = 0; // DECALN
virtual void SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) = 0; // DECSCUSR
virtual void SetVtChecksumReportSupport(const bool enabled) = 0;
virtual void SetClipboard(wil::zwstring_view content) = 0; // OSCSetClipboard

View File

@ -1304,6 +1304,11 @@ void AdaptDispatch::SelectAttributeChangeExtent(const DispatchTypes::ChangeExten
}
}
void AdaptDispatch::SetVtChecksumReportSupport(const bool enabled) noexcept
{
_vtChecksumReportEnabled = enabled;
}
// Routine Description:
// - DECRQCRA - Computes and reports a checksum of the specified area of
// the buffer memory.
@ -1320,59 +1325,62 @@ void AdaptDispatch::RequestChecksumRectangularArea(const VTInt id, const VTInt p
// If this feature is not enabled, we'll just report a zero checksum.
if constexpr (Feature_VtChecksumReport::IsEnabled())
{
// If the page number is 0, then we're meant to return a checksum of all
// of the pages, but we have no need for that, so we'll just return 0.
if (page != 0)
if (_vtChecksumReportEnabled)
{
// As part of the checksum, we need to include the color indices of each
// cell, and in the case of default colors, those indices come from the
// color alias table. But if they're not in the bottom 16 range, we just
// fallback to using white on black (7 and 0).
auto defaultFgIndex = _renderSettings.GetColorAliasIndex(ColorAlias::DefaultForeground);
auto defaultBgIndex = _renderSettings.GetColorAliasIndex(ColorAlias::DefaultBackground);
defaultFgIndex = defaultFgIndex < 16 ? defaultFgIndex : 7;
defaultBgIndex = defaultBgIndex < 16 ? defaultBgIndex : 0;
const auto target = _pages.Get(page);
const auto eraseRect = _CalculateRectArea(target, top, left, bottom, right);
for (auto row = eraseRect.top; row < eraseRect.bottom; row++)
// If the page number is 0, then we're meant to return a checksum of all
// of the pages, but we have no need for that, so we'll just return 0.
if (page != 0)
{
for (auto col = eraseRect.left; col < eraseRect.right; col++)
// As part of the checksum, we need to include the color indices of each
// cell, and in the case of default colors, those indices come from the
// color alias table. But if they're not in the bottom 16 range, we just
// fallback to using white on black (7 and 0).
auto defaultFgIndex = _renderSettings.GetColorAliasIndex(ColorAlias::DefaultForeground);
auto defaultBgIndex = _renderSettings.GetColorAliasIndex(ColorAlias::DefaultBackground);
defaultFgIndex = defaultFgIndex < 16 ? defaultFgIndex : 7;
defaultBgIndex = defaultBgIndex < 16 ? defaultBgIndex : 0;
const auto target = _pages.Get(page);
const auto eraseRect = _CalculateRectArea(target, top, left, bottom, right);
for (auto row = eraseRect.top; row < eraseRect.bottom; row++)
{
// The algorithm we're using here should match the DEC terminals
// for the ASCII and Latin-1 range. Their other character sets
// predate Unicode, though, so we'd need a custom mapping table
// to lookup the correct checksums. Considering this is only for
// testing at the moment, that doesn't seem worth the effort.
const auto cell = target.Buffer().GetCellDataAt({ col, row });
for (auto ch : cell->Chars())
for (auto col = eraseRect.left; col < eraseRect.right; col++)
{
// That said, I've made a special allowance for U+2426,
// since that is widely used in a lot of character sets.
checksum -= (ch == L'\u2426' ? 0x1B : ch);
// The algorithm we're using here should match the DEC terminals
// for the ASCII and Latin-1 range. Their other character sets
// predate Unicode, though, so we'd need a custom mapping table
// to lookup the correct checksums. Considering this is only for
// testing at the moment, that doesn't seem worth the effort.
const auto cell = target.Buffer().GetCellDataAt({ col, row });
for (auto ch : cell->Chars())
{
// That said, I've made a special allowance for U+2426,
// since that is widely used in a lot of character sets.
checksum -= (ch == L'\u2426' ? 0x1B : ch);
}
// Since we're attempting to match the DEC checksum algorithm,
// the only attributes affecting the checksum are the ones that
// were supported by DEC terminals.
const auto attr = cell->TextAttr();
checksum -= attr.IsProtected() ? 0x04 : 0;
checksum -= attr.IsInvisible() ? 0x08 : 0;
checksum -= attr.IsUnderlined() ? 0x10 : 0;
checksum -= attr.IsReverseVideo() ? 0x20 : 0;
checksum -= attr.IsBlinking() ? 0x40 : 0;
checksum -= attr.IsIntense() ? 0x80 : 0;
// For the same reason, we only care about the eight basic ANSI
// colors, although technically we also report the 8-16 index
// range. Everything else gets mapped to the default colors.
const auto colorIndex = [](const auto color, const auto defaultIndex) {
return color.IsLegacy() ? color.GetIndex() : defaultIndex;
};
const auto fgIndex = colorIndex(attr.GetForeground(), defaultFgIndex);
const auto bgIndex = colorIndex(attr.GetBackground(), defaultBgIndex);
checksum -= gsl::narrow_cast<uint16_t>(fgIndex << 4);
checksum -= gsl::narrow_cast<uint16_t>(bgIndex);
}
// Since we're attempting to match the DEC checksum algorithm,
// the only attributes affecting the checksum are the ones that
// were supported by DEC terminals.
const auto attr = cell->TextAttr();
checksum -= attr.IsProtected() ? 0x04 : 0;
checksum -= attr.IsInvisible() ? 0x08 : 0;
checksum -= attr.IsUnderlined() ? 0x10 : 0;
checksum -= attr.IsReverseVideo() ? 0x20 : 0;
checksum -= attr.IsBlinking() ? 0x40 : 0;
checksum -= attr.IsIntense() ? 0x80 : 0;
// For the same reason, we only care about the eight basic ANSI
// colors, although technically we also report the 8-16 index
// range. Everything else gets mapped to the default colors.
const auto colorIndex = [](const auto color, const auto defaultIndex) {
return color.IsLegacy() ? color.GetIndex() : defaultIndex;
};
const auto fgIndex = colorIndex(attr.GetForeground(), defaultFgIndex);
const auto bgIndex = colorIndex(attr.GetBackground(), defaultBgIndex);
checksum -= gsl::narrow_cast<uint16_t>(fgIndex << 4);
checksum -= gsl::narrow_cast<uint16_t>(bgIndex);
}
}
}

View File

@ -185,6 +185,8 @@ namespace Microsoft::Console::VirtualTerminal
void PlaySounds(const VTParameters parameters) override; // DECPS
void SetVtChecksumReportSupport(const bool enabled) noexcept override;
private:
enum class Mode
{
@ -307,6 +309,8 @@ namespace Microsoft::Console::VirtualTerminal
std::shared_ptr<SixelParser> _sixelParser;
std::unique_ptr<FontBuffer> _fontBuffer;
std::shared_ptr<MacroBuffer> _macroBuffer;
std::optional<unsigned int> _initialCodePage;
bool _vtChecksumReportEnabled = false;
// We have two instances of the saved cursor state, because we need
// one for the main buffer (at index 0), and another for the alt buffer

View File

@ -174,6 +174,8 @@ public:
StringHandler RestorePresentationState(const DispatchTypes::PresentationReportFormat /*format*/) override { return nullptr; } // DECRSPS
void PlaySounds(const VTParameters /*parameters*/) override{}; // DECPS
void SetVtChecksumReportSupport(const bool /*enabled*/) override{};
};
#pragma warning(default : 26440) // Restore "can be declared noexcept" warning

View File

@ -415,6 +415,7 @@ public:
auto& renderer = _testGetSet->_renderer;
auto& renderSettings = renderer._renderSettings;
auto adapter = std::make_unique<AdaptDispatch>(*_testGetSet, &renderer, renderSettings, _terminalInput);
adapter->SetVtChecksumReportSupport(true);
fSuccess = adapter.get() != nullptr;
if (fSuccess)