Compare commits

...

62 Commits

Author SHA1 Message Date
Carlos Zamora
04eaf867d9 PRE-MERGE #19647 Fix tab row acrylic material in unfocused windows 2026-01-20 10:57:33 -08:00
Carlos Zamora
a7c2187009 PRE-MERGE #19591 Add IconPicker to New Tab Menu folders in SUI 2026-01-20 10:57:17 -08:00
Carlos Zamora
1a689859d0 PRE-MERGE #19519 Implement search in Settings UI 2026-01-20 10:48:38 -08:00
Carlos Zamora
469a6d73be Merge branch 'main' into dev/cazamor/sui/ntm-icon-picker 2026-01-20 10:44:24 -08:00
Carlos Zamora
82a986af94 Merge branch 'main' into dev/cazamor/sui/search 2026-01-20 10:43:59 -08:00
Leonard Hecker
fe718b62b8 Merge remote-tracking branch 'origin/main' into tmux_cc_pr 2026-01-20 16:49:10 +01:00
Carlos Zamora
62a6b5eb2f address feedback from Pankaj's review 2026-01-16 17:15:17 -08:00
Carlos Zamora
6cc6fe1714 fix memory leak 2026-01-16 14:49:57 -08:00
Carlos Zamora
14e380a9b2 minor code health in _UpdateSearchIndex() 2026-01-15 15:51:35 -08:00
Carlos Zamora
9cbaa980d8 exclude Profiles_Base_Orphaned from index 2026-01-14 19:09:08 -08:00
Carlos Zamora
27d4a0b575 prevent multiple searches if we're not gonna use them 2026-01-14 18:27:13 -08:00
Carlos Zamora
e14dfec7b7 fix duplicate profile results when reloading 2026-01-14 18:04:57 -08:00
Carlos Zamora
672945c3bf Add secondary label to search results 2026-01-14 17:35:09 -08:00
Carlos Zamora
d008e80d02 fix search results + profile.defaults bugs 2026-01-14 15:27:37 -08:00
Leonard Hecker
00cc0c3cba Fix tmux setting not being respected 2026-01-14 19:26:50 +01:00
Leonard Hecker
e9ad3f485d Fix a crash when dragging tabs / pressing + 2026-01-14 19:26:30 +01:00
Leonard Hecker
be3db4f246 Merge remote-tracking branch 'origin/main' into tmux_cc_pr 2026-01-14 18:54:50 +01:00
Carlos Zamora
3252b7ddf0 Merge branch 'main' into dev/cazamor/sui/search 2026-01-12 16:52:21 -08:00
Carlos Zamora
fe4069dd13 Merge branch 'main' into fix-tab-acrylic-unfocused 2026-01-12 16:16:55 -08:00
Carlos Zamora
3abee35102 Remove shouldUseAcrylic 2026-01-12 13:57:43 -08:00
Carlos Zamora
acb19efea7 Remove unused variable 2026-01-12 13:18:23 -08:00
Leonard Hecker
7ec5d919e1 Merge remote-tracking branch 'origin/main' into tmux_cc_pr 2026-01-12 20:20:53 +01:00
Leonard Hecker
71effe1d73 Fix AuditMode nagging 2026-01-06 19:49:06 +01:00
Leonard Hecker
1b9e54e22c Address feedback 2026-01-06 18:34:15 +01:00
Leonard Hecker
7c05042f30 Revert accidental change 2026-01-06 18:20:11 +01:00
Leonard Hecker
76bd54fe42 Partially address feedback 2025-12-18 21:34:24 +01:00
Leonard Hecker
1aa4f17642 Merge remote-tracking branch 'origin/main' into tmux_cc_pr 2025-12-18 20:32:14 +01:00
Carlos Zamora
22ba243185 Merge branch 'main' into dev/cazamor/sui/search 2025-12-16 16:16:44 -08:00
Leonard Hecker
0d466b6866 Exclude from spell checking 2025-12-16 14:02:28 +01:00
Leonard Hecker
8e3e19ea1f Big, big refactor 2025-12-15 21:18:16 +01:00
Leonard Hecker
c1c86727e9 Merge remote-tracking branch 'origin/main' into tmux_cc_pr 2025-12-15 21:15:05 +01:00
AbhishekGiri04
018fade640 Fix tab row acrylic material in unfocused windows (#19544)
This commit fixes the issue where the tab row loses its acrylic material
when the window loses focus, even when 'Allow acrylic material in unfocused
windows' setting is enabled.

The fix modifies the _updateThemeColors() function in TerminalPage.cpp to
check both the UseAcrylicInTabRow setting AND the window focus state along
with the EnableUnfocusedAcrylic setting. Now the tab row will maintain its
acrylic effect when:
1. UseAcrylicInTabRow is enabled, AND
2. Either the window is focused OR EnableUnfocusedAcrylic is enabled

This ensures that the 'Allow acrylic material in unfocused windows' setting
is properly respected for the tab row, not just the terminal background.

Fixes #19544
2025-12-15 20:14:42 +05:30
Carlos Zamora
1a73aa6367 Merge branch 'main' into dev/cazamor/sui/ntm-icon-picker 2025-12-02 15:45:28 -08:00
Carlos Zamora
e87cc1f346 code format 2025-12-02 15:42:07 -08:00
Carlos Zamora
0228206e02 update resources and variable names 2025-12-02 15:41:19 -08:00
Carlos Zamora
072ab20a4d Add IconPicker to New Tab Menu folders in SUI 2025-11-25 15:50:52 -08:00
Carlos Zamora
6d968b54f3 remove TODO CARLOS 2025-11-24 16:19:22 -08:00
Carlos Zamora
20bdc21c79 clean up more TODOs 2025-11-17 17:42:43 -08:00
Carlos Zamora
a4c69cfc6a clean up some TODOs 2025-11-17 17:35:45 -08:00
Carlos Zamora
e5ea64586d NavigateToXArgs --> NavigateToPageArgs 2025-11-17 16:49:57 -08:00
Carlos Zamora
81f881a579 Fix navigation for profile.appearance settings (global profile too) 2025-11-17 15:41:19 -08:00
Carlos Zamora
45d75e701f registerIndex macro -> lambda 2025-11-17 14:11:56 -08:00
Carlos Zamora
83aa9fd889 profiles: fix BringIntoView (partially) 2025-11-13 10:34:20 -08:00
Carlos Zamora
8c99200e96 color schemes: fix BringIntoView 2025-11-12 15:49:00 -08:00
Carlos Zamora
14bab6cc1a more polish; more bugs found; I guess it's a stalemate 2025-11-07 12:24:33 -08:00
Carlos Zamora
be2b1d30cb fix color schemes; convert APPEND_RUNTIME_OBJECT_RESULTS to lambda 2025-11-06 16:17:32 -08:00
Carlos Zamora
6fbf953fb2 clear search box 2025-11-06 15:32:35 -08:00
Carlos Zamora
cff62cc60e update selected item 2025-11-06 13:57:13 -08:00
Carlos Zamora
82536fd756 bugfix: duplicate profile 2025-11-05 15:26:54 -08:00
Carlos Zamora
bf2e4e19d7 code format and spell check 2025-11-05 15:26:34 -08:00
Carlos Zamora
2706d05491 icons 2025-11-05 14:54:07 -08:00
Carlos Zamora
1dafcef36f FilteredSearchResult::CreateNoResultsItem and CreateRuntimeObjectItem 2025-11-05 13:02:30 -08:00
Carlos Zamora
53ddd92e7f remove SearchMetadata (old attempt) 2025-11-03 17:26:08 -08:00
Carlos Zamora
e84e8d408f add language neutral search 2025-11-03 17:02:03 -08:00
Carlos Zamora
532343f1ce runtime object indexing 2025-11-03 16:27:12 -08:00
Carlos Zamora
2a41f8a57c improve index 2025-11-03 11:48:36 -08:00
Carlos Zamora
e56eb74788 improve indexing perf and include help text 2025-10-29 15:01:31 -07:00
Carlos Zamora
cac844b1e9 minimum viable product 2025-10-28 12:59:31 -07:00
Carlos Zamora
915f085b60 load runtime index for search 2025-10-23 13:32:18 -07:00
Carlos Zamora
1b8c99dff8 Load build time index for search
- Adds referential XAML names to components of interest.
- Adds a script that generates the build time entries to be loaded
- Invokes the script in Editor.vcxproj
2025-10-15 15:44:17 -07:00
Carlos Zamora
e01ff4faf0 Introduce SearchMetadata and navigation by name
- SearchMetadata is unsused, but it is designed to hold information
   so that we can navigate to a setting
- Updated all pages to...
   - have an x:Name on relevant setting containers
   - have a NavigateToXArgs used in the OnNavigatedTo() function
   - update the NavigateToXArgs to include the name of an element
      to scroll down to
   - Add BringIntoViewWhenLoaded() to HasScrollViewer<T> which
      scrolls down to the element with a given name
These components aren't fully hooked up together yet and there's a
few TODO CARLOS's throughout. Main upcoming work:
- indexing
- runtime indexing
- search box UI
- search results UI
based on 079c69b8be/doc/specs/settings-search.md
2025-10-14 11:46:31 -07:00
Joe Xue
0d9bc0d433 Add support for tmux control mode (#3656) 2025-07-06 14:49:50 -04:00
108 changed files with 4664 additions and 751 deletions

View File

@@ -71,7 +71,9 @@ sustainability
sxn
Tencent
toolset
Uids
UEFI
UIDs
uiatextrange
und
vsdevcmd

View File

@@ -99,7 +99,8 @@ Resources/(?!en)
^NOTICE.md
^oss/.*?/
^samples/PixelShaders/Screenshots/
^src/cascadia/TerminalSettingsEditor/SegoeFluentIconList.h$
^src/cascadia/TerminalApp/TmuxControl\.cpp$
^src/cascadia/TerminalSettingsEditor/SegoeFluentIconList\.h$
^src/interactivity/onecore/BgfxEngine\.
^src/renderer/atlas/
^src/renderer/wddmcon/WddmConRenderer\.

View File

@@ -4,12 +4,13 @@
#include "pch.h"
#include "App.h"
#include "TerminalPage.h"
#include "ScratchpadContent.h"
#include "../WinRTUtils/inc/WtExeUtils.h"
#include "TerminalPage.h"
#include "TmuxControl.h"
#include "Utils.h"
#include "../../types/inc/utils.hpp"
#include "../TerminalSettingsAppAdapterLib/TerminalSettings.h"
#include "Utils.h"
#include "../WinRTUtils/inc/WtExeUtils.h"
using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::UI::Xaml;
@@ -284,6 +285,15 @@ namespace winrt::TerminalApp::implementation
const auto& activeTab{ _senderOrFocusedTab(sender) };
if constexpr (Feature_TmuxControl::IsEnabled())
{
//Tmux control takes over
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(activeTab))
{
return _tmuxControl->SplitPane(activeTab, realArgs.SplitDirection());
}
}
_SplitPane(activeTab,
realArgs.SplitDirection(),
// This is safe, we're already filtering so the value is (0, 1)

View File

@@ -1306,10 +1306,10 @@ void Pane::UpdateSettings(const CascadiaSettings& settings)
// - splitType: How the pane should be attached
// Return Value:
// - the new reference to the child created from the current pane.
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType)
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType, const float splitSize)
{
// Splice the new pane into the tree
const auto [first, _] = _Split(splitType, .5, pane);
const auto [first, _] = _Split(splitType, splitSize, pane);
// If the new pane has a child that was the focus, re-focus it
// to steal focus from the currently focused pane.
@@ -2298,8 +2298,7 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
_firstChild->Closed(_firstClosedToken);
_secondChild->Closed(_secondClosedToken);
// If we are not a leaf we should create a new pane that contains our children
auto first = std::make_shared<Pane>(_firstChild, _secondChild, _splitState, _desiredSplitPosition);
_firstChild = first;
_firstChild = std::make_shared<Pane>(_firstChild, _secondChild, _splitState, _desiredSplitPosition);
}
else
{

View File

@@ -131,7 +131,8 @@ public:
void Close();
std::shared_ptr<Pane> AttachPane(std::shared_ptr<Pane> pane,
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType);
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
const float splitSize = .5);
std::shared_ptr<Pane> DetachPane(std::shared_ptr<Pane> pane);
int GetLeafPaneCount() const noexcept;

View File

@@ -923,4 +923,11 @@
<data name="InvalidRegex" xml:space="preserve">
<value>An invalid regular expression was found.</value>
</data>
</root>
<data name="TmuxControlInfo" xml:space="preserve">
<value>Running in tmux control mode; Press 'q' to detach:</value>
<comment>{Locked="'q'"}</comment>
</data>
<data name="NewTmuxControlTab.Text" xml:space="preserve">
<value>Tmux Control Tab</value>
</data>
</root>

View File

@@ -173,6 +173,8 @@
<ClInclude Include="SettingsPaneContent.h">
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
</ClInclude>
<ClInclude Include="TmuxConnection.h" />
<ClInclude Include="TmuxControl.h" />
<ClInclude Include="Toast.h" />
<ClInclude Include="TerminalSettingsCache.h" />
<ClInclude Include="SuggestionsControl.h">
@@ -286,6 +288,8 @@
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<ClCompile Include="TmuxConnection.cpp" />
<ClCompile Include="TmuxControl.cpp" />
<ClCompile Include="Toast.cpp" />
<ClCompile Include="TerminalSettingsCache.cpp" />
<ClCompile Include="SuggestionsControl.cpp">
@@ -295,7 +299,6 @@
<DependentUpon>MarkdownPaneContent.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
@@ -422,7 +425,6 @@
<Private>true</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<!-- This is a hack to get the ARM64 CI build working. See
@@ -516,4 +518,4 @@
</ItemGroup>
</Target>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project>
</Project>

View File

@@ -33,6 +33,8 @@
<ClCompile Include="Toast.cpp" />
<ClCompile Include="LanguageProfileNotifier.cpp" />
<ClCompile Include="TerminalSettingsCache.cpp" />
<ClCompile Include="TmuxConnection.cpp" />
<ClCompile Include="TmuxControl.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
@@ -62,6 +64,8 @@
<ClInclude Include="LanguageProfileNotifier.h" />
<ClInclude Include="WindowsPackageManagerFactory.h" />
<ClInclude Include="TerminalSettingsCache.h" />
<ClInclude Include="TmuxConnection.h" />
<ClInclude Include="TmuxControl.h" />
</ItemGroup>
<ItemGroup>
<Midl Include="AppLogic.idl">
@@ -151,4 +155,4 @@
<Filter>app</Filter>
</ApplicationDefinition>
</ItemGroup>
</Project>
</Project>

View File

