Merge remote-tracking branch 'origin/main' into feature/llm

# Conflicts:
#	src/cascadia/TerminalApp/TabManagement.cpp
#	src/cascadia/TerminalApp/TerminalPage.h
This commit is contained in:
Dustin L. Howett 2024-08-26 08:18:01 -07:00
commit 8fe47932da
112 changed files with 1832 additions and 632 deletions

View File

@ -28,6 +28,7 @@ godbolt
gpt
hyperlinking
hyperlinks
Kbds
kje
libfuzzer
liga
@ -44,6 +45,7 @@ mkmk
mnt
mru
nje
NTMTo
notwrapped
ogonek
openai

View File

@ -9,7 +9,6 @@ ABORTIFHUNG
ACCESSTOKEN
acidev
ACIOSS
ACover
acp
actctx
ACTCTXW
@ -87,6 +86,7 @@ Autowrap
AVerify
awch
azurecr
AZZ
backgrounded
Backgrounder
backgrounding
@ -180,7 +180,6 @@ CFuzz
cgscrn
chafa
changelists
charinfo
CHARSETINFO
chh
chshdng
@ -264,7 +263,6 @@ consolegit
consolehost
CONSOLEIME
consoleinternal
Consoleroot
CONSOLESETFOREGROUND
consoletaeftemplates
consoleuwp
@ -386,7 +384,7 @@ DECCIR
DECCKM
DECCKSR
DECCOLM
DECCRA
deccra
DECCTR
DECDC
DECDHL
@ -398,7 +396,7 @@ DECEKBD
DECERA
DECFI
DECFNK
DECFRA
decfra
DECGCI
DECGCR
DECGNL
@ -727,7 +725,6 @@ GHIJKL
gitcheckin
gitfilters
gitlab
gitmodules
gle
GLOBALFOCUS
GLYPHENTRY
@ -1021,7 +1018,6 @@ lstatus
lstrcmp
lstrcmpi
LTEXT
LTLTLTLTL
ltsc
LUID
luma
@ -1116,7 +1112,6 @@ msrc
MSVCRTD
MTSM
Munged
munges
murmurhash
muxes
myapplet
@ -1218,7 +1213,6 @@ ntlpcapi
ntm
ntrtl
ntstatus
NTSYSCALLAPI
nttree
nturtl
ntuser
@ -1526,7 +1520,6 @@ rftp
rgbi
RGBQUAD
rgbs
rgci
rgfae
rgfte
rgn
@ -1604,6 +1597,7 @@ SELECTALL
SELECTEDFONT
SELECTSTRING
Selfhosters
Serbo
SERVERDLL
SETACTIVE
SETBUDDYINT
@ -1832,8 +1826,6 @@ TOPDOWNDIB
TOpt
tosign
touchpad
Tpp
Tpqrst
tracelogging
traceviewpp
trackbar
@ -1958,7 +1950,6 @@ VPACKMANIFESTDIRECTORY
VPR
VREDRAW
vsc
vsconfig
vscprintf
VSCROLL
vsdevshell
@ -2000,7 +1991,6 @@ wcswidth
wddm
wddmcon
WDDMCONSOLECONTEXT
WDK
wdm
webpage
websites
@ -2074,7 +2064,6 @@ winuserp
WINVER
wistd
wmain
wmemory
WMSZ
wnd
WNDALLOC
@ -2173,6 +2162,7 @@ yact
YCast
YCENTER
YCount
yizz
YLimit
YPan
YSubstantial
@ -2186,3 +2176,4 @@ ZCtrl
ZWJs
ZYXWVU
ZYXWVUTd
zzf

View File

@ -23,6 +23,12 @@
"name": "Upload package to nuget feed",
"icon": "\uE898",
"description": "Go download a .nupkg, put it in ~/Downloads, and use this to push to our private feed."
},
{
"input": "runut /name:**\u001b[D",
"name": "Run a test",
"icon": "",
"description": "Enter the name of a test to run"
}
]
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. See LICENSE in the project root for license information. -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Native-Platform Condition="'$(Platform)' == 'Win32'">x86</Native-Platform>
<Native-Platform Condition="'$(Platform)' != 'Win32'">$(Platform)</Native-Platform>
</PropertyGroup>
<ItemGroup>
<Reference Include="$(WinGetPackageRoot)\lib\Microsoft.Management.Deployment.winmd">
<IsWinMDFile>true</IsWinMDFile>
</Reference>
</ItemGroup>
<Target Name="_FixWinGetWinmdPackaging" BeforeTargets="_ComputeAppxPackagePayload">
<ItemGroup>
<PackagingOutputs Include="$(WinGetPackageRoot)\lib\Microsoft.Management.Deployment.winmd">
<OutputGroup>CustomOutputGroupForPackaging</OutputGroup>
<ProjectName>$(ProjectName)</ProjectName>
<TargetPath>Microsoft.Management.Deployment.winmd</TargetPath>
</PackagingOutputs>
</ItemGroup>
</Target>
</Project>

View File

@ -5,7 +5,7 @@
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
<XesBaseYearForStoreVersion>2024</XesBaseYearForStoreVersion>
<VersionMajor>1</VersionMajor>
<VersionMinor>22</VersionMinor>
<VersionMinor>23</VersionMinor>
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
</PropertyGroup>
</Project>

View File

@ -10,6 +10,7 @@
<package id="Microsoft.UI.Xaml" version="2.8.4" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.1661.34" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.240122.1" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.WindowsPackageManager.ComInterop" version="1.8.1911" targetFramework="native" developmentDependency="true" />
<!-- Managed packages -->
<package id="Appium.WebDriver" version="3.0.0.2" targetFramework="net45" />

View File

@ -3266,23 +3266,30 @@ MarkExtents TextBuffer::_scrollMarkExtentForRow(const til::CoordType rowOffset,
return mark;
}
std::wstring TextBuffer::_commandForRow(const til::CoordType rowOffset, const til::CoordType bottomInclusive) const
std::wstring TextBuffer::_commandForRow(const til::CoordType rowOffset,
const til::CoordType bottomInclusive,
const bool clipAtCursor) const
{
std::wstring commandBuilder;
MarkKind lastMarkKind = MarkKind::Prompt;
const auto cursorPosition = GetCursor().GetPosition();
for (auto y = rowOffset; y <= bottomInclusive; y++)
{
const bool onCursorRow = clipAtCursor && y == cursorPosition.y;
// Now we need to iterate over text attributes. We need to find a
// segment of Prompt attributes, we'll skip those. Then there should be
// Command attributes. Collect up all of those, till we get to the next
// Output attribute.
const auto& row = GetRowByOffset(y);
const auto runs = row.Attributes().runs();
auto x = 0;
for (const auto& [attr, length] : runs)
{
const auto nextX = gsl::narrow_cast<uint16_t>(x + length);
auto nextX = gsl::narrow_cast<uint16_t>(x + length);
if (onCursorRow)
{
nextX = std::min(nextX, gsl::narrow_cast<uint16_t>(cursorPosition.x));
}
const auto markKind{ attr.GetMarkAttributes() };
if (markKind != lastMarkKind)
{
@ -3302,6 +3309,10 @@ std::wstring TextBuffer::_commandForRow(const til::CoordType rowOffset, const ti
}
// advance to next run of text
x = nextX;
if (onCursorRow && x == cursorPosition.x)
{
return commandBuilder;
}
}
// we went over all the runs in this row, but we're not done yet. Keep iterating on the next row.
}
@ -3325,7 +3336,7 @@ std::wstring TextBuffer::CurrentCommand() const
// This row did start a prompt! Find the prompt that starts here.
// Presumably, no rows below us will have prompts, so pass in the last
// row with text as the bottom
return _commandForRow(promptY, _estimateOffsetOfLastCommittedRow());
return _commandForRow(promptY, _estimateOffsetOfLastCommittedRow(), true);
}
return L"";
}

View File

@ -326,7 +326,7 @@ private:
til::point _GetWordEndForSelection(const til::point target, const std::wstring_view wordDelimiters) const;
void _PruneHyperlinks();
std::wstring _commandForRow(const til::CoordType rowOffset, const til::CoordType bottomInclusive) const;
std::wstring _commandForRow(const til::CoordType rowOffset, const til::CoordType bottomInclusive, const bool clipAtCursor = false) const;
MarkExtents _scrollMarkExtentForRow(const til::CoordType rowOffset, const til::CoordType bottomInclusive) const;
bool _createPromptMarkIfNeeded();

View File

@ -442,16 +442,16 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
winrt::get_self<implementation::Peasant>(peasant)->ActiveTabTitle(title);
}
winrt::fire_and_forget WindowManager::RequestMoveContent(winrt::hstring window,
winrt::hstring content,
uint32_t tabIndex,
Windows::Foundation::IReference<Windows::Foundation::Rect> windowBounds)
safe_void_coroutine WindowManager::RequestMoveContent(winrt::hstring window,
winrt::hstring content,
uint32_t tabIndex,
Windows::Foundation::IReference<Windows::Foundation::Rect> windowBounds)
{
co_await winrt::resume_background();
_monarch.RequestMoveContent(window, content, tabIndex, windowBounds);
}
winrt::fire_and_forget WindowManager::RequestSendContent(Remoting::RequestReceiveContentArgs args)
safe_void_coroutine WindowManager::RequestSendContent(Remoting::RequestReceiveContentArgs args)
{
co_await winrt::resume_background();
_monarch.RequestSendContent(args);

View File

@ -43,8 +43,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
bool DoesQuakeWindowExist();
winrt::fire_and_forget RequestMoveContent(winrt::hstring window, winrt::hstring content, uint32_t tabIndex, Windows::Foundation::IReference<Windows::Foundation::Rect> windowBounds);
winrt::fire_and_forget RequestSendContent(Remoting::RequestReceiveContentArgs args);
safe_void_coroutine RequestMoveContent(winrt::hstring window, winrt::hstring content, uint32_t tabIndex, Windows::Foundation::IReference<Windows::Foundation::Rect> windowBounds);
safe_void_coroutine RequestSendContent(Remoting::RequestReceiveContentArgs args);
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs> FindTargetWindowRequested;

View File

@ -58,7 +58,7 @@ namespace winrt::TerminalApp::implementation
ShellExecute(nullptr, nullptr, currentPath.c_str(), nullptr, nullptr, SW_SHOW);
}
winrt::fire_and_forget AboutDialog::_queueUpdateCheck()
safe_void_coroutine AboutDialog::_queueUpdateCheck()
{
auto strongThis = get_strong();
auto now{ std::chrono::system_clock::now() };

View File

@ -26,7 +26,7 @@ namespace winrt::TerminalApp::implementation
void _ThirdPartyNoticesOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
void _SendFeedbackOnClick(const IInspectable& sender, const Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs& eventArgs);
winrt::fire_and_forget _queueUpdateCheck();
safe_void_coroutine _queueUpdateCheck();
};
}

View File

@ -900,7 +900,7 @@ namespace winrt::TerminalApp::implementation
// - <none>
// Important: Don't take the param by reference, since we'll be doing work
// on another thread.
fire_and_forget TerminalPage::_OpenNewWindow(const INewContentArgs newContentArgs)
safe_void_coroutine TerminalPage::_OpenNewWindow(const INewContentArgs newContentArgs)
{
auto terminalArgs{ newContentArgs.try_as<NewTerminalArgs>() };
@ -1458,7 +1458,7 @@ namespace winrt::TerminalApp::implementation
}
}
winrt::fire_and_forget TerminalPage::_doHandleSuggestions(SuggestionsArgs realArgs)
safe_void_coroutine TerminalPage::_doHandleSuggestions(SuggestionsArgs realArgs)
{
const auto source = realArgs.Source();
std::vector<Command> commandsCollection;

View File

@ -355,7 +355,7 @@ namespace winrt::TerminalApp::implementation
}
CATCH_LOG()
fire_and_forget AppLogic::_ApplyStartupTaskStateChange()
safe_void_coroutine AppLogic::_ApplyStartupTaskStateChange()
try
{
// First, make sure we're running in a packaged context. This method
@ -432,6 +432,10 @@ namespace winrt::TerminalApp::implementation
return;
}
}
else
{
_settings.LogSettingChanges(true);
}
if (initialLoad)
{

View File

@ -103,12 +103,12 @@ namespace winrt::TerminalApp::implementation
const Microsoft::Terminal::Settings::Model::WindowingMode& windowingBehavior);
void _ApplyLanguageSettingChange() noexcept;
fire_and_forget _ApplyStartupTaskStateChange();
safe_void_coroutine _ApplyStartupTaskStateChange();
[[nodiscard]] HRESULT _TryLoadSettings() noexcept;
void _ProcessLazySettingsChanges();
void _RegisterSettingsChange();
fire_and_forget _DispatchReloadSettings();
safe_void_coroutine _DispatchReloadSettings();
void _setupFolderPathEnvVar();

View File

@ -1204,8 +1204,6 @@ namespace winrt::TerminalApp::implementation
{
Visibility(Visibility::Collapsed);
PreviewAction.raise(*this, nullptr);
// Reset visibility in case anchor mode tab switcher just finished.
_searchBox().Visibility(Visibility::Visible);
@ -1216,6 +1214,7 @@ namespace winrt::TerminalApp::implementation
ParentCommandName(L"");
_currentNestedCommands.Clear();
PreviewAction.raise(*this, nullptr);
}
void CommandPalette::EnableTabSwitcherMode(const uint32_t startIdx, TabSwitcherMode tabSwitcherMode)

View File

