Compare commits

..

7 Commits

Author SHA1 Message Date
Gordon Lam (SH)
31aba26780 ci(wtr): fix cargo build PowerShell script and add x86 triple mapping
Two fixes:
1. Replace splat-array invocation with explicit if/else branches.
   The splat was passing a malformed argument (cargo's clap reported
   'unexpected argument "-"').
2. Add 'x86' -> 'i686-pc-windows-msvc' case in the switch and include
   that target in RustInstaller's additionalTargets. The pipeline matrix
   builds x86 too, not just x64/arm64.

Also added a LASTEXITCODE check so cargo build failures surface
properly even with ErrorActionPreference set.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-11 11:22:47 +08:00
Gordon Lam (SH)
754fff6915 ci(wtr): drop cratesIoFeedOverride; let config.toml + CargoAuthenticate own the registry
Investigation of the failing build showed that RustInstaller's
cratesIoFeedOverride parameter injects an env-var registry named
'ms_crates_io' that CargoAuthenticate cannot discover (it scans config
files only), so the override registry stays unauthenticated and Azure
Artifacts returns 404 on its sparse-index endpoint:

  note: name of alternative registry [...sudo_public_cargo...] set to ms_crates_io
  error: failed to query replaced source registry 'crates-io'
  Caused by: config.json not found in registry

Fix: remove cratesIoFeedOverride. The registry + source replacement
already live in src/tools/wtr/.cargo/config.toml, which CargoAuthenticate
reads and tokens. Cargo's normal config-file resolution then picks up
the authenticated registry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-11 10:55:30 +08:00
Gordon Lam (SH)
2bbdaf2e29 ci(wtr): add CargoAuthenticate@0 to issue Bearer token for Cargo feed
Mirrors microsoft/edit's 1ES Rust workflow. Without explicit auth,
Azure Artifacts returns 404 on the sparse index endpoint and cargo
reports 'config.json not found in registry'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-11 07:49:57 +08:00
Gordon Lam (SH)
9905c7ba49 ci(wtr): move Rust step early, harden VC tools workaround for empty-folder case (DD-1541167)
- Move Rust install/build before vcpkg/nuget/Set-LatestVCToolsVersion so
  Rust pipeline validation is independent of C++ build env setup.
- Patch Set-LatestVCToolsVersion.ps1 to also detect empty/partial VC
  tools folders (package metadata advertises a version but the folder
  has no bin/). Falls back to scanning siblings for a directory whose
  bin subdir actually contains files. Hard-fail if none found.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 10:41:20 +08:00
Yeelam Gordon
c1453406f3 ci(wtr): default-enable Rust build for ADO smoke test
Flips enableRustBuild parameter default from false to true so the gated Rust steps run on this branch when no top-level pipeline forwards the parameter (none currently do).

Revert before merging to main.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-08 12:31:15 +08:00
Gordon Lam (SH)
2eb4b9036d Forgot to add the empty one 2026-05-07 17:57:51 +08:00
Gordon Lam (SH)
edcf2fabe7 Add testing on Cargo.toml 2026-05-07 17:56:58 +08:00
39 changed files with 2480 additions and 203 deletions

View File

@@ -1075,7 +1075,6 @@ NOCONTEXTHELP
NOCOPYBITS
nodiscard
NODUP
NODEFAULT
noexcepts
NOFONT
NOHIDDENTEXT
@@ -1562,7 +1561,6 @@ SMARTQUOTE
SMTO
snapcx
snapcy
SND
snk
SOLIDBOX
Solutiondir

View File