@@ -23,6 +23,7 @@
#include "SnippetsPaneContent.h"
#include "TabRowControl.h"
#include "TerminalSettingsCache.h"
#include "TmuxControl.h"
#include "LaunchPositionRequest.g.cpp"
#include "RenameWindowRequestedArgs.g.cpp"
@@ -406,6 +407,15 @@ namespace winrt::TerminalApp::implementation
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
if constexpr (Feature_TmuxControl::IsEnabled())
{
// tmux control takes over
if (page->_tmuxControl && page->_tmuxControl->TabIsTmuxControl(page->_GetFocusedTabImpl()))
{
return;
}
}
page->_OpenNewTerminalViaDropdown(NewTerminalArgs());
}
});
@@ -1431,6 +1441,15 @@ namespace winrt::TerminalApp::implementation
}
if (altPressed && !debugTap)
{
// tmux control panes don't share tab with other panes
if constexpr (Feature_TmuxControl::IsEnabled())
{
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(_GetFocusedTabImpl()))
{
return;
}
}
this->_SplitPane(_GetFocusedTabImpl(),
SplitDirection::Automatic,
0.5f,
@@ -2535,6 +2554,15 @@ namespace winrt::TerminalApp::implementation
return false;
}
if constexpr (Feature_TmuxControl::IsEnabled())
{
//Tmux control tab doesn't support to drag
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(tab))
{
return false;
}
}
// If there was a windowId in the action, try to move it to the
// specified window instead of moving it in our tab row.
const auto windowId{ args.Window() };
@@ -3598,9 +3626,8 @@ namespace winrt::TerminalApp::implementation
control.RestoreFromPath(path);
}
auto paneContent{ winrt::make<TerminalPaneContent>(profile, _terminalSettingsCache, control) };
auto resultPane = std::make_shared<Pane>(paneContent);
const auto paneContent = winrt::make_self<TerminalPaneContent>(profile, _terminalSettingsCache, control);
auto resultPane = std::make_shared<Pane>(*paneContent);
if (debugConnection) // this will only be set if global debugging is on and tap is active
{
@@ -3621,6 +3648,28 @@ namespace winrt::TerminalApp::implementation
original->SetActive();
}
if constexpr (Feature_TmuxControl::IsEnabled())
{
if (!_tmuxControl)
{
_tmuxControl = std::make_shared<TmuxControl>(*this);
}
// We attach the callback to the control that paneContent owns.
// As such, using a weak-ref here is crucial.
control.EnterTmuxControl([tmuxControl = _tmuxControl.get(), paneContentWeak = winrt::make_weak(paneContent)](auto&&, auto&& args) {
if (const auto paneContent = paneContentWeak.get())
{
if (paneContent->AllowTmuxControl() && tmuxControl->AcquireSingleUseLock(paneContent->GetTermControl()))
{
args.InputCallback([tmuxControl](auto&& str) {
tmuxControl->FeedInput(winrt_array_to_wstring_view(str));
});
}
}
});
}
return resultPane;
}
@@ -4916,7 +4965,7 @@ namespace winrt::TerminalApp::implementation
theme.TabRow().UnfocusedBackground()) :
ThemeColor{ nullptr } };
if (_settings.GlobalSettings().UseAcrylicInTabRow())
if (_settings.GlobalSettings().UseAcrylicInTabRow() && (_activated || _settings.GlobalSettings().EnableUnfocusedAcrylic()))
{
if (tabRowBg)
{
@@ -5532,6 +5581,15 @@ namespace winrt::TerminalApp::implementation
tabImpl.copy_from(winrt::get_self<Tab>(tabBase));
if (tabImpl)
{
if constexpr (Feature_TmuxControl::IsEnabled())
{
//Tmux control tab doesn't support to drag
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(tabImpl))
{
return;
}
}
// First: stash the tab we started dragging.
// We're going to be asked for this.
_stashed.draggedTab = tabImpl;

View File

@@ -37,6 +37,7 @@ namespace winrt::Microsoft::Terminal::Settings
namespace winrt::TerminalApp::implementation
{
struct TerminalSettingsCache;
struct TmuxControl;
inline constexpr uint32_t DefaultRowsToScroll{ 3 };
inline constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
@@ -256,6 +257,7 @@ namespace winrt::TerminalApp::implementation
std::vector<std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>> _previouslyClosedPanesAndTabs{};
uint32_t _systemRowsToScroll{ DefaultRowsToScroll };
std::shared_ptr<TmuxControl> _tmuxControl{ nullptr };
// use a weak reference to prevent circular dependency with AppLogic
winrt::weak_ref<winrt::TerminalApp::IDialogPresenter> _dialogPresenter;
@@ -580,6 +582,7 @@ namespace winrt::TerminalApp::implementation
friend class TerminalAppLocalTests::TabTests;
friend class TerminalAppLocalTests::SettingsTests;
friend struct TmuxControl;
};
}

View File

@@ -27,6 +27,7 @@ namespace winrt::TerminalApp::implementation
_cache{ cache },
_profile{ profile }
{
_allowTmuxControl.store(_profile.AllowTmuxControl(), std::memory_order_relaxed);
_setupControlEvents();
}
@@ -342,6 +343,7 @@ namespace winrt::TerminalApp::implementation
// Reload our profile from the settings model to propagate bell mode, icon, and close on exit mode (anything that uses _profile).
const auto profile{ settings.FindProfile(_profile.Guid()) };
_profile = profile ? profile : settings.ProfileDefaults();
_allowTmuxControl.store(_profile.AllowTmuxControl(), std::memory_order_relaxed);
if (const auto settings{ _cache->TryLookup(_profile) })
{
@@ -363,6 +365,11 @@ namespace winrt::TerminalApp::implementation
return _control.BackgroundBrush();
}
bool TerminalPaneContent::AllowTmuxControl() const noexcept
{
return _allowTmuxControl.load(std::memory_order_relaxed);
}
float TerminalPaneContent::SnapDownToGrid(const TerminalApp::PaneSnapDirection direction, const float sizeToSnap)
{
return _control.SnapDimensionToGrid(direction == PaneSnapDirection::Width, sizeToSnap);

View File

@@ -49,6 +49,7 @@ namespace winrt::TerminalApp::implementation
winrt::hstring Icon() const;
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept;
winrt::Windows::UI::Xaml::Media::Brush BackgroundBrush();
bool AllowTmuxControl() const noexcept;
float SnapDownToGrid(const TerminalApp::PaneSnapDirection direction, const float sizeToSnap);
Windows::Foundation::Size GridUnitSize();
@@ -63,6 +64,13 @@ namespace winrt::TerminalApp::implementation
winrt::Microsoft::Terminal::Settings::Model::Profile _profile{ nullptr };
std::shared_ptr<TerminalSettingsCache> _cache{};
bool _isDefTermSession{ false };
// Settings, UI, etc., handling occurs on the main thread.
// The EnterTmuxControl callback on the other hand occurs on the VT connection thread.
// In order to avoid threading issues, we cache the value of AllowTmuxControl here.
// The reason it's stored here and not elsewhere is because right now all decision making
// about tmux occurs at the TerminalPage (= window) layer of the app. It would not make sense
// to expose it on the IControlSettings object. TerminalPaneContent is the closest thing to it.
std::atomic<bool> _allowTmuxControl{ false };
winrt::Windows::Media::Playback::MediaPlayer _bellPlayer{ nullptr };
bool _bellPlayerCreated{ false };

View File

@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "TmuxConnection.h"
namespace winrt::TerminalApp::implementation
{
void TmuxConnection::Initialize(const Windows::Foundation::Collections::ValueSet&) const noexcept
{
}
void TmuxConnection::Start() noexcept
{
}
void TmuxConnection::WriteInput(const winrt::array_view<const char16_t> buffer)
{
TerminalInput.raise(buffer);
}
void TmuxConnection::Resize(uint32_t /*rows*/, uint32_t /*columns*/) noexcept
{
}
void TmuxConnection::Close() noexcept
{
StateChanged.raise(*this, nullptr);
}
winrt::guid TmuxConnection::SessionId() const noexcept
{
return {};
}
Microsoft::Terminal::TerminalConnection::ConnectionState TmuxConnection::State() const noexcept
{
return Microsoft::Terminal::TerminalConnection::ConnectionState::Connected;
}
void TmuxConnection::WriteOutput(const winrt::array_view<const char16_t> wstr)
{
if (!wstr.empty())
{
TerminalOutput.raise(wstr);
}
}
}

View File

@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
namespace winrt::TerminalApp::implementation
{
struct TmuxConnection : winrt::implements<TmuxConnection, Microsoft::Terminal::TerminalConnection::ITerminalConnection>
{
// ITerminalConnection methods
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) const noexcept;
void Start() noexcept;
void WriteInput(winrt::array_view<const char16_t> buffer);
void Resize(uint32_t rows, uint32_t columns) noexcept;
void Close() noexcept;
til::event<Microsoft::Terminal::TerminalConnection::TerminalOutputHandler> TerminalOutput;
til::typed_event<Microsoft::Terminal::TerminalConnection::ITerminalConnection, IInspectable> StateChanged;
winrt::guid SessionId() const noexcept;
Microsoft::Terminal::TerminalConnection::ConnectionState State() const noexcept;
// TmuxConnection methods
void WriteOutput(winrt::array_view<const char16_t> wstr);
til::event<Microsoft::Terminal::TerminalConnection::TerminalOutputHandler> TerminalInput;
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
class Pane;
namespace winrt::TerminalApp::implementation
{
struct Tab;
struct TerminalPage;
struct TmuxConnection;
struct TmuxControl : std::enable_shared_from_this<TmuxControl>
{
TmuxControl(TerminalPage& page);
bool AcquireSingleUseLock(winrt::Microsoft::Terminal::Control::TermControl control) noexcept;
bool TabIsTmuxControl(const winrt::com_ptr<Tab>& tab);
void SplitPane(const winrt::com_ptr<Tab>& tab, winrt::Microsoft::Terminal::Settings::Model::SplitDirection direction);
void FeedInput(std::wstring_view str);
private:
enum class State
{
Init,
Attaching,
Attached,
};
enum class ResponseInfoType
{
Ignore,
DiscoverNewWindow,
DiscoverWindows,
CapturePane,
DiscoverPanes,
};
struct ResponseInfo
{
ResponseInfoType type;
union
{
struct
{
int64_t paneId;
} capturePane;
} data;
};
enum class TmuxLayoutType
{
// A single leaf pane
Pane,
// Indicates the start of a horizontal split layout
PushHorizontal,
// Indicates the start of a vertical split layout
PushVertical,
// Indicates the end of the most recent split layout
Pop,
};
struct TmuxLayout
{
TmuxLayoutType type = TmuxLayoutType::Pane;
// Only set for: Pane, PushHorizontal, PushVertical
til::CoordType width = 0;
// Only set for: Pane, PushHorizontal, PushVertical
til::CoordType height = 0;
// Only set for: Pane
int64_t id = -1;
};
struct AttachedPane
{
AttachedPane() = default;
AttachedPane(int64_t paneId, std::wstring outputBacklog);
~AttachedPane();
// Have to redefine them because they get implicitly deleted once a destructor is defined.
AttachedPane(AttachedPane&&) = default;
AttachedPane& operator=(AttachedPane&&) = default;
// Why would you want to copy this.
AttachedPane(const AttachedPane&) = delete;
AttachedPane& operator=(const AttachedPane&) = delete;
int64_t windowId = -1;
int64_t paneId = -1;
winrt::com_ptr<TmuxConnection> connection{ nullptr };
winrt::Microsoft::Terminal::Control::TermControl control{ nullptr };
std::wstring outputBacklog;
bool initialized = false;
bool ignoreOutput = false;
};
safe_void_coroutine _parseLine(std::wstring line);
void _handleAttach(); // A special case of _handleResponse()
void _handleDetach();
void _handleSessionChanged(int64_t sessionId);
void _handleWindowAdd(int64_t windowId);
void _handleWindowRenamed(int64_t windowId, winrt::hstring name);
void _handleWindowClose(int64_t windowId);
void _handleWindowPaneChanged(int64_t windowId, int64_t paneId);
void _handleLayoutChange(int64_t windowId, std::wstring_view layout);
void _handleResponse(std::wstring_view result);
void _sendSetOption(std::wstring_view option);
void _sendDiscoverWindows(int64_t sessionId);
void _handleResponseDiscoverWindows(std::wstring_view response);
void _sendDiscoverNewWindow(int64_t windowId);
void _handleResponseDiscoverNewWindow(std::wstring_view response);
void _sendCapturePane(int64_t paneId, til::CoordType history);
void _handleResponseCapturePane(const ResponseInfo& info, std::wstring_view response);
void _sendDiscoverPanes(int64_t windowId);
void _handleResponseDiscoverPanes(std::wstring_view response);
void _sendNewWindow();
void _sendKillWindow(int64_t windowId);
void _sendKillPane(int64_t paneId);
void _sendSplitPane(std::shared_ptr<Pane> pane, winrt::Microsoft::Terminal::Settings::Model::SplitDirection direction);
void _sendSelectWindow(int64_t windowId);
void _sendSelectPane(int64_t paneId);
void _sendResizeWindow(int64_t windowId, til::CoordType width, til::CoordType height);
void _sendResizePane(int64_t paneId, til::CoordType width, til::CoordType height);
void _sendSendKey(int64_t paneId, const std::wstring_view keys);
void _sendIgnoreResponse(wil::zwstring_view cmd);
void _sendWithResponseInfo(wil::zwstring_view cmd, ResponseInfo info);
std::shared_ptr<Pane> _layoutCreateRecursive(int64_t windowId, std::wstring_view& remaining, TmuxLayout parent);
std::wstring_view _layoutStripHash(std::wstring_view str);
TmuxLayout _layoutParseNextToken(std::wstring_view& remaining);
void _deliverOutputToPane(int64_t paneId, const std::wstring_view text);
winrt::com_ptr<Tab> _getTab(int64_t windowId) const;
void _newTab(int64_t windowId, winrt::hstring name, std::shared_ptr<Pane> pane);
std::pair<AttachedPane&, std::shared_ptr<Pane>> _newPane(int64_t windowId, int64_t paneId);
void _openNewTerminalViaDropdown();
TerminalPage& _page; // Non-owning, because TerminalPage owns us
winrt::Windows::System::DispatcherQueue _dispatcherQueue{ nullptr };
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _newTabMenu;
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
winrt::com_ptr<Tab> _controlTab{ nullptr };
winrt::Microsoft::Terminal::Settings::Model::Profile _profile{ nullptr };
State _state = State::Init;
bool _inUse = false;
std::wstring _lineBuffer;
std::wstring _responseBuffer;
bool _insideOutputBlock = false;
winrt::event_token _detachKeyDownRevoker;
winrt::event_token _windowSizeChangedRevoker;
winrt::event_token _newTabClickRevoker;
std::deque<ResponseInfo> _commandQueue;
std::unordered_map<int64_t, AttachedPane> _attachedPanes;
std::unordered_map<int64_t, winrt::com_ptr<Tab>> _attachedWindows;
int64_t _sessionId = -1;
int64_t _activePaneId = -1;
int64_t _activeWindowId = -1;
til::CoordType _terminalWidth = 0;
til::CoordType _terminalHeight = 0;
winrt::Windows::UI::Xaml::Thickness _thickness{ 0, 0, 0, 0 };
float _fontWidth = 0;
float _fontHeight = 0;
std::pair<std::shared_ptr<Pane>, winrt::Microsoft::Terminal::Settings::Model::SplitDirection> _splittingPane{
nullptr,
winrt::Microsoft::Terminal::Settings::Model::SplitDirection::Right,
};
};
}

View File

@@ -15,6 +15,7 @@
#include "../../renderer/atlas/AtlasEngine.h"
#include "../../renderer/base/renderer.hpp"
#include "../../renderer/uia/UiaRenderer.hpp"
#include "../../terminal/adapter/adaptDispatch.hpp"
#include "../../types/inc/CodepointWidthDetector.hpp"
#include "../../types/inc/utils.hpp"
@@ -139,6 +140,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
auto pfnWindowSizeChanged = [this](auto&& PH1, auto&& PH2) { _terminalWindowSizeChanged(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2)); };
_terminal->SetWindowSizeChangedCallback(pfnWindowSizeChanged);
_terminal->SetEnterTmuxControlCallback([this]() -> std::function<bool(wchar_t)> {
const auto args = winrt::make_self<EnterTmuxControlEventArgs>();
EnterTmuxControl.raise(*this, *args);
if (auto inputCallback = args->InputCallback())
{
return [inputCallback = std::move(inputCallback)](wchar_t ch) -> bool {
const auto c16 = static_cast<char16_t>(ch);
inputCallback({ &c16, 1 });
return true;
};
}
return nullptr;
});
// MSFT 33353327: Initialize the renderer in the ctor instead of Initialize().
// We need the renderer to be ready to accept new engines before the SwapChainPanel is ready to go.
// If we wait, a screen reader may try to get the AutomationPeer (aka the UIA Engine), and we won't be able to attach
@@ -1459,6 +1474,45 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_terminal->TrySnapOnInput();
}
void ControlCore::InjectTextAtCursor(const winrt::hstring& text)
{
if (text.empty())
{
return;
}
const auto lock = _terminal->LockForWriting();
std::wstring_view remaining{ text };
// Process one line at a time
for (;;)
{
// Get the (CR)LF position
const auto lf = std::min(remaining.size(), remaining.find(L'\n'));
// Strip off the CR
auto lineEnd = lf;
if (lineEnd != 0 && remaining[lineEnd - 1] == L'\r')
{
lineEnd -= 1;
}
// Split into line and whatever comes after
const auto line = remaining.substr(0, lineEnd);
remaining = remaining.substr(std::min(remaining.size(), lf + 1));
// This will not just print the line but also handle delay wrap, etc.
_terminal->GetAdaptDispatch().PrintString(line);
if (remaining.empty())
{
break;
}
_terminal->GetAdaptDispatch().LineFeed(DispatchTypes::LineFeedType::DependsOnMode);
}
}
FontInfo ControlCore::GetFont() const
{
return _actualFont;
@@ -1568,6 +1622,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return _terminal->GetViewport().Height();
}
// Function Description:
// - Gets the width of the terminal in lines of text. This is just the
// width of the viewport.
// Return Value:
// - The width of the terminal in lines of text
int ControlCore::ViewWidth() const
{
const auto lock = _terminal->LockForReading();
return _terminal->GetViewport().Width();
}
// Function Description:
// - Gets the height of the terminal in lines of text. This includes the
// history AND the viewport.

View File

@@ -23,6 +23,7 @@
#include "../../buffer/out/search.h"
#include "../../cascadia/TerminalCore/Terminal.hpp"
#include "../../renderer/inc/FontInfoDesired.hpp"
#include "../../terminal/adapter/ITermDispatch.hpp"
namespace Microsoft::Console::Render::Atlas
{
@@ -124,6 +125,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void SendInput(std::wstring_view wstr);
void PasteText(const winrt::hstring& hstr);
void InjectTextAtCursor(const winrt::hstring& text);
bool CopySelectionToClipboard(bool singleLine, bool withControlSequences, const CopyFormat formats);
void SelectAll();
void ClearSelection();
@@ -172,6 +174,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
int ScrollOffset();
int ViewHeight() const;
int ViewWidth() const;
int BufferHeight() const;
bool HasSelection() const;
@@ -295,10 +298,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
til::typed_event<IInspectable, Control::SearchMissingCommandEventArgs> SearchMissingCommand;
til::typed_event<> RefreshQuickFixUI;
til::typed_event<IInspectable, Control::WindowSizeChangedEventArgs> WindowSizeChanged;
til::typed_event<IInspectable, Control::EnterTmuxControlEventArgs> EnterTmuxControl;
til::typed_event<> CloseTerminalRequested;
til::typed_event<> RestartTerminalRequested;
til::typed_event<> Attached;
// clang-format on

View File

@@ -128,6 +128,7 @@ namespace Microsoft.Terminal.Control
Microsoft.Terminal.Core.ControlKeyStates modifiers);
void SendInput(String text);
void PasteText(String text);
void InjectTextAtCursor(String text);
void SelectAll();
void ClearSelection();
Boolean ToggleBlockSelection();
@@ -198,6 +199,7 @@ namespace Microsoft.Terminal.Control
event Windows.Foundation.TypedEventHandler<Object, SearchMissingCommandEventArgs> SearchMissingCommand;
event Windows.Foundation.TypedEventHandler<Object, Object> RefreshQuickFixUI;
event Windows.Foundation.TypedEventHandler<Object, WindowSizeChangedEventArgs> WindowSizeChanged;
event Windows.Foundation.TypedEventHandler<Object, EnterTmuxControlEventArgs> EnterTmuxControl;
// These events are always called from the UI thread (bugs aside)
event Windows.Foundation.TypedEventHandler<Object, FontSizeChangedArgs> FontSizeChanged;

View File

@@ -21,3 +21,4 @@
#include "StringSentEventArgs.g.cpp"
#include "SearchMissingCommandEventArgs.g.cpp"
#include "WindowSizeChangedEventArgs.g.cpp"
#include "EnterTmuxControlEventArgs.g.cpp"

View File

@@ -21,6 +21,7 @@
#include "StringSentEventArgs.g.h"
#include "SearchMissingCommandEventArgs.g.h"
#include "WindowSizeChangedEventArgs.g.h"
#include "EnterTmuxControlEventArgs.g.h"
namespace winrt::Microsoft::Terminal::Control::implementation
{
@@ -265,6 +266,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
WINRT_PROPERTY(int32_t, Width);
WINRT_PROPERTY(int32_t, Height);
};
struct EnterTmuxControlEventArgs : public EnterTmuxControlEventArgsT<EnterTmuxControlEventArgs>
{
til::property<TmuxControlInputCallback> InputCallback;
};
}
namespace winrt::Microsoft::Terminal::Control::factory_implementation

View File

@@ -159,4 +159,11 @@ namespace Microsoft.Terminal.Control
Int32 Width;
Int32 Height;
}
delegate void TmuxControlInputCallback(Char[] input);
runtimeclass EnterTmuxControlEventArgs
{
void InputCallback(TmuxControlInputCallback callback);
}
}

View File

@@ -40,6 +40,7 @@ namespace Microsoft.Terminal.Control
Int32 ScrollOffset { get; };
Int32 ViewHeight { get; };
Int32 ViewWidth { get; };
Int32 BufferHeight { get; };
Boolean HasSelection { get; };

View File

@@ -330,6 +330,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_revokers.SearchMissingCommand = _core.SearchMissingCommand(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleSearchMissingCommand });
_revokers.WindowSizeChanged = _core.WindowSizeChanged(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleWindowSizeChanged });
_revokers.WriteToClipboard = _core.WriteToClipboard(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleWriteToClipboard });
_revokers.EnterTmuxControl = _core.EnterTmuxControl(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleEnterTmuxControl });
_revokers.PasteFromClipboard = _interactivity.PasteFromClipboard(winrt::auto_revoke, { get_weak(), &TermControl::_bubblePasteFromClipboard });
@@ -1506,6 +1507,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
_core.SendInput(text);
}
void TermControl::InjectTextAtCursor(const winrt::hstring& text)
{
_core.InjectTextAtCursor(text);
}
// Method Description:
// - Manually handles key events for certain keys that can't be passed to us
// normally. Namely, the keys we're concerned with are F7 down and Alt up.
@@ -2667,6 +2673,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return _core.ViewHeight();
}
int TermControl::ViewWidth() const
{
return _core.ViewWidth();
}
int TermControl::BufferHeight() const
{
return _core.BufferHeight();
@@ -2866,7 +2877,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
else
{
// Do we ever get here (= uninitialized terminal)? If so: How?
assert(false);
// Yes, we can get here, when do Pane._Split, it need to call _SetupEntranceAnimation
// which need the control's size, while this size can only be available when the control
// is initialized.
return { 10, 10 };
}
}
@@ -4028,6 +4041,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}
void TermControl::_bubbleEnterTmuxControl(const IInspectable&, Control::EnterTmuxControlEventArgs args)
{
EnterTmuxControl.raise(*this, std::move(args));
}
til::CoordType TermControl::_calculateSearchScrollOffset() const
{
auto result = 0;

View File

@@ -97,6 +97,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
int ScrollOffset() const;
int ViewHeight() const;
int ViewWidth() const;
int BufferHeight() const;
bool HasSelection() const;
@@ -182,6 +183,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
bool RawWriteKeyEvent(const WORD vkey, const WORD scanCode, const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown);
bool RawWriteChar(const wchar_t character, const WORD scanCode, const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers);
void RawWriteString(const winrt::hstring& text);
void InjectTextAtCursor(const winrt::hstring& text);
void ShowContextMenu();
bool OpenQuickFixMenu();
@@ -217,6 +219,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
til::typed_event<IInspectable, Control::StringSentEventArgs> StringSent;
til::typed_event<IInspectable, Control::SearchMissingCommandEventArgs> SearchMissingCommand;
til::typed_event<IInspectable, Control::WindowSizeChangedEventArgs> WindowSizeChanged;
til::typed_event<IInspectable, Control::EnterTmuxControlEventArgs> EnterTmuxControl;
// UNDER NO CIRCUMSTANCES SHOULD YOU ADD A (PROJECTED_)FORWARDED_TYPED_EVENT HERE
// Those attach the handler to the core directly, and will explode if
@@ -437,6 +440,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void _bubbleSearchMissingCommand(const IInspectable& sender, const Control::SearchMissingCommandEventArgs& args);
winrt::fire_and_forget _bubbleWindowSizeChanged(const IInspectable& sender, Control::WindowSizeChangedEventArgs args);
void _bubbleEnterTmuxControl(const IInspectable& sender, Control::EnterTmuxControlEventArgs args);
til::CoordType _calculateSearchScrollOffset() const;
void _PasteCommandHandler(const IInspectable& sender, const IInspectable& args);
@@ -471,6 +475,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Control::ControlCore::SearchMissingCommand_revoker SearchMissingCommand;
Control::ControlCore::RefreshQuickFixUI_revoker RefreshQuickFixUI;
Control::ControlCore::WindowSizeChanged_revoker WindowSizeChanged;
Control::ControlCore::EnterTmuxControl_revoker EnterTmuxControl;
// These are set up in _InitializeTerminal
Control::ControlCore::RendererWarning_revoker RendererWarning;

View File

@@ -74,6 +74,7 @@ namespace Microsoft.Terminal.Control
event Windows.Foundation.TypedEventHandler<Object, Object> ReadOnlyChanged;
event Windows.Foundation.TypedEventHandler<Object, Object> FocusFollowMouseRequested;
event Windows.Foundation.TypedEventHandler<Object, WindowSizeChangedEventArgs> WindowSizeChanged;
event Windows.Foundation.TypedEventHandler<Object, EnterTmuxControlEventArgs> EnterTmuxControl;
event Windows.Foundation.TypedEventHandler<Object, CompletionsChangedEventArgs> CompletionsChanged;
@@ -130,6 +131,7 @@ namespace Microsoft.Terminal.Control
Boolean RawWriteKeyEvent(UInt16 vkey, UInt16 scanCode, Microsoft.Terminal.Core.ControlKeyStates modifiers, Boolean keyDown);
Boolean RawWriteChar(Char character, UInt16 scanCode, Microsoft.Terminal.Core.ControlKeyStates modifiers);
void RawWriteString(String text);
void InjectTextAtCursor(String text);
void BellLightOn();

View File

@@ -51,6 +51,7 @@ void Terminal::Create(til::size viewportSize, til::CoordType scrollbackLines, Re
_mainBuffer = std::make_unique<TextBuffer>(bufferSize, attr, cursorSize, true, &renderer);
auto dispatch = std::make_unique<AdaptDispatch>(*this, &renderer, _renderSettings, _terminalInput);
_adaptDispatch = dispatch.get();
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
_stateMachine = std::make_unique<StateMachine>(std::move(engine));
}
@@ -1039,6 +1040,12 @@ bool Terminal::IsFocused() const noexcept
return _focused;
}
AdaptDispatch& Microsoft::Terminal::Core::Terminal::GetAdaptDispatch() noexcept
{
_assertLocked();
return *_adaptDispatch;
}
RenderSettings& Terminal::GetRenderSettings() noexcept
{
_assertLocked();
@@ -1270,6 +1277,11 @@ void Microsoft::Terminal::Core::Terminal::SetSearchMissingCommandCallback(std::f
_pfnSearchMissingCommand.swap(pfn);
}
void Terminal::SetEnterTmuxControlCallback(std::function<std::function<bool(wchar_t)>()> pfn) noexcept
{
_pfnEnterTmuxControl = std::move(pfn);
}
void Microsoft::Terminal::Core::Terminal::SetClearQuickFixCallback(std::function<void()> pfn) noexcept
{
_pfnClearQuickFix.swap(pfn);

View File

@@ -116,6 +116,7 @@ public:
int ViewEndIndex() const noexcept;
bool IsFocused() const noexcept;
::Microsoft::Console::VirtualTerminal::AdaptDispatch& GetAdaptDispatch() noexcept;
RenderSettings& GetRenderSettings() noexcept;
const RenderSettings& GetRenderSettings() const noexcept;
@@ -153,14 +154,12 @@ public:
void ShowWindow(bool showOrHide) override;
void UseAlternateScreenBuffer(const TextAttribute& attrs) override;
void UseMainScreenBuffer() override;
bool IsVtInputEnabled() const noexcept override;
void NotifyBufferRotation(const int delta) override;
void NotifyShellIntegrationMark() override;
void InvokeCompletions(std::wstring_view menuJson, unsigned int replaceLength) override;
void SearchMissingCommand(const std::wstring_view command) override;
std::function<bool(wchar_t)> EnterTmuxControl() override;
#pragma endregion
@@ -230,6 +229,7 @@ public:
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, const til::CoordType)> pfn) noexcept;
void SetEnterTmuxControlCallback(std::function<std::function<bool(wchar_t)>()> pfn) noexcept;
void SetClearQuickFixCallback(std::function<void()> pfn) noexcept;
void SetWindowSizeChangedCallback(std::function<void(int32_t, int32_t)> pfn) noexcept;
void SetSearchHighlights(const std::vector<til::point_span>& highlights) noexcept;
@@ -338,10 +338,12 @@ private:
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, const til::CoordType)> _pfnSearchMissingCommand;
std::function<std::function<bool(wchar_t)>()> _pfnEnterTmuxControl;
std::function<void()> _pfnClearQuickFix;
std::function<void(int32_t, int32_t)> _pfnWindowSizeChanged;
RenderSettings _renderSettings;
::Microsoft::Console::VirtualTerminal::AdaptDispatch* _adaptDispatch = nullptr;
std::unique_ptr<::Microsoft::Console::VirtualTerminal::StateMachine> _stateMachine;
::Microsoft::Console::VirtualTerminal::TerminalInput _terminalInput;

View File

@@ -364,6 +364,11 @@ void Terminal::SearchMissingCommand(const std::wstring_view command)
}
}
std::function<bool(wchar_t)> Terminal::EnterTmuxControl()
{
return _pfnEnterTmuxControl ? _pfnEnterTmuxControl() : nullptr;
}
void Terminal::NotifyBufferRotation(const int delta)
{
// Update our selection, so it doesn't move as the buffer is cycled

View File

@@ -352,6 +352,7 @@ namespace winrt::Microsoft::Terminal::Settings
_AllowVtChecksumReport = profile.AllowVtChecksumReport();
_AllowVtClipboardWrite = profile.AllowVtClipboardWrite();
_PathTranslationStyle = profile.PathTranslationStyle();
_AllowTmuxControl = profile.AllowTmuxControl();
}
// Method Description:

View File

@@ -92,6 +92,7 @@ namespace winrt::Microsoft::Terminal::Settings
SIMPLE_OVERRIDABLE_SETTING(bool, Elevate, false);
SIMPLE_OVERRIDABLE_SETTING(IEnvironmentVariableMapView, EnvironmentVariables, nullptr);
SIMPLE_OVERRIDABLE_SETTING(bool, ReloadEnvironmentVariables, true);
SIMPLE_OVERRIDABLE_SETTING(bool, AllowTmuxControl, false);
public:
// TerminalApp overrides these when duplicating a session

View File