@ -21,7 +21,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
}
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) {}
~DebugInputTapConnection() = default;
winrt::fire_and_forget Start()
safe_void_coroutine Start()
{
// GH#11282: It's possible that we're about to be started, _before_
// our paired connection is started. Both will get Start()'ed when

View File

@ -60,7 +60,7 @@ static std::wstring _normalizeIconPath(std::wstring_view path)
// - settings - The settings object to update the jumplist with.
// Return Value:
// - <none>
winrt::fire_and_forget Jumplist::UpdateJumplist(const CascadiaSettings& settings) noexcept
safe_void_coroutine Jumplist::UpdateJumplist(const CascadiaSettings& settings) noexcept
{
if (!settings)
{

View File

@ -18,7 +18,7 @@ struct IShellLinkW;
class Jumplist
{
public:
static winrt::fire_and_forget UpdateJumplist(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) noexcept;
static safe_void_coroutine UpdateJumplist(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) noexcept;
private:
static void _updateProfiles(IObjectCollection* jumplistItems, winrt::Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Terminal::Settings::Model::Profile> profiles);

View File

@ -21,7 +21,8 @@ namespace winrt
namespace winrt::TerminalApp::implementation
{
SnippetsPaneContent::SnippetsPaneContent()
SnippetsPaneContent::SnippetsPaneContent() :
_allTasks{ winrt::single_threaded_observable_vector<TerminalApp::FilteredTask>() }
{
InitializeComponent();
@ -42,7 +43,7 @@ namespace winrt::TerminalApp::implementation
}
}
winrt::fire_and_forget SnippetsPaneContent::UpdateSettings(const CascadiaSettings& settings)
safe_void_coroutine SnippetsPaneContent::UpdateSettings(const CascadiaSettings& settings)
{
_settings = settings;
@ -54,7 +55,7 @@ namespace winrt::TerminalApp::implementation
const auto tasks = co_await _settings.GlobalSettings().ActionMap().FilterToSnippets(winrt::hstring{}, winrt::hstring{}); // IVector<Model::Command>
co_await wil::resume_foreground(Dispatcher());
_allTasks = winrt::single_threaded_observable_vector<TerminalApp::FilteredTask>();
_allTasks.Clear();
for (const auto& t : tasks)
{
const auto& filtered{ winrt::make<FilteredTask>(t) };

View File

@ -17,7 +17,7 @@ namespace winrt::TerminalApp::implementation
winrt::Windows::UI::Xaml::FrameworkElement GetRoot();
winrt::fire_and_forget UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
safe_void_coroutine UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
winrt::Windows::Foundation::Size MinimumSize();
void Focus(winrt::Windows::UI::Xaml::FocusState reason = winrt::Windows::UI::Xaml::FocusState::Programmatic);

View File

@ -269,6 +269,8 @@ namespace winrt::TerminalApp::implementation
const auto selectedCommand = _filteredActionsView().SelectedItem();
const auto filteredCommand{ selectedCommand.try_as<winrt::TerminalApp::FilteredCommand>() };
_filteredActionsView().ScrollIntoView(selectedCommand);
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"SelectedItem" });
// Make sure to not send the preview if we're collapsed. This can
@ -722,6 +724,20 @@ namespace winrt::TerminalApp::implementation
// ever allow non-sendInput actions.
DispatchCommandRequested.raise(*this, actionPaletteItem.Command());
if (const auto& sendInputCmd = actionPaletteItem.Command().ActionAndArgs().Args().try_as<SendInputArgs>())
{
if (til::starts_with(sendInputCmd.Input(), L"winget"))
{
TraceLoggingWrite(
g_hTerminalAppProvider,
"QuickFixSuggestionUsed",
TraceLoggingDescription("Event emitted when a winget suggestion from is used"),
TraceLoggingValue("SuggestionsUI", "Source"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
}
}
TraceLoggingWrite(
g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider
"SuggestionsControlDispatchedAction",
@ -795,14 +811,46 @@ namespace winrt::TerminalApp::implementation
// here will ensure that we can check this case appropriately.
_lastFilterTextWasEmpty = _searchBox().Text().empty();
const auto lastSelectedIndex = _filteredActionsView().SelectedIndex();
const auto lastSelectedIndex = std::max(0, _filteredActionsView().SelectedIndex()); // SelectedIndex will return -1 for "nothing"
_updateFilteredActions();
// In the command line mode we want the user to explicitly select the command
_filteredActionsView().SelectedIndex(std::min<int32_t>(lastSelectedIndex, _filteredActionsView().Items().Size() - 1));
if (const auto newSelectedIndex = _filteredActionsView().SelectedIndex();
newSelectedIndex == -1)
{
// Make sure something stays selected
_scrollToIndex(lastSelectedIndex);
}
else
{
// BODGY: Calling ScrollIntoView on a ListView doesn't always work
// immediately after a change to the items. See:
// https://stackoverflow.com/questions/16942580/why-doesnt-listview-scrollintoview-ever-work
// The SelectionChanged thing we do (in _selectedCommandChanged),
// but because we're also not changing the actual selected item when
// the size of the list grows (it _stays_ selected, so it never
// _changes_), we never get a SelectionChanged.
//
// To mitigate, only in the case of totally clearing out the filter
// (like hitting `esc`), we want to briefly select the 0th item,
// then immediately select the one we want to make visible. That
// will make sure we get a SelectionChanged when the ListView is
// ready, and we can use that to scroll to the right item.
//
// If we do this on _every_ change, then the preview text flickers
// between the 0th item and the correct one.
if (_lastFilterTextWasEmpty)
{
_filteredActionsView().SelectedIndex(0);
}
_scrollToIndex(newSelectedIndex);
}
const auto currentNeedleHasResults{ _filteredActions.Size() > 0 };
if (!currentNeedleHasResults)
{
PreviewAction.raise(*this, nullptr);
}
_noMatchesText().Visibility(currentNeedleHasResults ? Visibility::Collapsed : Visibility::Visible);
if (auto automationPeer{ Automation::Peers::FrameworkElementAutomationPeer::FromElement(_searchBox()) })
{
@ -1203,7 +1251,7 @@ namespace winrt::TerminalApp::implementation
if (_direction == TerminalApp::SuggestionsDirection::BottomUp)
{
const auto last = _filteredActionsView().Items().Size() - 1;
_filteredActionsView().SelectedIndex(last);
_scrollToIndex(last);
}
// Move the cursor to the very last position, so it starts immediately
// after the text. This is apparently done by starting a 0-wide

View File

@ -630,7 +630,7 @@ namespace winrt::TerminalApp::implementation
// - tab: tab to focus.
// Return Value:
// - <none>
winrt::fire_and_forget TerminalPage::_SetFocusedTab(const winrt::TerminalApp::TabBase tab)
safe_void_coroutine TerminalPage::_SetFocusedTab(const winrt::TerminalApp::TabBase tab)
{
// GH#1117: This is a workaround because _tabView.SelectedIndex(tabIndex)
// sometimes set focus to an incorrect tab after removing some tabs
@ -715,7 +715,7 @@ namespace winrt::TerminalApp::implementation
// - Close the currently focused pane. If the pane is the last pane in the
// tab, the tab will also be closed. This will happen when we handle the
// tab's Closed event.
winrt::fire_and_forget TerminalPage::_CloseFocusedPane()
safe_void_coroutine TerminalPage::_CloseFocusedPane()
{
if (const auto terminalTab{ _GetFocusedTabImpl() })
{
@ -781,7 +781,7 @@ namespace winrt::TerminalApp::implementation
// - Closes provided tabs one by one
// Arguments:
// - tabs - tabs to remove
winrt::fire_and_forget TerminalPage::_RemoveTabs(const std::vector<winrt::TerminalApp::TabBase> tabs)
safe_void_coroutine TerminalPage::_RemoveTabs(const std::vector<winrt::TerminalApp::TabBase> tabs)
{
for (auto& tab : tabs)
{

View File

@ -25,6 +25,7 @@
<PropertyGroup Label="NuGet Dependencies">
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalMUX>true</TerminalMUX>
<TerminalWinGetInterop>true</TerminalWinGetInterop>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
@ -177,6 +178,7 @@
<ClInclude Include="SuggestionsControl.h">
<DependentUpon>SuggestionsControl.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="WindowsPackageManagerFactory.h" />
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
@ -361,7 +363,7 @@
</Midl>
<Midl Include="FilteredCommand.idl" />
<Midl Include="IPaneContent.idl" />
<Midl Include="TerminalPaneContent.idl" >
<Midl Include="TerminalPaneContent.idl">
<DependentUpon>TaskPaneContent.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>

View File

@ -29,6 +29,7 @@
#include "LaunchPositionRequest.g.cpp"
using namespace winrt;
using namespace winrt::Microsoft::Management::Deployment;
using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalConnection;
@ -407,7 +408,7 @@ namespace winrt::TerminalApp::implementation
}
}
winrt::fire_and_forget TerminalPage::_NewTerminalByDrop(const Windows::Foundation::IInspectable&, winrt::Windows::UI::Xaml::DragEventArgs e)
safe_void_coroutine TerminalPage::_NewTerminalByDrop(const Windows::Foundation::IInspectable&, winrt::Windows::UI::Xaml::DragEventArgs e)
try
{
const auto data = e.DataView();
@ -525,7 +526,7 @@ namespace winrt::TerminalApp::implementation
// - filepath - the location to save the text
// - filename - the name of the file to save the text to
// - dialogGuid - the guid to associate with these specific saves (determines where the save dialog opens to by default)
fire_and_forget TerminalPage::_SaveStringToFileOrPromptUser(const winrt::hstring& text, const winrt::hstring& filepath, const std::wstring_view filename, const winrt::guid dialogGuid)
safe_void_coroutine TerminalPage::_SaveStringToFileOrPromptUser(const winrt::hstring& text, const winrt::hstring& filepath, const std::wstring_view filename, const winrt::guid dialogGuid)
{
// This will be used to set up the file picker "filter", to select .txt
// files by default.
@ -661,10 +662,10 @@ namespace winrt::TerminalApp::implementation
// nt -d .` from inside another directory to work as expected.
// Return Value:
// - <none>
winrt::fire_and_forget TerminalPage::ProcessStartupActions(Windows::Foundation::Collections::IVector<ActionAndArgs> actions,
const bool initial,
const winrt::hstring cwd,
const winrt::hstring env)
safe_void_coroutine TerminalPage::ProcessStartupActions(Windows::Foundation::Collections::IVector<ActionAndArgs> actions,
const bool initial,
const winrt::hstring cwd,
const winrt::hstring env)
{
auto weakThis{ get_weak() };
@ -749,7 +750,7 @@ namespace winrt::TerminalApp::implementation
// - <none>
// Return Value:
// - <none>
winrt::fire_and_forget TerminalPage::_CompleteInitialization()
safe_void_coroutine TerminalPage::_CompleteInitialization()
{
_startupState = StartupState::Initialized;
@ -2132,7 +2133,7 @@ namespace winrt::TerminalApp::implementation
// Method Description:
// - Warn the user that they are about to close all open windows, then
// signal that we want to close everything.
fire_and_forget TerminalPage::RequestQuit()
safe_void_coroutine TerminalPage::RequestQuit()
{
if (!_displayingCloseDialog)
{
@ -2220,7 +2221,7 @@ namespace winrt::TerminalApp::implementation
// Method Description:
// - Close the terminal app. If there is more
// than one tab opened, show a warning dialog.
fire_and_forget TerminalPage::CloseWindow()
safe_void_coroutine TerminalPage::CloseWindow()
{
if (_HasMultipleTabs() &&
_settings.GlobalSettings().ConfirmCloseAllTabs() &&
@ -2527,8 +2528,8 @@ namespace winrt::TerminalApp::implementation
// reattach instead of create new content, so this method simply needs to
// parse the JSON and pump it into our action handler. Almost the same as
// doing something like `wt -w 0 nt`.
winrt::fire_and_forget TerminalPage::AttachContent(IVector<Settings::Model::ActionAndArgs> args,
uint32_t tabIndex)
safe_void_coroutine TerminalPage::AttachContent(IVector<Settings::Model::ActionAndArgs> args,
uint32_t tabIndex)
{
if (args == nullptr ||
args.Size() == 0)
@ -2917,7 +2918,7 @@ namespace winrt::TerminalApp::implementation
// - Does some of this in a background thread, as to not hang/crash the UI thread.
// Arguments:
// - eventArgs: the PasteFromClipboard event sent from the TermControl
fire_and_forget TerminalPage::_PasteFromClipboardHandler(const IInspectable /*sender*/, const PasteFromClipboardEventArgs eventArgs)
safe_void_coroutine TerminalPage::_PasteFromClipboardHandler(const IInspectable /*sender*/, const PasteFromClipboardEventArgs eventArgs)
try
{
// The old Win32 clipboard API as used below is somewhere in the order of 300-1000x faster than
@ -3088,8 +3089,8 @@ namespace winrt::TerminalApp::implementation
// Important! Don't take this eventArgs by reference, we need to extend the
// lifetime of it to the other side of the co_await!
winrt::fire_and_forget TerminalPage::_ControlNoticeRaisedHandler(const IInspectable /*sender*/,
const Microsoft::Terminal::Control::NoticeEventArgs eventArgs)
safe_void_coroutine TerminalPage::_ControlNoticeRaisedHandler(const IInspectable /*sender*/,
const Microsoft::Terminal::Control::NoticeEventArgs eventArgs)
{
auto weakThis = get_weak();
co_await wil::resume_foreground(Dispatcher());
@ -3158,7 +3159,7 @@ namespace winrt::TerminalApp::implementation
// Arguments:
// - sender (not used)
// - eventArgs: the arguments specifying how to set the progress indicator
winrt::fire_and_forget TerminalPage::_SetTaskbarProgressHandler(const IInspectable /*sender*/, const IInspectable /*eventArgs*/)
safe_void_coroutine TerminalPage::_SetTaskbarProgressHandler(const IInspectable /*sender*/, const IInspectable /*eventArgs*/)
{
co_await wil::resume_foreground(Dispatcher());
SetTaskbarProgress.raise(*this, nullptr);
@ -3174,18 +3175,82 @@ namespace winrt::TerminalApp::implementation
ShowWindowChanged.raise(*this, args);
}
winrt::fire_and_forget TerminalPage::_SearchMissingCommandHandler(const IInspectable /*sender*/, const Microsoft::Terminal::Control::SearchMissingCommandEventArgs args)
Windows::Foundation::IAsyncOperation<IVectorView<MatchResult>> TerminalPage::_FindPackageAsync(hstring query)
{
assert(!Dispatcher().HasThreadAccess());
const PackageManager packageManager = WindowsPackageManagerFactory::CreatePackageManager();
PackageCatalogReference catalogRef{
packageManager.GetPredefinedPackageCatalog(PredefinedPackageCatalog::OpenWindowsCatalog)
};
catalogRef.PackageCatalogBackgroundUpdateInterval(std::chrono::hours(24));
ConnectResult connectResult{ nullptr };
for (int retries = 0;;)
{
connectResult = catalogRef.Connect();
if (connectResult.Status() == ConnectResultStatus::Ok)
{
break;
}
if (++retries == 3)
{
co_return nullptr;
}
}
PackageCatalog catalog = connectResult.PackageCatalog();
// clang-format off
static constexpr std::array<WinGetSearchParams, 3> searches{ {
{ .Field = PackageMatchField::Command, .MatchOption = PackageFieldMatchOption::StartsWithCaseInsensitive },
{ .Field = PackageMatchField::Name, .MatchOption = PackageFieldMatchOption::ContainsCaseInsensitive },
{ .Field = PackageMatchField::Moniker, .MatchOption = PackageFieldMatchOption::ContainsCaseInsensitive } } };
// clang-format on
PackageMatchFilter filter = WindowsPackageManagerFactory::CreatePackageMatchFilter();
filter.Value(query);
FindPackagesOptions options = WindowsPackageManagerFactory::CreateFindPackagesOptions();
options.Filters().Append(filter);
options.ResultLimit(20);
IVectorView<MatchResult> pkgList;
for (const auto& search : searches)
{
filter.Field(search.Field);
filter.Option(search.MatchOption);
const auto result = co_await catalog.FindPackagesAsync(options);
pkgList = result.Matches();
if (pkgList.Size() > 0)
{
break;
}
}
co_return pkgList;
}
Windows::Foundation::IAsyncAction TerminalPage::_SearchMissingCommandHandler(const IInspectable /*sender*/, const Microsoft::Terminal::Control::SearchMissingCommandEventArgs args)
{
if (!Feature_QuickFix::IsEnabled())
{
co_return;
}
co_await winrt::resume_background();
// no packages were found, nothing to suggest
const auto pkgList = co_await _FindPackageAsync(args.MissingCommand());
if (!pkgList || pkgList.Size() == 0)
{
co_return;
}
std::vector<hstring> suggestions;
suggestions.reserve(1);
suggestions.emplace_back(fmt::format(FMT_COMPILE(L"winget install {}"), args.MissingCommand()));
suggestions.reserve(pkgList.Size());
for (const auto& pkg : pkgList)
{
// --id and --source ensure we don't collide with another package catalog
suggestions.emplace_back(fmt::format(FMT_COMPILE(L"winget install --id {} -s winget"), pkg.CatalogPackage().Id()));
}
co_await wil::resume_foreground(Dispatcher());
@ -3230,7 +3295,7 @@ namespace winrt::TerminalApp::implementation
// - Called when the settings button is clicked. ShellExecutes the settings
// file, as to open it in the default editor for .json files. Does this in
// a background thread, as to not hang/crash the UI thread.
fire_and_forget TerminalPage::_LaunchSettings(const SettingsTarget target)
safe_void_coroutine TerminalPage::_LaunchSettings(const SettingsTarget target)
{
if (target == SettingsTarget::SettingsUI)
{
@ -4423,7 +4488,7 @@ namespace winrt::TerminalApp::implementation
// - <none>
// Return Value:
// - <none>
winrt::fire_and_forget TerminalPage::IdentifyWindow()
safe_void_coroutine TerminalPage::IdentifyWindow()
{
auto weakThis{ get_weak() };
co_await wil::resume_foreground(Dispatcher());
@ -4459,7 +4524,7 @@ namespace winrt::TerminalApp::implementation
// - <none>
// Return Value:
// - <none>
winrt::fire_and_forget TerminalPage::RenameFailed()
safe_void_coroutine TerminalPage::RenameFailed()
{
auto weakThis{ get_weak() };
co_await wil::resume_foreground(Dispatcher());
@ -4486,7 +4551,7 @@ namespace winrt::TerminalApp::implementation
}
}
winrt::fire_and_forget TerminalPage::ShowTerminalWorkingDirectory()
safe_void_coroutine TerminalPage::ShowTerminalWorkingDirectory()
{
auto weakThis{ get_weak() };
co_await wil::resume_foreground(Dispatcher());
@ -4712,7 +4777,7 @@ namespace winrt::TerminalApp::implementation
// - sender: the ICoreState instance containing the connection state
// Return Value:
// - <none>
winrt::fire_and_forget TerminalPage::_ConnectionStateChangedHandler(const IInspectable& sender, const IInspectable& /*args*/) const
safe_void_coroutine TerminalPage::_ConnectionStateChangedHandler(const IInspectable& sender, const IInspectable& /*args*/) const
{
if (const auto coreState{ sender.try_as<winrt::Microsoft::Terminal::Control::ICoreState>() })
{
@ -5007,8 +5072,8 @@ namespace winrt::TerminalApp::implementation
}
}
winrt::fire_and_forget TerminalPage::_ControlCompletionsChangedHandler(const IInspectable sender,
const CompletionsChangedEventArgs args)
safe_void_coroutine TerminalPage::_ControlCompletionsChangedHandler(const IInspectable sender,
const CompletionsChangedEventArgs args)
{
// This will come in on a background (not-UI, not output) thread.
@ -5179,6 +5244,14 @@ namespace winrt::TerminalApp::implementation
{
ctrl.ClearQuickFix();
}
TraceLoggingWrite(
g_hTerminalAppProvider,
"QuickFixSuggestionUsed",
TraceLoggingDescription("Event emitted when a winget suggestion from is used"),
TraceLoggingValue("QuickFixMenu", "Source"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
}
};
};
@ -5200,14 +5273,15 @@ namespace winrt::TerminalApp::implementation
item.Text(qf);
item.Click(makeCallback(qf));
ToolTipService::SetToolTip(item, box_value(qf));
menu.Items().Append(item);
}
}
// Handler for our WindowProperties's PropertyChanged event. We'll use this
// to pop the "Identify Window" toast when the user renames our window.
winrt::fire_and_forget TerminalPage::_windowPropertyChanged(const IInspectable& /*sender*/,
const WUX::Data::PropertyChangedEventArgs& args)
safe_void_coroutine TerminalPage::_windowPropertyChanged(const IInspectable& /*sender*/,
const WUX::Data::PropertyChangedEventArgs& args)
{
if (args.PropertyName() != L"WindowName")
{
@ -5303,8 +5377,8 @@ namespace winrt::TerminalApp::implementation
// - Called on the TARGET of a tab drag/drop. We'll unpack the DataPackage
// to find who the tab came from. We'll then ask the Monarch to ask the
// sender to move that tab to us.
winrt::fire_and_forget TerminalPage::_onTabStripDrop(winrt::Windows::Foundation::IInspectable /*sender*/,
winrt::Windows::UI::Xaml::DragEventArgs e)
safe_void_coroutine TerminalPage::_onTabStripDrop(winrt::Windows::Foundation::IInspectable /*sender*/,
winrt::Windows::UI::Xaml::DragEventArgs e)
{
// Get the PID and make sure it is the same as ours.
if (const auto& pidObj{ e.DataView().Properties().TryLookup(L"pid") })
@ -5375,7 +5449,7 @@ namespace winrt::TerminalApp::implementation
// the destination window.
// - Fortunately, sending the tab is basically just a MoveTab action, so we
// can largely reuse that.
winrt::fire_and_forget TerminalPage::SendContentToOther(winrt::TerminalApp::RequestReceiveContentArgs args)
safe_void_coroutine TerminalPage::SendContentToOther(winrt::TerminalApp::RequestReceiveContentArgs args)
{
// validate that we're the source window of the tab in this request
if (args.SourceWindow() != _WindowProperties.WindowId())
@ -5400,8 +5474,8 @@ namespace winrt::TerminalApp::implementation
}
}
winrt::fire_and_forget TerminalPage::_onTabDroppedOutside(winrt::IInspectable sender,
winrt::MUX::Controls::TabViewTabDroppedOutsideEventArgs e)
safe_void_coroutine TerminalPage::_onTabDroppedOutside(winrt::IInspectable sender,
winrt::MUX::Controls::TabViewTabDroppedOutsideEventArgs e)
{
// Get the current pointer point from the CoreWindow
const auto& pointerPoint{ CoreWindow::GetForCurrentThread().PointerPosition() };

View File

@ -13,6 +13,8 @@
#include "LaunchPositionRequest.g.h"
#include "Toast.h"
#include "WindowsPackageManagerFactory.h"
#define DECLARE_ACTION_HANDLER(action) void _Handle##action(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args);
namespace TerminalAppLocalTests
@ -87,6 +89,12 @@ namespace winrt::TerminalApp::implementation
til::property<winrt::Microsoft::Terminal::Settings::Model::LaunchPosition> Position;
};
struct WinGetSearchParams
{
winrt::Microsoft::Management::Deployment::PackageMatchField Field;
winrt::Microsoft::Management::Deployment::PackageFieldMatchOption MatchOption;
};
struct TerminalPage : TerminalPageT<TerminalPage>
{
public:
@ -117,8 +125,8 @@ namespace winrt::TerminalApp::implementation
CommandPalette LoadCommandPalette();
SuggestionsControl LoadSuggestionsUI();
winrt::fire_and_forget RequestQuit();
winrt::fire_and_forget CloseWindow();
safe_void_coroutine RequestQuit();
safe_void_coroutine CloseWindow();
void PersistState();
void ToggleFocusMode();
@ -145,16 +153,16 @@ namespace winrt::TerminalApp::implementation
void ShowKeyboardServiceWarning() const;
winrt::hstring KeyboardServiceDisabledText();
winrt::fire_and_forget IdentifyWindow();
safe_void_coroutine IdentifyWindow();
void ActionSaved(winrt::hstring input, winrt::hstring name, winrt::hstring keyChord);
void ActionSaveFailed(winrt::hstring message);
winrt::fire_and_forget RenameFailed();
winrt::fire_and_forget ShowTerminalWorkingDirectory();
safe_void_coroutine RenameFailed();
safe_void_coroutine ShowTerminalWorkingDirectory();
winrt::fire_and_forget ProcessStartupActions(Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::ActionAndArgs> actions,
const bool initial,
const winrt::hstring cwd = winrt::hstring{},
const winrt::hstring env = winrt::hstring{});
safe_void_coroutine ProcessStartupActions(Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::ActionAndArgs> actions,
const bool initial,
const winrt::hstring cwd = winrt::hstring{},
const winrt::hstring env = winrt::hstring{});
TerminalApp::WindowProperties WindowProperties() const noexcept { return _WindowProperties; };
@ -166,8 +174,8 @@ namespace winrt::TerminalApp::implementation
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
winrt::fire_and_forget AttachContent(Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::ActionAndArgs> args, uint32_t tabIndex);
winrt::fire_and_forget SendContentToOther(winrt::TerminalApp::RequestReceiveContentArgs args);
safe_void_coroutine AttachContent(Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::ActionAndArgs> args, uint32_t tabIndex);
safe_void_coroutine SendContentToOther(winrt::TerminalApp::RequestReceiveContentArgs args);
uint32_t NumberOfTabs() const;
@ -289,7 +297,7 @@ namespace winrt::TerminalApp::implementation
winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::NewConnection_revoker _newConnectionRevoker;
winrt::fire_and_forget _NewTerminalByDrop(const Windows::Foundation::IInspectable&, winrt::Windows::UI::Xaml::DragEventArgs e);
safe_void_coroutine _NewTerminalByDrop(const Windows::Foundation::IInspectable&, winrt::Windows::UI::Xaml::DragEventArgs e);
__declspec(noinline) CommandPalette _loadCommandPaletteSlowPath();
bool _commandPaletteIs(winrt::Windows::UI::Xaml::Visibility visibility);
@ -321,7 +329,7 @@ namespace winrt::TerminalApp::implementation
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _duplicateConnectionForRestart(const TerminalApp::TerminalPaneContent& paneContent);
void _restartPaneConnection(const TerminalApp::TerminalPaneContent&, const winrt::Windows::Foundation::IInspectable&);
winrt::fire_and_forget _OpenNewWindow(const Microsoft::Terminal::Settings::Model::INewContentArgs newContentArgs);
safe_void_coroutine _OpenNewWindow(const Microsoft::Terminal::Settings::Model::INewContentArgs newContentArgs);
void _OpenNewTerminalViaDropdown(const Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs);
@ -351,7 +359,7 @@ namespace winrt::TerminalApp::implementation
winrt::Windows::Foundation::IAsyncAction _HandleCloseTabRequested(winrt::TerminalApp::TabBase tab);
void _CloseTabAtIndex(uint32_t index);
void _RemoveTab(const winrt::TerminalApp::TabBase& tab);
winrt::fire_and_forget _RemoveTabs(const std::vector<winrt::TerminalApp::TabBase> tabs);
safe_void_coroutine _RemoveTabs(const std::vector<winrt::TerminalApp::TabBase> tabs);
void _InitializeTab(winrt::com_ptr<TerminalTab> newTabImpl, uint32_t insertPosition = -1);
void _RegisterTerminalEvents(Microsoft::Terminal::Control::TermControl term);
@ -396,8 +404,8 @@ namespace winrt::TerminalApp::implementation
TerminalApp::TabBase _GetTabByTabViewItem(const Microsoft::UI::Xaml::Controls::TabViewItem& tabViewItem) const noexcept;
void _HandleClosePaneRequested(std::shared_ptr<Pane> pane);
winrt::fire_and_forget _SetFocusedTab(const winrt::TerminalApp::TabBase tab);
winrt::fire_and_forget _CloseFocusedPane();
safe_void_coroutine _SetFocusedTab(const winrt::TerminalApp::TabBase tab);
safe_void_coroutine _CloseFocusedPane();
void _ClosePanes(weak_ref<TerminalTab> weakTab, std::vector<uint32_t> paneIds);
winrt::Windows::Foundation::IAsyncOperation<bool> _PaneConfirmCloseReadOnly(std::shared_ptr<Pane> pane);
void _AddPreviouslyClosedPaneOrTab(std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>&& args);
@ -415,8 +423,8 @@ namespace winrt::TerminalApp::implementation
void _ScrollToBufferEdge(ScrollDirection scrollDirection);
void _SetAcceleratorForMenuItem(Windows::UI::Xaml::Controls::MenuFlyoutItem& menuItem, const winrt::Microsoft::Terminal::Control::KeyChord& keyChord);
winrt::fire_and_forget _PasteFromClipboardHandler(const IInspectable sender,
const Microsoft::Terminal::Control::PasteFromClipboardEventArgs eventArgs);
safe_void_coroutine _PasteFromClipboardHandler(const IInspectable sender,
const Microsoft::Terminal::Control::PasteFromClipboardEventArgs eventArgs);
void _OpenHyperlinkHandler(const IInspectable sender, const Microsoft::Terminal::Control::OpenHyperlinkEventArgs eventArgs);
bool _IsUriSupported(const winrt::Windows::Foundation::Uri& parsedUri);
@ -424,14 +432,14 @@ namespace winrt::TerminalApp::implementation
void _ShowCouldNotOpenDialog(winrt::hstring reason, winrt::hstring uri);
bool _CopyText(const bool dismissSelection, const bool singleLine, const Windows::Foundation::IReference<Microsoft::Terminal::Control::CopyFormat>& formats);
winrt::fire_and_forget _SetTaskbarProgressHandler(const IInspectable sender, const IInspectable eventArgs);
safe_void_coroutine _SetTaskbarProgressHandler(const IInspectable sender, const IInspectable eventArgs);
void _PasteText();
winrt::fire_and_forget _ControlNoticeRaisedHandler(const IInspectable sender, const Microsoft::Terminal::Control::NoticeEventArgs eventArgs);
safe_void_coroutine _ControlNoticeRaisedHandler(const IInspectable sender, const Microsoft::Terminal::Control::NoticeEventArgs eventArgs);
void _ShowControlNoticeDialog(const winrt::hstring& title, const winrt::hstring& message);
fire_and_forget _LaunchSettings(const Microsoft::Terminal::Settings::Model::SettingsTarget target);
safe_void_coroutine _LaunchSettings(const Microsoft::Terminal::Settings::Model::SettingsTarget target);
void _TabDragStarted(const IInspectable& sender, const IInspectable& eventArgs);
void _TabDragCompleted(const IInspectable& sender, const IInspectable& eventArgs);
@ -450,7 +458,7 @@ namespace winrt::TerminalApp::implementation
void _OnInputSuggestionRequested(const IInspectable& sender, const winrt::hstring& suggestion);
void _OnExportChatHistoryRequested(const IInspectable& sender, const winrt::hstring& text);
fire_and_forget _SaveStringToFileOrPromptUser(const winrt::hstring& text, const winrt::hstring& filepath, const std::wstring_view filename, const winrt::guid dialogGuid);
safe_void_coroutine _SaveStringToFileOrPromptUser(const winrt::hstring& text, const winrt::hstring& filepath, const std::wstring_view filename, const winrt::guid dialogGuid);
void _Find(const TerminalTab& tab);
@ -474,7 +482,7 @@ namespace winrt::TerminalApp::implementation
void _StartInboundListener();
winrt::fire_and_forget _CompleteInitialization();
safe_void_coroutine _CompleteInitialization();
void _FocusActiveControl(IInspectable sender, IInspectable eventArgs);
@ -521,7 +529,7 @@ namespace winrt::TerminalApp::implementation
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile);
void _OpenElevatedWT(winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs);
winrt::fire_and_forget _ConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
safe_void_coroutine _ConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
void _CloseOnExitInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
void _KeyboardServiceWarningInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
@ -531,19 +539,20 @@ namespace winrt::TerminalApp::implementation
void _updateAllTabCloseButtons();
void _updatePaneResources(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme);
winrt::fire_and_forget _ControlCompletionsChangedHandler(const winrt::Windows::Foundation::IInspectable sender, const winrt::Microsoft::Terminal::Control::CompletionsChangedEventArgs args);
safe_void_coroutine _ControlCompletionsChangedHandler(const winrt::Windows::Foundation::IInspectable sender, const winrt::Microsoft::Terminal::Control::CompletionsChangedEventArgs args);
void _OpenSuggestions(const Microsoft::Terminal::Control::TermControl& sender, Windows::Foundation::Collections::IVector<winrt::Microsoft::Terminal::Settings::Model::Command> commandsCollection, winrt::TerminalApp::SuggestionsMode mode, winrt::hstring filterText);
void _ShowWindowChangedHandler(const IInspectable sender, const winrt::Microsoft::Terminal::Control::ShowWindowArgs args);
winrt::fire_and_forget _SearchMissingCommandHandler(const IInspectable sender, const winrt::Microsoft::Terminal::Control::SearchMissingCommandEventArgs args);
Windows::Foundation::IAsyncAction _SearchMissingCommandHandler(const IInspectable sender, const winrt::Microsoft::Terminal::Control::SearchMissingCommandEventArgs args);
Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Management::Deployment::MatchResult>> _FindPackageAsync(hstring query);
winrt::fire_and_forget _windowPropertyChanged(const IInspectable& sender, const winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs& args);
safe_void_coroutine _windowPropertyChanged(const IInspectable& sender, const winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs& args);
void _onTabDragStarting(const winrt::Microsoft::UI::Xaml::Controls::TabView& sender, const winrt::Microsoft::UI::Xaml::Controls::TabViewTabDragStartingEventArgs& e);
void _onTabStripDragOver(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::DragEventArgs& e);
winrt::fire_and_forget _onTabStripDrop(winrt::Windows::Foundation::IInspectable sender, winrt::Windows::UI::Xaml::DragEventArgs e);
winrt::fire_and_forget _onTabDroppedOutside(winrt::Windows::Foundation::IInspectable sender, winrt::Microsoft::UI::Xaml::Controls::TabViewTabDroppedOutsideEventArgs e);
safe_void_coroutine _onTabStripDrop(winrt::Windows::Foundation::IInspectable sender, winrt::Windows::UI::Xaml::DragEventArgs e);
safe_void_coroutine _onTabDroppedOutside(winrt::Windows::Foundation::IInspectable sender, winrt::Microsoft::UI::Xaml::Controls::TabViewTabDroppedOutsideEventArgs e);
void _DetachPaneFromWindow(std::shared_ptr<Pane> pane);
void _DetachTabFromWindow(const winrt::com_ptr<TabBase>& terminalTab);
@ -563,7 +572,7 @@ namespace winrt::TerminalApp::implementation
void _loadQueryExtension();
void _activePaneChanged(winrt::TerminalApp::TerminalTab tab, Windows::Foundation::IInspectable args);
winrt::fire_and_forget _doHandleSuggestions(Microsoft::Terminal::Settings::Model::SuggestionsArgs realArgs);
safe_void_coroutine _doHandleSuggestions(Microsoft::Terminal::Settings::Model::SuggestionsArgs realArgs);
#pragma region ActionHandlers
// These are all defined in AppActionHandlers.cpp

View File

@ -194,8 +194,8 @@ namespace winrt::TerminalApp::implementation
// - <none>
// Return Value:
// - <none>
winrt::fire_and_forget TerminalPaneContent::_controlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args)
safe_void_coroutine TerminalPaneContent::_controlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args)
{
ConnectionStateChanged.raise(sender, args);
auto newConnectionState = ConnectionState::Closed;
@ -300,7 +300,7 @@ namespace winrt::TerminalApp::implementation
}
}
winrt::fire_and_forget TerminalPaneContent::_playBellSound(winrt::Windows::Foundation::Uri uri)
safe_void_coroutine TerminalPaneContent::_playBellSound(winrt::Windows::Foundation::Uri uri)
{
auto weakThis{ get_weak() };
co_await wil::resume_foreground(_control.Dispatcher());

View File

@ -82,9 +82,9 @@ namespace winrt::TerminalApp::implementation
void _setupControlEvents();
void _removeControlEvents();
winrt::fire_and_forget _playBellSound(winrt::Windows::Foundation::Uri uri);
safe_void_coroutine _playBellSound(winrt::Windows::Foundation::Uri uri);
winrt::fire_and_forget _controlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& /*args*/);
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);
void _controlReadOnlyChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& e);

View File

@ -949,7 +949,7 @@ namespace winrt::TerminalApp::implementation
events.TitleChanged = content.TitleChanged(
winrt::auto_revoke,
[dispatcher, weakThis](auto&&, auto&&) -> winrt::fire_and_forget {
[dispatcher, weakThis](auto&&, auto&&) -> safe_void_coroutine {
// The lambda lives in the `std::function`-style container owned by `control`. That is, when the
// `control` gets destroyed the lambda struct also gets destroyed. In other words, we need to
// copy `weakThis` onto the stack, because that's the only thing that gets captured in coroutines.
@ -967,7 +967,7 @@ namespace winrt::TerminalApp::implementation
events.TabColorChanged = content.TabColorChanged(
winrt::auto_revoke,
[dispatcher, weakThis](auto&&, auto&&) -> winrt::fire_and_forget {
[dispatcher, weakThis](auto&&, auto&&) -> safe_void_coroutine {
const auto weakThisCopy = weakThis;
co_await wil::resume_foreground(dispatcher);
if (auto tab{ weakThisCopy.get() })
@ -981,7 +981,7 @@ namespace winrt::TerminalApp::implementation
events.TaskbarProgressChanged = content.TaskbarProgressChanged(
winrt::auto_revoke,
[dispatcher, weakThis](auto&&, auto&&) -> winrt::fire_and_forget {
[dispatcher, weakThis](auto&&, auto&&) -> safe_void_coroutine {
const auto weakThisCopy = weakThis;
co_await wil::resume_foreground(dispatcher);
// Check if Tab's lifetime has expired
@ -993,7 +993,7 @@ namespace winrt::TerminalApp::implementation
events.ConnectionStateChanged = content.ConnectionStateChanged(
winrt::auto_revoke,
[dispatcher, weakThis](auto&&, auto&&) -> winrt::fire_and_forget {
[dispatcher, weakThis](auto&&, auto&&) -> safe_void_coroutine {
const auto weakThisCopy = weakThis;
co_await wil::resume_foreground(dispatcher);
if (auto tab{ weakThisCopy.get() })
@ -1004,7 +1004,7 @@ namespace winrt::TerminalApp::implementation
events.ReadOnlyChanged = content.ReadOnlyChanged(
winrt::auto_revoke,
[dispatcher, weakThis](auto&&, auto&&) -> winrt::fire_and_forget {
[dispatcher, weakThis](auto&&, auto&&) -> safe_void_coroutine {
const auto weakThisCopy = weakThis;
co_await wil::resume_foreground(dispatcher);
if (auto tab{ weakThis.get() })
@ -1015,7 +1015,7 @@ namespace winrt::TerminalApp::implementation
events.FocusRequested = content.FocusRequested(
winrt::auto_revoke,
[dispatcher, weakThis](TerminalApp::IPaneContent sender, auto) -> winrt::fire_and_forget {
[dispatcher, weakThis](TerminalApp::IPaneContent sender, auto) -> safe_void_coroutine {
const auto weakThisCopy = weakThis;
co_await wil::resume_foreground(dispatcher);
if (const auto tab{ weakThisCopy.get() })
@ -1029,7 +1029,7 @@ namespace winrt::TerminalApp::implementation
events.BellRequested = content.BellRequested(
winrt::auto_revoke,
[dispatcher, weakThis](TerminalApp::IPaneContent sender, auto bellArgs) -> winrt::fire_and_forget {
[dispatcher, weakThis](TerminalApp::IPaneContent sender, auto bellArgs) -> safe_void_coroutine {
const auto weakThisCopy = weakThis;
co_await wil::resume_foreground(dispatcher);
if (const auto tab{ weakThisCopy.get() })

View File

@ -765,7 +765,7 @@ namespace winrt::TerminalApp::implementation
// This may be called on a background thread, or the main thread, but almost
// definitely not on OUR UI thread.
winrt::fire_and_forget TerminalWindow::UpdateSettings(winrt::TerminalApp::SettingsLoadEventArgs args)
safe_void_coroutine TerminalWindow::UpdateSettings(winrt::TerminalApp::SettingsLoadEventArgs args)
{
// GH#17620: We have a bug somewhere where a window doesn't get unregistered from the window list.
// This causes UpdateSettings calls where the thread dispatcher is already null.

View File

@ -75,7 +75,7 @@ namespace winrt::TerminalApp::implementation
void PersistState();
winrt::fire_and_forget UpdateSettings(winrt::TerminalApp::SettingsLoadEventArgs args);
safe_void_coroutine UpdateSettings(winrt::TerminalApp::SettingsLoadEventArgs args);
bool HasCommandlineArguments() const noexcept;

View File

@ -134,7 +134,7 @@ namespace winrt::TerminalApp::implementation
{
MinMaxCloseControl().PressButton(button);
}
winrt::fire_and_forget TitlebarControl::ClickButton(CaptionButton button)
safe_void_coroutine TitlebarControl::ClickButton(CaptionButton button)
{
// GH#8587: Handle this on the _next_ pass of the UI thread. If we
// handle this immediately, then we'll accidentally leave the button in

View File

@ -13,7 +13,7 @@ namespace winrt::TerminalApp::implementation
void HoverButton(CaptionButton button);
void PressButton(CaptionButton button);
winrt::fire_and_forget ClickButton(CaptionButton button);
safe_void_coroutine ClickButton(CaptionButton button);
void ReleaseButtons();
float CaptionButtonWidth();

View File

@ -0,0 +1,61 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// Module Name:
// - WindowsPackageManagerFactory.h
//
// Abstract:
// - This factory is designed to create production-level instances of WinGet objects.
// Elevated sessions require manual activation of WinGet objects and are not currently supported,
// while non-elevated sessions can use the standard WinRT activation system.
// Author:
// - Carlos Zamora (carlos-zamora) 23-Jul-2024
#pragma once
#include <winrt/Microsoft.Management.Deployment.h>
namespace winrt::TerminalApp::implementation
{
struct WindowsPackageManagerFactory
{
public:
static winrt::Microsoft::Management::Deployment::PackageManager CreatePackageManager()
{
return winrt::create_instance<winrt::Microsoft::Management::Deployment::PackageManager>(PackageManagerGuid, CLSCTX_ALL);
}
static winrt::Microsoft::Management::Deployment::FindPackagesOptions CreateFindPackagesOptions()
{
return winrt::create_instance<winrt::Microsoft::Management::Deployment::FindPackagesOptions>(FindPackageOptionsGuid, CLSCTX_ALL);
}
static winrt::Microsoft::Management::Deployment::CreateCompositePackageCatalogOptions CreateCreateCompositePackageCatalogOptions()
{
return winrt::create_instance<winrt::Microsoft::Management::Deployment::CreateCompositePackageCatalogOptions>(CreateCompositePackageCatalogOptionsGuid, CLSCTX_ALL);
}
static winrt::Microsoft::Management::Deployment::InstallOptions CreateInstallOptions()
{
return winrt::create_instance<winrt::Microsoft::Management::Deployment::InstallOptions>(InstallOptionsGuid, CLSCTX_ALL);
}
static winrt::Microsoft::Management::Deployment::UninstallOptions CreateUninstallOptions()
{
return winrt::create_instance<winrt::Microsoft::Management::Deployment::UninstallOptions>(UninstallOptionsGuid, CLSCTX_ALL);
}
static winrt::Microsoft::Management::Deployment::PackageMatchFilter CreatePackageMatchFilter()
{
return winrt::create_instance<winrt::Microsoft::Management::Deployment::PackageMatchFilter>(PackageMatchFilterGuid, CLSCTX_ALL);
}
private:
static constexpr winrt::guid PackageManagerGuid{ 0xC53A4F16, 0x787E, 0x42A4, { 0xB3, 0x04, 0x29, 0xEF, 0xFB, 0x4B, 0xF5, 0x97 } };
static constexpr winrt::guid FindPackageOptionsGuid{ 0x572DED96, 0x9C60, 0x4526, { 0x8F, 0x92, 0xEE, 0x7D, 0x91, 0xD3, 0x8C, 0x1A } };
static constexpr winrt::guid CreateCompositePackageCatalogOptionsGuid{ 0x526534B8, 0x7E46, 0x47C8, { 0x84, 0x16, 0xB1, 0x68, 0x5C, 0x32, 0x7D, 0x37 } };
static constexpr winrt::guid InstallOptionsGuid{ 0x1095F097, 0xEB96, 0x453B, { 0xB4, 0xE6, 0x16, 0x13, 0x63, 0x7F, 0x3B, 0x14 } };
static constexpr winrt::guid UninstallOptionsGuid{ 0xE1D9A11E, 0x9F85, 0x4D87, { 0x9C, 0x17, 0x2B, 0x93, 0x14, 0x3A, 0xDB, 0x8D } };
static constexpr winrt::guid PackageMatchFilterGuid{ 0xD02C9DAF, 0x99DC, 0x429C, { 0xB5, 0x03, 0x4E, 0x50, 0x4E, 0x4A, 0xB0, 0x00 } };
};
}

View File

@ -793,7 +793,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
// be awaiting our destruction breaks the deadlock.
// Arguments:
// - connection: the final living reference to an outgoing connection
winrt::fire_and_forget ConptyConnection::final_release(std::unique_ptr<ConptyConnection> connection)
safe_void_coroutine ConptyConnection::final_release(std::unique_ptr<ConptyConnection> connection)
{
co_await winrt::resume_background(); // move to background
connection.reset(); // explicitly destruct

View File

@ -18,7 +18,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
void Initialize(const Windows::Foundation::Collections::ValueSet& settings);
void InitializeFromHandoff(HANDLE* in, HANDLE* out, HANDLE signal, HANDLE reference, HANDLE server, HANDLE client, const TERMINAL_STARTUP_INFO* startupInfo);
static winrt::fire_and_forget final_release(std::unique_ptr<ConptyConnection> connection);
static safe_void_coroutine final_release(std::unique_ptr<ConptyConnection> connection);
void Start();
void WriteInput(const winrt::array_view<const char16_t> buffer);

View File

@ -98,7 +98,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Connection(connection);
_terminal->SetWriteInputCallback([this](std::wstring_view wstr) {
_sendInputToConnection(wstr);
_pendingResponses.append(wstr);
});
// GH#8969: pre-seed working directory to prevent potential races
@ -128,7 +128,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
auto pfnCompletionsChanged = [=](auto&& menuJson, auto&& replaceLength) { _terminalCompletionsChanged(menuJson, replaceLength); };
_terminal->CompletionsChangedCallback(pfnCompletionsChanged);
auto pfnSearchMissingCommand = [this](auto&& PH1) { _terminalSearchMissingCommand(std::forward<decltype(PH1)>(PH1)); };
auto pfnSearchMissingCommand = [this](auto&& PH1, auto&& PH2) { _terminalSearchMissingCommand(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2)); };
_terminal->SetSearchMissingCommandCallback(pfnSearchMissingCommand);
auto pfnClearQuickFix = [this] { ClearQuickFix(); };
@ -419,6 +419,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Return Value:
// - <none>
void ControlCore::_sendInputToConnection(std::wstring_view wstr)
{
_connection.WriteInput(winrt_wstring_to_array_view(wstr));
}
// Method Description:
// - Writes the given sequence as input to the active terminal connection,
// Arguments:
// - wstr: the string of characters to write to the terminal connection.
// Return Value:
// - <none>
void ControlCore::SendInput(const std::wstring_view wstr)
{
if (wstr.empty())
{
@ -435,21 +446,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
else
{
_connection.WriteInput(winrt_wstring_to_array_view(wstr));
_sendInputToConnection(wstr);
}
}
// Method Description:
// - Writes the given sequence as input to the active terminal connection,
// Arguments:
// - wstr: the string of characters to write to the terminal connection.
// Return Value:
// - <none>
void ControlCore::SendInput(const std::wstring_view wstr)
{
_sendInputToConnection(wstr);
}
bool ControlCore::SendCharEvent(const wchar_t ch,
const WORD scanCode,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers)
@ -485,7 +485,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
if (out)
{
_sendInputToConnection(*out);
SendInput(*out);
return true;
}
return false;
@ -643,7 +643,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
if (out)
{
_sendInputToConnection(*out);
SendInput(*out);
return true;
}
return false;
@ -662,7 +662,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
if (out)
{
_sendInputToConnection(*out);
SendInput(*out);
return true;
}
return false;
@ -1412,7 +1412,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
// It's important to not hold the terminal lock while calling this function as sending the data may take a long time.
_sendInputToConnection(filtered);
SendInput(filtered);
const auto lock = _terminal->LockForWriting();
_terminal->ClearSelection();
@ -1629,9 +1629,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_midiAudio.PlayNote(reinterpret_cast<HWND>(_owningHwnd), noteNumber, velocity, std::chrono::duration_cast<std::chrono::milliseconds>(duration));
}
void ControlCore::_terminalSearchMissingCommand(std::wstring_view missingCommand)
void ControlCore::_terminalSearchMissingCommand(std::wstring_view missingCommand, const til::CoordType& bufferRow)
{
SearchMissingCommand.raise(*this, make<implementation::SearchMissingCommandEventArgs>(hstring{ missingCommand }));
SearchMissingCommand.raise(*this, make<implementation::SearchMissingCommandEventArgs>(hstring{ missingCommand }, bufferRow));
}
void ControlCore::ClearQuickFix()
@ -1862,7 +1862,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
RendererWarning.raise(*this, winrt::make<RendererWarningArgs>(hr, winrt::hstring{ parameter }));
}
winrt::fire_and_forget ControlCore::_renderEngineSwapChainChanged(const HANDLE sourceHandle)
safe_void_coroutine ControlCore::_renderEngineSwapChainChanged(const HANDLE sourceHandle)
{
// `sourceHandle` is a weak ref to a HANDLE that's ultimately owned by the
// render engine's own unique_handle. We'll add another ref to it here.
@ -2107,7 +2107,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Sending input requires that we're unlocked, because
// writing the input pipe may block indefinitely.
const auto suspension = _terminal->SuspendLock();
_sendInputToConnection(buffer);
SendInput(buffer);
}
}
}
@ -2164,6 +2164,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_terminal->Write(hstr);
}
if (!_pendingResponses.empty())
{
_sendInputToConnection(_pendingResponses);
_pendingResponses.clear();
}
// Start the throttled update of where our hyperlinks are.
const auto shared = _shared.lock_shared();
if (shared->outputIdle)
@ -2285,7 +2291,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// If the very last thing in the list of recent commands, is exactly the
// same as the current command, then let's not include it in the
// history. It's literally the thing the user has typed, RIGHT now.
if (!commands.empty() && commands.back() == trimmedCurrentCommand)
// (also account for the fact that the cursor may be in the middle of a commandline)
if (!commands.empty() &&
!trimmedCurrentCommand.empty() &&
std::wstring_view{ commands.back() }.substr(0, trimmedCurrentCommand.size()) == trimmedCurrentCommand)
{
commands.pop_back();
}
@ -2480,9 +2489,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
if (out && !out->empty())
{
// _sendInputToConnection() asserts that we aren't in focus mode,
// but window focus events are always fine to send.
_connection.WriteInput(winrt_wstring_to_array_view(*out));
_sendInputToConnection(*out);
}
}
@ -2659,8 +2666,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
winrt::fire_and_forget ControlCore::_terminalCompletionsChanged(std::wstring_view menuJson,
unsigned int replaceLength)
safe_void_coroutine ControlCore::_terminalCompletionsChanged(std::wstring_view menuJson,
unsigned int replaceLength)
{
auto args = winrt::make_self<CompletionsChangedEventArgs>(winrt::hstring{ menuJson },
replaceLength);

View File

@ -319,6 +319,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
winrt::com_ptr<ControlSettings> _settings{ nullptr };
std::shared_ptr<::Microsoft::Terminal::Core::Terminal> _terminal{ nullptr };
std::wstring _pendingResponses;
// NOTE: _renderEngine must be ordered before _renderer.
//
@ -389,9 +390,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _terminalPlayMidiNote(const int noteNumber,
const int velocity,
const std::chrono::microseconds duration);
void _terminalSearchMissingCommand(std::wstring_view missingCommand);
void _terminalSearchMissingCommand(std::wstring_view missingCommand, const til::CoordType& bufferRow);
winrt::fire_and_forget _terminalCompletionsChanged(std::wstring_view menuJson, unsigned int replaceLength);
safe_void_coroutine _terminalCompletionsChanged(std::wstring_view menuJson, unsigned int replaceLength);
#pragma endregion
@ -400,7 +401,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
#pragma region RendererCallbacks
void _rendererWarning(const HRESULT hr, wil::zwstring_view parameter);
winrt::fire_and_forget _renderEngineSwapChainChanged(const HANDLE handle);
safe_void_coroutine _renderEngineSwapChainChanged(const HANDLE handle);
void _rendererBackgroundColorChanged();
void _rendererTabColorChanged();
#pragma endregion

View File

@ -329,7 +329,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_touchAnchor = contactPoint;
}
void ControlInteractivity::PointerMoved(Control::MouseButtonState buttonState,
bool ControlInteractivity::PointerMoved(Control::MouseButtonState buttonState,
const unsigned int pointerUpdateKind,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const bool focused,
@ -337,11 +337,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const bool pointerPressedInBounds)
{
const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition });
// Returning true from this function indicates that the caller should do no further processing of this movement.
bool handledCompletely = false;
// Short-circuit isReadOnly check to avoid warning dialog
if (focused && !_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers))
{
_sendMouseEventHelper(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState);
handledCompletely = true;
}
// GH#4603 - don't modify the selection if the pointer press didn't
// actually start _in_ the control bounds. Case in point - someone drags
@ -378,6 +381,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
_core->SetHoveredCell(terminalPosition.to_core_point());
return handledCompletely;
}
void ControlInteractivity::TouchMoved(const Core::Point newTouchPoint,
@ -682,13 +686,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const SHORT wheelDelta,
Control::MouseButtonState buttonState)
{
const auto adjustment = _core->ScrollOffset() > 0 ? _core->BufferHeight() - _core->ScrollOffset() - _core->ViewHeight() : 0;
// If the click happened outside the active region, just don't send any mouse event
if (const auto adjustedY = terminalPosition.y - adjustment; adjustedY >= 0)
{
return _core->SendMouseEvent({ terminalPosition.x, adjustedY }, pointerUpdateKind, modifiers, wheelDelta, toInternalMouseState(buttonState));
}
return false;
const auto adjustment = _core->BufferHeight() - _core->ScrollOffset() - _core->ViewHeight();
// If the click happened outside the active region, core should get a chance to filter it out or clamp it.
const auto adjustedY = terminalPosition.y - adjustment;
return _core->SendMouseEvent({ terminalPosition.x, adjustedY }, pointerUpdateKind, modifiers, wheelDelta, toInternalMouseState(buttonState));
}
// Method Description:

View File

@ -58,7 +58,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const Core::Point pixelPosition);
void TouchPressed(const Core::Point contactPoint);
void PointerMoved(Control::MouseButtonState buttonState,
bool PointerMoved(Control::MouseButtonState buttonState,
const unsigned int pointerUpdateKind,
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
const bool focused,

View File

@ -43,12 +43,12 @@ namespace Microsoft.Terminal.Control
Microsoft.Terminal.Core.Point pixelPosition);
void TouchPressed(Microsoft.Terminal.Core.Point contactPoint);
void PointerMoved(MouseButtonState buttonState,
UInt32 pointerUpdateKind,
Microsoft.Terminal.Core.ControlKeyStates modifiers,
Boolean focused,
Microsoft.Terminal.Core.Point pixelPosition,
Boolean pointerPressedInBounds);
Boolean PointerMoved(MouseButtonState buttonState,
UInt32 pointerUpdateKind,
Microsoft.Terminal.Core.ControlKeyStates modifiers,
Boolean focused,
Microsoft.Terminal.Core.Point pixelPosition,
Boolean pointerPressedInBounds);
void TouchMoved(Microsoft.Terminal.Core.Point newTouchPoint,
Boolean focused);

View File

@ -216,10 +216,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
struct SearchMissingCommandEventArgs : public SearchMissingCommandEventArgsT<SearchMissingCommandEventArgs>
{
public:
SearchMissingCommandEventArgs(const winrt::hstring& missingCommand) :
MissingCommand(missingCommand) {}
SearchMissingCommandEventArgs(const winrt::hstring& missingCommand, const til::CoordType& bufferRow) :
MissingCommand(missingCommand),
BufferRow(bufferRow) {}
til::property<winrt::hstring> MissingCommand;
til::property<til::CoordType> BufferRow;
};
}

View File

@ -130,5 +130,6 @@ namespace Microsoft.Terminal.Control
runtimeclass SearchMissingCommandEventArgs
{
String MissingCommand { get; };
Int32 BufferRow { get; };
}
}

View File

@ -700,16 +700,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
this->Focus(FocusState::Programmatic);
}
winrt::fire_and_forget TermControl::UpdateControlSettings(IControlSettings settings)
void TermControl::UpdateControlSettings(IControlSettings settings)
{
return UpdateControlSettings(settings, _core.UnfocusedAppearance());
UpdateControlSettings(settings, _core.UnfocusedAppearance());
}
// Method Description:
// - Given Settings having been updated, applies the settings to the current terminal.
// Return Value:
// - <none>
winrt::fire_and_forget TermControl::UpdateControlSettings(IControlSettings settings,
IControlAppearance unfocusedAppearance)
safe_void_coroutine TermControl::UpdateControlSettings(IControlSettings settings,
IControlAppearance unfocusedAppearance)
{
auto weakThis{ get_weak() };
@ -731,7 +731,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - Dispatches a call to the UI thread and updates the appearance
// Arguments:
// - newAppearance: the new appearance to set
winrt::fire_and_forget TermControl::UpdateAppearance(IControlAppearance newAppearance)
safe_void_coroutine TermControl::UpdateAppearance(IControlAppearance newAppearance)
{
auto weakThis{ get_weak() };
@ -1012,8 +1012,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// <unused>
// Return Value:
// - <none>
winrt::fire_and_forget TermControl::_coreBackgroundColorChanged(const IInspectable& /*sender*/,
const IInspectable& /*args*/)
safe_void_coroutine TermControl::_coreBackgroundColorChanged(const IInspectable& /*sender*/,
const IInspectable& /*args*/)
{
auto weakThis{ get_weak() };
co_await wil::resume_foreground(Dispatcher());
@ -1190,7 +1190,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - hr: an HRESULT describing the warning
// Return Value:
// - <none>
winrt::fire_and_forget TermControl::_RendererWarning(IInspectable /*sender*/, Control::RendererWarningArgs args)
safe_void_coroutine TermControl::_RendererWarning(IInspectable /*sender*/, Control::RendererWarningArgs args)
{
auto weakThis{ get_weak() };
co_await wil::resume_foreground(Dispatcher());
@ -1375,7 +1375,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return true;
}
winrt::fire_and_forget TermControl::_restoreInBackground()
safe_void_coroutine TermControl::_restoreInBackground()
{
const auto path = std::exchange(_restorePath, {});
const auto weakSelf = get_weak();
@ -1547,11 +1547,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation
auto encoding = s.encoding;
wchar_t buf[4]{};
size_t buf_len = 0;
bool handled = true;
if (encoding == AltNumpadEncoding::Unicode)
{
// UTF-32 -> UTF-16
if (s.accumulator <= 0xffff)
if (s.accumulator == 0)
{
// If the user pressed Alt + VK_ADD, then released Alt, they probably didn't intend to insert a numpad character at all.
// Send any accumulated key events instead.
for (auto&& e : _altNumpadState.cachedKeyEvents)
{
handled = handled && _TrySendKeyEvent(e.vkey, e.scanCode, e.modifiers, e.keyDown);
}
// Send the alt keyup we are currently processing
handled = handled && _TrySendKeyEvent(vkey, scanCode, modifiers, keyDown);
// do not accumulate into the buffer
}
else if (s.accumulator <= 0xffff)
{
buf[buf_len++] = static_cast<uint16_t>(s.accumulator);
}
@ -1595,7 +1608,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
s = {};
return true;
return handled;
}
// As a continuation of the above, this handles the key-down case.
if (modifiers.IsAltPressed())
@ -1609,53 +1622,58 @@ namespace winrt::Microsoft::Terminal::Control::implementation
SCROLLLOCK_ON |
CAPSLOCK_ON;
if (keyDown && (modifiers.Value() & ~permittedModifiers) == 0)
if ((modifiers.Value() & ~permittedModifiers) == 0)
{
auto& s = _altNumpadState;
if (vkey == VK_ADD)
if (keyDown)
{
// Alt '+' <number> is used to input Unicode code points.
// Every time you press + it resets the entire state
// in the original OS implementation as well.
s.encoding = AltNumpadEncoding::Unicode;
s.accumulator = 0;
s.active = true;
}
else if (vkey == VK_NUMPAD0 && s.encoding == AltNumpadEncoding::OEM && s.accumulator == 0)
{
// Alt '0' <number> is used to input ANSI code points.
// Otherwise, they're OEM codepoints.
s.encoding = AltNumpadEncoding::ANSI;
s.active = true;
}
else
{
// Otherwise, append the pressed key to the accumulator.
const uint32_t base = s.encoding == AltNumpadEncoding::Unicode ? 16 : 10;
uint32_t add = 0xffffff;
if (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9)
if (vkey == VK_ADD)
{
add = vkey - VK_NUMPAD0;
}
else if (vkey >= 'A' && vkey <= 'F')
{
add = vkey - 'A' + 10;
}
// Pressing Alt + <not a number> should not activate the Alt+Numpad input, however.
if (add < base)
{
s.accumulator = std::min(s.accumulator * base + add, 0x10FFFFu);
// Alt '+' <number> is used to input Unicode code points.
// Every time you press + it resets the entire state
// in the original OS implementation as well.
s.encoding = AltNumpadEncoding::Unicode;
s.accumulator = 0;
s.active = true;
}
else if (vkey == VK_NUMPAD0 && s.encoding == AltNumpadEncoding::OEM && s.accumulator == 0)
{
// Alt '0' <number> is used to input ANSI code points.
// Otherwise, they're OEM codepoints.
s.encoding = AltNumpadEncoding::ANSI;
s.active = true;
}
else
{
// Otherwise, append the pressed key to the accumulator.
const uint32_t base = s.encoding == AltNumpadEncoding::Unicode ? 16 : 10;
uint32_t add = 0xffffff;
if (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9)
{
add = vkey - VK_NUMPAD0;
}
else if (vkey >= 'A' && vkey <= 'F')
{
add = vkey - 'A' + 10;
}
// Pressing Alt + <not a number> should not activate the Alt+Numpad input, however.
if (add < base)
{
s.accumulator = std::min(s.accumulator * base + add, 0x10FFFFu);
s.active = true;
}
}
}
// If someone pressed Alt + <not a number>, we'll skip the early
// return and send the Alt key combination as per usual.
if (s.active)
{
// Cache it in case we have to emit it after alt is released
_altNumpadState.cachedKeyEvents.emplace_back(vkey, scanCode, modifiers, keyDown);
return true;
}
@ -1918,18 +1936,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
if (type == Windows::Devices::Input::PointerDeviceType::Mouse ||
type == Windows::Devices::Input::PointerDeviceType::Pen)
{
_interactivity.PointerMoved(TermControl::GetPressedMouseButtons(point),
TermControl::GetPointerUpdateKind(point),
ControlKeyStates(args.KeyModifiers()),
_focused,
pixelPosition.to_core_point(),
_pointerPressedInBounds);
auto suppressFurtherHandling = _interactivity.PointerMoved(TermControl::GetPressedMouseButtons(point),
TermControl::GetPointerUpdateKind(point),
ControlKeyStates(args.KeyModifiers()),
_focused,
pixelPosition.to_core_point(),
_pointerPressedInBounds);
// GH#9109 - Only start an auto-scroll when the drag actually
// started within our bounds. Otherwise, someone could start a drag
// outside the terminal control, drag into the padding, and trick us
// into starting to scroll.
if (_focused && _pointerPressedInBounds && point.Properties().IsLeftButtonPressed())
if (!suppressFurtherHandling && _focused && _pointerPressedInBounds && point.Properties().IsLeftButtonPressed())
{
// We want to find the distance relative to the bounds of the
// SwapChainPanel, not the entire control. If they drag out of
@ -2083,8 +2101,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - <unused>
// Return Value:
// - <none>
winrt::fire_and_forget TermControl::_coreTransparencyChanged(IInspectable /*sender*/,
Control::TransparencyChangedEventArgs /*args*/)
safe_void_coroutine TermControl::_coreTransparencyChanged(IInspectable /*sender*/,
Control::TransparencyChangedEventArgs /*args*/)
{
co_await wil::resume_foreground(Dispatcher());
try
@ -3055,8 +3073,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - e: The DragEventArgs from the Drop event
// Return Value:
// - <none>
winrt::fire_and_forget TermControl::_DragDropHandler(Windows::Foundation::IInspectable /*sender*/,
DragEventArgs e)
safe_void_coroutine TermControl::_DragDropHandler(Windows::Foundation::IInspectable /*sender*/,
DragEventArgs e)
{
if (_IsClosing())
{
@ -3291,8 +3309,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - Checks if the uri is valid and sends an event if so
// Arguments:
// - The uri
winrt::fire_and_forget TermControl::_HyperlinkHandler(IInspectable /*sender*/,
Control::OpenHyperlinkEventArgs args)
safe_void_coroutine TermControl::_HyperlinkHandler(IInspectable /*sender*/,
Control::OpenHyperlinkEventArgs args)
{
// Save things we need to resume later.
auto strongThis{ get_strong() };
@ -3308,8 +3326,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Method Description:
// - Produces the error dialog that notifies the user that rendering cannot proceed.
winrt::fire_and_forget TermControl::_RendererEnteredErrorState(IInspectable /*sender*/,
IInspectable /*args*/)
safe_void_coroutine TermControl::_RendererEnteredErrorState(IInspectable /*sender*/,
IInspectable /*args*/)
{
auto strongThis{ get_strong() };
co_await winrt::resume_foreground(Dispatcher()); // pop up onto the UI thread
@ -3532,7 +3550,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
OverlayCanvas().SetTop(HyperlinkTooltipBorder(), locationInDIPs.y - offset.y);
}
winrt::fire_and_forget TermControl::_updateSelectionMarkers(IInspectable /*sender*/, Control::UpdateSelectionMarkersEventArgs args)
safe_void_coroutine TermControl::_updateSelectionMarkers(IInspectable /*sender*/, Control::UpdateSelectionMarkersEventArgs args)
{
auto weakThis{ get_weak() };
co_await resume_foreground(Dispatcher());
@ -4041,18 +4059,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto rd = get_self<ControlCore>(_core)->GetRenderData();
rd->LockConsole();
const auto viewportBufferPosition = rd->GetViewport();
const auto cursorBufferPosition = rd->GetCursorPosition();
rd->UnlockConsole();
if (cursorBufferPosition.y < viewportBufferPosition.Top() || cursorBufferPosition.y > viewportBufferPosition.BottomInclusive())
if (_quickFixBufferPos < viewportBufferPosition.Top() || _quickFixBufferPos > viewportBufferPosition.BottomInclusive())
{
quickFixBtn.Visibility(Visibility::Collapsed);
return;
}
// draw the button in the gutter
const auto& cursorPosInDips = CursorPositionInDips();
const auto& quickFixBtnPosInDips = _toPosInDips({ 0, _quickFixBufferPos });
Controls::Canvas::SetLeft(quickFixBtn, -termPadding.Left);
Controls::Canvas::SetTop(quickFixBtn, cursorPosInDips.Y - termPadding.Top);
Controls::Canvas::SetTop(quickFixBtn, quickFixBtnPosInDips.y - termPadding.Top);
quickFixBtn.Visibility(Visibility::Visible);
if (auto automationPeer{ FrameworkElementAutomationPeer::FromElement(*this) })
@ -4067,6 +4084,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::_bubbleSearchMissingCommand(const IInspectable& /*sender*/, const Control::SearchMissingCommandEventArgs& args)
{
_quickFixBufferPos = args.BufferRow();
SearchMissingCommand.raise(*this, args);
}

View File

@ -52,8 +52,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
static Control::TermControl NewControlByAttachingContent(Control::ControlInteractivity content, const Microsoft::Terminal::Control::IKeyBindings& keyBindings);
winrt::fire_and_forget UpdateControlSettings(Control::IControlSettings settings);
winrt::fire_and_forget UpdateControlSettings(Control::IControlSettings settings, Control::IControlAppearance unfocusedAppearance);
void UpdateControlSettings(Control::IControlSettings settings);
safe_void_coroutine UpdateControlSettings(Control::IControlSettings settings, Control::IControlAppearance unfocusedAppearance);
IControlSettings Settings() const;
uint64_t ContentId() const;
@ -132,11 +132,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void RenderEngineSwapChainChanged(IInspectable sender, IInspectable args);
void _AttachDxgiSwapChainToXaml(HANDLE swapChainHandle);
winrt::fire_and_forget _RendererEnteredErrorState(IInspectable sender, IInspectable args);
safe_void_coroutine _RendererEnteredErrorState(IInspectable sender, IInspectable args);
void _RenderRetryButton_Click(const IInspectable& button, const IInspectable& args);
winrt::fire_and_forget _RendererWarning(IInspectable sender,
Control::RendererWarningArgs args);
safe_void_coroutine _RendererWarning(IInspectable sender,
Control::RendererWarningArgs args);
void CreateSearchBoxControl();
@ -256,12 +256,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
};
struct AltNumpadState
{
struct CachedKey
{
WORD vkey;
WORD scanCode;
::Microsoft::Terminal::Core::ControlKeyStates modifiers;
bool keyDown;
};
AltNumpadEncoding encoding = AltNumpadEncoding::OEM;
uint32_t accumulator = 0;
// Checking for accumulator != 0 to see if we have an ongoing Alt+Numpad composition is insufficient.
// The state can be active, while the accumulator is 0, if the user pressed Alt+Numpad0 which enabled
// the OEM encoding mode (= active), and then pressed Numpad0 again (= accumulator is still 0).
bool active = false;
til::small_vector<CachedKey, 4> cachedKeyEvents;
};
AltNumpadState _altNumpadState;
@ -270,6 +278,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
bool _initializedTerminal{ false };
bool _quickFixButtonCollapsible{ false };
bool _quickFixesAvailable{ false };
til::CoordType _quickFixBufferPos{};
std::shared_ptr<ThrottledFuncLeading> _playWarningBell;
@ -333,11 +342,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _UpdateAppearanceFromUIThread(Control::IControlAppearance newAppearance);
void _ApplyUISettings();
winrt::fire_and_forget UpdateAppearance(Control::IControlAppearance newAppearance);
safe_void_coroutine UpdateAppearance(Control::IControlAppearance newAppearance);
void _SetBackgroundImage(const IControlAppearance& newAppearance);
void _InitializeBackgroundBrush();
winrt::fire_and_forget _coreBackgroundColorChanged(const IInspectable& sender, const IInspectable& args);
safe_void_coroutine _coreBackgroundColorChanged(const IInspectable& sender, const IInspectable& args);
void _changeBackgroundColor(til::color bg);
static bool _isColorLight(til::color bg) noexcept;
void _changeBackgroundOpacity();
@ -348,7 +357,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Reattach
};
bool _InitializeTerminal(const InitializeReason reason);
winrt::fire_and_forget _restoreInBackground();
safe_void_coroutine _restoreInBackground();
void _SetFontSize(int fontSize);
void _TappedHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& e);
void _KeyDownHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::Input::KeyRoutedEventArgs& e);
@ -367,10 +376,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _GotFocusHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void _LostFocusHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
winrt::fire_and_forget _DragDropHandler(Windows::Foundation::IInspectable sender, Windows::UI::Xaml::DragEventArgs e);
safe_void_coroutine _DragDropHandler(Windows::Foundation::IInspectable sender, Windows::UI::Xaml::DragEventArgs e);
void _DragOverHandler(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::DragEventArgs& e);
winrt::fire_and_forget _HyperlinkHandler(Windows::Foundation::IInspectable sender, Control::OpenHyperlinkEventArgs e);
safe_void_coroutine _HyperlinkHandler(Windows::Foundation::IInspectable sender, Control::OpenHyperlinkEventArgs e);
void _CursorTimerTick(const Windows::Foundation::IInspectable& sender, const Windows::Foundation::IInspectable& e);
void _BlinkTimerTick(const Windows::Foundation::IInspectable& sender, const Windows::Foundation::IInspectable& e);
@ -411,10 +420,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _handleSearchResults(SearchResults results);
void _hoveredHyperlinkChanged(const IInspectable& sender, const IInspectable& args);
winrt::fire_and_forget _updateSelectionMarkers(IInspectable sender, Control::UpdateSelectionMarkersEventArgs args);
safe_void_coroutine _updateSelectionMarkers(IInspectable sender, Control::UpdateSelectionMarkersEventArgs args);
void _coreFontSizeChanged(const IInspectable& s, const Control::FontSizeChangedArgs& args);
winrt::fire_and_forget _coreTransparencyChanged(IInspectable sender, Control::TransparencyChangedEventArgs args);
safe_void_coroutine _coreTransparencyChanged(IInspectable sender, Control::TransparencyChangedEventArgs args);
void _coreRaisedNotice(const IInspectable& s, const Control::NoticeEventArgs& args);
void _coreWarningBell(const IInspectable& sender, const IInspectable& args);
void _coreOutputIdle(const IInspectable& sender, const IInspectable& args);

View File

@ -711,7 +711,7 @@ TerminalInput::OutputType Terminal::SendCharEvent(const wchar_t ch, const WORD s
// * AND we're not in the alt buffer
//
// Then treat this line like it's a prompt mark.
if (_autoMarkPrompts)
if (_autoMarkPrompts && _mainBuffer && !_inAltBuffer())
{
// We need to be a little tricky here, to try and support folks that are
// auto-marking prompts, but don't necessarily have the rest of shell
@ -725,10 +725,10 @@ TerminalInput::OutputType Terminal::SendCharEvent(const wchar_t ch, const WORD s
//
// (TextBuffer::_createPromptMarkIfNeeded does that work for us)
const bool createdMark = _activeBuffer().StartOutput();
const bool createdMark = _mainBuffer->StartOutput();
if (createdMark)
{
_activeBuffer().ManuallyMarkRowAsPrompt(_activeBuffer().GetCursor().GetPosition().y);
_mainBuffer->ManuallyMarkRowAsPrompt(_mainBuffer->GetCursor().GetPosition().y);
// This changed the scrollbar marks - raise a notification to update them
_NotifyScrollEvent();
@ -1233,7 +1233,7 @@ void Microsoft::Terminal::Core::Terminal::CompletionsChangedCallback(std::functi
_pfnCompletionsChanged.swap(pfn);
}
void Microsoft::Terminal::Core::Terminal::SetSearchMissingCommandCallback(std::function<void(std::wstring_view)> pfn) noexcept
void Microsoft::Terminal::Core::Terminal::SetSearchMissingCommandCallback(std::function<void(std::wstring_view, const til::CoordType)> pfn) noexcept
{
_pfnSearchMissingCommand.swap(pfn);
}
@ -1615,6 +1615,12 @@ void Terminal::PreviewText(std::wstring_view input)
static constexpr TextAttribute previewAttrs{ CharacterAttributes::Italics, TextColor{}, TextColor{}, 0u, TextColor{} };
auto lock = LockForWriting();
if (_mainBuffer == nullptr)
{
return;
}
if (input.empty())
{
snippetPreview.text = L"";

View File

@ -230,7 +230,7 @@ public:
void SetShowWindowCallback(std::function<void(bool)> pfn) noexcept;
void SetPlayMidiNoteCallback(std::function<void(const int, const int, const std::chrono::microseconds)> pfn) noexcept;
void CompletionsChangedCallback(std::function<void(std::wstring_view, unsigned int)> pfn) noexcept;
void SetSearchMissingCommandCallback(std::function<void(std::wstring_view)> pfn) noexcept;
void SetSearchMissingCommandCallback(std::function<void(std::wstring_view, const til::CoordType)> pfn) noexcept;
void SetClearQuickFixCallback(std::function<void()> pfn) noexcept;
void SetSearchHighlights(const std::vector<til::point_span>& highlights) noexcept;
void SetSearchHighlightFocused(const size_t focusedIdx, til::CoordType searchScrollOffset);
@ -342,7 +342,7 @@ private:
std::function<void(bool)> _pfnShowWindowChanged;
std::function<void(const int, const int, const std::chrono::microseconds)> _pfnPlayMidiNote;
std::function<void(std::wstring_view, unsigned int)> _pfnCompletionsChanged;
std::function<void(std::wstring_view)> _pfnSearchMissingCommand;
std::function<void(std::wstring_view, const til::CoordType)> _pfnSearchMissingCommand;
std::function<void()> _pfnClearQuickFix;
RenderSettings _renderSettings;

View File

@ -24,7 +24,6 @@ void Terminal::ReturnResponse(const std::wstring_view response)
{
if (_pfnWriteInput && !response.empty())
{
const auto suspension = _readWriteLock.suspend();
_pfnWriteInput(response);
}
}
@ -338,7 +337,8 @@ void Terminal::SearchMissingCommand(const std::wstring_view command)
{
if (_pfnSearchMissingCommand)
{
_pfnSearchMissingCommand(command);
const auto bufferRow = GetCursorPosition().y;
_pfnSearchMissingCommand(command, bufferRow);
}
}

View File

@ -1240,7 +1240,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
fire_and_forget Appearances::BackgroundImage_Click(const IInspectable&, const RoutedEventArgs&)
safe_void_coroutine Appearances::BackgroundImage_Click(const IInspectable&, const RoutedEventArgs&)
{
auto lifetime = get_strong();

View File

@ -182,7 +182,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void FontFaceBox_SuggestionChosen(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox&, const winrt::Windows::UI::Xaml::Controls::AutoSuggestBoxSuggestionChosenEventArgs&);
void FontFaceBox_TextChanged(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox&, const winrt::Windows::UI::Xaml::Controls::AutoSuggestBoxTextChangedEventArgs&);
void DeleteFontKeyValuePair_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
fire_and_forget BackgroundImage_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
safe_void_coroutine BackgroundImage_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void BIAlignment_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
// manually bind FontWeight

View File

@ -490,6 +490,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void MainPage::SaveButton_Click(const IInspectable& /*sender*/, const RoutedEventArgs& /*args*/)
{
_settingsClone.LogSettingChanges(false);
_settingsClone.WriteSettingsToDisk();
}

View File

@ -76,7 +76,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
winrt::get_self<ProfileViewModel>(_Profile)->DeleteProfile();
}
fire_and_forget Profiles_Base::Commandline_Click(const IInspectable&, const RoutedEventArgs&)
safe_void_coroutine Profiles_Base::Commandline_Click(const IInspectable&, const RoutedEventArgs&)
{
auto lifetime = get_strong();
@ -106,7 +106,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
fire_and_forget Profiles_Base::Icon_Click(const IInspectable&, const RoutedEventArgs&)
safe_void_coroutine Profiles_Base::Icon_Click(const IInspectable&, const RoutedEventArgs&)
{
auto lifetime = get_strong();
@ -118,7 +118,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
fire_and_forget Profiles_Base::StartingDirectory_Click(const IInspectable&, const RoutedEventArgs&)
safe_void_coroutine Profiles_Base::StartingDirectory_Click(const IInspectable&, const RoutedEventArgs&)
{
auto lifetime = get_strong();
const auto parentHwnd{ reinterpret_cast<HWND>(_windowRoot.GetHostingWindow()) };

View File

@ -17,9 +17,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void OnNavigatedTo(const Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
void OnNavigatedFrom(const Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
fire_and_forget StartingDirectory_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
fire_and_forget Icon_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
fire_and_forget Commandline_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
safe_void_coroutine StartingDirectory_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
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 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

@ -570,6 +570,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
const auto action = cmd.ActionAndArgs().Action();
const auto id = action == ShortcutAction::Invalid ? hstring{} : cmd.ID();
_KeyMap.insert_or_assign(keys, id);
_changeLog.emplace(KeysKey);
}
// Method Description:

View File

@ -73,6 +73,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
Json::Value ToJson() const;
Json::Value KeyBindingsToJson() const;
bool FixupsAppliedDuringLoad() const;
void LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const;
// modification
bool RebindKeys(const Control::KeyChord& oldKeys, const Control::KeyChord& newKeys);
@ -138,6 +139,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
til::shared_mutex<std::unordered_map<hstring, std::vector<Model::Command>>> _cwdLocalSnippetsCache{};
std::set<std::string> _changeLog;
friend class SettingsModelUnitTests::KeyBindingsTests;
friend class SettingsModelUnitTests::DeserializationTests;
friend class SettingsModelUnitTests::TerminalSettingsTests;

View File

@ -78,7 +78,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
// Now check if this is a command block
if (jsonBlock.isMember(JsonKey(CommandsKey)) || jsonBlock.isMember(JsonKey(ActionKey)))
{
AddAction(*Command::FromJson(jsonBlock, warnings, origin), keys);
auto command = Command::FromJson(jsonBlock, warnings, origin);
command->LogSettingChanges(_changeLog);
AddAction(*command, keys);
if (jsonBlock.isMember(JsonKey(KeysKey)))
{
@ -105,6 +107,28 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
// any existing keybinding with the same keychord in this layer will get overwritten
_KeyMap.insert_or_assign(keys, idJson);
if (!_changeLog.contains(KeysKey.data()))
{
// Log "keys" field, but only if it's one that isn't in userDefaults.json
static constexpr std::array<std::pair<std::wstring_view, std::string_view>, 3> userDefaultKbds{ { { L"Terminal.CopyToClipboard", "ctrl+c" },
{ L"Terminal.PasteFromClipboard", "ctrl+v" },
{ L"Terminal.DuplicatePaneAuto", "alt+shift+d" } } };
bool isUserDefaultKbd = false;
for (const auto& [id, kbd] : userDefaultKbds)
{
const auto keyJson{ jsonBlock.find(&*KeysKey.cbegin(), (&*KeysKey.cbegin()) + KeysKey.size()) };
if (idJson == id && keyJson->asString() == kbd)
{
isUserDefaultKbd = true;
break;
}
}
if (!isUserDefaultKbd)
{
_changeLog.emplace(KeysKey);
}
}
}
}
@ -156,4 +180,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return keybindingsList;
}
void ActionMap::LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const
{
for (const auto& setting : _changeLog)
{
changes.emplace(fmt::format(FMT_COMPILE("{}.{}"), context, setting));
}
}
}

View File

@ -90,27 +90,42 @@ Json::Value AppearanceConfig::ToJson() const
void AppearanceConfig::LayerJson(const Json::Value& json)
{
JsonUtils::GetValueForKey(json, ForegroundKey, _Foreground);
_logSettingIfSet(ForegroundKey, _Foreground.has_value());
JsonUtils::GetValueForKey(json, BackgroundKey, _Background);
_logSettingIfSet(BackgroundKey, _Background.has_value());
JsonUtils::GetValueForKey(json, SelectionBackgroundKey, _SelectionBackground);
_logSettingIfSet(SelectionBackgroundKey, _SelectionBackground.has_value());
JsonUtils::GetValueForKey(json, CursorColorKey, _CursorColor);
_logSettingIfSet(CursorColorKey, _CursorColor.has_value());
JsonUtils::GetValueForKey(json, LegacyAcrylicTransparencyKey, _Opacity);
JsonUtils::GetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<float, IntAsFloatPercentConversionTrait>{});
_logSettingIfSet(OpacityKey, _Opacity.has_value());
if (json["colorScheme"].isString())
{
// to make the UI happy, set ColorSchemeName.
JsonUtils::GetValueForKey(json, ColorSchemeKey, _DarkColorSchemeName);
_LightColorSchemeName = _DarkColorSchemeName;
_logSettingSet(ColorSchemeKey);
}
else if (json["colorScheme"].isObject())
{
// to make the UI happy, set ColorSchemeName to whatever the dark value is.
JsonUtils::GetValueForKey(json["colorScheme"], "dark", _DarkColorSchemeName);
JsonUtils::GetValueForKey(json["colorScheme"], "light", _LightColorSchemeName);
_logSettingSet("colorScheme.dark");
_logSettingSet("colorScheme.light");
}
#define APPEARANCE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
JsonUtils::GetValueForKey(json, jsonKey, _##name);
JsonUtils::GetValueForKey(json, jsonKey, _##name); \
_logSettingIfSet(jsonKey, _##name.has_value());
MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_LAYER_JSON)
#undef APPEARANCE_SETTINGS_LAYER_JSON
}
@ -156,3 +171,24 @@ winrt::hstring AppearanceConfig::ExpandedBackgroundImagePath()
return winrt::hstring{ wil::ExpandEnvironmentStringsW<std::wstring>(path.c_str()) };
}
}
void AppearanceConfig::_logSettingSet(const std::string_view& setting)
{
_changeLog.emplace(setting);
}
void AppearanceConfig::_logSettingIfSet(const std::string_view& setting, const bool isSet)
{
if (isSet)
{
_logSettingSet(setting);
}
}
void AppearanceConfig::LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const
{
for (const auto& setting : _changeLog)
{
changes.emplace(fmt::format(FMT_COMPILE("{}.{}"), context, setting));
}
}

View File

@ -31,6 +31,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static winrt::com_ptr<AppearanceConfig> CopyAppearance(const AppearanceConfig* source, winrt::weak_ref<Profile> sourceProfile);
Json::Value ToJson() const;
void LayerJson(const Json::Value& json);
void LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const;
Model::Profile SourceProfile();
@ -52,5 +53,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
private:
winrt::weak_ref<Profile> _sourceProfile;
std::set<std::string> _changeLog;
void _logSettingSet(const std::string_view& setting);
void _logSettingIfSet(const std::string_view& setting, const bool isSet);
};
}

View File

@ -1161,7 +1161,7 @@ void CascadiaSettings::_refreshDefaultTerminals()
std::pair<std::vector<Model::DefaultTerminal>, Model::DefaultTerminal> result{ {}, nullptr };
til::latch latch{ 1 };
std::ignore = [&]() -> winrt::fire_and_forget {
std::ignore = [&]() -> safe_void_coroutine {
const auto cleanup = wil::scope_exit([&]() {
latch.count_down();
});

View File

@ -48,6 +48,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
std::unordered_map<winrt::hstring, winrt::com_ptr<implementation::ColorScheme>> colorSchemes;
std::unordered_map<winrt::hstring, winrt::hstring> colorSchemeRemappings;
bool fixupsAppliedDuringLoad{ false };
std::set<std::string> themesChangeLog;
void clear();
};
@ -96,6 +97,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
void _executeGenerator(const IDynamicProfileGenerator& generator);
std::unordered_set<std::wstring_view> _ignoredNamespaces;
std::set<std::string> themesChangeLog;
// See _getNonUserOriginProfiles().
size_t _userProfileCount = 0;
};
@ -156,6 +158,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
void ExpandCommands();
void LogSettingChanges(bool isJsonLoad) const;
private:
static const std::filesystem::path& _settingsPath();
static const std::filesystem::path& _releaseSettingsPath();
@ -186,6 +190,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
winrt::com_ptr<implementation::Profile> _baseLayerProfile = winrt::make_self<implementation::Profile>();
winrt::Windows::Foundation::Collections::IObservableVector<Model::Profile> _allProfiles = winrt::single_threaded_observable_vector<Model::Profile>();
winrt::Windows::Foundation::Collections::IObservableVector<Model::Profile> _activeProfiles = winrt::single_threaded_observable_vector<Model::Profile>();
std::set<std::string> _themesChangeLog{};
// load errors
winrt::Windows::Foundation::Collections::IVector<Model::SettingsLoadWarnings> _warnings = winrt::single_threaded_vector<Model::SettingsLoadWarnings>();

View File

@ -24,6 +24,7 @@ namespace Microsoft.Terminal.Settings.Model
CascadiaSettings Copy();
void WriteSettingsToDisk();
void LogSettingChanges(Boolean isJsonLoad);
String Hash { get; };

View File

@ -78,7 +78,7 @@ static auto extractValueFromTaskWithoutMainThreadAwait(TTask&& task) -> decltype
std::optional<decltype(task.get())> finalVal;
til::latch latch{ 1 };
const auto _ = [&]() -> winrt::fire_and_forget {
const auto _ = [&]() -> safe_void_coroutine {
const auto cleanup = wil::scope_exit([&]() {
latch.count_down();
});
@ -109,6 +109,7 @@ void ParsedSettings::clear()
profilesByGuid.clear();
colorSchemes.clear();
fixupsAppliedDuringLoad = false;
themesChangeLog.clear();
}
// This is a convenience method used by the CascadiaSettings constructor.
@ -658,6 +659,12 @@ void SettingsLoader::_parse(const OriginTag origin, const winrt::hstring& source
// versions of these themes overriding the built-in ones.
continue;
}
if (origin != OriginTag::InBox)
{
static std::string themesContext{ "themes" };
theme->LogSettingChanges(settings.themesChangeLog, themesContext);
}
settings.globals->AddTheme(*theme);
}
}
@ -1222,6 +1229,7 @@ CascadiaSettings::CascadiaSettings(SettingsLoader&& loader) :
_allProfiles = winrt::single_threaded_observable_vector(std::move(allProfiles));
_activeProfiles = winrt::single_threaded_observable_vector(std::move(activeProfiles));
_warnings = winrt::single_threaded_vector(std::move(warnings));
_themesChangeLog = std::move(loader.userSettings.themesChangeLog);
_resolveDefaultProfile();
_resolveNewTabMenuProfiles();
@ -1596,3 +1604,73 @@ void CascadiaSettings::_resolveNewTabMenuProfilesSet(const IVector<Model::NewTab
}
}
}
void CascadiaSettings::LogSettingChanges(bool isJsonLoad) const
{
#ifndef _DEBUG
// Only do this if we're actually being sampled
if (!TraceLoggingProviderEnabled(g_hSettingsModelProvider, 0, MICROSOFT_KEYWORD_MEASURES))
{
return;
}
#endif // !_DEBUG
// aggregate setting changes
std::set<std::string> changes;
static constexpr std::string_view globalContext{ "global" };
_globals->LogSettingChanges(changes, globalContext);
// Actions are not expected to change when loaded from the settings UI
static constexpr std::string_view actionContext{ "action" };
winrt::get_self<implementation::ActionMap>(_globals->ActionMap())->LogSettingChanges(changes, actionContext);
static constexpr std::string_view profileContext{ "profile" };
for (const auto& profile : _allProfiles)
{
winrt::get_self<Profile>(profile)->LogSettingChanges(changes, profileContext);
}
static constexpr std::string_view profileDefaultsContext{ "profileDefaults" };
_baseLayerProfile->LogSettingChanges(changes, profileDefaultsContext);
// Themes are not expected to change when loaded from the settings UI
// DO NOT CALL Theme::LogSettingChanges!!
// We already collected the changes when we loaded the JSON
for (const auto& change : _themesChangeLog)
{
changes.insert(change);
}
// report changes
for (const auto& change : changes)
{
#ifndef _DEBUG
// A `isJsonLoad ? "JsonSettingsChanged" : "UISettingsChanged"`
// would be nice, but that apparently isn't allowed in the macro below.
// Also, there's guidance to not send too much data all in one event,
// so we'll be sending a ton of events here.
if (isJsonLoad)
{
TraceLoggingWrite(g_hSettingsModelProvider,
"JsonSettingsChanged",
TraceLoggingDescription("Event emitted when settings.json change"),
TraceLoggingValue(change.data()),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
}
else
{
TraceLoggingWrite(g_hSettingsModelProvider,
"UISettingsChanged",
TraceLoggingDescription("Event emitted when settings change via the UI"),
TraceLoggingValue(change.data()),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
}
#else
OutputDebugStringA(isJsonLoad ? "JsonSettingsChanged - " : "UISettingsChanged - ");
OutputDebugStringA(change.data());
OutputDebugStringA("\n");
#endif // !_DEBUG
}
}

View File

@ -741,4 +741,57 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return winrt::single_threaded_vector<Model::Command>(std::move(result));
}
void Command::LogSettingChanges(std::set<std::string>& changes)
{
if (_IterateOn != ExpandCommandType::None)
{
switch (_IterateOn)
{
case ExpandCommandType::Profiles:
changes.emplace(fmt::format(FMT_COMPILE("{}.{}"), IterateOnKey, "profiles"));
break;
case ExpandCommandType::ColorSchemes:
changes.emplace(fmt::format(FMT_COMPILE("{}.{}"), IterateOnKey, "schemes"));
break;
}
}
if (!_Description.empty())
{
changes.emplace(DescriptionKey);
}
if (IsNestedCommand())
{
changes.emplace(CommandsKey);
}
else
{
const auto json{ ActionAndArgs::ToJson(ActionAndArgs()) };
if (json.isString())
{
// covers actions w/out args
// - "command": "unbound" --> "unbound"
// - "command": "copy" --> "copy"
changes.emplace(fmt::format(FMT_COMPILE("{}"), json.asString()));
}
else
{
// covers actions w/ args
// - "command": { "action": "copy", "singleLine": true } --> "copy.singleLine"
// - "command": { "action": "copy", "singleLine": true, "dismissSelection": true } --> "copy.singleLine", "copy.dismissSelection"
const std::string shortcutActionName{ json[JsonKey("action")].asString() };
auto members = json.getMemberNames();
members.erase(std::remove_if(members.begin(), members.end(), [](const auto& member) { return member == "action"; }), members.end());
for (const auto& actionArg : members)
{
changes.emplace(fmt::format(FMT_COMPILE("{}.{}"), shortcutActionName, actionArg));
}
}
}
}
}

View File

@ -61,6 +61,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
const Json::Value& json,
const OriginTag origin);
Json::Value ToJson() const;
void LogSettingChanges(std::set<std::string>& changes);
bool HasNestedCommands() const;
bool IsNestedCommand() const noexcept;

View File

@ -83,17 +83,25 @@ void FontConfig::LayerJson(const Json::Value& json)
{
// A font object is defined, use that
const auto fontInfoJson = json[JsonKey(FontInfoKey)];
#define FONT_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
JsonUtils::GetValueForKey(fontInfoJson, jsonKey, _##name);
#define FONT_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
JsonUtils::GetValueForKey(fontInfoJson, jsonKey, _##name); \
_logSettingIfSet(jsonKey, _##name.has_value());
MTSM_FONT_SETTINGS(FONT_SETTINGS_LAYER_JSON)
#undef FONT_SETTINGS_LAYER_JSON
}
else
{
// No font object is defined
// Log settings as if they were a part of the font object
JsonUtils::GetValueForKey(json, LegacyFontFaceKey, _FontFace);
_logSettingIfSet("face", _FontFace.has_value());
JsonUtils::GetValueForKey(json, LegacyFontSizeKey, _FontSize);
_logSettingIfSet("size", _FontSize.has_value());
JsonUtils::GetValueForKey(json, LegacyFontWeightKey, _FontWeight);
_logSettingIfSet("weight", _FontWeight.has_value());
}
}
@ -101,3 +109,41 @@ winrt::Microsoft::Terminal::Settings::Model::Profile FontConfig::SourceProfile()
{
return _sourceProfile.get();
}
void FontConfig::_logSettingSet(const std::string_view& setting)
{
if (setting == "axes" && _FontAxes.has_value())
{
for (const auto& [mapKey, _] : _FontAxes.value())
{
_changeLog.emplace(fmt::format(FMT_COMPILE("{}.{}"), setting, til::u16u8(mapKey)));
}
}
else if (setting == "features" && _FontFeatures.has_value())
{
for (const auto& [mapKey, _] : _FontFeatures.value())
{
_changeLog.emplace(fmt::format(FMT_COMPILE("{}.{}"), setting, til::u16u8(mapKey)));
}
}
else
{
_changeLog.emplace(setting);
}
}
void FontConfig::_logSettingIfSet(const std::string_view& setting, const bool isSet)
{
if (isSet)
{
_logSettingSet(setting);
}
}
void FontConfig::LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const
{
for (const auto& setting : _changeLog)
{
changes.emplace(fmt::format(FMT_COMPILE("{}.{}"), context, setting));
}
}

View File

@ -35,6 +35,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static winrt::com_ptr<FontConfig> CopyFontInfo(const FontConfig* source, winrt::weak_ref<Profile> sourceProfile);
Json::Value ToJson() const;
void LayerJson(const Json::Value& json);
void LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const;
Model::Profile SourceProfile();
@ -45,5 +46,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
private:
winrt::weak_ref<Profile> _sourceProfile;
std::set<std::string> _changeLog;
void _logSettingSet(const std::string_view& setting);
void _logSettingIfSet(const std::string_view& setting, const bool isSet);
};
}

View File

@ -128,13 +128,16 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::FromJson(const Json::Value&
void GlobalAppSettings::LayerJson(const Json::Value& json, const OriginTag origin)
{
JsonUtils::GetValueForKey(json, DefaultProfileKey, _UnparsedDefaultProfile);
// GH#8076 - when adding enum values to this key, we also changed it from
// "useTabSwitcher" to "tabSwitcherMode". Continue supporting
// "useTabSwitcher", but prefer "tabSwitcherMode"
JsonUtils::GetValueForKey(json, LegacyUseTabSwitcherModeKey, _TabSwitcherMode);
#define GLOBAL_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
JsonUtils::GetValueForKey(json, jsonKey, _##name);
JsonUtils::GetValueForKey(json, jsonKey, _##name); \
_logSettingIfSet(jsonKey, _##name.has_value());
MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_LAYER_JSON)
#undef GLOBAL_SETTINGS_LAYER_JSON
@ -152,6 +155,25 @@ void GlobalAppSettings::LayerJson(const Json::Value& json, const OriginTag origi
LayerActionsFrom(json, origin, true);
JsonUtils::GetValueForKey(json, LegacyReloadEnvironmentVariablesKey, _legacyReloadEnvironmentVariables);
if (json[LegacyReloadEnvironmentVariablesKey.data()])
{
_logSettingSet(LegacyReloadEnvironmentVariablesKey);
}
// Remove settings included in userDefaults
static constexpr std::array<std::pair<std::string_view, std::string_view>, 2> userDefaultSettings{ { { "copyOnSelect", "false" },
{ "copyFormatting", "false" } } };
for (const auto& [setting, val] : userDefaultSettings)
{
if (const auto settingJson{ json.find(&*setting.cbegin(), (&*setting.cbegin()) + setting.size()) })
{
if (settingJson->asString() == val)
{
// false positive!
_changeLog.erase(std::string{ setting });
}
}
}
}
void GlobalAppSettings::LayerActionsFrom(const Json::Value& json, const OriginTag origin, const bool withKeybindings)
@ -317,3 +339,85 @@ bool GlobalAppSettings::ShouldUsePersistedLayout() const
{
return FirstWindowPreference() == FirstWindowPreference::PersistedWindowLayout && !IsolatedMode();
}
void GlobalAppSettings::_logSettingSet(const std::string_view& setting)
{
if (setting == "theme")
{
if (_Theme.has_value())
{
// ThemePair always has a Dark/Light value,
// so we need to check if they were explicitly set
if (_Theme->DarkName() == _Theme->LightName())
{
_changeLog.emplace(setting);
}
else
{
_changeLog.emplace(fmt::format(FMT_COMPILE("{}.{}"), setting, "dark"));
_changeLog.emplace(fmt::format(FMT_COMPILE("{}.{}"), setting, "light"));
}
}
}
else if (setting == "newTabMenu")
{
if (_NewTabMenu.has_value())
{
for (const auto& entry : *_NewTabMenu)
{
std::string entryType;
switch (entry.Type())
{
case NewTabMenuEntryType::Profile:
entryType = "profile";
break;
case NewTabMenuEntryType::Separator:
entryType = "separator";
break;
case NewTabMenuEntryType::Folder:
entryType = "folder";
break;
case NewTabMenuEntryType::RemainingProfiles:
entryType = "remainingProfiles";
break;
case NewTabMenuEntryType::MatchProfiles:
entryType = "matchProfiles";
break;
case NewTabMenuEntryType::Action:
entryType = "action";
break;
case NewTabMenuEntryType::Invalid:
// ignore invalid
continue;
}
_changeLog.emplace(fmt::format(FMT_COMPILE("{}.{}"), setting, entryType));
}
}
}
else
{
_changeLog.emplace(setting);
}
}
void GlobalAppSettings::_logSettingIfSet(const std::string_view& setting, const bool isSet)
{
if (isSet)
{
// Exclude some false positives from userDefaults.json
const bool settingCopyFormattingToDefault = til::equals_insensitive_ascii(setting, "copyFormatting") && _CopyFormatting.has_value() && _CopyFormatting.value() == static_cast<Control::CopyFormat>(0);
const bool settingNTMToDefault = til::equals_insensitive_ascii(setting, "newTabMenu") && _NewTabMenu.has_value() && _NewTabMenu->Size() == 1 && _NewTabMenu->GetAt(0).Type() == NewTabMenuEntryType::RemainingProfiles;
if (!settingCopyFormattingToDefault && !settingNTMToDefault)
{
_logSettingSet(setting);
}
}
}
void GlobalAppSettings::LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const
{
for (const auto& setting : _changeLog)
{
changes.emplace(fmt::format(FMT_COMPILE("{}.{}"), context, setting));
}
}

View File

@ -72,10 +72,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
bool LegacyReloadEnvironmentVariables() const noexcept { return _legacyReloadEnvironmentVariables; }
void LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const;
INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L"");
#define GLOBAL_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
INHERITABLE_SETTING(Model::GlobalAppSettings, type, name, ##__VA_ARGS__)
INHERITABLE_SETTING_WITH_LOGGING(Model::GlobalAppSettings, type, name, jsonKey, ##__VA_ARGS__)
MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_INITIALIZE)
#undef GLOBAL_SETTINGS_INITIALIZE
@ -89,9 +91,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
winrt::guid _defaultProfile{};
bool _legacyReloadEnvironmentVariables{ true };
winrt::com_ptr<implementation::ActionMap> _actionMap{ winrt::make_self<implementation::ActionMap>() };
std::set<std::string> _changeLog;
std::vector<SettingsLoadWarnings> _keybindingsWarnings;
Windows::Foundation::Collections::IMap<winrt::hstring, Model::ColorScheme> _colorSchemes{ winrt::single_threaded_map<winrt::hstring, Model::ColorScheme>() };
Windows::Foundation::Collections::IMap<winrt::hstring, Model::Theme> _themes{ winrt::single_threaded_map<winrt::hstring, Model::Theme>() };
void _logSettingSet(const std::string_view& setting);
void _logSettingIfSet(const std::string_view& setting, const bool isSet);
};
}

View File

@ -185,6 +185,27 @@ public: \
_##name = value; \
}
#define INHERITABLE_SETTING_WITH_LOGGING(projectedType, type, name, jsonKey, ...) \
_BASE_INHERITABLE_SETTING(projectedType, std::optional<type>, name, ...) \
public: \
/* Returns the resolved value for this setting */ \
/* fallback: user set value --> inherited value --> system set value */ \
type name() const \
{ \
const auto val{ _get##name##Impl() }; \
return val ? *val : type{ __VA_ARGS__ }; \
} \
\
/* Overwrite the user set value */ \
void name(const type& value) \
{ \
if (!_##name.has_value() || _##name.value() != value) \
{ \
_logSettingSet(jsonKey); \
} \
_##name = value; \
}
// This macro is similar to the one above, but is reserved for optional settings
// like Profile.Foreground (where null is interpreted
// as an acceptable value, rather than "inherit")

View File

@ -175,15 +175,22 @@ void Profile::LayerJson(const Json::Value& json)
JsonUtils::GetValueForKey(json, NameKey, _Name);
JsonUtils::GetValueForKey(json, UpdatesKey, _Updates);
JsonUtils::GetValueForKey(json, GuidKey, _Guid);
JsonUtils::GetValueForKey(json, HiddenKey, _Hidden);
// Make sure Source is before Hidden! We use that to exclude false positives from the settings logger!
JsonUtils::GetValueForKey(json, SourceKey, _Source);
JsonUtils::GetValueForKey(json, HiddenKey, _Hidden);
_logSettingIfSet(HiddenKey, _Hidden.has_value());
JsonUtils::GetValueForKey(json, IconKey, _Icon);
_logSettingIfSet(IconKey, _Icon.has_value());
// Padding was never specified as an integer, but it was a common working mistake.
// Allow it to be permissive.
JsonUtils::GetValueForKey(json, PaddingKey, _Padding, JsonUtils::OptionalConverter<hstring, JsonUtils::PermissiveStringConverter<std::wstring>>{});
_logSettingIfSet(PaddingKey, _Padding.has_value());
JsonUtils::GetValueForKey(json, TabColorKey, _TabColor);
_logSettingIfSet(TabColorKey, _TabColor.has_value());
// Try to load some legacy keys, to migrate them.
// Done _before_ the MTSM_PROFILE_SETTINGS, which have the updated keys.
@ -191,7 +198,8 @@ void Profile::LayerJson(const Json::Value& json)
JsonUtils::GetValueForKey(json, LegacyAutoMarkPromptsKey, _AutoMarkPrompts);
#define PROFILE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
JsonUtils::GetValueForKey(json, jsonKey, _##name);
JsonUtils::GetValueForKey(json, jsonKey, _##name); \
_logSettingIfSet(jsonKey, _##name.has_value());
MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_LAYER_JSON)
#undef PROFILE_SETTINGS_LAYER_JSON
@ -208,6 +216,8 @@ void Profile::LayerJson(const Json::Value& json)
unfocusedAppearance->LayerJson(json[JsonKey(UnfocusedAppearanceKey)]);
_UnfocusedAppearance = *unfocusedAppearance;
_logSettingSet(UnfocusedAppearanceKey);
}
}
@ -518,3 +528,58 @@ std::wstring Profile::NormalizeCommandLine(LPCWSTR commandLine)
return normalized;
}
void Profile::_logSettingSet(const std::string_view& setting)
{
_changeLog.emplace(setting);
}
void Profile::_logSettingIfSet(const std::string_view& setting, const bool isSet)
{
if (isSet)
{
// make sure this matches defaults.json.
static constexpr winrt::guid DEFAULT_WINDOWS_POWERSHELL_GUID{ 0x61c54bbd, 0xc2c6, 0x5271, { 0x96, 0xe7, 0x00, 0x9a, 0x87, 0xff, 0x44, 0xbf } };
static constexpr winrt::guid DEFAULT_COMMAND_PROMPT_GUID{ 0x0caa0dad, 0x35be, 0x5f56, { 0xa8, 0xff, 0xaf, 0xce, 0xee, 0xaa, 0x61, 0x01 } };
// Exclude some false positives from userDefaults.json
// NOTE: we can't use the OriginTag here because it hasn't been set yet!
const bool isWinPow = _Guid.has_value() && *_Guid == DEFAULT_WINDOWS_POWERSHELL_GUID; //_Name.has_value() && til::equals_insensitive_ascii(*_Name, L"Windows PowerShell");
const bool isCmd = _Guid.has_value() && *_Guid == DEFAULT_COMMAND_PROMPT_GUID; //_Name.has_value() && til::equals_insensitive_ascii(*_Name, L"Command Prompt");
const bool isACS = _Name.has_value() && til::equals_insensitive_ascii(*_Name, L"Azure Cloud Shell");
const bool isWTDynamicProfile = _Source.has_value() && til::starts_with(*_Source, L"Windows.Terminal");
const bool settingHiddenToFalse = til::equals_insensitive_ascii(setting, HiddenKey) && _Hidden.has_value() && _Hidden == false;
const bool settingCommandlineToWinPow = til::equals_insensitive_ascii(setting, "commandline") && _Commandline.has_value() && til::equals_insensitive_ascii(*_Commandline, L"%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe");
const bool settingCommandlineToCmd = til::equals_insensitive_ascii(setting, "commandline") && _Commandline.has_value() && til::equals_insensitive_ascii(*_Commandline, L"%SystemRoot%\\System32\\cmd.exe");
// clang-format off
if (!(isWinPow && (settingHiddenToFalse || settingCommandlineToWinPow))
&& !(isCmd && (settingHiddenToFalse || settingCommandlineToCmd))
&& !(isACS && settingHiddenToFalse)
&& !(isWTDynamicProfile && settingHiddenToFalse))
{
// clang-format on
_logSettingSet(setting);
}
}
}
void Profile::LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const
{
for (const auto& setting : _changeLog)
{
changes.emplace(fmt::format(FMT_COMPILE("{}.{}"), context, setting));
}
std::string fontContext{ fmt::format(FMT_COMPILE("{}.{}"), context, FontInfoKey) };
winrt::get_self<implementation::FontConfig>(_FontInfo)->LogSettingChanges(changes, fontContext);
// We don't want to distinguish between "profile.defaultAppearance.*" and "profile.unfocusedAppearance.*" settings,
// but we still want to aggregate all of the appearance settings from both appearances.
// Log them as "profile.appearance.*"
std::string appContext{ fmt::format(FMT_COMPILE("{}.{}"), context, "appearance") };
winrt::get_self<implementation::AppearanceConfig>(_DefaultAppearance)->LogSettingChanges(changes, appContext);
if (_UnfocusedAppearance)
{
winrt::get_self<implementation::AppearanceConfig>(*_UnfocusedAppearance)->LogSettingChanges(changes, appContext);
}
}

View File

@ -108,6 +108,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
void _FinalizeInheritance() override;
void LogSettingChanges(std::set<std::string>& changes, const std::string_view& context) const;
// Special fields
hstring Icon() const;
void Icon(const hstring& value);
@ -131,7 +133,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
public:
#define PROFILE_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
INHERITABLE_SETTING(Model::Profile, type, name, ##__VA_ARGS__)
INHERITABLE_SETTING_WITH_LOGGING(Model::Profile, type, name, jsonKey, ##__VA_ARGS__)
MTSM_PROFILE_SETTINGS(PROFILE_SETTINGS_INITIALIZE)
#undef PROFILE_SETTINGS_INITIALIZE
@ -140,12 +142,15 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
Model::FontConfig _FontInfo{ winrt::make<FontConfig>(weak_ref<Model::Profile>(*this)) };
std::optional<winrt::hstring> _evaluatedIcon{ std::nullopt };
std::set<std::string> _changeLog;
static std::wstring EvaluateStartingDirectory(const std::wstring& directory);
static guid _GenerateGuidForProfile(const std::wstring_view& name, const std::wstring_view& source) noexcept;
winrt::hstring _evaluateIcon() const;
void _logSettingSet(const std::string_view& setting);
void _logSettingIfSet(const std::string_view& setting, const bool isSet);
friend class SettingsModelUnitTests::DeserializationTests;
friend class SettingsModelUnitTests::ProfileTests;

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>Farbschema auswählen</value>
<value>Farbschema auswählen...</value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>Neue Registerkarte</value>
<value>Neue Registerkarte...</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>Bereich teilen</value>
<value>Bereich teilen...</value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>Bereich "Codeausschnitte" öffnen</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>Registerkartenfarbe festlegen</value>
<value>Registerkartenfarbe festlegen...</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>Einfügen</value>
@ -351,7 +351,7 @@
<value>Den Titel der Registerkarte zurücksetzen</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>Registerkartentitel umbenennen</value>
<value>Registerkarte umbenennen</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>Bereich skalieren</value>
@ -445,7 +445,7 @@
<value>Zur letzten Registerkarte wechseln</value>
</data>
<data name="TabSearchCommandKey" xml:space="preserve">
<value>Registerkarte suchen</value>
<value>Registerkarte suchen...</value>
</data>
<data name="ToggleAlwaysOnTopCommandKey" xml:space="preserve">
<value>Modus "Immer im Vordergrund" umschalten</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>Befehlspalette ein/aus</value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>Zuletzt verwendete Befehle</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>Vorschläge öffnen</value>
</data>
@ -519,7 +516,7 @@
<value>Fensternamen zurücksetzen</value>
</data>
<data name="OpenWindowRenamerCommandKey" xml:space="preserve">
<value>Fenster umbenennen</value>
<value>Fenster umbenennen...</value>
</data>
<data name="DisplayWorkingDirectoryCommandKey" xml:space="preserve">
<value>Aktuelles Arbeitsverzeichnis des Terminals anzeigen</value>
@ -570,7 +567,7 @@
<value>Terminal beenden</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>Hintergrunddeckkraft festlegen</value>
<value>Hintergrunddeckkraft festlegen...</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>Hintergrunddeckkraft um {0} % erhöhen</value>

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>Seleccionar combinación de colores</value>
<value>Seleccionar combinación de colores...</value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>Nueva pestaña</value>
<value>Nueva pestaña...</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>Dividir panel</value>
<value>Dividir panel...</value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>Apertura del panel de fragmentos</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>Establecer el color de la pestaña</value>
<value>Establecer color de pestaña...</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>Pegar</value>
@ -351,7 +351,7 @@
<value>Restablecer título de la pestaña</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>Cambiar título de la pestaña</value>
<value>Cambiar el nombre de la pestaña</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>Cambiar el tamaño del panel</value>
@ -445,7 +445,7 @@
<value>Cambiar a la última pestaña</value>
</data>
<data name="TabSearchCommandKey" xml:space="preserve">
<value>Buscar pestaña</value>
<value>Buscar pestañas...</value>
</data>
<data name="ToggleAlwaysOnTopCommandKey" xml:space="preserve">
<value>Alternar siempre en el modo superior</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>Alternar paleta de comandos</value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>Comandos recientes</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>Abrir sugerencias</value>
</data>
@ -570,7 +567,7 @@
<value>Salir del terminal</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>Establecer la opacidad del fondo</value>
<value>Establecer la opacidad del fondo...</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>Aumentar la opacidad del fondo en un {0} %</value>

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>Sélectionner un modèle de couleurs</value>
<value>Sélectionner le modèle de couleurs...</value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>Nouvel onglet</value>
<value>Nouvel onglet...</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>Fractionner le volet</value>
<value>Fractionner le volet...</value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>Ouvrir le volet des extraits de code</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>Définir la couleur de longlet</value>
<value>Définir la couleur de longlet...</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>Coller</value>
@ -351,7 +351,7 @@
<value>Rétablir le titre de longlet</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>Renommer le titre de l'onglet</value>
<value>Renommer l'onglet</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>Redimensionner le volet</value>
@ -445,7 +445,7 @@
<value>Basculer vers le dernier onglet</value>
</data>
<data name="TabSearchCommandKey" xml:space="preserve">
<value>Recherche de longlet</value>
<value>Rechercher longlet...</value>
</data>
<data name="ToggleAlwaysOnTopCommandKey" xml:space="preserve">
<value>Activer le mode Toujours visible</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>Activer/désactiver la palette de commandes</value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>Commandes récentes</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>Ouvrir les suggestions</value>
</data>
@ -519,7 +516,7 @@
<value>Réinitialiser le nom de la fenêtre</value>
</data>
<data name="OpenWindowRenamerCommandKey" xml:space="preserve">
<value>Fenêtre pour renommer</value>
<value>Renommer la fenêtre...</value>
</data>
<data name="DisplayWorkingDirectoryCommandKey" xml:space="preserve">
<value>Afficher le répertoire de travail actuel du terminal</value>
@ -570,7 +567,7 @@
<value>Quitter le terminal</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>Définir lopacité de larrière-plan</value>
<value>Définir lopacité de larrière-plan...</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>Augmenter lopacité de larrière-plan de {0} %</value>

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>Seleziona combinazione colori</value>
<value>Seleziona combinazione colori...</value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>Nuova scheda</value>
<value>Nuova scheda...</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>Suddividi riquadro</value>
<value>Suddividi riquadro...</value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>Apri riquadro frammenti di codice</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>Imposta il colore della scheda</value>
<value>Imposta il colore della scheda...</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>Incolla</value>
@ -351,7 +351,7 @@
<value>Reimposta il titolo della scheda</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>Rinomina il titolo della scheda</value>
<value>Rinomina scheda</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>Ridimensiona riquadro</value>
@ -445,7 +445,7 @@
<value>Passa all'ultima scheda</value>
</data>
<data name="TabSearchCommandKey" xml:space="preserve">
<value>Cerca scheda</value>
<value>Cerca scheda...</value>
</data>
<data name="ToggleAlwaysOnTopCommandKey" xml:space="preserve">
<value>Modalità attiva/disattiva sempre in alto</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>Attiva/disattiva riquadro dei comandi</value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>Comandi recenti</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>Apri i suggerimenti</value>
</data>
@ -519,7 +516,7 @@
<value>Reimposta nome finestra</value>
</data>
<data name="OpenWindowRenamerCommandKey" xml:space="preserve">
<value>Rinomina finestra</value>
<value>Rinomina finestra...</value>
</data>
<data name="DisplayWorkingDirectoryCommandKey" xml:space="preserve">
<value>Visualizza la directory di lavoro corrente del terminale</value>
@ -570,7 +567,7 @@
<value>Esci da Terminale</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>Imposta l'opacità di sfondo</value>
<value>Imposta l'opacità di sfondo...</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>Aumenta l'opacità di sfondo del {0}%</value>

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>配色パターンの選択</value>
<value>配色を選択...</value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>新しいタブ</value>
<value>新しいタブ...</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>ウィンドウを分割する</value>
<value>ウィンドウの分割...</value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>スニペット ウィンドウを開く</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>タブの色の設定</value>
<value>タブの色を設定...</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>貼り付け</value>
@ -351,7 +351,7 @@
<value>タブのタイトルをリセット</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>タブ タイトル名の変更</value>
<value>[名前の変更] タブ</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>ウィンドウのサイズの変更する</value>
@ -445,7 +445,7 @@
<value>最後のタブに切り替える</value>
</data>
<data name="TabSearchCommandKey" xml:space="preserve">
<value>タブの検索</value>
<value>タブを検索...</value>
</data>
<data name="ToggleAlwaysOnTopCommandKey" xml:space="preserve">
<value>常に手前に表示するモードに切り替える</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>コマンド パレットに切り替える</value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>最近使ったコマンド</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>候補を開く</value>
</data>
@ -570,7 +567,7 @@
<value>ターミナルの終了</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>背景の不透明度の設定</value>
<value>背景の不透明度を設定...</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>背景の不透明度を {0}% 上げる</value>

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>색 구성표 선택</value>
<value>색 구성표 선택...</value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>새 탭</value>
<value>새 탭...</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>분할 창</value>
<value>분할 창...</value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>코드 조각 창 열기</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>탭 색 설정</value>
<value>탭 색 설정...</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>붙여넣기</value>
@ -351,7 +351,7 @@
<value>탭 제목 재설정</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>탭 제목 이름 바꾸기</value>
<value>탭 이름 바꾸기</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>창 크기 조정</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>토글 명령 팔레트</value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>최근 명령</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>제안 사항 열기</value>
</data>
@ -570,7 +567,7 @@
<value>터미널 종료</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>배경 불투명도 설정</value>
<value>배경 불투명도 설정...</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>배경 불투명도를 {0}% 증가</value>

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>Selecionar esquema de cores</value>
<value>Selecionar esquema de cores...</value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>Nova guia</value>
<value>Nova guia...</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>Dividir painel</value>
<value>Dividir painel...</value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>Abrir painel de snippets</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>Definir a cor da guia</value>
<value>Definir cor da guia...</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>Colar</value>
@ -351,7 +351,7 @@
<value>Redefinir título da guia</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>Renomear título da guia</value>
<value>Renomear guia</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>Redimensionar painel</value>
@ -445,7 +445,7 @@
<value>Alternar para a última guia</value>
</data>
<data name="TabSearchCommandKey" xml:space="preserve">
<value>Pesquisar guia</value>
<value>Buscar guia...</value>
</data>
<data name="ToggleAlwaysOnTopCommandKey" xml:space="preserve">
<value>Alternar sempre no modo superior</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>Ativar/desativar paleta de comandos</value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>Comandos recentes</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>Abrir sugestões</value>
</data>
@ -519,7 +516,7 @@
<value>Definir nome da janela</value>
</data>
<data name="OpenWindowRenamerCommandKey" xml:space="preserve">
<value>Renomear janela</value>
<value>Renomear janela...</value>
</data>
<data name="DisplayWorkingDirectoryCommandKey" xml:space="preserve">
<value>Exibir o diretório de trabalho atual do Terminal</value>
@ -570,7 +567,7 @@
<value>Saia do Terminal</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>Definir opacidade da tela de fundo</value>
<value>Definir a opacidade da tela de fundo...</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>Aumentar a opacidade da tela de fundo em {0}%</value>

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>Ŝêĺĕćţ ćŏĺбŕ ѕćнêmē !!! !!!</value>
<value>Ŝêĺĕćţ ćŏĺбŕ ѕćнêmē... !!! !!! </value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>Ŋéŵ тάъ !!</value>
<value>Ŋéŵ тάъ... !!!</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>Śрĺíŧ ρāлë !!!</value>
<value>Śрĺíŧ ρāлë... !!! </value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>Òρëй ѕήїρφέţś ρªʼné !!! !!</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>Şėŧ ŧнę ťáь ċσŀőґ !!! !!</value>
<value>Şėŧ ŧăь ĉõľοґ... !!! !</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>Ρášτé !</value>
@ -351,7 +351,7 @@
<value>Řėś℮ŧ тαв τįтℓę !!! !</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>Гęйªm тåъ ŧīτļĕ !!! !</value>
<value>Гęйªm тåъ !!!</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>Ґëśîžє рãле !!!</value>
@ -445,7 +445,7 @@
<value>Ѕẃітčћ ţõ ťħέ ľάšť ţаь !!! !!! </value>
</data>
<data name="TabSearchCommandKey" xml:space="preserve">
<value>Ѕėàřĉħ ƒôґ ŧâь !!! !</value>
<value>Ѕėàřĉħ ƒôґ ŧâь... !!! !!</value>
</data>
<data name="ToggleAlwaysOnTopCommandKey" xml:space="preserve">
<value>Ŧōĝġļě αŀώªÿŝ òⁿ тοр мöðέ !!! !!! !</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>Ţōĝğļė čσmmάήđ рåŀęŧŧз !!! !!! </value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>Γë¢єйť ćøмmåηđŝ !!! !</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>Ǿрέʼn şµġġеšŧìŏπѕ !!! !</value>
</data>
@ -519,7 +516,7 @@
<value>Ŗεšзť ωĩйδōẁ ñâмé !!! !!</value>
</data>
<data name="OpenWindowRenamerCommandKey" xml:space="preserve">
<value>Ґёʼnάmë шϊйďθŵ !!! </value>
<value>Ґёʼnάmë шϊйďθŵ... !!! !</value>
</data>
<data name="DisplayWorkingDirectoryCommandKey" xml:space="preserve">
<value>Ďіŝρłάỳ Τѓmìйаĺ'š čûŗяēʼnτ ώоřκìņĝ ďιяęĉтσґỳ !!! !!! !!! !!! !</value>
@ -570,7 +567,7 @@
<value>Qυϊτ ŧħз Τέяmίŋăŀ !!! !!</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>Ѕěт ьªċķĝґøūņð óφǻĉїτў !!! !!! </value>
<value>Ѕěт ьªċķĝґøūņð óφǻĉїτў... !!! !!! !</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>Ĭñçŕ℮àŝę ваċкġřŏųлď ǿφāςíτу ьỳ {0}% !!! !!! !!! !</value>

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>Ŝêĺĕćţ ćŏĺбŕ ѕćнêmē !!! !!!</value>
<value>Ŝêĺĕćţ ćŏĺбŕ ѕćнêmē... !!! !!! </value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>Ŋéŵ тάъ !!</value>
<value>Ŋéŵ тάъ... !!!</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>Śрĺíŧ ρāлë !!!</value>
<value>Śрĺíŧ ρāлë... !!! </value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>Òρëй ѕήїρφέţś ρªʼné !!! !!</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>Şėŧ ŧнę ťáь ċσŀőґ !!! !!</value>
<value>Şėŧ ŧăь ĉõľοґ... !!! !</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>Ρášτé !</value>
@ -351,7 +351,7 @@
<value>Řėś℮ŧ тαв τįтℓę !!! !</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>Гęйªm тåъ ŧīτļĕ !!! !</value>
<value>Гęйªm тåъ !!!</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>Ґëśîžє рãле !!!</value>
@ -445,7 +445,7 @@
<value>Ѕẃітčћ ţõ ťħέ ľάšť ţаь !!! !!! </value>
</data>
<data name="TabSearchCommandKey" xml:space="preserve">
<value>Ѕėàřĉħ ƒôґ ŧâь !!! !</value>
<value>Ѕėàřĉħ ƒôґ ŧâь... !!! !!</value>
</data>
<data name="ToggleAlwaysOnTopCommandKey" xml:space="preserve">
<value>Ŧōĝġļě αŀώªÿŝ òⁿ тοр мöðέ !!! !!! !</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>Ţōĝğļė čσmmάήđ рåŀęŧŧз !!! !!! </value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>Γë¢єйť ćøмmåηđŝ !!! !</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>Ǿрέʼn şµġġеšŧìŏπѕ !!! !</value>
</data>
@ -519,7 +516,7 @@
<value>Ŗεšзť ωĩйδōẁ ñâмé !!! !!</value>
</data>
<data name="OpenWindowRenamerCommandKey" xml:space="preserve">
<value>Ґёʼnάmë шϊйďθŵ !!! </value>
<value>Ґёʼnάmë шϊйďθŵ... !!! !</value>
</data>
<data name="DisplayWorkingDirectoryCommandKey" xml:space="preserve">
<value>Ďіŝρłάỳ Τѓmìйаĺ'š čûŗяēʼnτ ώоřκìņĝ ďιяęĉтσґỳ !!! !!! !!! !!! !</value>
@ -570,7 +567,7 @@
<value>Qυϊτ ŧħз Τέяmίŋăŀ !!! !!</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>Ѕěт ьªċķĝґøūņð óφǻĉїτў !!! !!! </value>
<value>Ѕěт ьªċķĝґøūņð óφǻĉїτў... !!! !!! !</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>Ĭñçŕ℮àŝę ваċкġřŏųлď ǿφāςíτу ьỳ {0}% !!! !!! !!! !</value>

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>Ŝêĺĕćţ ćŏĺбŕ ѕćнêmē !!! !!!</value>
<value>Ŝêĺĕćţ ćŏĺбŕ ѕćнêmē... !!! !!! </value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>Ŋéŵ тάъ !!</value>
<value>Ŋéŵ тάъ... !!!</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>Śрĺíŧ ρāлë !!!</value>
<value>Śрĺíŧ ρāлë... !!! </value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>Òρëй ѕήїρφέţś ρªʼné !!! !!</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>Şėŧ ŧнę ťáь ċσŀőґ !!! !!</value>
<value>Şėŧ ŧăь ĉõľοґ... !!! !</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>Ρášτé !</value>
@ -351,7 +351,7 @@
<value>Řėś℮ŧ тαв τįтℓę !!! !</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>Гęйªm тåъ ŧīτļĕ !!! !</value>
<value>Гęйªm тåъ !!!</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>Ґëśîžє рãле !!!</value>
@ -445,7 +445,7 @@
<value>Ѕẃітčћ ţõ ťħέ ľάšť ţаь !!! !!! </value>
</data>
<data name="TabSearchCommandKey" xml:space="preserve">
<value>Ѕėàřĉħ ƒôґ ŧâь !!! !</value>
<value>Ѕėàřĉħ ƒôґ ŧâь... !!! !!</value>
</data>
<data name="ToggleAlwaysOnTopCommandKey" xml:space="preserve">
<value>Ŧōĝġļě αŀώªÿŝ òⁿ тοр мöðέ !!! !!! !</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>Ţōĝğļė čσmmάήđ рåŀęŧŧз !!! !!! </value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>Γë¢єйť ćøмmåηđŝ !!! !</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>Ǿрέʼn şµġġеšŧìŏπѕ !!! !</value>
</data>
@ -519,7 +516,7 @@
<value>Ŗεšзť ωĩйδōẁ ñâмé !!! !!</value>
</data>
<data name="OpenWindowRenamerCommandKey" xml:space="preserve">
<value>Ґёʼnάmë шϊйďθŵ !!! </value>
<value>Ґёʼnάmë шϊйďθŵ... !!! !</value>
</data>
<data name="DisplayWorkingDirectoryCommandKey" xml:space="preserve">
<value>Ďіŝρłάỳ Τѓmìйаĺ'š čûŗяēʼnτ ώоřκìņĝ ďιяęĉтσґỳ !!! !!! !!! !!! !</value>
@ -570,7 +567,7 @@
<value>Qυϊτ ŧħз Τέяmίŋăŀ !!! !!</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>Ѕěт ьªċķĝґøūņð óφǻĉїτў !!! !!! </value>
<value>Ѕěт ьªċķĝґøūņð óφǻĉїτў... !!! !!! !</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>Ĭñçŕ℮àŝę ваċкġřŏųлď ǿφāςíτу ьỳ {0}% !!! !!! !!! !</value>

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>Выбрать цветовую схему</value>
<value>Выбрать цветовую схему...</value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>Новая вкладка</value>
<value>Новая вкладка...</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>Разделить область</value>
<value>Разделить область...</value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>Открыть панель фрагментов</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>Задать цвет вкладки</value>
<value>Установить цвет вкладки...</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>Вставить</value>
@ -351,7 +351,7 @@
<value>Сбросить заголовок вкладки</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>Переименовать заголовок вкладки</value>
<value>Переименовать вкладку</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>Изменить размер области</value>
@ -445,7 +445,7 @@
<value>Переключиться на последнюю вкладку</value>
</data>
<data name="TabSearchCommandKey" xml:space="preserve">
<value>Поиск вкладки</value>
<value>Поиск вкладки...</value>
</data>
<data name="ToggleAlwaysOnTopCommandKey" xml:space="preserve">
<value>Режим "поверх других окон"</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>Показать или скрыть палитру команд</value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>Последние команды</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>Открыть предложения</value>
</data>
@ -519,7 +516,7 @@
<value>Сбросить имя окна</value>
</data>
<data name="OpenWindowRenamerCommandKey" xml:space="preserve">
<value>Переименовать окно</value>
<value>Переименовать окно...</value>
</data>
<data name="DisplayWorkingDirectoryCommandKey" xml:space="preserve">
<value>Отобразить текущий рабочий каталог Терминала</value>
@ -570,7 +567,7 @@
<value>Выйти из терминала</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>Установить непрозрачность фона</value>
<value>Установить непрозрачность фона...</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>Увеличить непрозрачность фона на {0}%</value>

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>选择配色方案</value>
<value>选择配色方案...</value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>新建标签页</value>
<value>新建选项卡...</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>拆分窗格</value>
<value>拆分窗格...</value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>打开代码片段窗格</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>设置选项卡颜色</value>
<value>设置选项卡颜色...</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>粘贴</value>
@ -351,7 +351,7 @@
<value>重置标签页标题</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>重命名选项卡标题</value>
<value>重命名选项卡</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>调整窗格大小</value>
@ -445,7 +445,7 @@
<value>切换到最后一个选项卡</value>
</data>
<data name="TabSearchCommandKey" xml:space="preserve">
<value>搜索选项卡</value>
<value>搜索选项卡...</value>
</data>
<data name="ToggleAlwaysOnTopCommandKey" xml:space="preserve">
<value>切换“总在最前面”模式</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>切换命令面板</value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>最近使用的命令</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>打开建议</value>
</data>
@ -519,7 +516,7 @@
<value>重置窗口名称</value>
</data>
<data name="OpenWindowRenamerCommandKey" xml:space="preserve">
<value>重命名窗口</value>
<value>重命名窗口...</value>
</data>
<data name="DisplayWorkingDirectoryCommandKey" xml:space="preserve">
<value>显示终端的当前工作目录</value>
@ -570,7 +567,7 @@
<value>退出终端</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>设置背景不透明度</value>
<value>设置背景不透明度...</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>将背景不透明度增加 {0}%</value>

View File

@ -118,13 +118,13 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SetColorSchemeParentCommandName" xml:space="preserve">
<value>選取彩色配置</value>
<value>選取彩色配置...</value>
</data>
<data name="NewTabParentCommandName" xml:space="preserve">
<value>新索引標籤</value>
<value>新索引標籤...</value>
</data>
<data name="SplitPaneParentCommandName" xml:space="preserve">
<value>分割窗格</value>
<value>分割窗格...</value>
</data>
<data name="SnippetsPaneCommandName" xml:space="preserve">
<value>開啟程式碼片段窗格</value>
@ -329,7 +329,7 @@
<comment>{Locked="JSON"}. "JSON" is the extension of the file that will be opened.</comment>
</data>
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
<value>設定索引標籤色彩</value>
<value>設定索引標籤色彩...</value>
</data>
<data name="PasteTextCommandKey" xml:space="preserve">
<value>貼上</value>
@ -351,7 +351,7 @@
<value>重設索引標籤標題</value>
</data>
<data name="OpenTabRenamerCommandKey" xml:space="preserve">
<value>重新命名索引標籤標題</value>
<value>重新命名索引標籤</value>
</data>
<data name="ResizePaneCommandKey" xml:space="preserve">
<value>調整頁面大小</value>
@ -445,7 +445,7 @@
<value>切換到最後一個索引標籤</value>
</data>
<data name="TabSearchCommandKey" xml:space="preserve">
<value>搜尋索引標籤</value>
<value>搜尋索引標籤...</value>
</data>
<data name="ToggleAlwaysOnTopCommandKey" xml:space="preserve">
<value>啟用 [最上層顯示] 模式</value>
@ -453,9 +453,6 @@
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
<value>切換命令選擇區</value>
</data>
<data name="SuggestionsCommandHistoryCommandKey" xml:space="preserve">
<value>最近使用的命令</value>
</data>
<data name="SuggestionsCommandKey" xml:space="preserve">
<value>開啟建議</value>
</data>
@ -519,7 +516,7 @@
<value>重設視窗名稱</value>
</data>
<data name="OpenWindowRenamerCommandKey" xml:space="preserve">
<value>重新命名視窗</value>
<value>重新命名視窗...</value>
</data>
<data name="DisplayWorkingDirectoryCommandKey" xml:space="preserve">
<value>顯示終端機目前的工作目錄</value>
@ -570,7 +567,7 @@
<value>結束 [終端機]</value>
</data>
<data name="SetOpacityParentCommandName" xml:space="preserve">
<value>設定背景不透明度</value>
<value>設定背景不透明度...</value>
</data>
<data name="IncreaseOpacityCommandKey" xml:space="preserve">
<value>增加背景不透明度為 {0}%</value>

View File

@ -292,6 +292,53 @@ winrt::com_ptr<Theme> Theme::FromJson(const Json::Value& json)
return result;
}
void Theme::LogSettingChanges(std::set<std::string>& changes, const std::string_view& context)
{
#pragma warning(push)
#pragma warning(disable : 5103) // pasting '{' and 'winrt' does not result in a valid preprocessing token
#define GENERATE_SET_CHECK_AND_JSON_KEYS(type, name, jsonKey, ...) \
const bool is##name##Set = _##name != nullptr; \
std::string_view outer##name##JsonKey = jsonKey;
MTSM_THEME_SETTINGS(GENERATE_SET_CHECK_AND_JSON_KEYS)
#define LOG_IF_SET(type, name, jsonKey, ...) \
if (obj.name() != type{##__VA_ARGS__ }) \
changes.emplace(fmt::format(FMT_COMPILE("{}.{}.{}"), context, outerJsonKey, jsonKey));
if (isWindowSet)
{
const auto obj = _Window;
const auto outerJsonKey = outerWindowJsonKey;
MTSM_THEME_WINDOW_SETTINGS(LOG_IF_SET)
}
if (isSettingsSet)
{
const auto obj = _Settings;
const auto outerJsonKey = outerSettingsJsonKey;
MTSM_THEME_SETTINGS_SETTINGS(LOG_IF_SET)
}
if (isTabRowSet)
{
const auto obj = _TabRow;
const auto outerJsonKey = outerTabRowJsonKey;
MTSM_THEME_TABROW_SETTINGS(LOG_IF_SET)
}
if (isTabSet)
{
const auto obj = _Tab;
const auto outerJsonKey = outerTabJsonKey;
MTSM_THEME_TAB_SETTINGS(LOG_IF_SET)
}
#undef LOG_IF_SET
#undef GENERATE_SET_CHECK_AND_JSON_KEYS
#pragma warning(pop)
}
// Method Description:
// - Create a new serialized JsonObject from an instance of this class
// Arguments:

View File

@ -97,8 +97,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
hstring ToString();
static com_ptr<Theme> FromJson(const Json::Value& json);
void LayerJson(const Json::Value& json);
Json::Value ToJson() const;
void LogSettingChanges(std::set<std::string>& changes, const std::string_view& context);
winrt::Windows::UI::Xaml::ElementTheme RequestedTheme() const noexcept;

View File

@ -41,6 +41,8 @@ namespace ControlUnitTests
TEST_METHOD(TestSelectCommandSimple);
TEST_METHOD(TestSelectOutputSimple);
TEST_METHOD(TestCommandContext);
TEST_METHOD(TestCommandContextWithPwshGhostText);
TEST_METHOD(TestSelectOutputScrolling);
TEST_METHOD(TestSelectOutputExactWrap);
@ -556,6 +558,61 @@ namespace ControlUnitTests
}
}
void ControlCoreTests::TestCommandContextWithPwshGhostText()
{
auto [settings, conn] = _createSettingsAndConnection();
Log::Comment(L"Create ControlCore object");
auto core = createCore(*settings, *conn);
VERIFY_IS_NOT_NULL(core);
_standardInit(core);
Log::Comment(L"Print some text");
_writePrompt(conn, L"C:\\Windows");
conn->WriteInput(winrt_wstring_to_array_view(L"Foo-bar"));
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;C\x7"));
conn->WriteInput(winrt_wstring_to_array_view(L"\r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"This is some text \r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"with varying amounts \r\n"));
conn->WriteInput(winrt_wstring_to_array_view(L"of whitespace \r\n"));
_writePrompt(conn, L"C:\\Windows");
Log::Comment(L"Check the command context");
const WEX::TestExecution::DisableVerifyExceptions disableExceptionsScope;
{
auto historyContext{ core->CommandHistory() };
VERIFY_ARE_EQUAL(1u, historyContext.History().Size());
VERIFY_ARE_EQUAL(L"", historyContext.CurrentCommandline());
}
Log::Comment(L"Write 'BarBar' to the command...");
conn->WriteInput(winrt_wstring_to_array_view(L"BarBar"));
{
auto historyContext{ core->CommandHistory() };
// BarBar shouldn't be in the history, it should be the current command
VERIFY_ARE_EQUAL(1u, historyContext.History().Size());
VERIFY_ARE_EQUAL(L"BarBar", historyContext.CurrentCommandline());
}
Log::Comment(L"then move the cursor to the left");
// This emulates the state the buffer is in when pwsh does it's "ghost
// text" thing. We don't want to include all that ghost text in the
// current commandline.
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b[D"));
conn->WriteInput(winrt_wstring_to_array_view(L"\x1b[D"));
{
auto historyContext{ core->CommandHistory() };
VERIFY_ARE_EQUAL(1u, historyContext.History().Size());
// The current commandline is only the text to the left of the cursor
auto curr{ historyContext.CurrentCommandline() };
VERIFY_ARE_EQUAL(4u, curr.size());
VERIFY_ARE_EQUAL(L"BarB", curr);
}
}
void ControlCoreTests::TestSelectOutputScrolling()
{
auto [settings, conn] = _createSettingsAndConnection();

View File

@ -998,16 +998,15 @@ namespace ControlUnitTests
VERIFY_IS_GREATER_THAN(core->ScrollOffset(), 0);
// Viewport is now above the mutable viewport, so the mouse event
// straight up won't be sent to the terminal.
// will be clamped to the top line.
expectedOutput.push_back(L"sentinel"); // Clearly, it won't be this string
expectedOutput.push_back(L"\x1b[M &!"); // 5, 1
interactivity->PointerPressed(leftMouseDown,
WM_LBUTTONDOWN, //pointerUpdateKind
0, // timestamp
modifiers,
cursorPosition0.to_core_point());
// Flush it out.
conn->WriteInput(winrt_wstring_to_array_view(L"sentinel"));
VERIFY_ARE_EQUAL(0u, expectedOutput.size(), L"Validate we drained all the expected output");
// This is the part as mentioned in GH#12719

View File

@ -455,7 +455,7 @@ void AppHost::Close()
}
}
winrt::fire_and_forget AppHost::_quit()
safe_void_coroutine AppHost::_quit()
{
const auto peasant = _peasant;
@ -903,7 +903,7 @@ void AppHost::_WindowActivated(bool activated)
}
}
winrt::fire_and_forget AppHost::_peasantNotifyActivateWindow()
safe_void_coroutine AppHost::_peasantNotifyActivateWindow()
{
const auto desktopManager = _desktopManager;
const auto peasant = _peasant;
@ -980,8 +980,8 @@ void AppHost::_HandleSummon(const winrt::Windows::Foundation::IInspectable& /*se
// - <unused>
// Return Value:
// - <none>
winrt::fire_and_forget AppHost::_IdentifyWindowsRequested(const winrt::Windows::Foundation::IInspectable /*sender*/,
const winrt::Windows::Foundation::IInspectable /*args*/)
safe_void_coroutine AppHost::_IdentifyWindowsRequested(const winrt::Windows::Foundation::IInspectable /*sender*/,
const winrt::Windows::Foundation::IInspectable /*args*/)
{
auto weakThis{ weak_from_this() };
@ -1015,8 +1015,8 @@ void AppHost::_DisplayWindowId(const winrt::Windows::Foundation::IInspectable& /
_windowLogic.IdentifyWindow();
}
winrt::fire_and_forget AppHost::_RenameWindowRequested(const winrt::Windows::Foundation::IInspectable /*sender*/,
const winrt::TerminalApp::RenameWindowRequestedArgs args)
safe_void_coroutine AppHost::_RenameWindowRequested(const winrt::Windows::Foundation::IInspectable /*sender*/,
const winrt::TerminalApp::RenameWindowRequestedArgs args)
{
// Switch to the BG thread - anything x-proc must happen on a BG thread
co_await winrt::resume_background();
@ -1350,8 +1350,8 @@ void AppHost::_PropertyChangedHandler(const winrt::Windows::Foundation::IInspect
}
}
winrt::fire_and_forget AppHost::_WindowInitializedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Windows::Foundation::IInspectable& /*arg*/)
safe_void_coroutine AppHost::_WindowInitializedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const winrt::Windows::Foundation::IInspectable& /*arg*/)
{
_isWindowInitialized = WindowInitializedState::Initializing;

View File

@ -63,7 +63,7 @@ private:
uint32_t _launchShowWindowCommand{ SW_NORMAL };
winrt::fire_and_forget _quit();
safe_void_coroutine _quit();
void _revokeWindowCallbacks();
void _HandleCommandlineArgs(const winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs& args);
@ -85,14 +85,14 @@ private:
const winrt::Windows::Foundation::IInspectable& arg);
void _AlwaysOnTopChanged(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& arg);
winrt::fire_and_forget _WindowInitializedHandler(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& arg);
safe_void_coroutine _WindowInitializedHandler(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& arg);
void _RaiseVisualBell(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& arg);
void _WindowMouseWheeled(const til::point coord, const int32_t delta);
void _WindowActivated(bool activated);
winrt::fire_and_forget _peasantNotifyActivateWindow();
safe_void_coroutine _peasantNotifyActivateWindow();
void _WindowMoved();
void _DispatchCommandline(winrt::Windows::Foundation::IInspectable sender,
@ -101,12 +101,12 @@ private:
void _HandleSummon(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior& args);
winrt::fire_and_forget _IdentifyWindowsRequested(const winrt::Windows::Foundation::IInspectable sender,
const winrt::Windows::Foundation::IInspectable args);
safe_void_coroutine _IdentifyWindowsRequested(const winrt::Windows::Foundation::IInspectable sender,
const winrt::Windows::Foundation::IInspectable args);
void _DisplayWindowId(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args);
winrt::fire_and_forget _RenameWindowRequested(const winrt::Windows::Foundation::IInspectable sender,
const winrt::TerminalApp::RenameWindowRequestedArgs args);
safe_void_coroutine _RenameWindowRequested(const winrt::Windows::Foundation::IInspectable sender,
const winrt::TerminalApp::RenameWindowRequestedArgs args);
void _HandleSettingsChanged(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::TerminalApp::SettingsLoadEventArgs& args);

View File

@ -1324,7 +1324,7 @@ void IslandWindow::_SetIsFullscreen(const bool fullscreenEnabled)
// - toggleVisibility: controls how we should behave when already in the foreground.
// Return Value:
// - <none>
winrt::fire_and_forget IslandWindow::SummonWindow(Remoting::SummonWindowBehavior args)
safe_void_coroutine IslandWindow::SummonWindow(Remoting::SummonWindowBehavior args)
{
// On the foreground thread:
co_await wil::resume_foreground(_rootGrid.Dispatcher());

View File

@ -55,7 +55,7 @@ public:
void FlashTaskbar();
void SetTaskbarProgress(const size_t state, const size_t progress);
winrt::fire_and_forget SummonWindow(winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior args);
safe_void_coroutine SummonWindow(winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior args);
bool IsQuakeWindow() const noexcept;
void IsQuakeWindow(bool isQuakeWindow) noexcept;

View File

@ -479,7 +479,7 @@ LRESULT WindowEmperor::_messageHandler(UINT const message, WPARAM const wParam,
// windows left, and we don't want to keep running anymore. This will discard
// all our refrigerated windows. If we try to use XAML on Windows 10 after this,
// we'll undoubtedly crash.
winrt::fire_and_forget WindowEmperor::_close()
safe_void_coroutine WindowEmperor::_close()
{
// Important! Switch back to the main thread for the emperor. That way, the
// quit will go to the emperor's message pump.
@ -582,7 +582,7 @@ void WindowEmperor::_finalizeSessionPersistence() const
// - args: Contains information on how we should name the window
// Return Value:
// - <none>
static winrt::fire_and_forget _createNewTerminalWindow(Settings::Model::GlobalSummonArgs args)
static safe_void_coroutine _createNewTerminalWindow(Settings::Model::GlobalSummonArgs args)
{
// Hop to the BG thread
co_await winrt::resume_background();
@ -704,7 +704,7 @@ void WindowEmperor::_unregisterHotKey(const int index) noexcept
LOG_IF_WIN32_BOOL_FALSE(::UnregisterHotKey(_window.get(), index));
}
winrt::fire_and_forget WindowEmperor::_setupGlobalHotkeys()
safe_void_coroutine WindowEmperor::_setupGlobalHotkeys()
{
// The hotkey MUST be registered on the main thread. It will fail otherwise!
co_await wil::resume_foreground(_dispatcher);
@ -844,13 +844,13 @@ void WindowEmperor::_hideNotificationIconRequested()
// A callback to the window's logic to let us know when the window's
// quake mode state changes. We'll use this to check if we need to add
// or remove the notification icon.
winrt::fire_and_forget WindowEmperor::_windowIsQuakeWindowChanged(winrt::Windows::Foundation::IInspectable sender,
winrt::Windows::Foundation::IInspectable args)
safe_void_coroutine WindowEmperor::_windowIsQuakeWindowChanged(winrt::Windows::Foundation::IInspectable sender,
winrt::Windows::Foundation::IInspectable args)
{
co_await wil::resume_foreground(this->_dispatcher);
_checkWindowsForNotificationIcon();
}
winrt::fire_and_forget WindowEmperor::_windowRequestUpdateSettings()
safe_void_coroutine WindowEmperor::_windowRequestUpdateSettings()
{
// We MUST be on the main thread to update the settings. We will crash when trying to enumerate fragment extensions otherwise.
co_await wil::resume_foreground(this->_dispatcher);

View File

@ -61,17 +61,17 @@ private:
void _becomeMonarch();
void _numberOfWindowsChanged(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&);
winrt::fire_and_forget _windowIsQuakeWindowChanged(winrt::Windows::Foundation::IInspectable sender, winrt::Windows::Foundation::IInspectable args);
winrt::fire_and_forget _windowRequestUpdateSettings();
safe_void_coroutine _windowIsQuakeWindowChanged(winrt::Windows::Foundation::IInspectable sender, winrt::Windows::Foundation::IInspectable args);
safe_void_coroutine _windowRequestUpdateSettings();
void _createMessageWindow();
void _hotkeyPressed(const long hotkeyIndex);
bool _registerHotKey(const int index, const winrt::Microsoft::Terminal::Control::KeyChord& hotkey) noexcept;
void _unregisterHotKey(const int index) noexcept;
winrt::fire_and_forget _setupGlobalHotkeys();
safe_void_coroutine _setupGlobalHotkeys();
winrt::fire_and_forget _close();
safe_void_coroutine _close();
void _finalizeSessionPersistence() const;
void _createNotificationIcon();

View File

@ -20,6 +20,7 @@
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalThemeHelpers>true</TerminalThemeHelpers>
<TerminalMUX>true</TerminalMUX>
<TerminalWinGetInterop>true</TerminalWinGetInterop>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />

View File

@ -17,6 +17,54 @@ Revision History:
#pragma once
// This type is identical to winrt::fire_and_forget, but its unhandled_exception
// handler logs the exception instead of terminating the application.
//
// Ideally, we'd just use wil::com_task<void>, but it currently crashes
// with an AV if an exception is thrown after the first suspension point.
struct safe_void_coroutine
{
};
namespace std
{
template<typename... Args>
struct coroutine_traits<safe_void_coroutine, Args...>
{
struct promise_type
{
safe_void_coroutine get_return_object() const noexcept
{
return {};
}
void return_void() const noexcept
{
}
suspend_never initial_suspend() const noexcept
{
return {};
}
suspend_never final_suspend() const noexcept
{
return {};
}
void unhandled_exception() const noexcept
{
LOG_CAUGHT_EXCEPTION();
// If you get here, an unhandled exception was thrown.
// In a Release build this would get silently swallowed.
// You should probably fix the source of the exception, because it may have
// unintended side effects, in particular with exception-unsafe logic.
assert(false);
}
};
};
}
template<>
struct fmt::formatter<winrt::hstring, wchar_t> : fmt::formatter<fmt::wstring_view, wchar_t>
{

View File

@ -39,4 +39,9 @@
<!-- WinUI (which depends on WebView2 as of 2.8.0) -->
<Import Project="$(MSBuildThisFileDirectory)..\packages\Microsoft.UI.Xaml.2.8.4\build\native\Microsoft.UI.Xaml.props" Condition="'$(TerminalMUX)' == 'true' and Exists('$(MSBuildThisFileDirectory)..\packages\Microsoft.UI.Xaml.2.8.4\build\native\Microsoft.UI.Xaml.props')" />
<!-- WinGet Interop -->
<PropertyGroup>
<WinGetPackageRoot>$(MSBuildThisFileDirectory)..\packages\Microsoft.WindowsPackageManager.ComInterop.1.8.1911\</WinGetPackageRoot>
</PropertyGroup>
</Project>

View File

@ -64,6 +64,8 @@
<!-- WIL (so widely used that this one does not have a TerminalWIL opt-in property; it is automatic) -->
<Import Project="$(MSBuildThisFileDirectory)..\packages\Microsoft.Windows.ImplementationLibrary.1.0.240122.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(MSBuildThisFileDirectory)..\packages\Microsoft.Windows.ImplementationLibrary.1.0.240122.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<!-- WinGet Interop -->
<Import Project="$(MSBuildThisFileDirectory)..\build\rules\Microsoft.WindowsPackageManager.ComInterop.Additional.targets" Condition="'$(TerminalWinGetInterop)' == 'true'" />
</ImportGroup>
<Target Name="Terminal_EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

View File

@ -185,8 +185,8 @@ void VtInputThread::_InputThread()
return S_OK;
}
void VtInputThread::WaitUntilDSR(DWORD timeout) const noexcept
til::enumset<DeviceAttribute, uint64_t> VtInputThread::WaitUntilDA1(DWORD timeout) const noexcept
{
const auto& engine = static_cast<InputStateMachineEngine&>(_pInputStateMachine->Engine());
engine.WaitUntilDSR(timeout);
return engine.WaitUntilDA1(timeout);
}

View File

@ -18,13 +18,18 @@ Author(s):
namespace Microsoft::Console
{
namespace VirtualTerminal
{
enum class DeviceAttribute : uint64_t;
}
class VtInputThread
{
public:
VtInputThread(_In_ wil::unique_hfile hPipe, const bool inheritCursor);
[[nodiscard]] HRESULT Start();
void WaitUntilDSR(DWORD timeout) const noexcept;
til::enumset<VirtualTerminal::DeviceAttribute, uint64_t> WaitUntilDA1(DWORD timeout) const noexcept;
private:
static DWORD WINAPI StaticVtInputThreadProc(_In_ LPVOID lpParameter);

Some files were not shown because too many files have changed in this diff Show More