@@ -21,6 +21,10 @@ parameters:
displayName: "Build Everything (Overrides all other build options)"
type: boolean
default: false
- name: enableRustBuild
displayName: "Build src/tools/wtr (requires RustInstaller extension + microsoft/Dart Azure Artifact feeds)"
type: boolean
default: true
- name: pgoBuildMode
type: string
default: None
@@ -166,6 +170,80 @@ jobs:
.\build\scripts\Generate-ThirdPartyNotices.ps1 -MarkdownNoticePath .\NOTICE.md -OutputPath .\src\cascadia\CascadiaPackage\NOTICE.html
displayName: Generate NOTICE.html from NOTICE.md
- ${{ if eq(parameters.enableRustBuild, true) }}:
# ────────────────────────────────────────────────────────────────────────
# Rust toolchain for src/tools/wtr (1ES-compliant pattern).
# Placed early — before vcpkg/nuget/VC-tools setup — so that Rust pipeline
# validation is independent of any C++ build environment problems.
#
# Pipeline lives at: https://microsoft.visualstudio.com/Dart/
# Reference for this pattern: microsoft/sudo (.pipelines/OneBranch.Common.yml)
#
# Compliance notes (per 1ES Rust workflow guidance):
# 1. Toolchain comes from the org-level `RustTools` Azure Artifact NuGet
# feed (already exists on `microsoft` ADO org; same feed used by
# microsoft/sudo, microsoft/vscode, microsoft/edit, microsoft/qdk).
# 2. Crates resolve through a project-level Azure Artifact Cargo feed
# named `Cargo` in microsoft/Dart (with crates.io upstream).
# 3. The Rust version uses the `ms-prod-X.YY` channel, pinned in
# `src/tools/wtr/rust-toolchain.toml`.
# 4. Component Governance scanning of Cargo.lock is auto-injected by
# 1ES PT (no extra task needed here).
#
# Prerequisites — until in place, leave `enableRustBuild` parameter false:
# - Azure Artifact Cargo feed `Cargo` exists in microsoft/Dart with
# `crates.io` upstream. (Project-scope, terminal team can create it.)
# - The CI account ("Project Collection Build Service (microsoft)") has
# at least Collaborator permission on the `RustTools` feed.
# ────────────────────────────────────────────────────────────────────────
- task: RustInstaller@1
displayName: Install Rust toolchain (MSRustup)
inputs:
rustVersion: ms-prod-1.93
toolchainFeed: https://pkgs.dev.azure.com/microsoft/_packaging/RustTools/nuget/v3/index.json
# NOTE: we deliberately do NOT set `cratesIoFeedOverride` here. That
# parameter injects an env-var registry override named `ms_crates_io`
# which CargoAuthenticate cannot see (it scans config files, not env
# vars), so the override registry ends up unauthenticated and Azure
# Artifacts returns 404 on its sparse-index endpoint.
# Instead, the registry + source replacement lives in
# src/tools/wtr/.cargo/config.toml — CargoAuthenticate@0 (next step)
# tokens it, and cargo's normal config-file resolution picks it up.
additionalTargets: 'x86_64-pc-windows-msvc i686-pc-windows-msvc aarch64-pc-windows-msvc'
# CargoAuthenticate issues a Bearer token (using System.AccessToken) for
# every Azure Artifacts Cargo feed referenced in the config file.
# Required: without it, Azure Artifacts returns 404 on the sparse index
# endpoint and cargo reports "config.json not found in registry".
# This is the canonical 1ES Rust auth pattern (mirrors microsoft/edit).
- task: CargoAuthenticate@0
displayName: Authenticate Cargo feeds
inputs:
configFile: src/tools/wtr/.cargo/config.toml
# Separate fetch step: some 1ES pools disable network during the build
# phase. Fetching upfront keeps `cargo build --frozen` fully offline.
- script: cargo fetch --manifest-path src/tools/wtr/Cargo.toml --locked
displayName: Fetch crates (offline-friendly)
- pwsh: |-
$ErrorActionPreference = 'Stop'
$triple = switch ('$(BuildPlatform)') {
'x64' { 'x86_64-pc-windows-msvc' }
'x86' { 'i686-pc-windows-msvc' }
'arm64' { 'aarch64-pc-windows-msvc' }
default { 'x86_64-pc-windows-msvc' }
}
$config = '$(BuildConfiguration)'
Write-Host "Building wtr for $triple ($config)"
if ($config -eq 'Release') {
cargo build --manifest-path src/tools/wtr/Cargo.toml --target $triple --frozen --release
} else {
cargo build --manifest-path src/tools/wtr/Cargo.toml --target $triple --frozen
}
if ($LASTEXITCODE -ne 0) { throw "cargo build failed with exit code $LASTEXITCODE" }
displayName: Build src/tools/wtr (Cargo)
- template: .\steps-install-vcpkg.yml
- template: .\steps-restore-nuget.yml

View File