@@ -4,6 +4,8 @@
#include "pch.h"
#include "Actions.h"
#include "Actions.g.cpp"
#include "NavigateToPageArgs.g.h"
#include "LibraryResources.h"
#include "../TerminalSettingsModel/AllShortcutActions.h"
using namespace winrt::Windows::UI::Xaml;
@@ -20,16 +22,17 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Actions::OnNavigatedTo(const NavigationEventArgs& e)
{
_ViewModel = e.Parameter().as<Editor::ActionsViewModel>();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_ViewModel = args.ViewModel().as<Editor::ActionsViewModel>();
_ViewModel.CurrentPage(ActionsSubPage::Base);
auto vmImpl = get_self<ActionsViewModel>(_ViewModel);
vmImpl->MarkAsVisited();
get_self<ActionsViewModel>(_ViewModel)->MarkAsVisited();
_layoutUpdatedRevoker = LayoutUpdated(winrt::auto_revoke, [this](auto /*s*/, auto /*e*/) {
// Only let this succeed once.
_layoutUpdatedRevoker.revoke();
AddNewButton().Focus(FocusState::Programmatic);
});
BringIntoViewWhenLoaded(args.ElementToFocus());
TraceLoggingWrite(
g_hTerminalSettingsEditorProvider,

View File

@@ -53,13 +53,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
public:
NavigateToCommandArgs(CommandViewModel command, Editor::IHostedInWindow windowRoot) :
_Command(command),
_WindowRoot(windowRoot) {}
_WeakWindowRoot(windowRoot) {}
Editor::IHostedInWindow WindowRoot() const noexcept { return _WindowRoot; }
Editor::IHostedInWindow WindowRoot() const noexcept { return _WeakWindowRoot.get(); }
Editor::CommandViewModel Command() const noexcept { return _Command; }
private:
Editor::IHostedInWindow _WindowRoot;
winrt::weak_ref<Editor::IHostedInWindow> _WeakWindowRoot;
Editor::CommandViewModel _Command{ nullptr };
};

View File

@@ -27,6 +27,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void AddProfile::OnNavigatedTo(const NavigationEventArgs& e)
{
_State = e.Parameter().as<Editor::AddProfilePageNavigationState>();
BringIntoViewWhenLoaded(_State.ElementToFocus());
TraceLoggingWrite(
g_hTerminalSettingsEditorProvider,

View File

@@ -26,8 +26,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
struct AddProfilePageNavigationState : AddProfilePageNavigationStateT<AddProfilePageNavigationState>
{
public:
AddProfilePageNavigationState(const Model::CascadiaSettings& settings) :
_Settings{ settings } {}
AddProfilePageNavigationState(const Model::CascadiaSettings& settings, const hstring& elementToFocus = {}) :
_Settings{ settings },
_ElementToFocus{ elementToFocus } {}
void RequestAddNew()
{
@@ -42,6 +43,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
til::event<AddNewArgs> AddNew;
WINRT_PROPERTY(Model::CascadiaSettings, Settings, nullptr);
WINRT_PROPERTY(hstring, ElementToFocus);
};
struct AddProfile : public HasScrollViewer<AddProfile>, AddProfileT<AddProfile>

View File

@@ -8,6 +8,8 @@ namespace Microsoft.Terminal.Settings.Editor
runtimeclass AddProfilePageNavigationState
{
Microsoft.Terminal.Settings.Model.CascadiaSettings Settings;
String ElementToFocus { get; };
void RequestAddNew();
void RequestDuplicate(Guid profile);
event AddNewArgs AddNew;

View File

@@ -37,7 +37,8 @@
</Button>
</Border>
<StackPanel Margin="{StaticResource StandardControlMargin}">
<local:SettingContainer x:Uid="AddProfile_Duplicate">
<local:SettingContainer x:Name="DuplicateProfile"
x:Uid="AddProfile_Duplicate">
<ComboBox x:Name="Profiles"
AutomationProperties.AccessibilityView="Content"
ItemsSource="{x:Bind State.Settings.AllProfiles, Mode=OneWay}"

View File

@@ -1138,6 +1138,27 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
INITIALIZE_BINDABLE_ENUM_SETTING(IntenseTextStyle, IntenseTextStyle, winrt::Microsoft::Terminal::Settings::Model::IntenseStyle, L"Appearance_IntenseTextStyle", L"Content");
}
// Appearances doesn't implement HasScrollViewer<T> which normally adds this function.
void Appearances::BringIntoViewWhenLoaded(hstring elementToFocus)
{
if (elementToFocus.empty())
{
return;
}
_loadedRevoker = this->Loaded(winrt::auto_revoke, [weakThis{ get_weak() }, elementToFocus](auto&&, auto&&) {
if (const auto strongThis = weakThis.get())
{
if (const auto& controlToFocus{ strongThis->FindName(elementToFocus).try_as<Controls::Control>() })
{
controlToFocus.as<FrameworkElement>().StartBringIntoView();
controlToFocus.Focus(FocusState::Programmatic);
}
strongThis->_loadedRevoker.revoke();
}
});
}
IObservableVector<Editor::Font> Appearances::FilteredFontList()
{
if (!_filteredFonts)

View File

@@ -188,6 +188,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
struct Appearances : AppearancesT<Appearances>
{
Appearances();
void BringIntoViewWhenLoaded(hstring elementToFocus);
// CursorShape visibility logic
bool IsVintageCursor() const;
@@ -210,6 +211,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
bool IsCustomFontWeight();
til::property_changed_event PropertyChanged;
winrt::Windows::UI::Xaml::FrameworkElement::Loaded_revoker _loadedRevoker;
WINRT_PROPERTY(Windows::Foundation::Collections::IObservableVector<Microsoft::Terminal::Settings::Editor::EnumEntry>, FontWeightList);

View File

@@ -75,7 +75,8 @@
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Color Scheme -->
<!-- This currently only display the Dark color scheme, even if the user has a pair of schemes set. -->
<local:SettingContainer x:Uid="Profile_ColorScheme"
<local:SettingContainer x:Name="ColorScheme"
x:Uid="Profile_ColorScheme"
ClearSettingValue="{x:Bind Appearance.ClearColorScheme}"
CurrentValueAccessibleName="{x:Bind Appearance.CurrentColorScheme.Name, Mode=OneWay}"
HasSettingValue="{x:Bind Appearance.HasDarkColorSchemeName, Mode=OneWay}"
@@ -284,17 +285,20 @@
IsChecked="{x:Bind ShowAllFonts, Mode=TwoWay}" />
</StackPanel>
</local:SettingContainer>
<local:SettingContainer x:Uid="Profile_MissingFontFaces"
<local:SettingContainer x:Name="MissingFontFaces"
x:Uid="Profile_MissingFontFaces"
HelpText="{x:Bind Appearance.MissingFontFaces, Mode=OneWay}"
Style="{StaticResource SettingContainerErrorStyle}"
Visibility="{x:Bind mtu:Converters.StringNotEmptyToVisibility(Appearance.MissingFontFaces), Mode=OneWay}" />
<local:SettingContainer x:Uid="Profile_ProportionalFontFaces"
<local:SettingContainer x:Name="ProportionalFontFaces"
x:Uid="Profile_ProportionalFontFaces"
HelpText="{x:Bind Appearance.ProportionalFontFaces, Mode=OneWay}"
Style="{StaticResource SettingContainerWarningStyle}"
Visibility="{x:Bind mtu:Converters.StringNotEmptyToVisibility(Appearance.ProportionalFontFaces), Mode=OneWay}" />
<!-- Font Size -->
<local:SettingContainer x:Uid="Profile_FontSize"
<local:SettingContainer x:Name="FontSize"
x:Uid="Profile_FontSize"
ClearSettingValue="{x:Bind Appearance.ClearFontSize}"
HasSettingValue="{x:Bind Appearance.HasFontSize, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.FontSizeOverrideSource, Mode=OneWay}"
@@ -310,7 +314,8 @@
</local:SettingContainer>
<!-- Line Height -->
<local:SettingContainer x:Uid="Profile_LineHeight"
<local:SettingContainer x:Name="LineHeight"
x:Uid="Profile_LineHeight"
ClearSettingValue="{x:Bind Appearance.ClearLineHeight}"
HasSettingValue="{x:Bind Appearance.HasLineHeight, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.LineHeightOverrideSource, Mode=OneWay}"
@@ -326,7 +331,8 @@
</local:SettingContainer>
<!-- Cell Width -->
<local:SettingContainer x:Uid="Profile_CellWidth"
<local:SettingContainer x:Name="CellWidth"
x:Uid="Profile_CellWidth"
ClearSettingValue="{x:Bind Appearance.ClearCellWidth}"
HasSettingValue="{x:Bind Appearance.HasCellWidth, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.CellWidthOverrideSource, Mode=OneWay}"
@@ -342,7 +348,8 @@
</local:SettingContainer>
<!-- Font Weight -->
<local:SettingContainer x:Uid="Profile_FontWeight"
<local:SettingContainer x:Name="FontWeight"
x:Uid="Profile_FontWeight"
ClearSettingValue="{x:Bind Appearance.ClearFontWeight}"
HasSettingValue="{x:Bind Appearance.HasFontWeight, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.FontWeightOverrideSource, Mode=OneWay}"
@@ -378,7 +385,8 @@
</Grid>
</StackPanel>
</local:SettingContainer>
<local:SettingContainer x:Uid="Profile_FontAxes"
<local:SettingContainer x:Name="FontAxes"
x:Uid="Profile_FontAxes"
ClearSettingValue="{x:Bind Appearance.ClearFontAxes}"
HasSettingValue="{x:Bind Appearance.HasFontAxes, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.FontAxesOverrideSource, Mode=OneWay}"
@@ -405,7 +413,8 @@
</muxc:DropDownButton>
</StackPanel>
</local:SettingContainer>
<local:SettingContainer x:Uid="Profile_FontFeatures"
<local:SettingContainer x:Name="FontFeatures"
x:Uid="Profile_FontFeatures"
ClearSettingValue="{x:Bind Appearance.ClearFontFeatures}"
HasSettingValue="{x:Bind Appearance.HasFontFeatures, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.FontFeaturesOverrideSource, Mode=OneWay}"
@@ -434,7 +443,8 @@
</local:SettingContainer>
<!-- Builtin Glyphs -->
<local:SettingContainer x:Uid="Profile_EnableBuiltinGlyphs"
<local:SettingContainer x:Name="EnableBuiltinGlyphs"
x:Uid="Profile_EnableBuiltinGlyphs"
ClearSettingValue="{x:Bind Appearance.ClearEnableBuiltinGlyphs}"
HasSettingValue="{x:Bind Appearance.HasEnableBuiltinGlyphs, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.EnableBuiltinGlyphsOverrideSource, Mode=OneWay}">
@@ -443,7 +453,8 @@
</local:SettingContainer>
<!-- Color Glyphs -->
<local:SettingContainer x:Uid="Profile_EnableColorGlyphs"
<local:SettingContainer x:Name="EnableColorGlyphs"
x:Uid="Profile_EnableColorGlyphs"
ClearSettingValue="{x:Bind Appearance.ClearEnableColorGlyphs}"
HasSettingValue="{x:Bind Appearance.HasEnableColorGlyphs, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.EnableColorGlyphsOverrideSource, Mode=OneWay}">
@@ -452,7 +463,8 @@
</local:SettingContainer>
<!-- Retro Terminal Effect -->
<local:SettingContainer x:Uid="Profile_RetroTerminalEffect"
<local:SettingContainer x:Name="RetroTerminalEffect"
x:Uid="Profile_RetroTerminalEffect"
ClearSettingValue="{x:Bind Appearance.ClearRetroTerminalEffect}"
HasSettingValue="{x:Bind Appearance.HasRetroTerminalEffect, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.RetroTerminalEffectOverrideSource, Mode=OneWay}">
@@ -461,7 +473,8 @@
</local:SettingContainer>
<!-- Adjust Indistinguishable Colors -->
<local:SettingContainer x:Uid="Profile_AdjustIndistinguishableColors"
<local:SettingContainer x:Name="AdjustIndistinguishableColors"
x:Uid="Profile_AdjustIndistinguishableColors"
ClearSettingValue="{x:Bind Appearance.ClearAdjustIndistinguishableColors}"
HasSettingValue="{x:Bind Appearance.HasAdjustIndistinguishableColors, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.AdjustIndistinguishableColorsOverrideSource, Mode=OneWay}">
@@ -479,7 +492,8 @@
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Cursor Shape -->
<local:SettingContainer x:Uid="Profile_CursorShape"
<local:SettingContainer x:Name="CursorShape"
x:Uid="Profile_CursorShape"
ClearSettingValue="{x:Bind Appearance.ClearCursorShape}"
HasSettingValue="{x:Bind Appearance.HasCursorShape, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.CursorShapeOverrideSource, Mode=OneWay}">
@@ -491,7 +505,8 @@
</local:SettingContainer>
<!-- Cursor Height -->
<local:SettingContainer x:Uid="Profile_CursorHeight"
<local:SettingContainer x:Name="CursorHeight"
x:Uid="Profile_CursorHeight"
ClearSettingValue="{x:Bind Appearance.ClearCursorHeight}"
HasSettingValue="{x:Bind Appearance.HasCursorHeight, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.CursorHeightOverrideSource, Mode=OneWay}"
@@ -563,7 +578,8 @@
</local:SettingContainer>
<!-- Background Image Stretch Mode -->
<local:SettingContainer x:Uid="Profile_BackgroundImageStretchMode"
<local:SettingContainer x:Name="BackgroundImageStretchMode"
x:Uid="Profile_BackgroundImageStretchMode"
ClearSettingValue="{x:Bind Appearance.ClearBackgroundImageStretchMode}"
HasSettingValue="{x:Bind Appearance.HasBackgroundImageStretchMode, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.BackgroundImageStretchModeOverrideSource, Mode=OneWay}"
@@ -576,7 +592,8 @@
</local:SettingContainer>
<!-- Background Image Alignment -->
<local:SettingContainer x:Uid="Profile_BackgroundImageAlignment"
<local:SettingContainer x:Name="BackgroundImageAlignment"
x:Uid="Profile_BackgroundImageAlignment"
ClearSettingValue="{x:Bind Appearance.ClearBackgroundImageAlignment}"
CurrentValue="{x:Bind Appearance.BackgroundImageAlignmentCurrentValue, Mode=OneWay}"
HasSettingValue="{x:Bind Appearance.HasBackgroundImageAlignment, Mode=OneWay}"
@@ -764,7 +781,8 @@
</local:SettingContainer>
<!-- Background Image Opacity -->
<local:SettingContainer x:Uid="Profile_BackgroundImageOpacity"
<local:SettingContainer x:Name="BackgroundImageOpacity"
x:Uid="Profile_BackgroundImageOpacity"
ClearSettingValue="{x:Bind Appearance.ClearBackgroundImageOpacity}"
HasSettingValue="{x:Bind Appearance.HasBackgroundImageOpacity, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.BackgroundImageOpacityOverrideSource, Mode=OneWay}"
@@ -790,7 +808,8 @@
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Intense is bold, bright -->
<local:SettingContainer x:Uid="Appearance_IntenseTextStyle"
<local:SettingContainer x:Name="IntenseTextStyle"
x:Uid="Appearance_IntenseTextStyle"
ClearSettingValue="{x:Bind Appearance.ClearIntenseTextStyle}"
HasSettingValue="{x:Bind Appearance.HasIntenseTextStyle, Mode=OneWay}"
SettingOverrideSource="{x:Bind Appearance.IntenseTextStyleOverrideSource, Mode=OneWay}">

View File

@@ -4,6 +4,7 @@
#include "pch.h"
#include "ColorSchemes.h"
#include "ColorTableEntry.g.cpp"
#include "NavigateToPageArgs.g.h"
#include "ColorSchemes.g.cpp"
using namespace winrt;
@@ -33,9 +34,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void ColorSchemes::OnNavigatedTo(const NavigationEventArgs& e)
{
_ViewModel = e.Parameter().as<Editor::ColorSchemesPageViewModel>();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_ViewModel = args.ViewModel().as<Editor::ColorSchemesPageViewModel>();
_ViewModel.CurrentPage(ColorSchemesSubPage::Base);
BringIntoViewWhenLoaded(args.ElementToFocus());
_layoutUpdatedRevoker = LayoutUpdated(winrt::auto_revoke, [this](auto /*s*/, auto /*e*/) {
// Only let this succeed once.
_layoutUpdatedRevoker.revoke();

View File

@@ -37,6 +37,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
WINRT_OBSERVABLE_PROPERTY(ColorSchemesSubPage, CurrentPage, _propertyChangedHandlers, ColorSchemesSubPage::Base);
WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector<Editor::ColorSchemeViewModel>, AllColorSchemes, _propertyChangedHandlers, nullptr);
WINRT_PROPERTY(hstring, ElementToFocus);
private:
Editor::ColorSchemeViewModel _CurrentScheme{ nullptr };

View File

@@ -6,6 +6,7 @@
#include "EnumEntry.h"
#include "Compatibility.g.cpp"
#include "CompatibilityViewModel.g.cpp"
#include "NavigateToPageArgs.g.h"
using namespace winrt::Windows::UI::Xaml::Navigation;
using namespace winrt::Microsoft::Terminal::Settings::Model;
@@ -54,7 +55,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Compatibility::OnNavigatedTo(const NavigationEventArgs& e)
{
_ViewModel = e.Parameter().as<Editor::CompatibilityViewModel>();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_ViewModel = args.ViewModel().as<Editor::CompatibilityViewModel>();
BringIntoViewWhenLoaded(args.ElementToFocus());
TraceLoggingWrite(
g_hTerminalSettingsEditorProvider,

View File

@@ -26,13 +26,15 @@
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Allow Headless -->
<local:SettingContainer x:Uid="Globals_AllowHeadless">
<local:SettingContainer x:Name="AllowHeadless"
x:Uid="Globals_AllowHeadless">
<ToggleSwitch IsOn="{x:Bind ViewModel.AllowHeadless, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Text Measurement -->
<local:SettingContainer x:Uid="Globals_TextMeasurement">
<local:SettingContainer x:Name="TextMeasurement"
x:Uid="Globals_TextMeasurement">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.TextMeasurementList}"
@@ -41,14 +43,16 @@
</local:SettingContainer>
<!-- Debug Features -->
<local:SettingContainer x:Uid="Globals_DebugFeaturesEnabled"
<local:SettingContainer x:Name="DebugFeaturesEnabled"
x:Uid="Globals_DebugFeaturesEnabled"
Visibility="{x:Bind ViewModel.DebugFeaturesAvailable}">
<ToggleSwitch IsOn="{x:Bind ViewModel.DebugFeaturesEnabled, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Reset Application State -->
<local:SettingContainer x:Uid="Settings_ResetApplicationState">
<local:SettingContainer x:Name="ResetApplicationState"
x:Uid="Settings_ResetApplicationState">
<Button x:Uid="Settings_ResetApplicationStateButton"
Style="{StaticResource DeleteButtonStyle}">
<Button.Flyout>
@@ -69,7 +73,8 @@
</local:SettingContainer>
<!-- Reset to Default Settings -->
<local:SettingContainer x:Uid="Settings_ResetToDefaultSettings">
<local:SettingContainer x:Name="ResetToDefaultSettings"
x:Uid="Settings_ResetToDefaultSettings">
<Button x:Uid="Settings_ResetToDefaultSettingsButton"
Style="{StaticResource DeleteButtonStyle}">
<Button.Flyout>

View File

@@ -4,6 +4,7 @@
#include "pch.h"
#include "EditColorScheme.h"
#include "EditColorScheme.g.cpp"
#include "NavigateToPageArgs.g.h"
using namespace winrt;
using namespace winrt::Windows::UI;
@@ -38,7 +39,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void EditColorScheme::OnNavigatedTo(const NavigationEventArgs& e)
{
_ViewModel = e.Parameter().as<Editor::ColorSchemeViewModel>();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_ViewModel = args.ViewModel().as<Editor::ColorSchemeViewModel>();
BringIntoViewWhenLoaded(args.ElementToFocus());
const auto schemeName = _ViewModel.Name();
NameBox().Text(schemeName);

View File

@@ -200,7 +200,8 @@
</Grid>
</Border>
<local:SettingContainer x:Uid="ColorScheme_InboxSchemeDuplicate"
<local:SettingContainer x:Name="InboxSchemeDuplicate"
x:Uid="ColorScheme_InboxSchemeDuplicate"
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(ViewModel.IsEditable), Mode=OneWay}">
<Button x:Name="DuplicateSchemeButton"
x:Uid="ColorScheme_DuplicateButton"
@@ -208,7 +209,8 @@
Style="{StaticResource BrowseButtonStyle}" />
</local:SettingContainer>
<local:SettingContainer x:Uid="ColorScheme_ColorsHeader"
<local:SettingContainer x:Name="ColorsHeader"
x:Uid="ColorScheme_ColorsHeader"
StartExpanded="True"
Style="{StaticResource ExpanderSettingContainerStyle}"
Visibility="{x:Bind ViewModel.IsEditable, Mode=OneWay}">

View File

@@ -3,6 +3,7 @@
#include "pch.h"
#include "Extensions.h"
#include "NavigateToPageArgs.g.h"
#include "Extensions.g.cpp"
#include "ExtensionPackageViewModel.g.cpp"
#include "ExtensionsViewModel.g.cpp"
@@ -33,11 +34,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Extensions::OnNavigatedTo(const NavigationEventArgs& e)
{
_ViewModel = e.Parameter().as<Editor::ExtensionsViewModel>();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_ViewModel = args.ViewModel().as<Editor::ExtensionsViewModel>();
auto vmImpl = get_self<ExtensionsViewModel>(_ViewModel);
vmImpl->ExtensionPackageIdentifierTemplateSelector(_extensionPackageIdentifierTemplateSelector);
vmImpl->LazyLoadExtensions();
BringIntoViewWhenLoaded(args.ElementToFocus());
if (vmImpl->IsExtensionView())
{
const auto currentPkgVM = vmImpl->CurrentExtensionPackage();

View File

@@ -500,7 +500,8 @@
<muxc:Expander.Content>
<StackPanel>
<!-- Scope -->
<local:SettingContainer x:Uid="Extensions_Scope"
<local:SettingContainer x:Name="Scope"
x:Uid="Extensions_Scope"
Content="{x:Bind ViewModel.CurrentExtensionPackage.Scope, Mode=OneWay}"
IsTabStop="False"
Style="{StaticResource SettingContainerWithTextContent}" />

View File

@@ -3,6 +3,7 @@
#include "pch.h"
#include "GlobalAppearance.h"
#include "NavigateToPageArgs.g.h"
#include "GlobalAppearance.g.cpp"
#include <WtExeUtils.h>
@@ -23,7 +24,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void GlobalAppearance::OnNavigatedTo(const NavigationEventArgs& e)
{
_ViewModel = e.Parameter().as<Editor::GlobalAppearanceViewModel>();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_ViewModel = args.ViewModel().as<Editor::GlobalAppearanceViewModel>();
BringIntoViewWhenLoaded(args.ElementToFocus());
TraceLoggingWrite(
g_hTerminalSettingsEditorProvider,

View File

@@ -5,7 +5,7 @@ import "GlobalAppearanceViewModel.idl";
namespace Microsoft.Terminal.Settings.Editor
{
[default_interface] runtimeclass GlobalAppearance : Windows.UI.Xaml.Controls.Page
runtimeclass GlobalAppearance : Windows.UI.Xaml.Controls.Page
{
GlobalAppearance();
GlobalAppearanceViewModel ViewModel { get; };

View File

@@ -28,7 +28,8 @@
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Theme -->
<local:SettingContainer x:Uid="Globals_Theme">
<local:SettingContainer x:Name="Theme"
x:Uid="Globals_Theme">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemsSource="{x:Bind ViewModel.ThemeList, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.CurrentTheme, Mode=TwoWay}"
@@ -42,7 +43,8 @@
</local:SettingContainer>
<!-- Position of new tab -->
<local:SettingContainer x:Uid="Globals_NewTabPosition">
<local:SettingContainer x:Name="NewTabPosition"
x:Uid="Globals_NewTabPosition">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.NewTabPositionList, Mode=OneWay}"
@@ -51,45 +53,52 @@
</local:SettingContainer>
<!-- Show Titlebar -->
<local:SettingContainer x:Uid="Globals_ShowTitlebar">
<local:SettingContainer x:Name="ShowTitlebar"
x:Uid="Globals_ShowTitlebar">
<ToggleSwitch IsOn="{x:Bind ViewModel.ShowTabsInTitlebar, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}"
Toggled="{x:Bind ViewModel.ShowTitlebarToggled}" />
</local:SettingContainer>
<!-- Always show tabs -->
<local:SettingContainer x:Uid="Globals_AlwaysShowTabs">
<local:SettingContainer x:Name="AlwaysShowTabs"
x:Uid="Globals_AlwaysShowTabs">
<ToggleSwitch IsEnabled="{x:Bind mtu:Converters.InvertBoolean(ViewModel.ShowTabsInTitlebar), Mode=OneWay}"
IsOn="{x:Bind ViewModel.AlwaysShowTabs, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Show tabs in full screen -->
<local:SettingContainer x:Uid="Globals_ShowTabsFullscreen">
<local:SettingContainer x:Name="ShowTabsFullscreen"
x:Uid="Globals_ShowTabsFullscreen">
<ToggleSwitch IsOn="{x:Bind ViewModel.ShowTabsFullscreen, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Show Acrylic in Tab Row -->
<local:SettingContainer x:Uid="Globals_AcrylicTabRow">
<local:SettingContainer x:Name="AcrylicTabRow"
x:Uid="Globals_AcrylicTabRow">
<ToggleSwitch IsOn="{x:Bind ViewModel.UseAcrylicInTabRow, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Show Title in Titlebar -->
<local:SettingContainer x:Uid="Globals_ShowTitleInTitlebar">
<local:SettingContainer x:Name="ShowTitleInTitlebar"
x:Uid="Globals_ShowTitleInTitlebar">
<ToggleSwitch IsOn="{x:Bind ViewModel.ShowTitleInTitlebar, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Always on Top -->
<local:SettingContainer x:Uid="Globals_AlwaysOnTop">
<local:SettingContainer x:Name="AlwaysOnTop"
x:Uid="Globals_AlwaysOnTop">
<ToggleSwitch IsOn="{x:Bind ViewModel.AlwaysOnTop, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Tab Width Mode -->
<local:SettingContainer x:Uid="Globals_TabWidthMode">
<local:SettingContainer x:Name="TabWidthMode"
x:Uid="Globals_TabWidthMode">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.TabWidthModeList, Mode=OneWay}"
@@ -99,37 +108,43 @@
<!-- Disable Animations -->
<!-- NOTE: the UID is "DisablePaneAnimationsReversed" not "DisablePaneAnimations". See GH#9124 for more details. -->
<local:SettingContainer x:Uid="Globals_DisableAnimationsReversed">
<local:SettingContainer x:Name="DisableAnimations"
x:Uid="Globals_DisableAnimationsReversed">
<ToggleSwitch IsOn="{x:Bind ViewModel.InvertedDisableAnimations, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Always Show Notification Icon -->
<local:SettingContainer x:Uid="Globals_AlwaysShowNotificationIcon">
<local:SettingContainer x:Name="AlwaysShowNotificationIcon"
x:Uid="Globals_AlwaysShowNotificationIcon">
<ToggleSwitch IsOn="{x:Bind ViewModel.AlwaysShowNotificationIcon, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Minimize To Notification Area -->
<local:SettingContainer x:Uid="Globals_MinimizeToNotificationArea">
<local:SettingContainer x:Name="MinimizeToNotificationArea"
x:Uid="Globals_MinimizeToNotificationArea">
<ToggleSwitch IsOn="{x:Bind ViewModel.MinimizeToNotificationArea, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Automatically hide window -->
<local:SettingContainer x:Uid="Globals_AutoHideWindow">
<local:SettingContainer x:Name="AutoHideWindow"
x:Uid="Globals_AutoHideWindow">
<ToggleSwitch IsOn="{x:Bind ViewModel.AutoHideWindow, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Show Admin Shield -->
<local:SettingContainer x:Uid="Globals_ShowAdminShield">
<local:SettingContainer x:Name="ShowAdminShield"
x:Uid="Globals_ShowAdminShield">
<ToggleSwitch IsOn="{x:Bind ViewModel.ShowAdminShield, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Enable Unfocused Acrylic -->
<local:SettingContainer x:Uid="Globals_EnableUnfocusedAcrylic">
<local:SettingContainer x:Name="EnableUnfocusedAcrylic"
x:Uid="Globals_EnableUnfocusedAcrylic">
<ToggleSwitch IsOn="{x:Bind ViewModel.EnableUnfocusedAcrylic, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>

View File

@@ -0,0 +1,330 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "IconPicker.h"
#include "IconPicker.g.cpp"
#include <LibraryResources.h>
#include "SegoeFluentIconList.h"
#include "../../types/inc/utils.hpp"
#include "../WinRTUtils/inc/Utils.h"
using namespace winrt;
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Navigation;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Media;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Microsoft::UI::Xaml::Controls;
namespace winrt
{
namespace MUX = Microsoft::UI::Xaml;
namespace WUX = Windows::UI::Xaml;
}
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
static constexpr std::wstring_view HideIconValue{ L"none" };
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> IconPicker::_BuiltInIcons{ nullptr };
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> IconPicker::_IconTypes{ nullptr };
DependencyProperty IconPicker::_CurrentIconPathProperty{ nullptr };
DependencyProperty IconPicker::_WindowRootProperty{ nullptr };
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> IconPicker::BuiltInIcons() noexcept
{
if (!_BuiltInIcons)
{
// lazy load the built-in icons
std::vector<Editor::EnumEntry> builtInIcons;
for (auto& [val, name] : s_SegoeFluentIcons)
{
builtInIcons.emplace_back(make<EnumEntry>(hstring{ name }, box_value(val)));
}
_BuiltInIcons = single_threaded_observable_vector<Editor::EnumEntry>(std::move(builtInIcons));
}
return _BuiltInIcons;
}
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> IconPicker::IconTypes() noexcept
{
if (!_IconTypes)
{
// lazy load the icon types
std::vector<Editor::EnumEntry> iconTypes;
iconTypes.reserve(4);
iconTypes.emplace_back(make<EnumEntry>(RS_(L"IconPicker_IconTypeNone"), box_value(IconType::None)));
iconTypes.emplace_back(make<EnumEntry>(RS_(L"IconPicker_IconTypeFontIcon"), box_value(IconType::FontIcon)));
iconTypes.emplace_back(make<EnumEntry>(RS_(L"IconPicker_IconTypeEmoji"), box_value(IconType::Emoji)));
iconTypes.emplace_back(make<EnumEntry>(RS_(L"IconPicker_IconTypeImage"), box_value(IconType::Image)));
_IconTypes = winrt::single_threaded_observable_vector<Editor::EnumEntry>(std::move(iconTypes));
}
return _IconTypes;
}
IconPicker::IconPicker()
{
_InitializeProperties();
InitializeComponent();
_DeduceCurrentIconType();
PropertyChanged([this](auto&&, const PropertyChangedEventArgs& args) {
const auto propertyName{ args.PropertyName() };
// "CurrentIconPath" changes are handled by _OnCurrentIconPathChanged()
if (propertyName == L"CurrentIconType")
{
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"UsingNoIcon" });
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"UsingBuiltInIcon" });
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"UsingEmojiIcon" });
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"UsingImageIcon" });
}
else if (propertyName == L"CurrentBuiltInIcon")
{
CurrentIconPath(unbox_value<hstring>(_CurrentBuiltInIcon.EnumValue()));
}
else if (propertyName == L"CurrentEmojiIcon")
{
CurrentIconPath(CurrentEmojiIcon());
}
});
}
void IconPicker::_InitializeProperties()
{
// Initialize any dependency properties here.
// This performs a lazy load on these properties, instead of
// initializing them when the DLL loads.
if (!_CurrentIconPathProperty)
{
_CurrentIconPathProperty =
DependencyProperty::Register(
L"CurrentIconPath",
xaml_typename<hstring>(),
xaml_typename<Editor::IconPicker>(),
PropertyMetadata{ nullptr, PropertyChangedCallback{ &IconPicker::_OnCurrentIconPathChanged } });
}
if (!_WindowRootProperty)
{
_WindowRootProperty =
DependencyProperty::Register(
L"WindowRoot",
xaml_typename<IHostedInWindow>(),
xaml_typename<Editor::IconPicker>(),
PropertyMetadata{ nullptr });
}
}
void IconPicker::_OnCurrentIconPathChanged(const DependencyObject& d, const DependencyPropertyChangedEventArgs& /*e*/)
{
d.as<IconPicker>()->_DeduceCurrentIconType();
}
safe_void_coroutine IconPicker::Icon_Click(const IInspectable&, const RoutedEventArgs&)
{
auto lifetime = get_strong();
const auto parentHwnd{ reinterpret_cast<HWND>(WindowRoot().GetHostingWindow()) };
auto file = co_await OpenImagePicker(parentHwnd);
if (!file.empty())
{
CurrentIconPath(file);
}
}
void IconPicker::BuiltInIconPicker_GotFocus(const IInspectable& sender, const RoutedEventArgs& /*e*/)
{
_updateIconFilter({});
sender.as<AutoSuggestBox>().IsSuggestionListOpen(true);
}
void IconPicker::BuiltInIconPicker_QuerySubmitted(const AutoSuggestBox& /*sender*/, const AutoSuggestBoxQuerySubmittedEventArgs& e)
{
const auto iconEntry = unbox_value_or<Editor::EnumEntry>(e.ChosenSuggestion(), nullptr);
if (!iconEntry)
{
return;
}
CurrentBuiltInIcon(iconEntry);
}
void IconPicker::BuiltInIconPicker_TextChanged(const AutoSuggestBox& sender, const AutoSuggestBoxTextChangedEventArgs& e)
{
if (e.Reason() != AutoSuggestionBoxTextChangeReason::UserInput)
{
return;
}
std::wstring_view filter{ sender.Text() };
filter = til::trim(filter, L' ');
_updateIconFilter(filter);
}
void IconPicker::_updateIconFilter(std::wstring_view filter)
{
if (_iconFilter != filter)
{
_filteredBuiltInIcons = nullptr;
_iconFilter = filter;
_updateFilteredIconList();
PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"FilteredBuiltInIconList" });
}
}
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> IconPicker::FilteredBuiltInIconList()
{
if (!_filteredBuiltInIcons)
{
_updateFilteredIconList();
}
return _filteredBuiltInIcons;
}
void IconPicker::_updateFilteredIconList()
{
_filteredBuiltInIcons = BuiltInIcons();
if (_iconFilter.empty())
{
return;
}
// Find matching icons and populate the filtered list
std::vector<Editor::EnumEntry> filtered;
filtered.reserve(_filteredBuiltInIcons.Size());
for (const auto& icon : _filteredBuiltInIcons)
{
if (til::contains_linguistic_insensitive(icon.EnumName(), _iconFilter))
{
filtered.emplace_back(icon);
}
}
_filteredBuiltInIcons = winrt::single_threaded_observable_vector(std::move(filtered));
}
void IconPicker::CurrentIconType(const Windows::Foundation::IInspectable& value)
{
if (_currentIconType != value)
{
// Switching from...
if (_currentIconType && unbox_value<IconType>(_currentIconType.as<Editor::EnumEntry>().EnumValue()) == IconType::Image)
{
// Stash the current value of Icon. If the user
// switches out of then back to IconType::Image, we want
// the path that we display in the text box to remain unchanged.
_lastIconPath = CurrentIconPath();
}
// Set the member here instead of after setting Icon() below!
// We have an Icon property changed handler defined for when we discard changes.
// Inadvertently, that means that we call this setter again.
// Setting the member here means that we early exit at the beginning of the function
// because _currentIconType == value.
_currentIconType = value;
// Switched to...
switch (unbox_value<IconType>(value.as<Editor::EnumEntry>().EnumValue()))
{
case IconType::None:
{
CurrentIconPath(winrt::hstring{ HideIconValue });
break;
}
case IconType::Image:
{
if (!_lastIconPath.empty())
{
// Conversely, if we switch to Image,
// retrieve that saved value and apply it
CurrentIconPath(_lastIconPath);
}
break;
}
case IconType::FontIcon:
{
if (_CurrentBuiltInIcon)
{
CurrentIconPath(unbox_value<hstring>(_CurrentBuiltInIcon.EnumValue()));
}
break;
}
case IconType::Emoji:
{
// Don't set Icon here!
// Clear out the text box so we direct the user to use the emoji picker.
CurrentEmojiIcon({});
}
}
// We're not using the VM's Icon() setter above,
// so notify HasIcon changed manually
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"CurrentIconType" });
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"HasIcon" });
}
}
bool IconPicker::UsingNoIcon() const
{
return _currentIconType == IconTypes().GetAt(0);
}
bool IconPicker::UsingBuiltInIcon() const
{
return _currentIconType == IconTypes().GetAt(1);
}
bool IconPicker::UsingEmojiIcon() const
{
return _currentIconType == IconTypes().GetAt(2);
}
bool IconPicker::UsingImageIcon() const
{
return _currentIconType == IconTypes().GetAt(3);
}
void IconPicker::_DeduceCurrentIconType()
{
const auto icon = CurrentIconPath();
if (icon.empty() || icon == HideIconValue)
{
_currentIconType = IconTypes().GetAt(0);
}
else if (icon.size() == 1 && (L'\uE700' <= til::at(icon, 0) && til::at(icon, 0) <= L'\uF8B3'))
{
_currentIconType = IconTypes().GetAt(1);
_DeduceCurrentBuiltInIcon();
}
else if (::Microsoft::Console::Utils::IsLikelyToBeEmojiOrSymbolIcon(icon))
{
// We already did a range check for MDL2 Assets in the previous one,
// so if we're out of that range but still short, assume we're an emoji
_currentIconType = IconTypes().GetAt(2);
}
else
{
_currentIconType = IconTypes().GetAt(3);
}
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"CurrentIconType" });
}
void IconPicker::_DeduceCurrentBuiltInIcon()
{
const auto icon = CurrentIconPath();
for (uint32_t i = 0; i < BuiltInIcons().Size(); i++)
{
const auto& builtIn = BuiltInIcons().GetAt(i);
if (icon == unbox_value<hstring>(builtIn.EnumValue()))
{
CurrentBuiltInIcon(builtIn);
return;
}
}
CurrentBuiltInIcon(BuiltInIcons().GetAt(0));
}
WUX::Controls::IconSource IconPicker::BuiltInIconConverter(const IInspectable& iconVal)
{
return Microsoft::Terminal::UI::IconPathConverter::IconSourceWUX(unbox_value<hstring>(iconVal));
}
}

View File

@@ -0,0 +1,64 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "IconPicker.g.h"
#include "EnumEntry.h"
#include "Utils.h"
#include "cppwinrt_utils.h"
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
struct IconPicker : public HasScrollViewer<IconPicker>, IconPickerT<IconPicker>
{
public:
IconPicker();
static Windows::UI::Xaml::Controls::IconSource BuiltInIconConverter(const Windows::Foundation::IInspectable& iconVal);
static Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> BuiltInIcons() noexcept;
static Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> IconTypes() noexcept;
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> FilteredBuiltInIconList();
safe_void_coroutine Icon_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void BuiltInIconPicker_GotFocus(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void BuiltInIconPicker_TextChanged(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const Windows::UI::Xaml::Controls::AutoSuggestBoxTextChangedEventArgs& e);
void BuiltInIconPicker_QuerySubmitted(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const Windows::UI::Xaml::Controls::AutoSuggestBoxQuerySubmittedEventArgs& e);
Windows::Foundation::IInspectable CurrentIconType() const noexcept { return _currentIconType; }
void CurrentIconType(const Windows::Foundation::IInspectable& value);
bool UsingNoIcon() const;
bool UsingBuiltInIcon() const;
bool UsingEmojiIcon() const;
bool UsingImageIcon() const;
til::property_changed_event PropertyChanged;
WINRT_OBSERVABLE_PROPERTY(hstring, CurrentEmojiIcon, PropertyChanged.raise);
WINRT_OBSERVABLE_PROPERTY(Editor::EnumEntry, CurrentBuiltInIcon, PropertyChanged.raise, nullptr);
DEPENDENCY_PROPERTY(hstring, CurrentIconPath);
DEPENDENCY_PROPERTY(IHostedInWindow, WindowRoot);
private:
static Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> _BuiltInIcons;
static Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> _IconTypes;
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> _filteredBuiltInIcons;
std::wstring _iconFilter;
Windows::Foundation::IInspectable _currentIconType{};
winrt::hstring _lastIconPath;
static void _InitializeProperties();
static void _OnCurrentIconPathChanged(const Windows::UI::Xaml::DependencyObject& d, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e);
void _DeduceCurrentIconType();
void _DeduceCurrentBuiltInIcon();
void _updateIconFilter(std::wstring_view filter);
void _updateFilteredIconList();
};
}
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
{
BASIC_FACTORY(IconPicker);
}

View File

@@ -0,0 +1,42 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import "EnumEntry.idl";
import "MainPage.idl";
namespace Microsoft.Terminal.Settings.Editor
{
enum IconType
{
None = 0,
FontIcon,
Image,
Emoji
};
[default_interface] runtimeclass IconPicker : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged
{
IconPicker();
IInspectable CurrentIconType;
Windows.Foundation.Collections.IObservableVector<EnumEntry> IconTypes { get; };
Boolean UsingBuiltInIcon { get; };
Boolean UsingEmojiIcon { get; };
Boolean UsingImageIcon { get; };
String CurrentEmojiIcon;
EnumEntry CurrentBuiltInIcon;
Windows.Foundation.Collections.IObservableVector<EnumEntry> BuiltInIcons { get; };
Windows.Foundation.Collections.IObservableVector<EnumEntry> FilteredBuiltInIconList { get; };
static Windows.UI.Xaml.Controls.IconSource BuiltInIconConverter(IInspectable iconVal);
String CurrentIconPath;
static Windows.UI.Xaml.DependencyProperty CurrentIconPathProperty { get; };
IHostedInWindow WindowRoot;
static Windows.UI.Xaml.DependencyProperty WindowRootProperty { get; };
}
}

View File

@@ -0,0 +1,100 @@
<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<UserControl x:Class="Microsoft.Terminal.Settings.Editor.IconPicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="using:Microsoft.Terminal.Settings.Model"
xmlns:mtu="using:Microsoft.Terminal.UI"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="CommonResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<!-- Icon Type -->
<ComboBox x:Uid="IconPicker_IconType"
Grid.Column="0"
ItemsSource="{x:Bind IconTypes}"
SelectedItem="{x:Bind CurrentIconType, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="local:EnumEntry">
<TextBlock Text="{x:Bind EnumName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- Built-In Icon -->
<AutoSuggestBox x:Uid="IconPicker_BuiltInIcon"
Grid.Column="1"
GotFocus="BuiltInIconPicker_GotFocus"
ItemsSource="{x:Bind FilteredBuiltInIconList, Mode=OneWay}"
QuerySubmitted="BuiltInIconPicker_QuerySubmitted"
Text="{x:Bind CurrentBuiltInIcon.EnumName, Mode=OneWay}"
TextBoxStyle="{StaticResource TextBoxSettingStyle}"
TextChanged="BuiltInIconPicker_TextChanged"
Visibility="{x:Bind UsingBuiltInIcon, Mode=OneWay}">
<AutoSuggestBox.ItemTemplate>
<DataTemplate x:DataType="local:EnumEntry">
<Grid ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<IconSourceElement Grid.Column="0"
Width="16"
Height="16"
IconSource="{x:Bind local:IconPicker.BuiltInIconConverter(EnumValue), Mode=OneTime}" />
<TextBlock Grid.Column="1"
Text="{x:Bind EnumName}" />
</Grid>
</DataTemplate>
</AutoSuggestBox.ItemTemplate>
</AutoSuggestBox>
<!-- Image (File) Icon -->
<TextBox x:Uid="IconPicker_ImagePathBox"
Grid.Column="1"
MaxWidth="Infinity"
HorizontalAlignment="Stretch"
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
IsSpellCheckEnabled="False"
Style="{StaticResource TextBoxSettingStyle}"
Text="{x:Bind CurrentIconPath, Mode=TwoWay}"
Visibility="{x:Bind UsingImageIcon, Mode=OneWay}" />
<Button x:Uid="IconPicker_IconBrowse"
Grid.Column="2"
Margin="0"
VerticalAlignment="Top"
Click="Icon_Click"
Style="{StaticResource BrowseButtonStyle}"
Visibility="{x:Bind UsingImageIcon, Mode=OneWay}" />
<!-- Emoji Icon -->
<TextBox x:Uid="IconPicker_EmojiBox"
Grid.Column="1"
MaxWidth="Infinity"
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
IsSpellCheckEnabled="False"
Style="{StaticResource TextBoxSettingStyle}"
Text="{x:Bind CurrentEmojiIcon, Mode=TwoWay}"
Visibility="{x:Bind UsingEmojiIcon, Mode=OneWay}" />
</Grid>
</UserControl>

View File

@@ -4,6 +4,7 @@
#include "pch.h"
#include "Interaction.h"
#include "Interaction.g.cpp"
#include "NavigateToPageArgs.g.h"
#include "EnumEntry.h"
@@ -21,7 +22,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Interaction::OnNavigatedTo(const NavigationEventArgs& e)
{
_ViewModel = e.Parameter().as<Editor::InteractionViewModel>();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_ViewModel = args.ViewModel().as<Editor::InteractionViewModel>();
BringIntoViewWhenLoaded(args.ElementToFocus());
TraceLoggingWrite(
g_hTerminalSettingsEditorProvider,

View File

@@ -27,13 +27,15 @@
<StackPanel>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Copy On Select -->
<local:SettingContainer x:Uid="Globals_CopyOnSelect">
<local:SettingContainer x:Name="CopyOnSelect"
x:Uid="Globals_CopyOnSelect">
<ToggleSwitch IsOn="{x:Bind ViewModel.CopyOnSelect, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Copy Format -->
<local:SettingContainer x:Uid="Globals_CopyFormat">
<local:SettingContainer x:Name="CopyFormat"
x:Uid="Globals_CopyFormat">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.CopyFormatList, Mode=OneWay}"
@@ -42,19 +44,22 @@
</local:SettingContainer>
<!-- Trim Block Selection -->
<local:SettingContainer x:Uid="Globals_TrimBlockSelection">
<local:SettingContainer x:Name="TrimBlockSelection"
x:Uid="Globals_TrimBlockSelection">
<ToggleSwitch IsOn="{x:Bind ViewModel.TrimBlockSelection, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Trim Paste -->
<local:SettingContainer x:Uid="Globals_TrimPaste">
<local:SettingContainer x:Name="TrimPaste"
x:Uid="Globals_TrimPaste">
<ToggleSwitch IsOn="{x:Bind ViewModel.TrimPaste, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Word Delimiters -->
<local:SettingContainer x:Uid="Globals_WordDelimiters"
<local:SettingContainer x:Name="WordDelimiters"
x:Uid="Globals_WordDelimiters"
CurrentValue="{x:Bind ViewModel.WordDelimiters, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyle}">
<TextBox IsSpellCheckEnabled="False"
@@ -63,13 +68,15 @@
</local:SettingContainer>
<!-- Snap On Resize -->
<local:SettingContainer x:Uid="Globals_SnapToGridOnResize">
<local:SettingContainer x:Name="SnapToGridOnResize"
x:Uid="Globals_SnapToGridOnResize">
<ToggleSwitch IsOn="{x:Bind ViewModel.SnapToGridOnResize, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Tab Switcher Mode -->
<local:SettingContainer x:Uid="Globals_TabSwitcherMode">
<local:SettingContainer x:Name="TabSwitcherMode"
x:Uid="Globals_TabSwitcherMode">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.TabSwitcherModeList}"
@@ -78,31 +85,36 @@
</local:SettingContainer>
<!-- Focus Follow Mouse Mode -->
<local:SettingContainer x:Uid="Globals_FocusFollowMouse">
<local:SettingContainer x:Name="FocusFollowMouse"
x:Uid="Globals_FocusFollowMouse">
<ToggleSwitch IsOn="{x:Bind ViewModel.FocusFollowMouse, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Enable Font Size Changes with Scrolling -->
<local:SettingContainer x:Uid="Globals_ScrollToZoom">
<local:SettingContainer x:Name="ScrollToZoom"
x:Uid="Globals_ScrollToZoom">
<ToggleSwitch IsOn="{x:Bind ViewModel.ScrollToZoom, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Enable Window Opacity Changes with Scrolling -->
<local:SettingContainer x:Uid="Globals_ScrollToChangeOpacity">
<local:SettingContainer x:Name="ScrollToChangeOpacity"
x:Uid="Globals_ScrollToChangeOpacity">
<ToggleSwitch IsOn="{x:Bind ViewModel.ScrollToChangeOpacity, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Detect URLs -->
<local:SettingContainer x:Uid="Globals_DetectURLs">
<local:SettingContainer x:Name="DetectURLs"
x:Uid="Globals_DetectURLs">
<ToggleSwitch IsOn="{x:Bind ViewModel.DetectURLs, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Search Web Default Query URL -->
<local:SettingContainer x:Uid="Globals_SearchWebDefaultQueryUrl"
<local:SettingContainer x:Name="SearchWebDefaultQueryUrl"
x:Uid="Globals_SearchWebDefaultQueryUrl"
CurrentValue="{x:Bind ViewModel.SearchWebDefaultQueryUrl, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyle}">
<TextBox IsSpellCheckEnabled="False"
@@ -111,7 +123,8 @@
</local:SettingContainer>
<!-- Enable Color Selection -->
<local:SettingContainer x:Uid="Globals_EnableColorSelection">
<local:SettingContainer x:Name="EnableColorSelection"
x:Uid="Globals_EnableColorSelection">
<ToggleSwitch IsOn="{x:Bind ViewModel.EnableColorSelection, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
@@ -123,25 +136,29 @@
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Close All Tabs Warning -->
<local:SettingContainer x:Uid="Globals_ConfirmCloseAllTabs">
<local:SettingContainer x:Name="ConfirmCloseAllTabs"
x:Uid="Globals_ConfirmCloseAllTabs">
<ToggleSwitch IsOn="{x:Bind ViewModel.ConfirmCloseAllTabs, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Input Service Warning -->
<local:SettingContainer x:Uid="Globals_InputServiceWarning">
<local:SettingContainer x:Name="InputServiceWarning"
x:Uid="Globals_InputServiceWarning">
<ToggleSwitch IsOn="{x:Bind ViewModel.InputServiceWarning, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Large Paste Warning -->
<local:SettingContainer x:Uid="Globals_WarnAboutLargePaste">
<local:SettingContainer x:Name="WarnAboutLargePaste"
x:Uid="Globals_WarnAboutLargePaste">
<ToggleSwitch IsOn="{x:Bind ViewModel.WarnAboutLargePaste, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Multi Line Paste Warning -->
<local:SettingContainer x:Uid="Globals_WarnAboutMultiLinePaste">
<local:SettingContainer x:Name="WarnAboutMultiLinePaste"
x:Uid="Globals_WarnAboutMultiLinePaste">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind WarnAboutMultiLinePasteList}"