@@ -10,13 +10,30 @@ $VCToolsRoot = Join-Path $VSRoot "VC\Tools\MSVC"
# differs from the version on the files themselves. We might as well check
# whether the version we just found _actually exists_ before we use it.
# We'll use whichever highest version exists.
#
# Some pool images report a package version (e.g. 14.44.35208) but ship only
# package metadata, not the actual toolchain — the version folder either
# doesn't exist or is empty. Detect both cases by also requiring a non-empty
# `bin` subdirectory (where cl.exe / link.exe live).
$PackageVCToolPath = Join-Path $VCToolsRoot $LatestVCToolsVersion
If ($Null -Eq (Get-Item $PackageVCToolPath -ErrorAction:Ignore)) {
$VCToolsVersions = Get-ChildItem $VCToolsRoot | ForEach-Object {
$PackageVCBinPath = Join-Path $PackageVCToolPath "bin"
$PackageIsValid = ($Null -Ne (Get-Item $PackageVCToolPath -ErrorAction:Ignore)) -And `
($Null -Ne (Get-Item $PackageVCBinPath -ErrorAction:Ignore))
If (-Not $PackageIsValid) {
$VCToolsVersions = Get-ChildItem $VCToolsRoot -Directory -ErrorAction:Ignore | Where-Object {
# Only consider directories that actually contain a populated `bin`.
$binDir = Join-Path $_.FullName "bin"
(Test-Path $binDir) -And ((Get-ChildItem $binDir -Recurse -File -ErrorAction:Ignore | Select-Object -First 1) -Ne $Null)
} | ForEach-Object {
[Version]$_.Name
} | Sort -Descending
$LatestActualVCToolsVersion = $VCToolsVersions | Select -First 1
If ($Null -Eq $LatestActualVCToolsVersion) {
Write-Error "No usable VC Tools installation found under $VCToolsRoot. Package version was $LatestVCToolsVersion. This typically indicates a partial/broken pool image (DD-1541167)."
Exit 1
}
If ([Version]$LatestVCToolsVersion -Ne $LatestActualVCToolsVersion) {
Write-Output "VC Tools Mismatch: Directory = $LatestActualVCToolsVersion, Package = $LatestVCToolsVersion"
$LatestVCToolsVersion = $LatestActualVCToolsVersion.ToString(3)

View File

@@ -2472,13 +2472,6 @@
},
"type": "array"
},
"safeUriSchemes": {
"description": "Specifies a list of URI schemes that are considered safe. No confirmation will be required to open URIs with these schemes.",
"items": {
"type": "string"
},
"type": "array"
},
"rendering.graphicsAPI": {
"description": "Direct3D 11 provides a more performant and feature-rich experience, whereas Direct2D is more stable. The default option \"Automatic\" will pick the API that best fits your graphics hardware. If you experience significant issues, consider using Direct2D.",
"type": "string",

View File

@@ -24,6 +24,21 @@
<EntryPointProjectUniqueName>..\WindowsTerminal\WindowsTerminal.vcxproj</EntryPointProjectUniqueName>
<DebuggerType>NativeOnly</DebuggerType>
</PropertyGroup>
<!-- Map MSBuild Platform to Rust target triple for wtr.exe inclusion. -->
<PropertyGroup>
<WtrRustTarget Condition="'$(Platform)'=='x64'">x86_64-pc-windows-msvc</WtrRustTarget>
<WtrRustTarget Condition="'$(Platform)'=='ARM64'">aarch64-pc-windows-msvc</WtrRustTarget>
<WtrRustProfile Condition="'$(Configuration)'=='Debug'">debug</WtrRustProfile>
<WtrRustProfile Condition="'$(Configuration)'!='Debug'">release</WtrRustProfile>
</PropertyGroup>
<ItemGroup>
<Content Include="$(SolutionDir)src\tools\wtr\target\$(WtrRustTarget)\$(WtrRustProfile)\wtr.exe"
Condition="Exists('$(SolutionDir)src\tools\wtr\target\$(WtrRustTarget)\$(WtrRustProfile)\wtr.exe')">
<Link>wtr.exe</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<PropertyGroup Condition="!Exists('CascadiaPackage_TemporaryKey.pfx')">
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
<AppxBundle>Never</AppxBundle>

View File

@@ -344,7 +344,7 @@
<TextBlock x:Name="_parentCommandText"
Padding="16,4"
VerticalAlignment="Center"
FontWeight="SemiBold"
FontStyle="Italic"
Text="{x:Bind ParentCommandName, Mode=OneWay}" />
</StackPanel>
@@ -358,8 +358,8 @@
<ScrollViewer MaxHeight="200"
VerticalScrollBarVisibility="Auto">
<TextBlock Text="{x:Bind ParsedCommandLineText, Mode=OneWay}"
TextAlignment="Left"
<TextBlock FontStyle="Italic"
Text="{x:Bind ParsedCommandLineText, Mode=OneWay}"
TextWrapping="Wrap" />
</ScrollViewer>
</Border>
@@ -371,6 +371,7 @@
Visibility="Collapsed">
<TextBlock Padding="12,0"
VerticalAlignment="Center"
FontStyle="Italic"
Text="{x:Bind NoMatchesText, Mode=OneWay}" />
</Border>

View File

@@ -152,8 +152,8 @@ namespace winrt::TerminalApp::implementation
}
else
{
// Default style: semibold
run.FontWeight(FontWeights::SemiBold());
// Default style: bold
run.FontWeight(FontWeights::Bold());
}
inlinesCollection.Append(run);

View File

@@ -443,13 +443,13 @@
<value>Open a new tab</value>
</data>
<data name="NewPaneRun.Text" xml:space="preserve">
<value>Alt + Click to split the current window</value>
<value>Alt+Click to split the current window</value>
</data>
<data name="NewWindowRun.Text" xml:space="preserve">
<value>Shift + Click to open a new window</value>
<value>Shift+Click to open a new window</value>
</data>
<data name="ElevatedRun.Text" xml:space="preserve">
<value>Ctrl + Click to open as administrator</value>
<value>Ctrl+Click to open as administrator</value>
</data>
<data name="WindowCloseButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Close</value>

View File

@@ -496,48 +496,12 @@
<value>第三方通知</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="ConfirmCloseDialog_Cancel" xml:space="preserve">
<value>取消</value>
</data>
<data name="ConfirmCloseDialog_CloseAllTitle" xml:space="preserve">
<value>是否要关闭所有窗口?</value>
</data>
<data name="ConfirmCloseDialog_CloseAllPrimary" xml:space="preserve">
<value>全部关闭</value>
</data>
<data name="ConfirmCloseDialog_WindowTitle" xml:space="preserve">
<value>是否要关闭所有标签页?</value>
</data>
<data name="ConfirmCloseDialog_WindowPrimary" xml:space="preserve">
<value>全部关闭</value>
</data>
<data name="ConfirmCloseDialog_TabTitle" xml:space="preserve">
<value>是否要关闭此选项卡?</value>
</data>
<data name="ConfirmCloseDialog_TabPrimary" xml:space="preserve">
<value>关闭选项卡</value>
</data>
<data name="ConfirmCloseDialog_PaneTitle" xml:space="preserve">
<value>是否要关闭此窗格?</value>
</data>
<data name="ConfirmCloseDialog_PanePrimary" xml:space="preserve">
<value>关闭窗格</value>
</data>
<data name="ConfirmCloseDialog_MultipleTabsTitle" xml:space="preserve">
<value>是否要关闭这些选项卡?</value>
</data>
<data name="ConfirmCloseDialog_MultipleTabsPrimary" xml:space="preserve">
<value>关闭选项卡</value>
</data>
<data name="ConfirmCloseDialog_MultiplePanesTitle" xml:space="preserve">
<value>是否要关闭这些窗格?</value>
</data>
<data name="ConfirmCloseDialog_MultiplePanesPrimary" xml:space="preserve">
<value>关闭窗格</value>
</data>
<data name="DontAskAgainCheckBox.Content" xml:space="preserve">
<value>不再询问</value>
</data>
<data name="CloseReadOnlyDialog.CloseButtonText" xml:space="preserve">
<value>取消</value>
</data>

View File

@@ -167,7 +167,7 @@
<TextBlock x:Name="_parentCommandText"
Padding="16,4"
VerticalAlignment="Center"
FontWeight="SemiBold"
FontStyle="Italic"
Text="{x:Bind ParentCommandName, Mode=OneWay}" />
</StackPanel>
@@ -179,6 +179,7 @@
Visibility="Collapsed">
<TextBlock Padding="12,0"
VerticalAlignment="Center"
FontStyle="Italic"
Text="{x:Bind NoMatchesText, Mode=OneWay}" />
</Border>
@@ -227,7 +228,7 @@
Visibility="Collapsed">
<TextBlock x:Name="_descriptionTitle"
FontSize="14"
FontWeight="SemiBold"
FontWeight="Bold"
IsTextSelectionEnabled="True"
TextWrapping="WrapWholeWords">
<TextBlock.ContextFlyout>

View File

@@ -235,14 +235,14 @@ namespace winrt::TerminalApp::implementation
auto textBlock = WUX::Controls::TextBlock{};
textBlock.TextWrapping(WUX::TextWrapping::Wrap);
textBlock.TextAlignment(WUX::TextAlignment::Left);
textBlock.TextAlignment(WUX::TextAlignment::Center);
textBlock.Inlines().Append(titleRun);
if (!_keyChord.empty())
{
auto keyChordRun = WUX::Documents::Run();
keyChordRun.Text(_keyChord);
textBlock.Inlines().Append(WUX::Documents::LineBreak{});
keyChordRun.FontStyle(winrt::Windows::UI::Text::FontStyle::Italic);
textBlock.Inlines().Append(WUX::Documents::LineBreak{});
textBlock.Inlines().Append(keyChordRun);
}

View File

@@ -71,9 +71,11 @@
<ToolTipService.ToolTip>
<ToolTip Placement="Mouse">
<TextBlock TextWrapping="Wrap">
<Run x:Uid="NewTabRun" /> <LineBreak /><LineBreak />
<Run x:Uid="NewPaneRun" /> <LineBreak />
<Run x:Uid="NewWindowRun" />
<Run x:Uid="NewTabRun" /> <LineBreak />
<Run x:Uid="NewPaneRun"
FontStyle="Italic" /> <LineBreak />
<Run x:Uid="NewWindowRun"
FontStyle="Italic" />
</TextBlock>
</ToolTip>
</ToolTipService.ToolTip>

View File

@@ -1295,15 +1295,17 @@ namespace winrt::TerminalApp::implementation
newTabRun.Text(RS_(L"NewTabRun/Text"));
auto newPaneRun = WUX::Documents::Run();
newPaneRun.Text(RS_(L"NewPaneRun/Text"));
newPaneRun.FontStyle(FontStyle::Italic);
auto newWindowRun = WUX::Documents::Run();
newWindowRun.Text(RS_(L"NewWindowRun/Text"));
newWindowRun.FontStyle(FontStyle::Italic);
auto elevatedRun = WUX::Documents::Run();
elevatedRun.Text(RS_(L"ElevatedRun/Text"));
elevatedRun.FontStyle(FontStyle::Italic);
auto textBlock = WUX::Controls::TextBlock{};
textBlock.Inlines().Append(newTabRun);
textBlock.Inlines().Append(WUX::Documents::LineBreak{});
textBlock.Inlines().Append(WUX::Documents::LineBreak{});
textBlock.Inlines().Append(newPaneRun);
textBlock.Inlines().Append(WUX::Documents::LineBreak{});
textBlock.Inlines().Append(newWindowRun);
@@ -3305,15 +3307,13 @@ namespace winrt::TerminalApp::implementation
return true;
}
bool TerminalPage::_IsUriConsideredSomewhatSafe(const winrt::Windows::Foundation::Uri& parsedUri) const
bool TerminalPage::_IsUriConsideredSomewhatSafe(const winrt::Windows::Foundation::Uri& parsedUri)
{
const auto& schemeName = parsedUri.SchemeName();
if (schemeName == L"http" || schemeName == L"https")
if (parsedUri.SchemeName() == L"http" || parsedUri.SchemeName() == L"https")
{
return true;
}
if (schemeName == L"file")
if (parsedUri.SchemeName() == L"file")
{
static const auto pathext{ wil::TryGetEnvironmentVariableW<std::wstring>(L"PATHEXT") };
const auto filename = parsedUri.Path();
@@ -3327,16 +3327,6 @@ namespace winrt::TerminalApp::implementation
return true;
}
if (const auto& safeSchemes = _settings.GlobalSettings().SafeUriSchemes())
{
for (const auto& scheme : safeSchemes)
{
if (til::equals_insensitive_ascii(schemeName, scheme))
{
return true;
}
}
}
return false;
}

View File

@@ -438,7 +438,7 @@ namespace winrt::TerminalApp::implementation
safe_void_coroutine _OpenHyperlinkHandler(const IInspectable sender, const Microsoft::Terminal::Control::OpenHyperlinkEventArgs eventArgs);
static bool _IsUriSupported(const winrt::Windows::Foundation::Uri& parsedUri);
bool _IsUriConsideredSomewhatSafe(const winrt::Windows::Foundation::Uri& parsedUri) const;
static bool _IsUriConsideredSomewhatSafe(const winrt::Windows::Foundation::Uri& parsedUri);
void _ShowCouldNotOpenDialog(winrt::hstring reason, winrt::hstring uri);
bool _CopyText(bool dismissSelection, bool singleLine, bool withControlSequences, Microsoft::Terminal::Control::CopyFormat formats);

View File

@@ -71,6 +71,18 @@ namespace winrt::TerminalApp::implementation
_removeControlEvents();
_control.Close();
// Clear out our media player callbacks, and stop any playing media. This
// will prevent the callback from being triggered after we've closed, and
// also make sure that our sound stops when we're closed.
if (_bellPlayer)
{
_bellPlayer.Pause();
_bellPlayer.Source(nullptr);
_bellPlayer.Close();
_bellPlayer = nullptr;
_bellPlayerCreated = false;
}
}
winrt::hstring TerminalPaneContent::Icon() const
@@ -263,15 +275,14 @@ namespace winrt::TerminalApp::implementation
auto sounds{ _profile.BellSound() };
if (sounds && sounds.Size() > 0)
{
// Sound paths are resolved and validated by CascadiaSettings
// before we reach this point.
auto soundPath{ sounds.GetAt(rand() % sounds.Size()).Resolved() };
PlaySoundW(soundPath.c_str(), nullptr, SND_FILENAME | SND_ASYNC | SND_SENTRY | SND_NODEFAULT);
winrt::hstring soundPath{ sounds.GetAt(rand() % sounds.Size()).Resolved() };
winrt::Windows::Foundation::Uri uri{ soundPath };
_playBellSound(uri);
}
else
{
const auto soundAlias = reinterpret_cast<LPCWSTR>(SND_ALIAS_SYSTEMHAND);
PlaySoundW(soundAlias, nullptr, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY);
const auto soundAlias = reinterpret_cast<LPCTSTR>(SND_ALIAS_SYSTEMHAND);
PlaySound(soundAlias, NULL, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY);
}
}
@@ -289,6 +300,33 @@ namespace winrt::TerminalApp::implementation
}
}
safe_void_coroutine TerminalPaneContent::_playBellSound(winrt::Windows::Foundation::Uri uri)
{
auto weakThis{ get_weak() };
co_await wil::resume_foreground(_control.Dispatcher());
if (auto pane{ weakThis.get() })
{
if (!_bellPlayerCreated)
{
// The MediaPlayer might not exist on Windows N SKU.
try
{
_bellPlayerCreated = true;
_bellPlayer = winrt::Windows::Media::Playback::MediaPlayer();
// GH#12258: The media keys (like play/pause) should have no effect on our bell sound.
_bellPlayer.CommandManager().IsEnabled(false);
}
CATCH_LOG();
}
if (_bellPlayer)
{
const auto source{ winrt::Windows::Media::Core::MediaSource::CreateFromUri(uri) };
const auto item{ winrt::Windows::Media::Playback::MediaPlaybackItem(source) };
_bellPlayer.Source(item);
_bellPlayer.Play();
}
}
}
void TerminalPaneContent::_closeTerminalRequestedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Windows::Foundation::IInspectable& /*args*/)
{

View File

@@ -76,6 +76,9 @@ namespace winrt::TerminalApp::implementation
std::shared_ptr<TerminalSettingsCache> _cache{};
bool _isDefTermSession{ false };
winrt::Windows::Media::Playback::MediaPlayer _bellPlayer{ nullptr };
bool _bellPlayerCreated{ false };
struct ControlEventTokens
{
winrt::Microsoft::Terminal::Control::TermControl::ConnectionStateChanged_revoker _ConnectionStateChanged;
@@ -93,6 +96,8 @@ namespace winrt::TerminalApp::implementation
void _setupControlEvents();
void _removeControlEvents();
safe_void_coroutine _playBellSound(winrt::Windows::Foundation::Uri uri);
safe_void_coroutine _controlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& /*args*/);
void _controlWarningBellHandler(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& e);

View File

@@ -925,7 +925,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Manually turn off acrylic if they turn off transparency.
_runtimeUseAcrylic = _settings.Opacity() < 1.0 && _settings.UseAcrylic();
const auto sizeChanged = _setFontSizeUnderLock(_settings.FontSize() + _accumulatedFontSizeDelta);
const auto sizeChanged = _setFontSizeUnderLock(_settings.FontSize());
// Update the terminal core with its new Core settings
_terminal->UpdateSettings(_settings);
@@ -1163,10 +1163,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - none
void ControlCore::ResetFontSize()
{
if (std::exchange(_accumulatedFontSizeDelta, 0.f) != 0.f)
const auto lock = _terminal->LockForWriting();
if (_setFontSizeUnderLock(_settings.FontSize()))
{
// No point in doing this if there was no delta.
AdjustFontSize(0);
_refreshSizeUnderLock();
}
}
@@ -1176,11 +1177,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - fontSizeDelta: The amount to increase or decrease the font size by.
void ControlCore::AdjustFontSize(float fontSizeDelta)
{
_accumulatedFontSizeDelta += fontSizeDelta;
const auto lock = _terminal->LockForWriting();
if (_setFontSizeUnderLock(_settings.FontSize() + _accumulatedFontSizeDelta))
if (_setFontSizeUnderLock(_desiredFont.GetFontSize() + fontSizeDelta))
{
_refreshSizeUnderLock();
}

View File

@@ -391,7 +391,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
bool _colorGlyphs = true;
CSSLengthPercentage _cellWidth;
CSSLengthPercentage _cellHeight;
float _accumulatedFontSizeDelta = 0.f; // Preserved across reloads to prevent user zoom from being overwritten.
// Rendering stuff.
winrt::handle _lastSwapChainHandle{ nullptr };

View File

@@ -98,6 +98,7 @@ void Terminal::UpdateSettings(ICoreSettings settings)
_answerbackMessage = settings.AnswerbackMessage();
_wordDelimiters = settings.WordDelimiters();
_suppressApplicationTitle = settings.SuppressApplicationTitle();
_startingTitle = settings.StartingTitle();
_trimBlockSelection = settings.TrimBlockSelection();
_autoMarkPrompts = settings.AutoMarkPrompts();
_rainbowSuggestions = settings.RainbowSuggestions();
@@ -123,11 +124,6 @@ void Terminal::UpdateSettings(ICoreSettings settings)
// Save the changes made above and in UpdateAppearance as the new default render settings.
GetRenderSettings().SaveDefaultSettings();
if (!_startingTitle)
{
_startingTitle = settings.StartingTitle();
}
if (!_startingTabColor && settings.StartingTabColor())
{
_startingTabColor = settings.StartingTabColor().Value();

View File

@@ -349,7 +349,7 @@ private:
::Microsoft::Console::VirtualTerminal::TerminalInput _terminalInput;
std::optional<std::wstring> _title;
std::optional<std::wstring> _startingTitle;
std::wstring _startingTitle;
std::optional<til::color> _startingTabColor;
std::vector<til::point_span> _searchHighlights;

View File

@@ -91,12 +91,8 @@ void Terminal::SetWindowTitle(const std::wstring_view title)
_assertLocked();
if (!_suppressApplicationTitle)
{
_title.reset();
if (!title.empty())
{
_title.emplace(title);
}
_pfnTitleChanged(GetConsoleTitle());
_title.emplace(title.empty() ? _startingTitle : title);
_pfnTitleChanged(_title.value());
}
}
@@ -116,13 +112,6 @@ bool Terminal::ResizeWindow(const til::CoordType width, const til::CoordType hei
return false;
}
const auto currentDimensions = _GetMutableViewport().Dimensions();
if (width == currentDimensions.width && height == currentDimensions.height)
{
return false;
}
if (_pfnWindowSizeChanged)
{
_pfnWindowSizeChanged(width, height);

View File

@@ -184,18 +184,11 @@ void Terminal::SelectNewRegion(const til::point coordStart, const til::point coo
std::wstring_view Terminal::GetConsoleTitle() const noexcept
{
_assertLocked();
if (_title)
if (_title.has_value())
{
return *_title;
}
if (_startingTitle)
{
return *_startingTitle;
}
return {};
return _startingTitle;
}
// Method Description:

View File

@@ -1334,6 +1334,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
const auto conflictingCmdName{ conflictingCmd.Name() };
TextBlock conflictingCommandNameTB{};
conflictingCommandNameTB.Text(fmt::format(L"\"{}\"", conflictingCmdName.empty() ? RS_(L"Actions_UnnamedCommandName") : conflictingCmdName));
conflictingCommandNameTB.FontStyle(Windows::UI::Text::FontStyle::Italic);
TextBlock confirmationQuestionTB{};
confirmationQuestionTB.Text(RS_(L"Actions_RenameConflictConfirmationQuestion"));

View File

@@ -19,6 +19,12 @@
<ResourceDictionary Source="CommonResources.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="ItalicDisclaimerStyle"
BasedOn="{StaticResource DisclaimerStyle}"
TargetType="TextBlock">
<Setter Property="FontStyle" Value="Italic" />
</Style>
<Style x:Key="CodeBlockStyle"
TargetType="TextBlock">
<Setter Property="FontFamily" Value="Cascadia Mono, Consolas" />

View File

@@ -121,7 +121,7 @@
Style="{StaticResource NewTabMenuEntryControlsWrapper}">
<TextBlock x:Uid="NewTabMenuEntry_Separator"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
FontStyle="Italic" />
</ContentControl>
</DataTemplate>
@@ -201,7 +201,7 @@
DataContext="{Binding Mode=OneWay}"
Style="{StaticResource NewTabMenuEntryControlsWrapper}">
<TextBlock VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
FontStyle="Italic"
Text="{x:Bind DisplayText, Mode=OneWay}" />
</ContentControl>
</DataTemplate>
@@ -213,7 +213,7 @@
Style="{StaticResource NewTabMenuEntryControlsWrapper}">
<TextBlock x:Uid="NewTabMenuEntry_RemainingProfiles"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
FontStyle="Italic" />
</ContentControl>
</DataTemplate>

View File

@@ -2201,26 +2201,10 @@
<value>关闭多个选项卡时发出警告</value>
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
</data>
<data name="Globals_ConfirmOnClose.Header" xml:space="preserve">
<value>关闭时发出警告</value>
<comment>Header for a dropdown controlling when to show a confirmation dialog before closing.</comment>
</data>
<data name="Globals_ConfirmOnClose.HelpText" xml:space="preserve">
<value>控制在关闭选项卡或窗口之前何时显示确认对话框。“始终”在关闭任何窗格时显示对话框。</value>
<comment>Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content.</comment>
</data>
<data name="Globals_ConfirmOnCloseNever.Content" xml:space="preserve">
<value>从不</value>
<comment>Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing.</comment>
</data>
<data name="Globals_ConfirmOnCloseAlways.Content" xml:space="preserve">
<value>始终</value>
<comment>Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing.</comment>
</data>
<data name="Globals_ConfirmOnCloseAutomatic.Content" xml:space="preserve">
<value>多个选项卡或窗格</value>
<comment>Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present.</comment>
</data>
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
<value>禁用“触摸键盘和手写面板服务”时发出警告</value>
</data>

View File

@@ -102,14 +102,6 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
globals->_DisabledProfileSources->Append(src);
}
}
if (_SafeUriSchemes)
{
globals->_SafeUriSchemes = winrt::single_threaded_vector<hstring>();
for (const auto& src : *_SafeUriSchemes)
{
globals->_SafeUriSchemes->Append(src);
}
}
for (const auto& parent : _parents)
{

View File

@@ -114,7 +114,6 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_SETTING(Boolean, EnableUnfocusedAcrylic);
INHERITABLE_SETTING(Boolean, AllowHeadless);
INHERITABLE_SETTING(String, SearchWebDefaultQueryUrl);
INHERITABLE_SETTING(IVector<String>, SafeUriSchemes);
Windows.Foundation.Collections.IMapView<String, ColorScheme> ColorSchemes();
void AddColorScheme(ColorScheme scheme);

View File

@@ -63,7 +63,6 @@ Author(s):
X(bool, MinimizeToNotificationArea, "minimizeToNotificationArea", false) \
X(bool, AlwaysShowNotificationIcon, "alwaysShowNotificationIcon", false) \
X(winrt::Windows::Foundation::Collections::IVector<winrt::hstring>, DisabledProfileSources, "disabledProfileSources", nullptr) \
X(winrt::Windows::Foundation::Collections::IVector<winrt::hstring>, SafeUriSchemes, "safeUriSchemes", nullptr) \
X(bool, ShowAdminShield, "showAdminShield", true) \
X(bool, TrimPaste, "trimPaste", true) \
X(bool, EnableColorSelection, "experimental.enableColorSelection", false) \

View File

@@ -467,7 +467,6 @@ namespace SettingsModelUnitTests
"$schema" : "https://aka.ms/terminal-profiles-schema",
"defaultProfile": "{61c54bbd-1111-5271-96e7-009a87ff44bf}",
"disabledProfileSources": [ "Windows.Terminal.Wsl" ],
"safeUriSchemes": [ "vscode" ],
"newTabMenu":
[
{

View File

@@ -123,7 +123,6 @@ class ScreenBufferTests
TEST_METHOD(VtResizePreservingAttributes);
TEST_METHOD(VtSoftResetCursorPosition);
TEST_METHOD(VtSoftResetAltBufferCursorState);
TEST_METHOD(VtScrollMarginsNewlineColor);
@@ -1511,30 +1510,6 @@ void ScreenBufferTests::VtSoftResetCursorPosition()
VERIFY_ARE_EQUAL(til::point(1, 1), cursor.GetPosition());
}
void ScreenBufferTests::VtSoftResetAltBufferCursorState()
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
gci.LockConsole(); // Lock must be taken to manipulate buffer.
auto unlock = wil::scope_exit([&] { gci.UnlockConsole(); });
auto& si = gci.GetActiveOutputBuffer();
auto& stateMachine = si.GetStateMachine();
Log::Comment(L"Move cursor on the main buffer.");
stateMachine.ProcessString(L"\x1b[4;7H");
VERIFY_ARE_EQUAL(til::point(6, 3), si.GetTextBuffer().GetCursor().GetPosition());
Log::Comment(L"Enter alt buffer, soft reset, and return to main buffer.");
stateMachine.ProcessString(L"\x1b[?1049h");
VERIFY_IS_TRUE(gci.GetActiveOutputBuffer()._IsAltBuffer());
stateMachine.ProcessString(L"\x1b[!p");
stateMachine.ProcessString(L"\x1b[?1049l");
VERIFY_IS_FALSE(gci.GetActiveOutputBuffer()._IsAltBuffer());
Log::Comment(L"Returning from alt buffer should restore the main cursor position.");
VERIFY_ARE_EQUAL(til::point(6, 3), gci.GetActiveOutputBuffer().GetTextBuffer().GetCursor().GetPosition());
}
void ScreenBufferTests::VtScrollMarginsNewlineColor()
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();

View File

@@ -90,15 +90,7 @@ std::function<bool(wchar_t)> SixelParser::DefineImage(const VTInt macroParameter
_state = States::Normal;
_parameters.clear();
return [&](const auto ch) {
try
{
_parseCommandChar(ch);
}
catch (...)
{
// Ignore all further content.
return false;
}
_parseCommandChar(ch);
return true;
};
}
@@ -242,18 +234,10 @@ void SixelParser::_executeNextLine()
_executeCarriageReturn();
_imageLineCount++;
_maybeFlushImageBuffer();
// If we don't have any available pixel height, that means the image has
// extended beyond the bottom of the display and we haven't triggered a
// a scroll (because sixel display mode is enabled). In this state, there
// is no point in extending the image any further, because the additional
// content will never be seen, so we'll just be wasting memory.
if (_availablePixelHeight > 0)
{
_imageCursor.y += _sixelHeight;
_availablePixelHeight -= _sixelHeight;
_resizeImageBuffer(_sixelHeight);
_fillImageBackgroundWhenScrolled();
}
_imageCursor.y += _sixelHeight;
_availablePixelHeight -= _sixelHeight;
_resizeImageBuffer(_sixelHeight);
_fillImageBackgroundWhenScrolled();
}
void SixelParser::_executeMoveToHome()

View File

@@ -3002,15 +3002,17 @@ void AdaptDispatch::SoftReset()
SetGraphicsRendition({}); // Normal rendition.
SetCharacterProtectionAttribute({}); // Default (unprotected)
// Reset only the active saved cursor state.
// This matches xterm behavior when DECSTR is processed while using
// the alternate screen buffer (GH#19918).
_savedCursorState.at(_usingAltBuffer ? 1 : 0) = {};
// Reset the saved cursor state.
// Note that XTerm only resets the main buffer state, but that
// seems likely to be a bug. Most other terminals reset both.
_savedCursorState.at(0) = {}; // Main buffer
_savedCursorState.at(1) = {}; // Alt buffer
// The TerminalOutput state in this buffer must be reset to
// The TerminalOutput state in these buffers must be reset to
// the same state as the _termOutput instance, which is not
// necessarily equivalent to a full reset.
_savedCursorState.at(_usingAltBuffer ? 1 : 0).TermOutput = _termOutput;
_savedCursorState.at(0).TermOutput = _termOutput;
_savedCursorState.at(1).TermOutput = _termOutput;
// Soft reset the Sixel parser if in use.
if (_sixelParser)

View File

@@ -0,0 +1,12 @@
# Cargo source replacement: route crates-io fetches through an Azure Artifact
# Cargo feed (1ES compliance — disallow direct public crates.io access).
#
# Reusing the sudo team's `sudo_public_cargo` feed in microsoft/Dart for now.
# TODO(wtr): replace with our own `microsoft/Dart` Cargo feed once provisioned.
[registries]
WindowsTerminalCargo = { index = "sparse+https://pkgs.dev.azure.com/microsoft/Dart/_packaging/sudo_public_cargo/Cargo/index/" }
[source.crates-io]
replace-with = "WindowsTerminalCargo"

1
src/tools/wtr/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target/

2208
src/tools/wtr/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

32
src/tools/wtr/Cargo.toml Normal file
View File

@@ -0,0 +1,32 @@
[package]
name = "wtr"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "wtr"
path = "src/main.rs"
[dependencies]
tokio = { version = "1", features = ["full"] }
tokio-util = { version = "0.7", features = ["compat"] }
async-trait = "0.1"
anyhow = "1"
serde_json = "1"
clap = { version = "4", features = ["derive"] }
ratatui = "0.30"
crossterm = { version = "0.29", features = ["event-stream"] }
futures = "0.3"
unicode-width = "0.2"
textwrap = "0.16"
base64 = "0.22"
serde = { version = "1", features = ["derive"] }
windows-sys = { version = "0.61", features = [
"Win32_Foundation",
"Win32_System_Environment",
"Win32_System_Registry",
"Win32_System_Threading",
] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
tracing-appender = "0.2"

View File

@@ -0,0 +1,4 @@
# Pin the Rust toolchain channel for both local dev and 1ES CI.
# Use the MSRustup `ms-prod-X.YY` channel for compliance.
[toolchain]
channel = "ms-prod-1.93"

View File

@@ -0,0 +1 @@
fn main() {}