View File

@@ -38,7 +38,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Launch::OnNavigatedTo(const NavigationEventArgs& e)
{
_ViewModel = e.Parameter().as<Editor::LaunchViewModel>();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_ViewModel = args.ViewModel().as<Editor::LaunchViewModel>();
BringIntoViewWhenLoaded(args.ElementToFocus());
auto innerViewModel{ winrt::get_self<Editor::implementation::LaunchViewModel>(_ViewModel) };
/* coroutine dispatch */ innerViewModel->PrepareStartOnUserLoginSettings();

View File

@@ -44,9 +44,9 @@
<StackPanel>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Default Profile -->
<local:SettingContainer x:Uid="Globals_DefaultProfile">
<ComboBox x:Name="DefaultProfile"
ItemsSource="{x:Bind ViewModel.DefaultProfiles}"
<local:SettingContainer x:Name="DefaultProfile"
x:Uid="Globals_DefaultProfile">
<ComboBox ItemsSource="{x:Bind ViewModel.DefaultProfiles}"
SelectedItem="{x:Bind ViewModel.CurrentDefaultProfile, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}">
<ComboBox.ItemTemplate>
@@ -141,7 +141,8 @@
</local:SettingContainer>
<!-- Language -->
<local:SettingContainer x:Uid="Globals_Language">
<local:SettingContainer x:Name="Language"
x:Uid="Globals_Language">
<ComboBox ItemsSource="{x:Bind ViewModel.LanguageList}"
SelectedItem="{x:Bind ViewModel.CurrentLanguage, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}">
@@ -154,7 +155,8 @@
</local:SettingContainer>
<!-- Language -->
<local:SettingContainer x:Uid="Globals_DefaultInputScope">
<local:SettingContainer x:Name="DefaultInputScope"
x:Uid="Globals_DefaultInputScope">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.DefaultInputScopeList}"
@@ -163,7 +165,8 @@
</local:SettingContainer>
<!-- Start on User Login -->
<local:SettingContainer x:Uid="Globals_StartOnUserLogin"
<local:SettingContainer x:Name="StartOnUserLogin"
x:Uid="Globals_StartOnUserLogin"
HelpText="{x:Bind ViewModel.StartOnUserLoginStatefulHelpText, Mode=OneWay}"
Visibility="{x:Bind ViewModel.StartOnUserLoginAvailable, Mode=OneTime}">
<ToggleSwitch IsEnabled="{x:Bind ViewModel.StartOnUserLoginConfigurable, Mode=OneWay}"
@@ -172,7 +175,8 @@
</local:SettingContainer>
<!-- First Window Behavior -->
<local:SettingContainer x:Uid="Globals_FirstWindowPreference">
<local:SettingContainer x:Name="FirstWindowPreference"
x:Uid="Globals_FirstWindowPreference">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.FirstWindowPreferenceList}"
@@ -181,7 +185,8 @@
</local:SettingContainer>
<!-- Windowing Behavior -->
<local:SettingContainer x:Uid="Globals_WindowingBehavior">
<local:SettingContainer x:Name="WindowingBehavior"
x:Uid="Globals_WindowingBehavior">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.WindowingBehaviorList}"
@@ -190,7 +195,8 @@
</local:SettingContainer>
<!-- Launch Size -->
<local:SettingContainer x:Uid="Globals_LaunchSize"
<local:SettingContainer x:Name="LaunchSize"
x:Uid="Globals_LaunchSize"
CurrentValue="{x:Bind ViewModel.LaunchSizeCurrentValue, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyle}">
<Grid ColumnSpacing="12"
@@ -233,7 +239,8 @@
</local:SettingContainer>
<!-- Launch Parameters -->
<local:SettingContainer x:Uid="Globals_LaunchParameters"
<local:SettingContainer x:Name="LaunchParameters"
x:Uid="Globals_LaunchParameters"
CurrentValue="{x:Bind ViewModel.LaunchParametersCurrentValue, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyle}">
<Grid RowSpacing="8">

File diff suppressed because it is too large Load Diff

View File

@@ -5,10 +5,19 @@
#include "MainPage.g.h"
#include "Breadcrumb.g.h"
#include "NavigateToPageArgs.g.h"
#include "FilteredSearchResult.g.h"
#include "SearchResultTemplateSelector.g.h"
#include "Utils.h"
#include "GeneratedSettingsIndex.g.h"
#include <til/generational.h>
class ScopedResourceLoader;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
const ScopedResourceLoader& EnglishOnlyResourceLoader() noexcept;
struct Breadcrumb : BreadcrumbT<Breadcrumb>
{
Breadcrumb(IInspectable tag, winrt::hstring label, BreadcrumbSubPage subPage) :
@@ -23,6 +32,68 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
WINRT_PROPERTY(BreadcrumbSubPage, SubPage);
};
struct NavigateToPageArgs : NavigateToPageArgsT<NavigateToPageArgs>
{
public:
NavigateToPageArgs(Windows::Foundation::IInspectable viewModel, Editor::IHostedInWindow windowRoot, const hstring& elementToFocus = {}) :
_ViewModel(viewModel),
_WeakWindowRoot(windowRoot),
_ElementToFocus(elementToFocus) {}
Editor::IHostedInWindow WindowRoot() const noexcept { return _WeakWindowRoot.get(); }
Windows::Foundation::IInspectable ViewModel() const noexcept { return _ViewModel; }
hstring ElementToFocus() const noexcept { return _ElementToFocus; }
private:
winrt::weak_ref<Editor::IHostedInWindow> _WeakWindowRoot;
Windows::Foundation::IInspectable _ViewModel{ nullptr };
hstring _ElementToFocus{};
};
struct LocalizedIndexEntry
{
std::optional<winrt::hstring> DisplayTextNeutral = std::nullopt;
std::optional<winrt::hstring> HelpTextNeutral = std::nullopt;
const IndexEntry* Entry = nullptr;
};
struct FilteredSearchResult : FilteredSearchResultT<FilteredSearchResult>
{
FilteredSearchResult(const LocalizedIndexEntry* entry, const Windows::Foundation::IInspectable& navigationArgOverride = nullptr, const std::optional<hstring>& label = std::nullopt, const hstring secondaryLabel = {}) :
_SearchIndexEntry{ entry },
_NavigationArgOverride{ navigationArgOverride },
_overrideLabel{ label },
_secondaryLabel{ secondaryLabel } {}
static Editor::FilteredSearchResult CreateNoResultsItem(const winrt::hstring& query);
static Editor::FilteredSearchResult CreateRuntimeObjectItem(const LocalizedIndexEntry* searchIndexEntry, const Windows::Foundation::IInspectable& runtimeObj);
hstring ToString() { return Label(); }
winrt::hstring Label() const;
winrt::hstring SecondaryLabel() const { return _secondaryLabel; };
bool IsNoResultsPlaceholder() const;
const LocalizedIndexEntry& SearchIndexEntry() const noexcept { return *_SearchIndexEntry; }
Windows::Foundation::IInspectable NavigationArg() const;
Windows::UI::Xaml::Controls::IconElement Icon() const;
private:
const std::optional<winrt::hstring> _overrideLabel{ std::nullopt };
const winrt::hstring _secondaryLabel{};
const Windows::Foundation::IInspectable _NavigationArgOverride{ nullptr };
const LocalizedIndexEntry* _SearchIndexEntry{ nullptr };
};
struct SearchResultTemplateSelector : SearchResultTemplateSelectorT<SearchResultTemplateSelector>
{
SearchResultTemplateSelector() = default;
Windows::UI::Xaml::DataTemplate SelectTemplateCore(const Windows::Foundation::IInspectable& item, const Windows::UI::Xaml::DependencyObject& container);
Windows::UI::Xaml::DataTemplate SelectTemplateCore(const Windows::Foundation::IInspectable& item);
til::property<winrt::Windows::UI::Xaml::DataTemplate> BasicTemplate;
til::property<winrt::Windows::UI::Xaml::DataTemplate> ComplexTemplate;
};
struct MainPage : MainPageT<MainPage>
{
MainPage() = delete;
@@ -30,6 +101,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void UpdateSettings(const Model::CascadiaSettings& settings);
safe_void_coroutine SettingsSearchBox_TextChanged(const Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const Windows::UI::Xaml::Controls::AutoSuggestBoxTextChangedEventArgs& args);
void SettingsSearchBox_QuerySubmitted(const Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const Windows::UI::Xaml::Controls::AutoSuggestBoxQuerySubmittedEventArgs& args);
void SettingsSearchBox_SuggestionChosen(const Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const Windows::UI::Xaml::Controls::AutoSuggestBoxSuggestionChosenEventArgs& args);
void SettingsNav_Loaded(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args);
void SettingsNav_ItemInvoked(const Microsoft::UI::Xaml::Controls::NavigationView& sender, const Microsoft::UI::Xaml::Controls::NavigationViewItemInvokedEventArgs& args);
void SaveButton_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args);
@@ -68,21 +143,55 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void _SetupProfileEventHandling(const winrt::Microsoft::Terminal::Settings::Editor::ProfileViewModel profile);
void _PreNavigateHelper();
void _Navigate(hstring clickedItemTag, BreadcrumbSubPage subPage);
void _Navigate(const Editor::ProfileViewModel& profile, BreadcrumbSubPage subPage);
void _Navigate(const Editor::NewTabMenuEntryViewModel& ntmEntryVM, BreadcrumbSubPage subPage);
void _Navigate(const Editor::ExtensionPackageViewModel& extPkgVM, BreadcrumbSubPage subPage);
void _Navigate(hstring clickedItemTag, BreadcrumbSubPage subPage, hstring elementToFocus = {});
void _Navigate(const Editor::ProfileViewModel& profile, BreadcrumbSubPage subPage, hstring elementToFocus = {});
void _Navigate(const Editor::ColorSchemeViewModel& colorSchemeVM, BreadcrumbSubPage subPage, hstring elementToFocus = {});
void _Navigate(const Editor::NewTabMenuEntryViewModel& ntmEntryVM, BreadcrumbSubPage subPage, hstring elementToFocus = {});
void _Navigate(const Editor::ExtensionPackageViewModel& extPkgVM, BreadcrumbSubPage subPage, hstring elementToFocus = {});
void _NavigateToProfileHandler(const IInspectable& sender, winrt::guid profileGuid);
void _NavigateToColorSchemeHandler(const IInspectable& sender, const IInspectable& args);
Microsoft::UI::Xaml::Controls::NavigationViewItem _FindProfileNavItem(winrt::guid profileGuid) const;
void _UpdateBackgroundForMica();
void _MoveXamlParsedNavItemsIntoItemSource();
til::generation_t _QuerySearchIndex(const hstring& queryText);
safe_void_coroutine _UpdateSearchIndex();
winrt::Microsoft::Terminal::Settings::Editor::ProfileViewModel _profileDefaultsVM{ nullptr };
Windows::Foundation::Collections::IVector<winrt::Microsoft::Terminal::Settings::Editor::ProfileViewModel> _profileVMs{ nullptr };
winrt::Microsoft::Terminal::Settings::Editor::ColorSchemesPageViewModel _colorSchemesPageVM{ nullptr };
winrt::Microsoft::Terminal::Settings::Editor::ActionsViewModel _actionsVM{ nullptr };
winrt::Microsoft::Terminal::Settings::Editor::NewTabMenuViewModel _newTabMenuPageVM{ nullptr };
winrt::Microsoft::Terminal::Settings::Editor::ExtensionsViewModel _extensionsVM{ nullptr };
struct SearchIndex
{
SearchIndex& operator=(const SearchIndex& other) = default;
std::vector<LocalizedIndexEntry> mainIndex;
std::vector<LocalizedIndexEntry> profileIndex;
std::vector<LocalizedIndexEntry> ntmFolderIndex;
std::vector<LocalizedIndexEntry> colorSchemeIndex;
// Links to main page; used when searching runtime objects (i.e. profile/extension name --> Profile_Base/Extension View)
LocalizedIndexEntry profileIndexEntry;
LocalizedIndexEntry ntmFolderIndexEntry;
LocalizedIndexEntry colorSchemeIndexEntry;
LocalizedIndexEntry extensionIndexEntry;
};
til::generational<SearchIndex> _searchIndex;
struct FilteredSearchIndex
{
std::vector<const LocalizedIndexEntry*> mainIndex;
std::vector<const LocalizedIndexEntry*> profileIndex;
std::vector<const LocalizedIndexEntry*> ntmFolderIndex;
std::vector<const LocalizedIndexEntry*> colorSchemeIndex;
};
til::generational<FilteredSearchIndex> _filteredSearchIndex;
std::atomic<uint32_t> _latestSearchId{ 0 };
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _profileViewModelChangedRevoker;
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _colorSchemesPageViewModelChangedRevoker;
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _actionsViewModelChangedRevoker;
@@ -94,4 +203,5 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
{
BASIC_FACTORY(MainPage);
BASIC_FACTORY(SearchResultTemplateSelector);
}

View File

@@ -16,6 +16,13 @@ namespace Microsoft.Terminal.Settings.Editor
UInt64 GetHostingWindow();
}
runtimeclass NavigateToPageArgs
{
IHostedInWindow WindowRoot { get; };
IInspectable ViewModel { get; };
String ElementToFocus { get; };
}
enum BreadcrumbSubPage
{
None = 0,
@@ -28,6 +35,21 @@ namespace Microsoft.Terminal.Settings.Editor
Extensions_Extension
};
runtimeclass FilteredSearchResult : Windows.Foundation.IStringable
{
String Label { get; };
String SecondaryLabel { get; };
Windows.UI.Xaml.Controls.IconElement Icon { get; };
}
[default_interface] runtimeclass SearchResultTemplateSelector : Windows.UI.Xaml.Controls.DataTemplateSelector
{
SearchResultTemplateSelector();
Windows.UI.Xaml.DataTemplate BasicTemplate;
Windows.UI.Xaml.DataTemplate ComplexTemplate;
}
runtimeclass Breadcrumb : Windows.Foundation.IStringable
{
IInspectable Tag;

View File

@@ -52,6 +52,75 @@
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:Key="BasicSearchResultTemplate"
x:DataType="local:FilteredSearchResult">
<Grid HorizontalAlignment="Stretch"
ColumnSpacing="8"
ToolTipService.ToolTip="{x:Bind Label}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{x:Bind Icon}" />
<TextBlock Grid.Column="1"
Text="{x:Bind Label}"
TextTrimming="CharacterEllipsis" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="ComplexSearchResultTemplate"
x:DataType="local:FilteredSearchResult">
<Grid HorizontalAlignment="Stretch"
ColumnSpacing="8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ContentPresenter Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{x:Bind Icon}" />
<TextBlock Grid.Row="0"
Grid.Column="1"
FontSize="{ThemeResource BodyTextBlockFontSize}"
Foreground="{ThemeResource TextFillColorPrimary}"
Text="{x:Bind Label}"
TextTrimming="CharacterEllipsis" />
<TextBlock Grid.Row="1"
Grid.Column="1"
FontSize="{ThemeResource CaptionTextBlockFontSize}"
Foreground="{ThemeResource TextFillColorSecondary}"
Text="{x:Bind SecondaryLabel}"
TextTrimming="CharacterEllipsis" />
<ToolTipService.ToolTip>
<StackPanel>
<TextBlock FontSize="{ThemeResource CaptionTextBlockFontSize}"
Foreground="{ThemeResource TextFillColorPrimary}"
Text="{x:Bind Label}" />
<TextBlock FontSize="{ThemeResource CaptionTextBlockFontSize}"
Foreground="{ThemeResource TextFillColorSecondary}"
Text="{x:Bind SecondaryLabel}" />
</StackPanel>
</ToolTipService.ToolTip>
</Grid>
</DataTemplate>
<local:SearchResultTemplateSelector x:Key="SearchResultTemplateSelector"
BasicTemplate="{StaticResource BasicSearchResultTemplate}"
ComplexTemplate="{StaticResource ComplexSearchResultTemplate}" />
<SolidColorBrush x:Key="NavigationViewExpandedPaneBackground"
Color="Transparent" />
<SolidColorBrush x:Key="NavigationViewContentBackground"
@@ -99,62 +168,45 @@
</Grid>
</muxc:NavigationView.Header>
<muxc:NavigationView.MenuItems>
<muxc:NavigationView.AutoSuggestBox>
<AutoSuggestBox x:Name="SettingsSearchBox"
x:Uid="Nav_SearchBox"
ItemTemplateSelector="{StaticResource SearchResultTemplateSelector}"
QueryIcon="Find"
QuerySubmitted="SettingsSearchBox_QuerySubmitted"
SuggestionChosen="SettingsSearchBox_SuggestionChosen"
TextChanged="SettingsSearchBox_TextChanged" />
</muxc:NavigationView.AutoSuggestBox>
<muxc:NavigationView.MenuItems>
<muxc:NavigationViewItem x:Name="LaunchNavItem"
x:Uid="Nav_Launch"
Tag="Launch_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xE7B5;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
Tag="Launch_Nav" />
<muxc:NavigationViewItem x:Name="InteractionNavItem"
x:Uid="Nav_Interaction"
Tag="Interaction_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xE7C9;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
Tag="Interaction_Nav" />
<muxc:NavigationViewItem x:Name="AppearanceNavItem"
x:Uid="Nav_Appearance"
Tag="GlobalAppearance_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xE771;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
Tag="GlobalAppearance_Nav" />
<muxc:NavigationViewItem x:Name="ColorSchemesNavItem"
x:Uid="Nav_ColorSchemes"
Tag="ColorSchemes_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xE790;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
Tag="ColorSchemes_Nav" />
<muxc:NavigationViewItem x:Name="RenderingNavItem"
x:Uid="Nav_Rendering"
Tag="Rendering_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xE7F8;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
Tag="Rendering_Nav" />
<muxc:NavigationViewItem x:Name="CompatibilityNavItem"
x:Uid="Nav_Compatibility"
Tag="Compatibility_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xEC7A;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
Tag="Compatibility_Nav" />
<muxc:NavigationViewItem x:Name="ActionsNavItem"
x:Uid="Nav_Actions"
Tag="Actions_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xE765;" />
</muxc:NavigationViewItem.Icon>
<muxc:NavigationViewItem.InfoBadge>
<muxc:InfoBadge Style="{StaticResource NewInfoBadge}"
Visibility="{x:Bind ActionsVM.DisplayBadge, Mode=OneWay}" />
@@ -163,42 +215,24 @@
<muxc:NavigationViewItem x:Name="NewTabMenuNavItem"
x:Uid="Nav_NewTabMenu"
Tag="NewTabMenu_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xE71d;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
Tag="NewTabMenu_Nav" />
<muxc:NavigationViewItem x:Name="ExtensionsNavItem"
x:Uid="Nav_Extensions"
Tag="Extensions_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xEA86;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
Tag="Extensions_Nav" />
<muxc:NavigationViewItemHeader x:Uid="Nav_Profiles" />
<muxc:NavigationViewItem x:Name="BaseLayerMenuItem"
x:Uid="Nav_ProfileDefaults"
Tag="GlobalProfile_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xE81E;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
Tag="GlobalProfile_Nav" />
</muxc:NavigationView.MenuItems>
<muxc:NavigationView.FooterMenuItems>
<!-- The OpenJson item needs both Tapped and KeyDown handler -->
<muxc:NavigationViewItem x:Name="OpenJsonNavItem"
x:Uid="Nav_OpenJSON"
SelectsOnInvoked="False"
Tag="OpenJson_Nav">
<muxc:NavigationViewItem.Icon>
<FontIcon Glyph="&#xE713;" />
</muxc:NavigationViewItem.Icon>
</muxc:NavigationViewItem>
Tag="OpenJson_Nav" />
</muxc:NavigationView.FooterMenuItems>
<Grid>

View File

@@ -69,6 +69,10 @@
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="IconPicker.h">
<DependentUpon>IconPicker.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="EditColorScheme.h">
<DependentUpon>EditColorScheme.xaml</DependentUpon>
<SubType>Code</SubType>
@@ -169,6 +173,7 @@
</ClInclude>
<ClInclude Include="Utils.h" />
<ClInclude Include="PreviewConnection.h" />
<ClInclude Include="$(GeneratedFilesDir)GeneratedSettingsIndex.g.h" />
</ItemGroup>
<!-- ========================= XAML files ======================== -->
<ItemGroup>
@@ -193,6 +198,9 @@
<Page Include="NullableColorPicker.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="IconPicker.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="EditColorScheme.xaml">
<SubType>Designer</SubType>
</Page>
@@ -269,6 +277,10 @@
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="IconPicker.cpp">
<DependentUpon>IconPicker.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="EditColorScheme.cpp">
<DependentUpon>EditColorScheme.xaml</DependentUpon>
<SubType>Code</SubType>
@@ -373,6 +385,7 @@
<ClCompile Include="PreviewConnection.cpp">
<DependentUpon>PreviewConnection.h</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)GeneratedSettingsIndex.g.cpp" />
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
@@ -397,6 +410,10 @@
<DependentUpon>NullableColorPicker.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="IconPicker.idl">
<DependentUpon>IconPicker.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="EditColorScheme.idl">
<DependentUpon>EditColorScheme.xaml</DependentUpon>
<SubType>Code</SubType>
@@ -541,4 +558,10 @@
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
<Target Name="GenerateSettingsIndex"
Inputs="@(Page);$(OpenConsoleDir)tools\GenerateSettingsIndex.ps1"
Outputs="$(GeneratedFilesDir)GeneratedSettingsIndex.g.h;$(GeneratedFilesDir)GeneratedSettingsIndex.g.cpp"
BeforeTargets="ClCompile">
<Exec Command="pwsh.exe -NoProfile -ExecutionPolicy Unrestricted &quot;$(OpenConsoleDir)tools\GenerateSettingsIndex.ps1&quot; -SourceDir &quot;$(MSBuildThisFileDirectory).&quot; -OutputDir &quot;$(MSBuildThisFileDirectory)$(GeneratedFilesDir).&quot;" />
</Target>
</Project>

View File

@@ -55,6 +55,7 @@
<Page Include="AddProfile.xaml" />
<Page Include="KeyChordListener.xaml" />
<Page Include="NullableColorPicker.xaml" />
<Page Include="IconPicker.xaml" />
<Page Include="NewTabMenu.xaml" />
</ItemGroup>
</Project>

View File

@@ -3,7 +3,9 @@
#include "pch.h"
#include "NewTabMenu.h"
#include "NavigateToPageArgs.g.h"
#include "NewTabMenu.g.cpp"
#include "NavigateToPageArgs.g.h"
#include "NewTabMenuEntryTemplateSelector.g.cpp"
#include "EnumEntry.h"
@@ -41,7 +43,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void NewTabMenu::OnNavigatedTo(const NavigationEventArgs& e)
{
_ViewModel = e.Parameter().as<Editor::NewTabMenuViewModel>();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_ViewModel = args.ViewModel().as<Editor::NewTabMenuViewModel>();
_windowRoot = args.WindowRoot();
BringIntoViewWhenLoaded(args.ElementToFocus());
TraceLoggingWrite(
g_hTerminalSettingsEditorProvider,

View File

@@ -38,11 +38,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void AddFolderNameTextBox_KeyDown(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::Input::KeyRoutedEventArgs& e);
void AddFolderNameTextBox_TextChanged(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::Controls::TextChangedEventArgs& e);
Editor::IHostedInWindow WindowRoot() const noexcept { return _windowRoot; }
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
WINRT_OBSERVABLE_PROPERTY(Editor::NewTabMenuViewModel, ViewModel, _PropertyChangedHandlers, nullptr);
private:
Editor::NewTabMenuEntryViewModel _draggedEntry{ nullptr };
Editor::IHostedInWindow _windowRoot;
void _ScrollToEntry(const Editor::NewTabMenuEntryViewModel& entry);
};

View File

@@ -9,6 +9,7 @@ namespace Microsoft.Terminal.Settings.Editor
{
NewTabMenu();
NewTabMenuViewModel ViewModel { get; };
IHostedInWindow WindowRoot { get; };
}
[default_interface] runtimeclass NewTabMenuEntryTemplateSelector : Windows.UI.Xaml.Controls.DataTemplateSelector

View File

@@ -319,29 +319,51 @@
Visibility="{x:Bind ViewModel.IsFolderView, Mode=OneWay}">
<TextBlock x:Uid="NewTabMenu_CurrentFolderTextBlock"
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- TODO GH #18281: Icon -->
<!-- Once PR #17965 merges, we can add that kind of control to set an icon -->
<!-- Name -->
<local:SettingContainer x:Uid="NewTabMenu_CurrentFolderName"
Grid.Row="0"
<local:SettingContainer x:Name="CurrentFolderName"
x:Uid="NewTabMenu_CurrentFolderName"
CurrentValue="{x:Bind ViewModel.CurrentFolderName, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyle}">
<TextBox Style="{StaticResource TextBoxSettingStyle}"
Text="{x:Bind ViewModel.CurrentFolderName, Mode=TwoWay}" />
</local:SettingContainer>
<!-- Icon -->
<local:SettingContainer x:Uid="NewTabMenu_CurrentFolderIcon"
CurrentValueAccessibleName="{x:Bind ViewModel.CurrentFolderLocalizedIcon, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyleWithComplexPreview}">
<local:SettingContainer.CurrentValue>
<Grid>
<ContentControl Width="16"
Height="16"
Content="{x:Bind ViewModel.CurrentFolderIconPreview, Mode=OneWay}"
IsTabStop="False"
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(ViewModel.CurrentFolderUsingNoIcon), Mode=OneWay}" />
<TextBlock Margin="0,0,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
Style="{StaticResource SettingsPageItemDescriptionStyle}"
Text="{x:Bind ViewModel.CurrentFolderLocalizedIcon, Mode=OneWay}"
Visibility="{x:Bind ViewModel.CurrentFolderUsingNoIcon, Mode=OneWay}" />
</Grid>
</local:SettingContainer.CurrentValue>
<local:SettingContainer.Content>
<local:IconPicker CurrentIconPath="{x:Bind ViewModel.CurrentFolderIconPath, Mode=TwoWay}"
WindowRoot="{x:Bind WindowRoot, Mode=OneWay}" />
</local:SettingContainer.Content>
</local:SettingContainer>
<!-- Inlining -->
<local:SettingContainer x:Uid="NewTabMenu_CurrentFolderInlining"
Grid.Row="1">
<local:SettingContainer x:Name="CurrentFolderInlining"
x:Uid="NewTabMenu_CurrentFolderInlining">
<ToggleSwitch IsOn="{x:Bind ViewModel.CurrentFolderInlining, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Allow Empty -->
<local:SettingContainer x:Uid="NewTabMenu_CurrentFolderAllowEmpty"
Grid.Row="2">
<local:SettingContainer x:Name="CurrentFolderAllowEmpty"
x:Uid="NewTabMenu_CurrentFolderAllowEmpty">
<ToggleSwitch IsOn="{x:Bind ViewModel.CurrentFolderAllowEmpty, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
@@ -353,7 +375,8 @@
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Add Profile -->
<local:SettingContainer x:Uid="NewTabMenu_AddProfile"
<local:SettingContainer x:Name="AddProfile"
x:Uid="NewTabMenu_AddProfile"
FontIconGlyph="&#xE756;"
Style="{StaticResource SettingContainerWithIcon}">
@@ -402,7 +425,8 @@
</local:SettingContainer>
<!-- Add Separator -->
<local:SettingContainer x:Uid="NewTabMenu_AddSeparator"
<local:SettingContainer x:Name="AddSeparator"
x:Uid="NewTabMenu_AddSeparator"
FontIconGlyph="&#xE76f;"
Style="{StaticResource SettingContainerWithIcon}">
<Button x:Name="AddSeparatorButton"
@@ -418,7 +442,8 @@
</local:SettingContainer>
<!-- Add Folder -->
<local:SettingContainer x:Uid="NewTabMenu_AddFolder"
<local:SettingContainer x:Name="AddFolder"
x:Uid="NewTabMenu_AddFolder"
FontIconGlyph="&#xF12B;"
Style="{StaticResource SettingContainerWithIcon}">
<StackPanel Orientation="Horizontal"
@@ -444,7 +469,8 @@
</local:SettingContainer>
<!-- Add Match Profiles -->
<local:SettingContainer x:Uid="NewTabMenu_AddMatchProfiles"
<local:SettingContainer x:Name="AddMatchProfiles"
x:Uid="NewTabMenu_AddMatchProfiles"
FontIconGlyph="&#xE748;"
Style="{StaticResource ExpanderSettingContainerStyleWithIcon}">
<StackPanel Spacing="8">

View File

@@ -22,6 +22,8 @@ using namespace winrt::Windows::UI::Xaml::Data;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
static constexpr std::wstring_view HideIconValue{ L"none" };
static IObservableVector<Editor::NewTabMenuEntryViewModel> _ConvertToViewModelEntries(const IVector<Model::NewTabMenuEntry>& settingsModelEntries, const Model::CascadiaSettings& settings)
{
std::vector<Editor::NewTabMenuEntryViewModel> result{};
@@ -160,6 +162,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// FolderTree needs to be updated when a folder is renamed
_folderTreeCache = nullptr;
}
else if (viewModelProperty == L"Icon")
{
_NotifyChanges(L"CurrentFolderIconPreview", L"CurrentFolderLocalizedIcon", L"CurrentFolderIconPath", L"CurrentFolderUsingNoIcon");
}
}
hstring NewTabMenuViewModel::CurrentFolderName() const
@@ -216,6 +222,60 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
Windows::UI::Xaml::Controls::IconElement NewTabMenuViewModel::CurrentFolderIconPreview() const
{
if (!_CurrentFolder)
{
return nullptr;
}
// IconWUX sets the icon width/height to 32 by default
auto icon = Microsoft::Terminal::UI::IconPathConverter::IconWUX(_CurrentFolder.Icon());
icon.Width(16);
icon.Height(16);
return icon;
}
winrt::hstring NewTabMenuViewModel::CurrentFolderLocalizedIcon() const
{
if (!_CurrentFolder)
{
return {};
}
if (CurrentFolderUsingNoIcon())
{
return RS_(L"IconPicker_IconTypeNone");
}
return _CurrentFolder.Icon(); // For display as a string
}
winrt::hstring NewTabMenuViewModel::CurrentFolderIconPath() const
{
if (!_CurrentFolder)
{
return {};
}
return _CurrentFolder.Icon();
}
void NewTabMenuViewModel::CurrentFolderIconPath(const winrt::hstring& path)
{
if (_CurrentFolder && _CurrentFolder.Icon() != path)
{
_CurrentFolder.Icon(path);
_NotifyChanges(L"CurrentFolderIconPath", L"CurrentFolderIconPreview", L"UsingNoIcon");
}
}
bool NewTabMenuViewModel::CurrentFolderUsingNoIcon() const noexcept
{
if (!_CurrentFolder)
{
return false;
}
const auto icon{ _CurrentFolder.Icon() };
return icon.empty() || icon == HideIconValue;
}
Windows::Foundation::Collections::IObservableVector<Editor::NewTabMenuEntryViewModel> NewTabMenuViewModel::CurrentView() const
{
if (!_CurrentFolder)
@@ -451,6 +511,25 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
return _folderTreeCache;
}
Collections::IObservableVector<Editor::FolderEntryViewModel> NewTabMenuViewModel::FolderTreeFlatList() const
{
std::vector<Editor::FolderEntryViewModel> flatList;
_FolderTreeFlatListImpl(_rootEntries, flatList);
return single_threaded_observable_vector<Editor::FolderEntryViewModel>(std::move(flatList));
}
void NewTabMenuViewModel::_FolderTreeFlatListImpl(const Windows::Foundation::Collections::IVector<Editor::NewTabMenuEntryViewModel>& entriesToAdd, std::vector<Editor::FolderEntryViewModel>& flatList)
{
for (const auto& entry : entriesToAdd)
{
if (const auto& folderVM = entry.try_as<Editor::FolderEntryViewModel>())
{
flatList.push_back(folderVM);
_FolderTreeFlatListImpl(folderVM.Entries(), flatList);
}
}
}
// This recursively constructs the FolderTree
FolderTreeViewEntry::FolderTreeViewEntry(Editor::FolderEntryViewModel folderEntry) :
_folderEntry{ folderEntry },

View File

@@ -47,8 +47,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
bool CurrentFolderAllowEmpty() const;
void CurrentFolderAllowEmpty(bool value);
Windows::UI::Xaml::Controls::IconElement CurrentFolderIconPreview() const;
winrt::hstring CurrentFolderLocalizedIcon() const;
winrt::hstring CurrentFolderIconPath() const;
void CurrentFolderIconPath(const winrt::hstring& path);
bool CurrentFolderUsingNoIcon() const noexcept;
Windows::Foundation::Collections::IObservableVector<Model::Profile> AvailableProfiles() const { return _Settings.AllProfiles(); }
Windows::Foundation::Collections::IObservableVector<Editor::FolderTreeViewEntry> FolderTree() const;
Windows::Foundation::Collections::IObservableVector<Editor::FolderEntryViewModel> FolderTreeFlatList() const;
Windows::Foundation::Collections::IObservableVector<Editor::NewTabMenuEntryViewModel> CurrentView() const;
VIEW_MODEL_OBSERVABLE_PROPERTY(Editor::FolderEntryViewModel, CurrentFolder, nullptr);
VIEW_MODEL_OBSERVABLE_PROPERTY(Editor::FolderTreeViewEntry, CurrentFolderTreeViewSelectedItem, nullptr);
@@ -67,6 +74,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
Windows::Foundation::Collections::IObservableVector<Editor::NewTabMenuEntryViewModel>::VectorChanged_revoker _rootEntriesChangedRevoker;
static bool _IsRemainingProfilesEntryMissing(const Windows::Foundation::Collections::IVector<Editor::NewTabMenuEntryViewModel>& entries);
static void _FolderTreeFlatListImpl(const Windows::Foundation::Collections::IVector<Editor::NewTabMenuEntryViewModel>& entriesToAdd, std::vector<Editor::FolderEntryViewModel>& flatList);
void _FolderPropertyChanged(const IInspectable& sender, const Windows::UI::Xaml::Data::PropertyChangedEventArgs& args);
};
@@ -134,6 +142,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Inlining(bool value);
hstring Icon() const { return _FolderEntry.Icon().Path(); }
void Icon(const hstring& value)
{
_FolderEntry.Icon(Model::MediaResourceHelper::FromString(value));
_NotifyChanges(L"Icon");
}
GETSET_OBSERVABLE_PROJECTED_SETTING(_FolderEntry, Name);
GETSET_OBSERVABLE_PROJECTED_SETTING(_FolderEntry, AllowEmpty);

View File

@@ -41,6 +41,11 @@ namespace Microsoft.Terminal.Settings.Editor
String ProfileMatcherCommandline;
String AddFolderName;
Windows.UI.Xaml.Controls.IconElement CurrentFolderIconPreview { get; };
String CurrentFolderLocalizedIcon { get; };
String CurrentFolderIconPath;
Boolean CurrentFolderUsingNoIcon { get; };
void RequestReorderEntry(NewTabMenuEntryViewModel vm, Boolean goingUp);
void RequestDeleteEntry(NewTabMenuEntryViewModel vm);
void RequestMoveEntriesToFolder(IVector<NewTabMenuEntryViewModel> entries, FolderEntryViewModel folderEntry);
@@ -83,7 +88,7 @@ namespace Microsoft.Terminal.Settings.Editor
FolderEntryViewModel(Microsoft.Terminal.Settings.Model.FolderEntry folderEntry, Microsoft.Terminal.Settings.Model.CascadiaSettings settings);
String Name;
String Icon { get; };
String Icon;
Boolean Inlining;
Boolean AllowEmpty;
IObservableVector<Microsoft.Terminal.Settings.Editor.NewTabMenuEntryViewModel> Entries;

View File

@@ -4,14 +4,12 @@
#include "pch.h"
#include "ProfileViewModel.h"
#include "ProfileViewModel.g.cpp"
#include "EnumEntry.h"
#include "Appearances.h"
#include "EnumEntry.h"
#include "../WinRTUtils/inc/Utils.h"
#include "../../renderer/base/FontCache.h"
#include "../TerminalSettingsAppAdapterLib/TerminalSettings.h"
#include "SegoeFluentIconList.h"
#include "../../types/inc/utils.hpp"
using namespace winrt::Windows::UI::Text;
using namespace winrt::Windows::UI::Xaml;
@@ -24,13 +22,11 @@ using namespace winrt::Microsoft::Terminal::Settings::Model;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
static constexpr std::wstring_view HideIconValue{ L"none" };
static Editor::Font fontObjectForDWriteFont(IDWriteFontFamily* family, const wchar_t* locale);
Windows::Foundation::Collections::IObservableVector<Editor::Font> ProfileViewModel::_MonospaceFontList{ nullptr };
Windows::Foundation::Collections::IObservableVector<Editor::Font> ProfileViewModel::_FontList{ nullptr };
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> ProfileViewModel::_BuiltInIcons{ nullptr };
static constexpr std::wstring_view HideIconValue{ L"none" };
ProfileViewModel::ProfileViewModel(const Model::Profile& profile, const Model::CascadiaSettings& appSettings, const Windows::UI::Core::CoreDispatcher& dispatcher) :
_profile{ profile },
@@ -47,17 +43,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_InitializeCurrentBellSounds();
// set up IconTypes
std::vector<IInspectable> iconTypes;
iconTypes.reserve(4);
iconTypes.emplace_back(make<EnumEntry>(RS_(L"Profile_IconTypeNone"), box_value(IconType::None)));
iconTypes.emplace_back(make<EnumEntry>(RS_(L"Profile_IconTypeFontIcon"), box_value(IconType::FontIcon)));
iconTypes.emplace_back(make<EnumEntry>(RS_(L"Profile_IconTypeEmoji"), box_value(IconType::Emoji)));
iconTypes.emplace_back(make<EnumEntry>(RS_(L"Profile_IconTypeImage"), box_value(IconType::Image)));
_IconTypes = winrt::single_threaded_vector<IInspectable>(std::move(iconTypes));
_DeduceCurrentIconType();
_DeduceCurrentBuiltInIcon();
// Add a property changed handler to our own property changed event.
// This propagates changes from the settings model to anybody listening to our
// unique view model members.
@@ -92,32 +77,15 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
else if (viewModelProperty == L"Icon")
{
// _DeduceCurrentIconType() ends with a "CurrentIconType" notification
// so we don't need to call _UpdateIconPreview() here
_DeduceCurrentIconType();
// The icon changed; let's re-evaluate it with its new context.
_appSettings.ResolveMediaResources();
}
else if (viewModelProperty == L"CurrentIconType")
{
// "Using*" handles the visibility of the IconType-related UI.
// The others propagate the rendered icon into a preview (i.e. nav view, container item)
_NotifyChanges(L"UsingNoIcon",
L"UsingBuiltInIcon",
L"UsingEmojiIcon",
L"UsingImageIcon",
L"LocalizedIcon",
// Propagate the rendered icon into a preview (i.e. nav view, container item)
_NotifyChanges(L"LocalizedIcon",
L"IconPreview",
L"IconPath",
L"EvaluatedIcon");
}
else if (viewModelProperty == L"CurrentBuiltInIcon")
{
IconPath(unbox_value<hstring>(_CurrentBuiltInIcon.EnumValue()));
}
else if (viewModelProperty == L"CurrentEmojiIcon")
{
IconPath(CurrentEmojiIcon());
L"EvaluatedIcon",
L"UsingNoIcon");
}
else if (viewModelProperty == L"CurrentBellSounds")
{
@@ -190,61 +158,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_defaultAppearanceViewModel.IsDefault(true);
}
void ProfileViewModel::_UpdateBuiltInIcons()
{
std::vector<Editor::EnumEntry> builtInIcons;
for (auto& [val, name] : s_SegoeFluentIcons)
{
builtInIcons.emplace_back(make<EnumEntry>(hstring{ name }, box_value(val)));
}
_BuiltInIcons = single_threaded_observable_vector<Editor::EnumEntry>(std::move(builtInIcons));
}
void ProfileViewModel::_DeduceCurrentIconType()
{
const auto profileIcon = IconPath();
if (profileIcon == HideIconValue)
{
_currentIconType = _IconTypes.GetAt(0);
}
else if (profileIcon.size() == 1 && (L'\uE700' <= til::at(profileIcon, 0) && til::at(profileIcon, 0) <= L'\uF8B3'))
{
_currentIconType = _IconTypes.GetAt(1);
_DeduceCurrentBuiltInIcon();
}
else if (::Microsoft::Console::Utils::IsLikelyToBeEmojiOrSymbolIcon(profileIcon))
{
// We already did a range check for MDL2 Assets in the previous one,
// so if we're out of that range but still short, assume we're an emoji
_currentIconType = _IconTypes.GetAt(2);
}
else
{
_currentIconType = _IconTypes.GetAt(3);
}
_NotifyChanges(L"CurrentIconType");
}
void ProfileViewModel::_DeduceCurrentBuiltInIcon()
{
if (!_BuiltInIcons)
{
_UpdateBuiltInIcons();
}
const auto profileIcon = IconPath();
for (uint32_t i = 0; i < _BuiltInIcons.Size(); i++)
{
const auto& builtIn = _BuiltInIcons.GetAt(i);
if (profileIcon == unbox_value<hstring>(builtIn.EnumValue()))
{
_CurrentBuiltInIcon = builtIn;
return;
}
}
_CurrentBuiltInIcon = _BuiltInIcons.GetAt(0);
_NotifyChanges(L"CurrentBuiltInIcon");
}
void ProfileViewModel::LeftPadding(double value) noexcept
{
if (std::abs(_parsedPadding.Left - value) >= .0001)
@@ -636,9 +549,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
winrt::hstring ProfileViewModel::LocalizedIcon() const
{
if (_currentIconType && unbox_value<IconType>(_currentIconType.as<Editor::EnumEntry>().EnumValue()) == IconType::None)
if (UsingNoIcon())
{
return RS_(L"Profile_IconTypeNone");
return RS_(L"IconPicker_IconTypeNone");
}
return IconPath(); // For display as a string
}
@@ -652,83 +565,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
return icon;
}
void ProfileViewModel::CurrentIconType(const Windows::Foundation::IInspectable& value)
bool ProfileViewModel::UsingNoIcon() const noexcept
{
if (_currentIconType != value)
{
// Switching from...
if (_currentIconType && unbox_value<IconType>(_currentIconType.as<Editor::EnumEntry>().EnumValue()) == IconType::Image)
{
// Stash the current value of Icon. If the user
// switches out of then back to IconType::Image, we want
// the path that we display in the text box to remain unchanged.
_lastIconPath = IconPath();
}
// Set the member here instead of after setting Icon() below!
// We have an Icon property changed handler defined for when we discard changes.
// Inadvertently, that means that we call this setter again.
// Setting the member here means that we early exit at the beginning of the function
// because _currentIconType == value.
_currentIconType = value;
// Switched to...
switch (unbox_value<IconType>(value.as<Editor::EnumEntry>().EnumValue()))
{
case IconType::None:
{
IconPath(winrt::hstring{ HideIconValue });
break;
}
case IconType::Image:
{
if (!_lastIconPath.empty())
{
// Conversely, if we switch to Image,
// retrieve that saved value and apply it
IconPath(_lastIconPath);
}
break;
}
case IconType::FontIcon:
{
if (_CurrentBuiltInIcon)
{
IconPath(unbox_value<hstring>(_CurrentBuiltInIcon.EnumValue()));
}
break;
}
case IconType::Emoji:
{
// Don't set Icon here!
// Clear out the text box so we direct the user to use the emoji picker.
CurrentEmojiIcon({});
}
}
// We're not using the VM's Icon() setter above,
// so notify HasIcon changed manually
_NotifyChanges(L"CurrentIconType", L"HasIcon");
}
}
bool ProfileViewModel::UsingNoIcon() const
{
return _currentIconType == _IconTypes.GetAt(0);
}
bool ProfileViewModel::UsingBuiltInIcon() const
{
return _currentIconType == _IconTypes.GetAt(1);
}
bool ProfileViewModel::UsingEmojiIcon() const
{
return _currentIconType == _IconTypes.GetAt(2);
}
bool ProfileViewModel::UsingImageIcon() const
{
return _currentIconType == _IconTypes.GetAt(3);
const auto iconPath{ IconPath() };
return iconPath.empty() || iconPath == HideIconValue;
}
hstring ProfileViewModel::BellStylePreview() const

View File

@@ -4,7 +4,6 @@
#pragma once
#include "DeleteProfileEventArgs.g.h"
#include "NavigateToProfileArgs.g.h"
#include "BellSoundViewModel.g.h"
#include "ProfileViewModel.g.h"
#include "Utils.h"
@@ -12,21 +11,6 @@
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
struct NavigateToProfileArgs : NavigateToProfileArgsT<NavigateToProfileArgs>
{
public:
NavigateToProfileArgs(ProfileViewModel profile, Editor::IHostedInWindow windowRoot) :
_Profile(profile),
_WindowRoot(windowRoot) {}
Editor::IHostedInWindow WindowRoot() const noexcept { return _WindowRoot; }
Editor::ProfileViewModel Profile() const noexcept { return _Profile; }
private:
Editor::IHostedInWindow _WindowRoot;
Editor::ProfileViewModel _Profile{ nullptr };
};
struct BellSoundViewModel : BellSoundViewModelT<BellSoundViewModel>, ViewModelHelper<BellSoundViewModel>
{
public:
@@ -49,13 +33,18 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
static void UpdateFontList() noexcept;
static Windows::Foundation::Collections::IObservableVector<Editor::Font> CompleteFontList() noexcept { return _FontList; };
static Windows::Foundation::Collections::IObservableVector<Editor::Font> MonospaceFontList() noexcept { return _MonospaceFontList; };
static Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> BuiltInIcons() noexcept { return _BuiltInIcons; };
ProfileViewModel(const Model::Profile& profile, const Model::CascadiaSettings& settings, const Windows::UI::Core::CoreDispatcher& dispatcher);
Control::IControlSettings TermSettings() const;
void DeleteProfile();
void SetupAppearances(Windows::Foundation::Collections::IObservableVector<Editor::ColorSchemeViewModel> schemesList);
void ForceRefreshCurrentPage()
{
// Used to trigger the PropertyChanged handler in MainPage.cpp
// This forces the page to refresh
_NotifyChanges(L"CurrentPage");
}
// bell style bits
hstring BellStylePreview() const;
@@ -86,23 +75,20 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
return _profile.Icon().Resolved();
}
Windows::Foundation::IInspectable CurrentIconType() const noexcept
{
return _currentIconType;
}
Windows::UI::Xaml::Controls::IconElement IconPreview() const;
winrt::hstring LocalizedIcon() const;
void CurrentIconType(const Windows::Foundation::IInspectable& value);
bool UsingNoIcon() const;
bool UsingBuiltInIcon() const;
bool UsingEmojiIcon() const;
bool UsingImageIcon() const;
winrt::hstring IconPath() const { return _profile.Icon().Path(); }
void IconPath(const winrt::hstring& path)
{
Icon(Model::MediaResourceHelper::FromString(path));
_NotifyChanges(L"Icon", L"IconPath");
}
bool UsingNoIcon() const noexcept;
constexpr bool TmuxControlEnabled() noexcept
{
return Feature_TmuxControl::IsEnabled();
}
// starting directory
hstring CurrentStartingDirectoryPreview() const;
@@ -134,8 +120,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
VIEW_MODEL_OBSERVABLE_PROPERTY(ProfileSubPage, CurrentPage);
VIEW_MODEL_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector<Editor::BellSoundViewModel>, CurrentBellSounds);
VIEW_MODEL_OBSERVABLE_PROPERTY(Editor::EnumEntry, CurrentBuiltInIcon, nullptr);
VIEW_MODEL_OBSERVABLE_PROPERTY(hstring, CurrentEmojiIcon);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, Guid);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, ConnectionType);
@@ -171,10 +155,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
OBSERVABLE_PROJECTED_SETTING(_profile, AnswerbackMessage);
OBSERVABLE_PROJECTED_SETTING(_profile, RainbowSuggestions);
OBSERVABLE_PROJECTED_SETTING(_profile, PathTranslationStyle);
OBSERVABLE_PROJECTED_SETTING(_profile, AllowTmuxControl);
WINRT_PROPERTY(bool, IsBaseLayer, false);
WINRT_PROPERTY(bool, FocusDeleteButton, false);
WINRT_PROPERTY(Windows::Foundation::Collections::IVector<Windows::Foundation::IInspectable>, IconTypes);
WINRT_PROPERTY(hstring, ElementToFocus);
GETSET_BINDABLE_ENUM_SETTING(AntiAliasingMode, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode);
GETSET_BINDABLE_ENUM_SETTING(CloseOnExitMode, Microsoft::Terminal::Settings::Model::CloseOnExitMode, CloseOnExit);
GETSET_BINDABLE_ENUM_SETTING(ScrollState, Microsoft::Terminal::Control::ScrollbarState, ScrollState);
@@ -185,8 +170,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
winrt::guid _originalProfileGuid{};
winrt::hstring _lastBgImagePath;
winrt::hstring _lastStartingDirectoryPath;
winrt::hstring _lastIconPath;
Windows::Foundation::IInspectable _currentIconType{};
Editor::AppearanceViewModel _defaultAppearanceViewModel;
Windows::UI::Core::CoreDispatcher _dispatcher;
@@ -197,13 +180,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void _MarkDuplicateBellSoundDirectories();
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _MonospaceFontList;
static Windows::Foundation::Collections::IObservableVector<Editor::Font> _FontList;
static Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> _BuiltInIcons;
Model::CascadiaSettings _appSettings;
Editor::AppearanceViewModel _unfocusedAppearanceViewModel;
void _UpdateBuiltInIcons();
void _DeduceCurrentIconType();
void _DeduceCurrentBuiltInIcon();
};
struct DeleteProfileEventArgs :

View File

@@ -14,12 +14,6 @@ import "ColorSchemesPageViewModel.idl";
namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass NavigateToProfileArgs
{
ProfileViewModel Profile { get; };
IHostedInWindow WindowRoot { get; };
}
runtimeclass DeleteProfileEventArgs
{
Guid ProfileGuid { get; };
@@ -42,14 +36,6 @@ namespace Microsoft.Terminal.Settings.Editor
Advanced = 3
};
enum IconType
{
None = 0,
FontIcon,
Image,
Emoji
};
runtimeclass ProfileViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
event Windows.Foundation.TypedEventHandler<ProfileViewModel, DeleteProfileEventArgs> DeleteProfileRequested;
@@ -107,17 +93,9 @@ namespace Microsoft.Terminal.Settings.Editor
Windows.UI.Xaml.Controls.IconElement IconPreview { get; };
String EvaluatedIcon { get; };
String LocalizedIcon { get; };
String CurrentEmojiIcon;
IInspectable CurrentIconType;
Windows.Foundation.Collections.IVector<IInspectable> IconTypes { get; };
Boolean UsingNoIcon { get; };
Boolean UsingBuiltInIcon { get; };
Boolean UsingEmojiIcon { get; };
Boolean UsingImageIcon { get; };
Boolean TmuxControlEnabled { get; };
String IconPath;
EnumEntry CurrentBuiltInIcon;
Windows.Foundation.Collections.IObservableVector<EnumEntry> BuiltInIcons { get; };
Boolean UsingNoIcon { get; };
String TabTitlePreview { get; };
String AnswerbackMessagePreview { get; };
@@ -162,5 +140,6 @@ namespace Microsoft.Terminal.Settings.Editor
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, RainbowSuggestions);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.PathTranslationStyle, PathTranslationStyle);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AllowVtClipboardWrite);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AllowTmuxControl);
}
}

View File

@@ -25,9 +25,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Profiles_Advanced::OnNavigatedTo(const NavigationEventArgs& e)
{
const auto args = e.Parameter().as<Editor::NavigateToProfileArgs>();
_Profile = args.Profile();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_Profile = args.ViewModel().as<Editor::ProfileViewModel>();
_windowRoot = args.WindowRoot();
BringIntoViewWhenLoaded(args.ElementToFocus());
TraceLoggingWrite(
g_hTerminalSettingsEditorProvider,

View File

@@ -37,7 +37,8 @@
<StackPanel Grid.Row="1"
Style="{StaticResource SettingsStackStyle}">
<!-- Antialiasing Mode -->
<local:SettingContainer x:Uid="Profile_AntialiasingMode"
<local:SettingContainer x:Name="AntialiasingMode"
x:Uid="Profile_AntialiasingMode"
ClearSettingValue="{x:Bind Profile.ClearAntialiasingMode}"
HasSettingValue="{x:Bind Profile.HasAntialiasingMode, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.AntialiasingModeOverrideSource, Mode=OneWay}">
@@ -49,7 +50,8 @@
</local:SettingContainer>
<!-- AltGr Aliasing -->
<local:SettingContainer x:Uid="Profile_AltGrAliasing"
<local:SettingContainer x:Name="AltGrAliasing"
x:Uid="Profile_AltGrAliasing"
ClearSettingValue="{x:Bind Profile.ClearAltGrAliasing}"
HasSettingValue="{x:Bind Profile.HasAltGrAliasing, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.AltGrAliasingOverrideSource, Mode=OneWay}">
@@ -58,7 +60,8 @@
</local:SettingContainer>
<!-- Snap On Input -->
<local:SettingContainer x:Uid="Profile_SnapOnInput"
<local:SettingContainer x:Name="SnapOnInput"
x:Uid="Profile_SnapOnInput"
ClearSettingValue="{x:Bind Profile.ClearSnapOnInput}"
HasSettingValue="{x:Bind Profile.HasSnapOnInput, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.SnapOnInputOverrideSource, Mode=OneWay}">
@@ -67,7 +70,8 @@
</local:SettingContainer>
<!-- History Size -->
<local:SettingContainer x:Uid="Profile_HistorySize"
<local:SettingContainer x:Name="HistorySize"
x:Uid="Profile_HistorySize"
ClearSettingValue="{x:Bind Profile.ClearHistorySize}"
HasSettingValue="{x:Bind Profile.HasHistorySize, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.HistorySizeOverrideSource, Mode=OneWay}">
@@ -80,7 +84,8 @@
</local:SettingContainer>
<!-- Close On Exit -->
<local:SettingContainer x:Uid="Profile_CloseOnExit"
<local:SettingContainer x:Name="CloseOnExit"
x:Uid="Profile_CloseOnExit"
ClearSettingValue="{x:Bind Profile.ClearCloseOnExit}"
HasSettingValue="{x:Bind Profile.HasCloseOnExit, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.CloseOnExitOverrideSource, Mode=OneWay}">
@@ -92,7 +97,8 @@
</local:SettingContainer>
<!-- Bell Style -->
<local:SettingContainer x:Uid="Profile_BellStyle"
<local:SettingContainer x:Name="BellStyle"
x:Uid="Profile_BellStyle"
ClearSettingValue="{x:Bind Profile.ClearBellStyle}"
CurrentValue="{x:Bind Profile.BellStylePreview, Mode=OneWay}"
HasSettingValue="{x:Bind Profile.HasBellStyle, Mode=OneWay}"
@@ -109,7 +115,8 @@
</local:SettingContainer>
<!-- Bell Sound -->
<local:SettingContainer x:Uid="Profile_BellSound"
<local:SettingContainer x:Name="BellSound"
x:Uid="Profile_BellSound"
ClearSettingValue="{x:Bind Profile.ClearBellSound}"
CurrentValue="{x:Bind Profile.BellSoundPreview, Mode=OneWay}"
HasSettingValue="{x:Bind Profile.HasBellSound, Mode=OneWay}"
@@ -190,7 +197,8 @@
</local:SettingContainer>
<!-- RightClickContextMenu -->
<local:SettingContainer x:Uid="Profile_RightClickContextMenu"
<local:SettingContainer x:Name="RightClickContextMenu"
x:Uid="Profile_RightClickContextMenu"
ClearSettingValue="{x:Bind Profile.ClearRightClickContextMenu}"
HasSettingValue="{x:Bind Profile.HasRightClickContextMenu, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.RightClickContextMenuOverrideSource, Mode=OneWay}">
@@ -199,7 +207,8 @@
</local:SettingContainer>
<!-- ShowMarks -->
<local:SettingContainer x:Uid="Profile_ShowMarks"
<local:SettingContainer x:Name="ShowMarks"
x:Uid="Profile_ShowMarks"
ClearSettingValue="{x:Bind Profile.ClearShowMarks}"
HasSettingValue="{x:Bind Profile.HasShowMarks, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.ShowMarksOverrideSource, Mode=OneWay}"
@@ -209,7 +218,8 @@
</local:SettingContainer>
<!-- AutoMarkPrompts -->
<local:SettingContainer x:Uid="Profile_AutoMarkPrompts"
<local:SettingContainer x:Name="AutoMarkPrompts"
x:Uid="Profile_AutoMarkPrompts"
ClearSettingValue="{x:Bind Profile.ClearAutoMarkPrompts}"
HasSettingValue="{x:Bind Profile.HasAutoMarkPrompts, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.AutoMarkPromptsOverrideSource, Mode=OneWay}"
@@ -219,7 +229,8 @@
</local:SettingContainer>
<!-- ReloadEnvVars -->
<local:SettingContainer x:Uid="Profile_ReloadEnvVars"
<local:SettingContainer x:Name="ReloadEnvVars"
x:Uid="Profile_ReloadEnvVars"
ClearSettingValue="{x:Bind Profile.ClearReloadEnvironmentVariables}"
HasSettingValue="{x:Bind Profile.HasReloadEnvironmentVariables, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.ReloadEnvironmentVariablesOverrideSource, Mode=OneWay}">
@@ -228,7 +239,8 @@
</local:SettingContainer>
<!-- RepositionCursorWithMouse -->
<local:SettingContainer x:Uid="Profile_RepositionCursorWithMouse"
<local:SettingContainer x:Name="RepositionCursorWithMouse"
x:Uid="Profile_RepositionCursorWithMouse"
ClearSettingValue="{x:Bind Profile.ClearRepositionCursorWithMouse}"
HasSettingValue="{x:Bind Profile.HasRepositionCursorWithMouse, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.RepositionCursorWithMouseOverrideSource, Mode=OneWay}"
@@ -238,7 +250,8 @@
</local:SettingContainer>
<!-- RainbowSuggestions -->
<local:SettingContainer x:Uid="Profile_RainbowSuggestions"
<local:SettingContainer x:Name="RainbowSuggestions"
x:Uid="Profile_RainbowSuggestions"
ClearSettingValue="{x:Bind Profile.ClearRainbowSuggestions}"
HasSettingValue="{x:Bind Profile.HasRainbowSuggestions, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.RainbowSuggestionsOverrideSource, Mode=OneWay}">
@@ -247,7 +260,8 @@
</local:SettingContainer>
<!-- Path Translation -->
<local:SettingContainer x:Uid="Profile_PathTranslationStyle"
<local:SettingContainer x:Name="PathTranslationStyle"
x:Uid="Profile_PathTranslationStyle"
ClearSettingValue="{x:Bind Profile.ClearPathTranslationStyle}"
HasSettingValue="{x:Bind Profile.HasPathTranslationStyle, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.PathTranslationStyleOverrideSource, Mode=OneWay}">

View File

@@ -3,6 +3,7 @@
#include "pch.h"
#include "Profiles_Appearance.h"
#include "Appearances.h"
#include "ProfileViewModel.h"
#include "PreviewConnection.h"
@@ -12,6 +13,8 @@
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Navigation;
static constexpr std::wstring_view AppearanceSettingPrefix{ L"App." };
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
Profiles_Appearance::Profiles_Appearance()
@@ -22,10 +25,24 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Profiles_Appearance::OnNavigatedTo(const NavigationEventArgs& e)
{
const auto args = e.Parameter().as<Editor::NavigateToProfileArgs>();
_Profile = args.Profile();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_Profile = args.ViewModel().as<Editor::ProfileViewModel>();
_windowRoot = args.WindowRoot();
// Settings are stored in Profiles_Appearance and Appearances.
// We use the "App." prefix to indicate if it's in Appearances,
// and remove it on the way to Appearances object.
const auto elementToFocus = args.ElementToFocus();
if (elementToFocus.starts_with(AppearanceSettingPrefix))
{
std::wstring correctedName{ elementToFocus.c_str() };
get_self<implementation::Appearances>(DefaultAppearanceView())->BringIntoViewWhenLoaded(hstring{ correctedName.substr(AppearanceSettingPrefix.size()) });
}
else
{
BringIntoViewWhenLoaded(elementToFocus);
}
if (!_previewControl)
{
const auto settings = winrt::get_self<implementation::ProfileViewModel>(_Profile)->TermSettings();

View File

@@ -5,11 +5,10 @@
#include <ThrottledFunc.h>
#include "Profiles_Appearance.g.h"
#include "PreviewConnection.h"
#include "Utils.h"
#include "Profiles_Appearance.g.h"
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
struct Profiles_Appearance : public HasScrollViewer<Profiles_Appearance>, Profiles_AppearanceT<Profiles_Appearance>

View File

@@ -75,7 +75,8 @@
CornerRadius="{StaticResource ControlCornerRadius}" />
</Border>
<local:Appearances Appearance="{x:Bind Profile.DefaultAppearance, Mode=OneWay}"
<local:Appearances x:Name="DefaultAppearanceView"
Appearance="{x:Bind Profile.DefaultAppearance, Mode=OneWay}"
SourceProfile="{x:Bind Profile, Mode=OneWay}"
WindowRoot="{x:Bind WindowRoot, Mode=OneTime}" />
@@ -85,12 +86,12 @@
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Opacity -->
<local:SettingContainer x:Name="OpacityContainer"
<local:SettingContainer x:Name="Opacity"
x:Uid="Profile_Opacity"
ClearSettingValue="{x:Bind Profile.ClearOpacity}"
HasSettingValue="{x:Bind Profile.HasOpacity, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.OpacityOverrideSource, Mode=OneWay}">
<StackPanel x:Name="OpacityControl">
<StackPanel>
<Grid Style="{StaticResource CustomSliderControlGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
@@ -107,12 +108,12 @@
</local:SettingContainer>
<!-- Use Acrylic -->
<local:SettingContainer x:Uid="Profile_UseAcrylic"
<local:SettingContainer x:Name="UseAcrylic"
x:Uid="Profile_UseAcrylic"
ClearSettingValue="{x:Bind Profile.ClearUseAcrylic}"
HasSettingValue="{x:Bind Profile.HasUseAcrylic, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.UseAcrylicOverrideSource, Mode=OneWay}">
<ToggleSwitch x:Name="UseAcrylicToggleSwitch"
IsOn="{x:Bind Profile.UseAcrylic, Mode=TwoWay}"
<ToggleSwitch IsOn="{x:Bind Profile.UseAcrylic, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
@@ -124,7 +125,8 @@
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Padding -->
<local:SettingContainer x:Uid="Profile_Padding"
<local:SettingContainer x:Name="Padding"
x:Uid="Profile_Padding"
ClearSettingValue="{x:Bind Profile.ClearPadding}"
CurrentValue="{x:Bind Profile.Padding, Mode=OneWay}"
HasSettingValue="{x:Bind Profile.HasPadding, Mode=OneWay}"
@@ -191,7 +193,8 @@
</local:SettingContainer>
<!-- Scrollbar Visibility -->
<local:SettingContainer x:Uid="Profile_ScrollbarVisibility"
<local:SettingContainer x:Name="ScrollbarVisibility"
x:Uid="Profile_ScrollbarVisibility"
ClearSettingValue="{x:Bind Profile.ClearScrollState}"
HasSettingValue="{x:Bind Profile.HasScrollState, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.ScrollStateOverrideSource, Mode=OneWay}">
@@ -207,7 +210,10 @@
Visibility="{x:Bind Profile.EditableUnfocusedAppearance, Mode=OneWay}">
<TextBlock x:Uid="Profile_UnfocusedAppearanceTextBlock"
Style="{StaticResource TextBlockSubtitleStyle}" />
<Button x:Uid="Profile_CreateUnfocusedAppearanceButton"
<!-- Create Unfocused Appearance -->
<Button x:Name="CreateUnfocusedAppearance"
x:Uid="Profile_CreateUnfocusedAppearanceButton"
Margin="8,0,0,0"
VerticalAlignment="Bottom"
Click="CreateUnfocusedAppearance_Click"
@@ -224,7 +230,10 @@
</StackPanel>
</Button.Content>
</Button>
<Button x:Uid="Profile_DeleteUnfocusedAppearanceButton"
<!-- Delete Unfocused Appearance -->
<Button x:Name="DeleteUnfocusedAppearance"
x:Uid="Profile_DeleteUnfocusedAppearanceButton"
Margin="8,0,0,0"
VerticalAlignment="Bottom"
Click="DeleteUnfocusedAppearance_Click"
@@ -241,7 +250,10 @@
</Button.Content>
</Button>
</StackPanel>
<local:Appearances Appearance="{x:Bind Profile.UnfocusedAppearance, Mode=OneWay}"
<!-- Unfocused Appearance -->
<local:Appearances x:Name="UnfocusedAppearanceView"
Appearance="{x:Bind Profile.UnfocusedAppearance, Mode=OneWay}"
SourceProfile="{x:Bind Profile, Mode=OneWay}"
Visibility="{x:Bind Profile.ShowUnfocusedAppearance, Mode=OneWay}"
WindowRoot="{x:Bind WindowRoot, Mode=OneTime}" />

View File

@@ -29,9 +29,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Profiles_Base::OnNavigatedTo(const NavigationEventArgs& e)
{
const auto args = e.Parameter().as<Editor::NavigateToProfileArgs>();
_Profile = args.Profile();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_Profile = args.ViewModel().as<Editor::ProfileViewModel>();
_windowRoot = args.WindowRoot();
BringIntoViewWhenLoaded(args.ElementToFocus());
// Check the use parent directory box if the starting directory is empty
if (_Profile.StartingDirectory().empty())
@@ -133,18 +134,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
safe_void_coroutine Profiles_Base::Icon_Click(const IInspectable&, const RoutedEventArgs&)
{
auto lifetime = get_strong();
const auto parentHwnd{ reinterpret_cast<HWND>(_windowRoot.GetHostingWindow()) };
auto file = co_await OpenImagePicker(parentHwnd);
if (!file.empty())
{
_Profile.IconPath(file);
}
}
safe_void_coroutine Profiles_Base::StartingDirectory_Click(const IInspectable&, const RoutedEventArgs&)
{
auto lifetime = get_strong();
@@ -169,77 +158,4 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_Profile.StartingDirectory(folder);
}
}
IconSource Profiles_Base::BuiltInIconConverter(const IInspectable& iconVal)
{
return Microsoft::Terminal::UI::IconPathConverter::IconSourceWUX(unbox_value<hstring>(iconVal));
}
void Profiles_Base::BuiltInIconPicker_GotFocus(const IInspectable& sender, const RoutedEventArgs& /*e*/)
{
_updateIconFilter({});
sender.as<AutoSuggestBox>().IsSuggestionListOpen(true);
}
void Profiles_Base::BuiltInIconPicker_QuerySubmitted(const AutoSuggestBox& /*sender*/, const AutoSuggestBoxQuerySubmittedEventArgs& e)
{
const auto iconEntry = unbox_value_or<EnumEntry>(e.ChosenSuggestion(), nullptr);
if (!iconEntry)
{
return;
}
_Profile.CurrentBuiltInIcon(iconEntry);
}
void Profiles_Base::BuiltInIconPicker_TextChanged(const AutoSuggestBox& sender, const AutoSuggestBoxTextChangedEventArgs& e)
{
if (e.Reason() != AutoSuggestionBoxTextChangeReason::UserInput)
{
return;
}
std::wstring_view filter{ sender.Text() };
filter = til::trim(filter, L' ');
_updateIconFilter(filter);
}
void Profiles_Base::_updateIconFilter(std::wstring_view filter)
{
if (_iconFilter != filter)
{
_filteredBuiltInIcons = nullptr;
_iconFilter = filter;
_updateFilteredIconList();
PropertyChanged.raise(*this, PropertyChangedEventArgs{ L"FilteredBuiltInIconList" });
}
}
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> Profiles_Base::FilteredBuiltInIconList()
{
if (!_filteredBuiltInIcons)
{
_updateFilteredIconList();
}
return _filteredBuiltInIcons;
}
void Profiles_Base::_updateFilteredIconList()
{
_filteredBuiltInIcons = ProfileViewModel::BuiltInIcons();
if (_iconFilter.empty())
{
return;
}
// Find matching icons and populate the filtered list
std::vector<Editor::EnumEntry> filtered;
filtered.reserve(_filteredBuiltInIcons.Size());
for (const auto& icon : _filteredBuiltInIcons)
{
if (til::contains_linguistic_insensitive(icon.EnumName(), _iconFilter))
{
filtered.emplace_back(icon);
}
}
_filteredBuiltInIcons = winrt::single_threaded_observable_vector(std::move(filtered));
}
}

View File

@@ -18,32 +18,20 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void OnNavigatedFrom(const Windows::UI::Xaml::Navigation::NavigationEventArgs& 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 Terminal_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void Advanced_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void DeleteConfirmation_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> FilteredBuiltInIconList();
void BuiltInIconPicker_GotFocus(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
void BuiltInIconPicker_TextChanged(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const Windows::UI::Xaml::Controls::AutoSuggestBoxTextChangedEventArgs& e);
void BuiltInIconPicker_QuerySubmitted(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const Windows::UI::Xaml::Controls::AutoSuggestBoxQuerySubmittedEventArgs& e);
static Windows::UI::Xaml::Controls::IconSource BuiltInIconConverter(const Windows::Foundation::IInspectable& iconVal);
til::property_changed_event PropertyChanged;
Editor::IHostedInWindow WindowRoot() const noexcept { return _windowRoot; }
WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);
private:
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _ViewModelChangedRevoker;
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker;
Editor::IHostedInWindow _windowRoot;
Windows::Foundation::Collections::IObservableVector<Editor::EnumEntry> _filteredBuiltInIcons;
std::wstring _iconFilter;
void _updateIconFilter(std::wstring_view filter);
void _updateFilteredIconList();
};
};

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license.
import "ProfileViewModel.idl";
import "MainPage.idl";
namespace Microsoft.Terminal.Settings.Editor
{
@@ -9,8 +10,6 @@ namespace Microsoft.Terminal.Settings.Editor
{
Profiles_Base();
ProfileViewModel Profile { get; };
Windows.Foundation.Collections.IObservableVector<EnumEntry> FilteredBuiltInIconList { get; };
static Windows.UI.Xaml.Controls.IconSource BuiltInIconConverter(IInspectable iconVal);
IHostedInWindow WindowRoot { get; };
}
}

View File

@@ -40,7 +40,8 @@
Additionally, the JSON stubs generated by auto-generated profiles come with a name,
so the name will always be overridden.
-->
<local:SettingContainer x:Uid="Profile_Name"
<local:SettingContainer x:Name="Name"
x:Uid="Profile_Name"
CurrentValue="{x:Bind Profile.Name, Mode=OneWay}"
Style="{StaticResource ExpanderSettingContainerStyle}"
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(Profile.IsBaseLayer), Mode=OneWay}">
@@ -49,7 +50,7 @@
</local:SettingContainer>
<!-- Commandline -->
<local:SettingContainer x:Name="CommandlineContainer"
<local:SettingContainer x:Name="Commandline"
x:Uid="Profile_Commandline"
ClearSettingValue="{x:Bind Profile.ClearCommandline}"
CurrentValue="{x:Bind Profile.Commandline, Mode=OneWay}"
@@ -70,7 +71,7 @@
</local:SettingContainer>
<!-- Starting Directory -->
<local:SettingContainer x:Name="StartingDirectoryContainer"
<local:SettingContainer x:Name="StartingDirectory"
x:Uid="Profile_StartingDirectory"
ClearSettingValue="{x:Bind Profile.ClearStartingDirectory}"
CurrentValue="{x:Bind Profile.CurrentStartingDirectoryPreview, Mode=OneWay}"
@@ -99,7 +100,8 @@
</local:SettingContainer>
<!-- Icon -->
<local:SettingContainer x:Uid="Profile_Icon"
<local:SettingContainer x:Name="Icon"
x:Uid="Profile_Icon"
ClearSettingValue="{x:Bind Profile.ClearIcon}"
CurrentValueAccessibleName="{x:Bind Profile.LocalizedIcon, Mode=OneWay}"
HasSettingValue="{x:Bind Profile.HasIcon, Mode=OneWay}"
@@ -122,87 +124,14 @@
</Grid>
</local:SettingContainer.CurrentValue>
<local:SettingContainer.Content>
<Grid ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<!-- Icon Type -->
<ComboBox x:Uid="Profile_IconType"
Grid.Column="0"
ItemsSource="{x:Bind Profile.IconTypes}"
SelectedItem="{x:Bind Profile.CurrentIconType, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="local:EnumEntry">
<TextBlock Text="{x:Bind EnumName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- Built-In Icon -->
<AutoSuggestBox x:Uid="Profile_BuiltInIcon"
Grid.Column="1"
GotFocus="BuiltInIconPicker_GotFocus"
ItemsSource="{x:Bind FilteredBuiltInIconList, Mode=OneWay}"
QuerySubmitted="BuiltInIconPicker_QuerySubmitted"
Text="{x:Bind Profile.CurrentBuiltInIcon.EnumName, Mode=OneWay}"
TextBoxStyle="{StaticResource TextBoxSettingStyle}"
TextChanged="BuiltInIconPicker_TextChanged"
Visibility="{x:Bind Profile.UsingBuiltInIcon, Mode=OneWay}">
<AutoSuggestBox.ItemTemplate>
<DataTemplate x:DataType="local:EnumEntry">
<Grid ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<IconSourceElement Grid.Column="0"
Width="16"
Height="16"
IconSource="{x:Bind local:Profiles_Base.BuiltInIconConverter(EnumValue), Mode=OneTime}" />
<TextBlock Grid.Column="1"
Text="{x:Bind EnumName}" />
</Grid>
</DataTemplate>
</AutoSuggestBox.ItemTemplate>
</AutoSuggestBox>
<!-- Image (File) Icon -->
<TextBox x:Uid="Profile_IconBox"
Grid.Column="1"
MaxWidth="Infinity"
HorizontalAlignment="Stretch"
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
IsSpellCheckEnabled="False"
Style="{StaticResource TextBoxSettingStyle}"
Text="{x:Bind Profile.IconPath, Mode=TwoWay}"
Visibility="{x:Bind Profile.UsingImageIcon, Mode=OneWay}" />
<Button x:Uid="Profile_IconBrowse"
Grid.Column="2"
Margin="0"
VerticalAlignment="Top"
Click="Icon_Click"
Style="{StaticResource BrowseButtonStyle}"
Visibility="{x:Bind Profile.UsingImageIcon, Mode=OneWay}" />
<!-- Emoji Icon -->
<TextBox x:Uid="Profile_IconEmojiBox"
Grid.Column="1"
MaxWidth="Infinity"
FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
IsSpellCheckEnabled="False"
Style="{StaticResource TextBoxSettingStyle}"
Text="{x:Bind Profile.CurrentEmojiIcon, Mode=TwoWay}"
Visibility="{x:Bind Profile.UsingEmojiIcon, Mode=OneWay}" />
</Grid>
<local:IconPicker CurrentIconPath="{x:Bind Profile.IconPath, Mode=TwoWay}"
WindowRoot="{x:Bind WindowRoot, Mode=OneWay}" />
</local:SettingContainer.Content>
</local:SettingContainer>
<!-- Tab Title -->
<local:SettingContainer x:Uid="Profile_TabTitle"
<local:SettingContainer x:Name="TabTitle"
x:Uid="Profile_TabTitle"
ClearSettingValue="{x:Bind Profile.ClearTabTitle}"
CurrentValue="{x:Bind Profile.TabTitlePreview, Mode=OneWay}"
HasSettingValue="{x:Bind Profile.HasTabTitle, Mode=OneWay}"
@@ -229,7 +158,8 @@
</local:SettingContainer>
<!-- Elevate -->
<local:SettingContainer x:Uid="Profile_Elevate"
<local:SettingContainer x:Name="Elevate"
x:Uid="Profile_Elevate"
ClearSettingValue="{x:Bind Profile.ClearElevate}"
HasSettingValue="{x:Bind Profile.HasElevate, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.ElevateOverrideSource, Mode=OneWay}">
@@ -238,7 +168,8 @@
</local:SettingContainer>
<!-- Hidden -->
<local:SettingContainer x:Uid="Profile_Hidden"
<local:SettingContainer x:Name="Hidden"
x:Uid="Profile_Hidden"
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(Profile.IsBaseLayer), Mode=OneWay}">
<ToggleSwitch IsOn="{x:Bind Profile.Hidden, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />

View File

@@ -22,8 +22,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Profiles_Base_Orphaned::OnNavigatedTo(const NavigationEventArgs& e)
{
const auto args = e.Parameter().as<Editor::NavigateToProfileArgs>();
_Profile = args.Profile();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_Profile = args.ViewModel().as<Editor::ProfileViewModel>();
_layoutUpdatedRevoker = LayoutUpdated(winrt::auto_revoke, [this](auto /*s*/, auto /*e*/) {
// This event fires every time the layout changes, but it is always the last one to fire

View File

@@ -23,7 +23,8 @@
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Delete Button -->
<local:SettingContainer x:Uid="Profile_Delete_Orphaned">
<local:SettingContainer x:Name="DeleteOrphaned"
x:Uid="Profile_Delete_Orphaned">
<local:SettingContainer.Content>
<Button x:Name="DeleteButton"
Click="DeleteConfirmation_Click"
@@ -40,7 +41,8 @@
</local:SettingContainer.Content>
</local:SettingContainer>
<local:SettingContainer x:Uid="Profile_Name">
<local:SettingContainer x:Name="Name"
x:Uid="Profile_Name">
<local:SettingContainer.Content>
<TextBlock FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
Style="{StaticResource SettingsPageItemDescriptionStyle}"
@@ -48,7 +50,8 @@
</local:SettingContainer.Content>
</local:SettingContainer>
<local:SettingContainer x:Uid="Profile_Source_Orphaned">
<local:SettingContainer x:Name="Source"
x:Uid="Profile_Source_Orphaned">
<local:SettingContainer.Content>
<TextBlock FontFamily="Segoe UI, Segoe Fluent Icons, Segoe MDL2 Assets"
Style="{StaticResource SettingsPageItemDescriptionStyle}"

View File

@@ -20,7 +20,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Profiles_Terminal::OnNavigatedTo(const NavigationEventArgs& e)
{
_Profile = e.Parameter().as<Editor::ProfileViewModel>();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_Profile = args.ViewModel().as<Editor::ProfileViewModel>();
BringIntoViewWhenLoaded(args.ElementToFocus());
TraceLoggingWrite(
g_hTerminalSettingsEditorProvider,

View File

@@ -32,7 +32,8 @@
Style="{StaticResource SettingsStackStyle}">
<!-- Suppress Application Title -->
<local:SettingContainer x:Uid="Profile_SuppressApplicationTitle"
<local:SettingContainer x:Name="SuppressApplicationTitle"
x:Uid="Profile_SuppressApplicationTitle"
ClearSettingValue="{x:Bind Profile.ClearSuppressApplicationTitle}"
HasSettingValue="{x:Bind Profile.HasSuppressApplicationTitle, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.SuppressApplicationTitleOverrideSource, Mode=OneWay}">
@@ -41,7 +42,8 @@
</local:SettingContainer>
<!-- Force VT Input -->
<local:SettingContainer x:Uid="Profile_ForceVTInput"
<local:SettingContainer x:Name="ForceVTInput"
x:Uid="Profile_ForceVTInput"
ClearSettingValue="{x:Bind Profile.ClearForceVTInput}"
HasSettingValue="{x:Bind Profile.HasForceVTInput, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.ForceVTInputOverrideSource, Mode=OneWay}">
@@ -50,7 +52,8 @@
</local:SettingContainer>
<!-- Allow VT Checksum Report -->
<local:SettingContainer x:Uid="Profile_AllowVtChecksumReport"
<local:SettingContainer x:Name="AllowVtChecksumReport"
x:Uid="Profile_AllowVtChecksumReport"
ClearSettingValue="{x:Bind Profile.ClearAllowVtChecksumReport}"
HasSettingValue="{x:Bind Profile.HasAllowVtChecksumReport, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.AllowVtChecksumReportOverrideSource, Mode=OneWay}">
@@ -59,7 +62,8 @@
</local:SettingContainer>
<!-- Allow VT Clipboard Writing -->
<local:SettingContainer x:Uid="Profile_AllowVtClipboardWrite"
<local:SettingContainer x:Name="AllowVtClipboardWrite"
x:Uid="Profile_AllowVtClipboardWrite"
ClearSettingValue="{x:Bind Profile.ClearAllowVtClipboardWrite}"
HasSettingValue="{x:Bind Profile.HasAllowVtClipboardWrite, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.AllowVtClipboardWriteOverrideSource, Mode=OneWay}">
@@ -68,7 +72,8 @@
</local:SettingContainer>
<!-- Answerback Message -->
<local:SettingContainer x:Uid="Profile_AnswerbackMessage"
<local:SettingContainer x:Name="AnswerbackMessage"
x:Uid="Profile_AnswerbackMessage"
ClearSettingValue="{x:Bind Profile.ClearAnswerbackMessage}"
CurrentValue="{x:Bind Profile.AnswerbackMessagePreview, Mode=OneWay}"
HasSettingValue="{x:Bind Profile.HasAnswerbackMessage, Mode=OneWay}"
@@ -77,6 +82,16 @@
<TextBox Style="{StaticResource TextBoxSettingStyle}"
Text="{x:Bind Profile.AnswerbackMessage, Mode=TwoWay}" />
</local:SettingContainer>
<!-- Allow Tmux Control -->
<local:SettingContainer x:Uid="Profile_AllowTmuxControl"
ClearSettingValue="{x:Bind Profile.ClearAllowTmuxControl}"
HasSettingValue="{x:Bind Profile.HasAllowTmuxControl, Mode=OneWay}"
SettingOverrideSource="{x:Bind Profile.AllowTmuxControlOverrideSource, Mode=OneWay}"
Visibility="{x:Bind Profile.TmuxControlEnabled, Mode=OneTime}">
<ToggleSwitch IsOn="{x:Bind Profile.AllowTmuxControl, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
</StackPanel>
</Grid>
</Page>

View File

@@ -3,6 +3,7 @@
#include "pch.h"
#include "Rendering.h"
#include "NavigateToPageArgs.g.h"
#include "Rendering.g.cpp"
using namespace winrt::Windows::UI::Xaml::Navigation;
@@ -16,7 +17,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void Rendering::OnNavigatedTo(const NavigationEventArgs& e)
{
_ViewModel = e.Parameter().as<Editor::RenderingViewModel>();
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
_ViewModel = args.ViewModel().as<Editor::RenderingViewModel>();
BringIntoViewWhenLoaded(args.ElementToFocus());
TraceLoggingWrite(
g_hTerminalSettingsEditorProvider,

View File

@@ -24,7 +24,8 @@
</Page.Resources>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<local:SettingContainer x:Uid="Globals_GraphicsAPI">
<local:SettingContainer x:Name="GraphicsAPI"
x:Uid="Globals_GraphicsAPI">
<ComboBox AutomationProperties.AccessibilityView="Content"
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
ItemsSource="{x:Bind ViewModel.GraphicsAPIList}"
@@ -32,12 +33,14 @@
Style="{StaticResource ComboBoxSettingStyle}" />
</local:SettingContainer>
<local:SettingContainer x:Uid="Globals_DisablePartialInvalidation">
<local:SettingContainer x:Name="DisablePartialInvalidation"
x:Uid="Globals_DisablePartialInvalidation">
<ToggleSwitch IsOn="{x:Bind ViewModel.DisablePartialInvalidation, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<local:SettingContainer x:Uid="Globals_SoftwareRendering">
<local:SettingContainer x:Name="SoftwareRendering"
x:Uid="Globals_SoftwareRendering">
<ToggleSwitch IsOn="{x:Bind ViewModel.SoftwareRendering, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>

View File

@@ -542,6 +542,10 @@
<value>Always on top</value>
<comment>Header for a control to toggle if the app will always be presented on top of other windows, or is treated normally (when disabled).</comment>
</data>
<data name="Profile_AllowTmuxControl.Header" xml:space="preserve">
<value>Allow Tmux Control</value>
<comment>Header for a control to toggle tmux control.</comment>
</data>
<data name="Profile_ForceVTInput.Header" xml:space="preserve">
<value>Use the legacy input encoding</value>
<comment>Header for a control to toggle legacy input encoding for the terminal.</comment>
@@ -1110,11 +1114,11 @@
<value>Icon</value>
<comment>Header for a control to determine what icon can be used to represent this profile. This is not necessarily a file path, but can be one.</comment>
</data>
<data name="Profile_IconBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<data name="IconPicker_ImagePathBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Icon</value>
<comment>Name for a control to determine what icon can be used to represent this profile. This is not necessarily a file path, but can be one.</comment>
<comment>Name for a control to determine what icon can be used. This is not necessarily a file path, but can be one. It's usually used for images.</comment>
</data>
<data name="Profile_IconEmojiBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<data name="IconPicker_EmojiBox.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Icon</value>
<comment>Name for a control to determine what icon can be used to represent this profile.</comment>
</data>
@@ -1122,7 +1126,7 @@
<value>Emoji or image file location of the icon used in the profile.</value>
<comment>A description for what the "icon" setting does. Presented near "Profile_Icon".</comment>
</data>
<data name="Profile_IconBrowse.Content" xml:space="preserve">
<data name="IconPicker_IconBrowse.Content" xml:space="preserve">
<value>Browse...</value>
<comment>Button label that opens a file picker in a new window. The "..." is standard to mean it will open a new window.</comment>
</data>
@@ -2318,31 +2322,31 @@
<value>Use theme color</value>
<comment>Label for a button directing the user to use the tab color defined in the terminal's current theme.</comment>
</data>
<data name="Profile_IconTypeNone" xml:space="preserve">
<data name="IconPicker_IconTypeNone" xml:space="preserve">
<value>None</value>
<comment>An option to choose from for the "icon style" dropdown. When selected, there will be no icon for the profile.</comment>
<comment>An option to choose from for the "icon style" dropdown. When selected, there will be no icon set.</comment>
</data>
<data name="Profile_IconTypeImage" xml:space="preserve">
<data name="IconPicker_IconTypeImage" xml:space="preserve">
<value>File</value>
<comment>An option to choose from for the "icon style" dropdown. When selected, a custom image can set for the profile's icon.</comment>
<comment>An option to choose from for the "icon style" dropdown. When selected, a custom image can set as the icon.</comment>
</data>
<data name="Profile_IconTypeEmoji" xml:space="preserve">
<data name="IconPicker_IconTypeEmoji" xml:space="preserve">
<value>Emoji</value>
<comment>An option to choose from for the "icon style" dropdown. When selected, an emoji can be set for the profile's icon.</comment>
<comment>An option to choose from for the "icon style" dropdown. When selected, an emoji can be set as the icon.</comment>
</data>
<data name="Profile_IconTypeFontIcon" xml:space="preserve">
<data name="IconPicker_IconTypeFontIcon" xml:space="preserve">
<value>Built-in Icon</value>
<comment>An option to choose from for the "icon style" dropdown. When selected, the user can choose from several preselected options to set the profile's icon.</comment>
<comment>An option to choose from for the "icon style" dropdown. When selected, the user can choose from several preselected options to set as the icon.</comment>
</data>
<data name="Profile_IconEmojiBox.PlaceholderText" xml:space="preserve">
<data name="IconPicker_EmojiBox.PlaceholderText" xml:space="preserve">
<value>Use "Win + period" to open the emoji picker</value>
<comment>"Win + period" refers to the OS key binding to open the emoji picker.</comment>
</data>
<data name="Profile_IconType.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<data name="IconPicker_IconType.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Icon type</value>
<comment>Accessible name for a control allowing the user to select the type of icon they would like to use.</comment>
</data>
<data name="Profile_BuiltInIcon.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<data name="IconPicker_BuiltInIcon.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Icon</value>
<comment>Accessible name for a control allowing the user to select the icon from a list of built in icons.</comment>
</data>
@@ -2446,6 +2450,14 @@
<value>Folder Name</value>
<comment>Header for a control that allows the user to modify the name of the current folder entry.</comment>
</data>
<data name="NewTabMenu_CurrentFolderIcon.Header" xml:space="preserve">
<value>Folder Icon</value>
<comment>Header for a control that allows the user to modify the icon of the current folder entry.</comment>
</data>
<data name="NewTabMenu_CurrentFolderIcon.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Folder Icon</value>
<comment>Name for a control to that allows the user to modify the icon of the current folder entry.</comment>
</data>
<data name="NewTabMenu_CurrentFolderInlining.Header" xml:space="preserve">
<value>Allow inlining</value>
<comment>Header for a control that allows the nested entries to be presented inline rather than with a folder.</comment>
@@ -2701,4 +2713,16 @@
<data name="Settings_ResetApplicationStateConfirmationButton.Content" xml:space="preserve">
<value>Yes, clear the cache</value>
</data>
</root>
<data name="Nav_SearchBox.PlaceholderText" xml:space="preserve">
<value>Search for settings</value>
<comment>Placeholder text for the main search box in the settings editor.</comment>
</data>
<data name="Search_NoResults" xml:space="preserve">
<value>No results for "{}"</value>
<comment>{Locked="{}"} Displayed when no results were found for a given query. "{}" will be replaced with the query.</comment>
</data>
<data name="IconPicker_BuiltInIcon.PlaceholderText" xml:space="preserve">
<value>Type to filter icons</value>
<comment>Placeholder text for a text box to filter and select an icon.</comment>
</data>
</root>

View File

@@ -3,6 +3,8 @@
#pragma once
#include "SettingContainer.h"
// This macro must be used alongside GETSET_BINDABLE_ENUM_SETTING.
// Use this in your class's constructor after Initialize_Component().
// It sorts and initializes the observable list of enum entries with the enum name
@@ -116,4 +118,32 @@ struct HasScrollViewer
DismissAllPopups(uielem.XamlRoot());
}
}
// Finds the element with the given name and brings it into view
void BringIntoViewWhenLoaded(const winrt::hstring elementName)
{
if (elementName.empty())
{
return;
}
auto* pThis = static_cast<T*>(this);
_loadedRevoker = pThis->Loaded(winrt::auto_revoke, [weakThis{ pThis->get_weak() }, elementName](auto&&, auto&&) {
if (auto page{ weakThis.get() })
{
if (const auto& controlToFocus{ page->FindName(elementName).try_as<winrt::Windows::UI::Xaml::Controls::Control>() })
{
// We need to wait for the page to be loaded
// or else the call to StartBringIntoView()
// will end up doing nothing
controlToFocus.StartBringIntoView();
controlToFocus.Focus(winrt::Windows::UI::Xaml::FocusState::Programmatic);
}
page->_loadedRevoker.revoke();
}
});
}
protected:
winrt::Windows::UI::Xaml::FrameworkElement::Loaded_revoker _loadedRevoker;
};

View File

@@ -59,9 +59,8 @@ namespace winrt
namespace WARC = ::winrt::Windows::ApplicationModel::Resources::Core;
}
// Like RS_ and RS_fmt, but they use an ambient boolean named "localized" to
// determine whether to load the English version of a resource or the localized
// one.
// Like RS_ and RS_fmt, but they use an ambient context to determine
// whether to load the English version of a resource or the localized one.
#define RS_switchable_(x) RS_switchable_impl(context, USES_RESOURCE(x))
#define RS_switchable_fmt(x, ...) RS_switchable_fmt_impl(context, USES_RESOURCE(x), __VA_ARGS__)

View File

@@ -106,6 +106,7 @@ Author(s):
X(bool, AllowVtChecksumReport, "compatibility.allowDECRQCRA", false) \
X(bool, AllowVtClipboardWrite, "compatibility.allowOSC52", true) \
X(bool, AllowKeypadMode, "compatibility.allowDECNKM", false) \
X(bool, AllowTmuxControl, "AllowTmuxControl", false) \
X(Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle, "pathTranslationStyle", Microsoft::Terminal::Control::PathTranslationStyle::None)
// Intentionally omitted Profile settings:

View File

@@ -91,6 +91,7 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_PROFILE_SETTING(Boolean, AllowVtChecksumReport);
INHERITABLE_PROFILE_SETTING(Boolean, AllowKeypadMode);
INHERITABLE_PROFILE_SETTING(Boolean, AllowVtClipboardWrite);
INHERITABLE_PROFILE_SETTING(Boolean, AllowTmuxControl);
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.PathTranslationStyle, PathTranslationStyle);
}

View File

@@ -244,6 +244,39 @@ private:
static winrt::Windows::UI::Xaml::DependencyProperty _##name##Property;
#endif
#ifndef ATTACHED_DEPENDENCY_PROPERTY
#define ATTACHED_DEPENDENCY_PROPERTY(type, name) \
public: \
static winrt::Windows::UI::Xaml::DependencyProperty name##Property() \
{ \
return _##name##Property; \
} \
static type Get##name(winrt::Windows::UI::Xaml::DependencyObject const& target) \
{ \
auto&& temp{ target.GetValue(_##name##Property) }; \
if (temp) \
{ \
return winrt::unbox_value<type>(temp); \
} \
\
if constexpr (std::is_base_of_v<winrt::Windows::Foundation::IInspectable, type>) \
{ \
return { nullptr }; \
} \
else \
{ \
return {}; \
} \
} \
static void Set##name(winrt::Windows::UI::Xaml::DependencyObject const& target, const type& value) \
{ \
target.SetValue(_##name##Property, winrt::box_value(value)); \
} \
\
private: \
static winrt::Windows::UI::Xaml::DependencyProperty _##name##Property;
#endif
// Use this macro for quickly defining the factory_implementation part of a
// class. CppWinrt requires these for the compiler, but more often than not,
// they require no customization. See

View File

@@ -187,4 +187,16 @@
<alwaysDisabledReleaseTokens/>
</feature>
<feature>
<name>Feature_TmuxControl</name>
<description>Enables Tmux Control</description>
<id>3656</id>
<stage>AlwaysDisabled</stage>
<alwaysEnabledBrandingTokens>
<brandingToken>Dev</brandingToken>
<brandingToken>Canary</brandingToken>
<brandingToken>Preview</brandingToken>
</alwaysEnabledBrandingTokens>
</feature>
</featureStaging>

View File

@@ -427,7 +427,14 @@ void ConhostInternalGetSet::InvokeCompletions(std::wstring_view /*menuJson*/, un
{
// Not implemented for conhost.
}
void ConhostInternalGetSet::SearchMissingCommand(std::wstring_view /*missingCommand*/)
{
// Not implemented for conhost.
}
std::function<bool(wchar_t)> ConhostInternalGetSet::EnterTmuxControl()
{
// Not implemented for conhost.
return {};
}

View File

@@ -71,6 +71,7 @@ public:
void InvokeCompletions(std::wstring_view menuJson, unsigned int replaceLength) override;
void SearchMissingCommand(std::wstring_view missingCommand) override;
std::function<bool(wchar_t)> EnterTmuxControl() override;
private:
Microsoft::Console::IIoProvider& _io;

View File

@@ -192,6 +192,8 @@ public:
virtual void PlaySounds(const VTParameters parameters) = 0; // DECPS
virtual void SetOptionalFeatures(const til::enumset<OptionalFeature> features) = 0;
virtual StringHandler EnterTmuxControl(const VTParameters parameters) = 0; // tmux -CC
};
inline Microsoft::Console::VirtualTerminal::ITermDispatch::~ITermDispatch() = default;
#pragma warning(pop)

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