From f22295ef2c230f79340763b91a57f3f6c6739a24 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Tue, 22 Jul 2025 10:04:19 -0500 Subject: [PATCH] Merge TabBase+TerminalTab into just Tab (#19136) This removes the need to construct two objects per tab (TabBase, Actual Tab) and the other overhead inherent in WinRT composition-based inheritance. Important renames: - `GetTerminalTabImpl` -> `GetTabImpl` This pull request does not rename `TerminalTabStatus`; that is left as work for a future PR. Closes #17529 --- .../LocalTests_TerminalApp/TabTests.cpp | 54 +- .../TerminalApp/AppActionHandlers.cpp | 31 +- src/cascadia/TerminalApp/CommandPalette.cpp | 4 +- src/cascadia/TerminalApp/CommandPalette.h | 6 +- src/cascadia/TerminalApp/CommandPalette.idl | 6 +- .../TerminalApp/CommandPaletteItems.cpp | 10 +- .../TerminalApp/CommandPaletteItems.h | 11 +- src/cascadia/TerminalApp/Pane.cpp | 2 +- src/cascadia/TerminalApp/Pane.h | 4 +- .../TerminalApp/SuggestionsControl.idl | 1 - .../TerminalApp/{TerminalTab.cpp => Tab.cpp} | 853 ++++++++++++++++-- .../TerminalApp/{TerminalTab.h => Tab.h} | 88 +- .../TerminalApp/{TabBase.idl => Tab.idl} | 6 +- src/cascadia/TerminalApp/TabBase.cpp | 753 ---------------- src/cascadia/TerminalApp/TabBase.h | 92 -- src/cascadia/TerminalApp/TabManagement.cpp | 58 +- .../TerminalApp/TerminalAppLib.vcxproj | 17 +- .../TerminalAppLib.vcxproj.filters | 5 +- src/cascadia/TerminalApp/TerminalPage.cpp | 150 ++- src/cascadia/TerminalApp/TerminalPage.h | 66 +- src/cascadia/TerminalApp/TerminalTab.idl | 13 - .../TerminalApp/dll/TerminalApp.vcxproj | 1 - 22 files changed, 1034 insertions(+), 1197 deletions(-) rename src/cascadia/TerminalApp/{TerminalTab.cpp => Tab.cpp} (64%) rename src/cascadia/TerminalApp/{TerminalTab.h => Tab.h} (67%) rename src/cascadia/TerminalApp/{TabBase.idl => Tab.idl} (78%) delete mode 100644 src/cascadia/TerminalApp/TabBase.cpp delete mode 100644 src/cascadia/TerminalApp/TabBase.h delete mode 100644 src/cascadia/TerminalApp/TerminalTab.idl diff --git a/src/cascadia/LocalTests_TerminalApp/TabTests.cpp b/src/cascadia/LocalTests_TerminalApp/TabTests.cpp index 941d5fa06f..4e1744c66c 100644 --- a/src/cascadia/LocalTests_TerminalApp/TabTests.cpp +++ b/src/cascadia/LocalTests_TerminalApp/TabTests.cpp @@ -8,7 +8,7 @@ #include "../TerminalApp/MinMaxCloseControl.h" #include "../TerminalApp/TabRowControl.h" #include "../TerminalApp/ShortcutActionDispatch.h" -#include "../TerminalApp/TerminalTab.h" +#include "../TerminalApp/Tab.h" #include "../TerminalApp/CommandPalette.h" #include "../TerminalApp/ContentManager.h" #include "CppWinrtTailored.h" @@ -307,7 +307,7 @@ namespace TerminalAppLocalTests // reliably in the unit tests. Log::Comment(L"Ensure we set the first tab as the selected one."); auto tab = page->_tabs.GetAt(0); - auto tabImpl = page->_GetTerminalTabImpl(tab); + auto tabImpl = page->_GetTabImpl(tab); page->_tabView.SelectedItem(tabImpl->TabViewItem()); page->_UpdatedSelectedTab(tab); }); @@ -510,7 +510,7 @@ namespace TerminalAppLocalTests result = RunOnUIThread([&page]() { VERIFY_ARE_EQUAL(1u, page->_tabs.Size()); - auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto tab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(1, tab->GetLeafPaneCount()); }); VERIFY_SUCCEEDED(result); @@ -520,7 +520,7 @@ namespace TerminalAppLocalTests page->_SplitPane(nullptr, SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr)); VERIFY_ARE_EQUAL(1u, page->_tabs.Size()); - auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto tab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(2, tab->GetLeafPaneCount()); }); VERIFY_SUCCEEDED(result); @@ -538,7 +538,7 @@ namespace TerminalAppLocalTests page->_SplitPane(nullptr, SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr)); VERIFY_ARE_EQUAL(1u, page->_tabs.Size()); - auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto tab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(3, tab->GetLeafPaneCount(), L"We should successfully duplicate a pane hosting a deleted profile."); @@ -706,7 +706,7 @@ namespace TerminalAppLocalTests SplitPaneArgs args{ SplitType::Duplicate }; ActionEventArgs eventArgs{ args }; page->_HandleSplitPane(nullptr, eventArgs); - auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount()); VERIFY_IS_FALSE(firstTab->IsZoomed()); @@ -717,7 +717,7 @@ namespace TerminalAppLocalTests result = RunOnUIThread([&page]() { ActionEventArgs eventArgs{}; page->_HandleTogglePaneZoom(nullptr, eventArgs); - auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount()); VERIFY_IS_TRUE(firstTab->IsZoomed()); }); @@ -727,7 +727,7 @@ namespace TerminalAppLocalTests result = RunOnUIThread([&page]() { ActionEventArgs eventArgs{}; page->_HandleTogglePaneZoom(nullptr, eventArgs); - auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount()); VERIFY_IS_FALSE(firstTab->IsZoomed()); }); @@ -744,7 +744,7 @@ namespace TerminalAppLocalTests SplitPaneArgs args{ SplitType::Duplicate }; ActionEventArgs eventArgs{ args }; page->_HandleSplitPane(nullptr, eventArgs); - auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount()); VERIFY_IS_FALSE(firstTab->IsZoomed()); @@ -758,7 +758,7 @@ namespace TerminalAppLocalTests page->_HandleTogglePaneZoom(nullptr, eventArgs); - auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount()); VERIFY_IS_TRUE(firstTab->IsZoomed()); }); @@ -772,7 +772,7 @@ namespace TerminalAppLocalTests page->_HandleMoveFocus(nullptr, eventArgs); - auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount()); VERIFY_IS_TRUE(firstTab->IsZoomed()); }); @@ -789,7 +789,7 @@ namespace TerminalAppLocalTests SplitPaneArgs args{ SplitType::Duplicate }; ActionEventArgs eventArgs{ args }; page->_HandleSplitPane(nullptr, eventArgs); - auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount()); VERIFY_IS_FALSE(firstTab->IsZoomed()); @@ -803,7 +803,7 @@ namespace TerminalAppLocalTests page->_HandleTogglePaneZoom(nullptr, eventArgs); - auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount()); VERIFY_IS_TRUE(firstTab->IsZoomed()); }); @@ -816,7 +816,7 @@ namespace TerminalAppLocalTests page->_HandleClosePane(nullptr, eventArgs); - auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_IS_FALSE(firstTab->IsZoomed()); }); VERIFY_SUCCEEDED(result); @@ -827,7 +827,7 @@ namespace TerminalAppLocalTests Log::Comment(L"Check to ensure there's only one pane left."); result = RunOnUIThread([&page]() { - auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(1, firstTab->GetLeafPaneCount()); VERIFY_IS_FALSE(firstTab->IsZoomed()); }); @@ -850,7 +850,7 @@ namespace TerminalAppLocalTests uint32_t firstId = 0, secondId = 0, thirdId = 0, fourthId = 0; TestOnUIThread([&]() { VERIFY_ARE_EQUAL(1u, page->_tabs.Size()); - auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto tab = page->_GetTabImpl(page->_tabs.GetAt(0)); firstId = tab->_activePane->Id().value(); // We start with 1 tab, split vertically to get // ------------------- @@ -876,7 +876,7 @@ namespace TerminalAppLocalTests // | | | // ------------------- page->_SplitPane(nullptr, SplitDirection::Down, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr)); - auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto tab = page->_GetTabImpl(page->_tabs.GetAt(0)); // Split again to make the 3rd tab thirdId = tab->_activePane->Id().value(); }); @@ -896,13 +896,13 @@ namespace TerminalAppLocalTests // | | | // ------------------- page->_SplitPane(nullptr, SplitDirection::Down, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr)); - auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto tab = page->_GetTabImpl(page->_tabs.GetAt(0)); fourthId = tab->_activePane->Id().value(); }); Sleep(250); TestOnUIThread([&]() { - auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto tab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount()); // just to be complete, make sure we actually have 4 different ids VERIFY_ARE_NOT_EQUAL(firstId, fourthId); @@ -936,7 +936,7 @@ namespace TerminalAppLocalTests Sleep(250); TestOnUIThread([&]() { - auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto tab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount()); // Our currently focused pane should be `4` VERIFY_ARE_EQUAL(fourthId, tab->_activePane->Id().value()); @@ -967,7 +967,7 @@ namespace TerminalAppLocalTests Sleep(250); TestOnUIThread([&]() { - auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto tab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount()); // Our currently focused pane should be `4` VERIFY_ARE_EQUAL(fourthId, tab->_activePane->Id().value()); @@ -998,7 +998,7 @@ namespace TerminalAppLocalTests Sleep(250); TestOnUIThread([&]() { - auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto tab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount()); // Our currently focused pane should be `4` VERIFY_ARE_EQUAL(fourthId, tab->_activePane->Id().value()); @@ -1029,7 +1029,7 @@ namespace TerminalAppLocalTests Sleep(250); TestOnUIThread([&]() { - auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0)); + auto tab = page->_GetTabImpl(page->_tabs.GetAt(0)); VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount()); // Our currently focused pane should be `4` VERIFY_ARE_EQUAL(fourthId, tab->_activePane->Id().value()); @@ -1174,16 +1174,16 @@ namespace TerminalAppLocalTests Log::Comment(L"give alphabetical names to all switch tab actions"); TestOnUIThread([&page]() { - page->_GetTerminalTabImpl(page->_tabs.GetAt(0))->Title(L"a"); + page->_GetTabImpl(page->_tabs.GetAt(0))->Title(L"a"); }); TestOnUIThread([&page]() { - page->_GetTerminalTabImpl(page->_tabs.GetAt(1))->Title(L"b"); + page->_GetTabImpl(page->_tabs.GetAt(1))->Title(L"b"); }); TestOnUIThread([&page]() { - page->_GetTerminalTabImpl(page->_tabs.GetAt(2))->Title(L"c"); + page->_GetTabImpl(page->_tabs.GetAt(2))->Title(L"c"); }); TestOnUIThread([&page]() { - page->_GetTerminalTabImpl(page->_tabs.GetAt(3))->Title(L"d"); + page->_GetTabImpl(page->_tabs.GetAt(3))->Title(L"d"); }); TestOnUIThread([&page]() { diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index afb3e0a6e5..65845ffc6c 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -41,13 +41,13 @@ namespace winrt::TerminalApp::implementation } return _GetActiveControl(); } - winrt::com_ptr TerminalPage::_senderOrFocusedTab(const IInspectable& sender) + winrt::com_ptr TerminalPage::_senderOrFocusedTab(const IInspectable& sender) { if (sender) { - if (auto tab{ sender.try_as() }) + if (auto tab = sender.try_as()) { - return _GetTerminalTabImpl(tab); + return _GetTabImpl(tab); } } return _GetFocusedTabImpl(); @@ -193,17 +193,17 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_HandleCloseOtherPanes(const IInspectable& sender, const ActionEventArgs& args) { - if (const auto& terminalTab{ _senderOrFocusedTab(sender) }) + if (const auto& activeTab{ _senderOrFocusedTab(sender) }) { - const auto activePane = terminalTab->GetActivePane(); - if (terminalTab->GetRootPane() != activePane) + const auto activePane = activeTab->GetActivePane(); + if (activeTab->GetRootPane() != activePane) { _UnZoomIfNeeded(); // Accumulate list of all unfocused leaf panes, ignore read-only panes std::vector unfocusedPaneIds; const auto activePaneId = activePane->Id(); - terminalTab->GetRootPane()->WalkTree([&](auto&& p) { + activeTab->GetRootPane()->WalkTree([&](auto&& p) { const auto id = p->Id(); if (id.has_value() && id != activePaneId && !p->ContainsReadOnly()) { @@ -215,7 +215,7 @@ namespace winrt::TerminalApp::implementation { // Start by removing the panes that were least recently added sort(begin(unfocusedPaneIds), end(unfocusedPaneIds), std::less()); - _ClosePanes(terminalTab->get_weak(), std::move(unfocusedPaneIds)); + _ClosePanes(activeTab->get_weak(), std::move(unfocusedPaneIds)); args.Handled(true); return; } @@ -281,9 +281,9 @@ namespace winrt::TerminalApp::implementation const auto& duplicateFromTab{ realArgs.SplitMode() == SplitType::Duplicate ? _GetFocusedTab() : nullptr }; - const auto& terminalTab{ _senderOrFocusedTab(sender) }; + const auto& activeTab{ _senderOrFocusedTab(sender) }; - _SplitPane(terminalTab, + _SplitPane(activeTab, realArgs.SplitDirection(), // This is safe, we're already filtering so the value is (0, 1) realArgs.SplitSize(), @@ -302,14 +302,14 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_HandleTogglePaneZoom(const IInspectable& sender, const ActionEventArgs& args) { - if (const auto terminalTab{ _senderOrFocusedTab(sender) }) + if (const auto activeTab{ _senderOrFocusedTab(sender) }) { // Don't do anything if there's only one pane. It's already zoomed. - if (terminalTab->GetLeafPaneCount() > 1) + if (activeTab->GetLeafPaneCount() > 1) { // Togging the zoom on the tab will cause the tab to inform us of // the new root Content for this tab. - terminalTab->ToggleZoom(); + activeTab->ToggleZoom(); } } @@ -783,7 +783,7 @@ namespace winrt::TerminalApp::implementation } // Since _RemoveTabs is asynchronous, create a snapshot of the tabs we want to remove - std::vector tabsToRemove; + std::vector tabsToRemove; if (index > 0) { std::copy(begin(_tabs), begin(_tabs) + index, std::back_inserter(tabsToRemove)); @@ -822,7 +822,7 @@ namespace winrt::TerminalApp::implementation } // Since _RemoveTabs is asynchronous, create a snapshot of the tabs we want to remove - std::vector tabsToRemove; + std::vector tabsToRemove; std::copy(begin(_tabs) + index + 1, end(_tabs), std::back_inserter(tabsToRemove)); _RemoveTabs(tabsToRemove); @@ -1559,7 +1559,6 @@ namespace winrt::TerminalApp::implementation activeTab->ToggleBroadcastInput(); args.Handled(true); } - // If the focused tab wasn't a TerminalTab, then leave handled=false } void TerminalPage::_HandleRestartConnection(const IInspectable& sender, diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index 02c368e7e8..6caca24036 100644 --- a/src/cascadia/TerminalApp/CommandPalette.cpp +++ b/src/cascadia/TerminalApp/CommandPalette.cpp @@ -1072,7 +1072,7 @@ namespace winrt::TerminalApp::implementation // Return Value: // - void CommandPalette::_bindTabs( - const Windows::Foundation::Collections::IObservableVector& source, + const Windows::Foundation::Collections::IObservableVector& source, const Windows::Foundation::Collections::IVector& target) { target.Clear(); @@ -1084,7 +1084,7 @@ namespace winrt::TerminalApp::implementation } } - void CommandPalette::SetTabs(const Collections::IObservableVector& tabs, const Collections::IObservableVector& mruTabs) + void CommandPalette::SetTabs(const Collections::IObservableVector& tabs, const Collections::IObservableVector& mruTabs) { _bindTabs(tabs, _tabActions); _bindTabs(mruTabs, _mruTabActions); diff --git a/src/cascadia/TerminalApp/CommandPalette.h b/src/cascadia/TerminalApp/CommandPalette.h index 0da7ee1334..8e621b104d 100644 --- a/src/cascadia/TerminalApp/CommandPalette.h +++ b/src/cascadia/TerminalApp/CommandPalette.h @@ -31,7 +31,7 @@ namespace winrt::TerminalApp::implementation Windows::Foundation::Collections::IObservableVector FilteredActions(); - void SetTabs(const Windows::Foundation::Collections::IObservableVector& tabs, const Windows::Foundation::Collections::IObservableVector& mruTabs); + void SetTabs(const Windows::Foundation::Collections::IObservableVector& tabs, const Windows::Foundation::Collections::IObservableVector& mruTabs); void SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap); bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down); @@ -48,7 +48,7 @@ namespace winrt::TerminalApp::implementation void EnableTabSearchMode(); til::property_changed_event PropertyChanged; - til::typed_event SwitchToTabRequested; + til::typed_event SwitchToTabRequested; til::typed_event CommandLineExecutionRequested; til::typed_event DispatchCommandRequested; til::typed_event PreviewAction; @@ -135,7 +135,7 @@ namespace winrt::TerminalApp::implementation Microsoft::Terminal::Settings::Model::TabSwitcherMode _tabSwitcherMode; uint32_t _switcherStartIdx; - void _bindTabs(const Windows::Foundation::Collections::IObservableVector& source, const Windows::Foundation::Collections::IVector& target); + void _bindTabs(const Windows::Foundation::Collections::IObservableVector& source, const Windows::Foundation::Collections::IVector& target); void _anchorKeyUpHandler(); winrt::Windows::UI::Xaml::Controls::ListView::SizeChanged_revoker _sizeChangedRevoker; diff --git a/src/cascadia/TerminalApp/CommandPalette.idl b/src/cascadia/TerminalApp/CommandPalette.idl index 48787135a9..79fa26d736 100644 --- a/src/cascadia/TerminalApp/CommandPalette.idl +++ b/src/cascadia/TerminalApp/CommandPalette.idl @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import "TabBase.idl"; +import "Tab.idl"; import "HighlightedTextControl.idl"; import "FilteredCommand.idl"; @@ -20,7 +20,7 @@ namespace TerminalApp Windows.Foundation.Collections.IObservableVector FilteredActions { get; }; - void SetTabs(Windows.Foundation.Collections.IObservableVector tabs, Windows.Foundation.Collections.IObservableVector mruTabs); + void SetTabs(Windows.Foundation.Collections.IObservableVector tabs, Windows.Foundation.Collections.IObservableVector mruTabs); void SetActionMap(Microsoft.Terminal.Settings.Model.IActionMapView actionMap); @@ -30,7 +30,7 @@ namespace TerminalApp void EnableTabSwitcherMode(UInt32 startIdx, Microsoft.Terminal.Settings.Model.TabSwitcherMode tabSwitcherMode); void EnableTabSearchMode(); - event Windows.Foundation.TypedEventHandler SwitchToTabRequested; + event Windows.Foundation.TypedEventHandler SwitchToTabRequested; event Windows.Foundation.TypedEventHandler DispatchCommandRequested; event Windows.Foundation.TypedEventHandler CommandLineExecutionRequested; event Windows.Foundation.TypedEventHandler PreviewAction; diff --git a/src/cascadia/TerminalApp/CommandPaletteItems.cpp b/src/cascadia/TerminalApp/CommandPaletteItems.cpp index e23009cff9..e7e66a5164 100644 --- a/src/cascadia/TerminalApp/CommandPaletteItems.cpp +++ b/src/cascadia/TerminalApp/CommandPaletteItems.cpp @@ -2,7 +2,7 @@ // Licensed under the MIT license. #include "pch.h" -#include "TerminalTab.h" +#include "Tab.h" #include @@ -19,11 +19,11 @@ using namespace winrt::Microsoft::Terminal::Settings::Model; namespace winrt::TerminalApp::implementation { - TabPaletteItem::TabPaletteItem(const winrt::TerminalApp::TabBase& tab) : + TabPaletteItem::TabPaletteItem(const winrt::TerminalApp::Tab& tab) : _tab{ tab } { _tabChangedRevoker = tab.PropertyChanged(winrt::auto_revoke, [=](auto& sender, auto& e) { - if (auto senderTab{ sender.try_as() }) + if (auto senderTab{ sender.try_as() }) { auto changedProperty = e.PropertyName(); if (changedProperty == L"Title") @@ -38,10 +38,8 @@ namespace winrt::TerminalApp::implementation } }); - if (const auto terminalTab{ tab.try_as() }) + if (const auto status = tab.TabStatus()) { - const auto status = terminalTab.TabStatus(); - _tabStatusChangedRevoker = status.PropertyChanged(winrt::auto_revoke, [=](auto& /*sender*/, auto& /*e*/) { // Sometimes nested bindings do not get updated, // thus let's notify property changed on TabStatus when one of its properties changes diff --git a/src/cascadia/TerminalApp/CommandPaletteItems.h b/src/cascadia/TerminalApp/CommandPaletteItems.h index e625ac1d76..1912ee37b4 100644 --- a/src/cascadia/TerminalApp/CommandPaletteItems.h +++ b/src/cascadia/TerminalApp/CommandPaletteItems.h @@ -71,9 +71,9 @@ namespace winrt::TerminalApp::implementation public TabPaletteItemT, BasePaletteItem { - TabPaletteItem(const winrt::TerminalApp::TabBase& tab); + TabPaletteItem(const winrt::TerminalApp::Tab& tab); - winrt::TerminalApp::TabBase Tab() const noexcept + winrt::TerminalApp::Tab Tab() const noexcept { return _tab.get(); } @@ -105,16 +105,13 @@ namespace winrt::TerminalApp::implementation { if (auto tab = _tab.get()) { - if (auto terminalTab = tab.try_as()) - { - return terminalTab.TabStatus(); - } + return tab.TabStatus(); } return { nullptr }; } private: - winrt::weak_ref _tab; + winrt::weak_ref _tab; Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _tabChangedRevoker; Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _tabStatusChangedRevoker; }; diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index d8c7cd47d8..1afe0d118a 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -2429,7 +2429,7 @@ std::optional Pane::Id() noexcept // Method Description: // - Sets this pane's ID -// - Panes are given IDs upon creation by TerminalTab +// - Panes are given IDs upon creation by Tab // Arguments: // - The number to set this pane's ID to void Pane::Id(uint32_t id) noexcept diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h index 8bce64852d..ecc81fad82 100644 --- a/src/cascadia/TerminalApp/Pane.h +++ b/src/cascadia/TerminalApp/Pane.h @@ -31,7 +31,7 @@ namespace TerminalAppLocalTests namespace winrt::TerminalApp::implementation { - struct TerminalTab; + struct Tab; } enum class Borders : int @@ -398,6 +398,6 @@ private: LayoutSizeNode& operator=(const LayoutSizeNode& other); }; - friend struct winrt::TerminalApp::implementation::TerminalTab; + friend struct winrt::TerminalApp::implementation::Tab; friend class ::TerminalAppLocalTests::TabTests; }; diff --git a/src/cascadia/TerminalApp/SuggestionsControl.idl b/src/cascadia/TerminalApp/SuggestionsControl.idl index 0faea43928..e2b00784d9 100644 --- a/src/cascadia/TerminalApp/SuggestionsControl.idl +++ b/src/cascadia/TerminalApp/SuggestionsControl.idl @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import "TabBase.idl"; import "HighlightedTextControl.idl"; import "FilteredCommand.idl"; diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/Tab.cpp similarity index 64% rename from src/cascadia/TerminalApp/TerminalTab.cpp rename to src/cascadia/TerminalApp/Tab.cpp index c19730b597..6c305c66d1 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -4,9 +4,9 @@ #include "pch.h" #include #include "ColorPickupFlyout.h" -#include "TerminalTab.h" +#include "Tab.h" #include "SettingsPaneContent.h" -#include "TerminalTab.g.cpp" +#include "Tab.g.cpp" #include "Utils.h" #include "ColorHelper.h" #include "AppLogic.h" @@ -30,7 +30,7 @@ namespace winrt namespace winrt::TerminalApp::implementation { - TerminalTab::TerminalTab(std::shared_ptr rootPane) + Tab::Tab(std::shared_ptr rootPane) { _rootPane = rootPane; _activePane = nullptr; @@ -77,7 +77,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalTab::_Setup() + void Tab::_Setup() { _rootClosedToken = _rootPane->Closed([=](auto&& /*s*/, auto&& /*e*/) { Closed.raise(nullptr, nullptr); @@ -118,7 +118,7 @@ namespace winrt::TerminalApp::implementation // - Removes the bell indicator from the tab header // Arguments: // - sender, e: not used - void TerminalTab::_BellIndicatorTimerTick(const Windows::Foundation::IInspectable& /*sender*/, const Windows::Foundation::IInspectable& /*e*/) + void Tab::_BellIndicatorTimerTick(const Windows::Foundation::IInspectable& /*sender*/, const Windows::Foundation::IInspectable& /*e*/) { ShowBellIndicator(false); _bellIndicatorTimer.Stop(); @@ -130,9 +130,31 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalTab::_MakeTabViewItem() + void Tab::_MakeTabViewItem() { - TabBase::_MakeTabViewItem(); + TabViewItem(::winrt::MUX::Controls::TabViewItem{}); + + // GH#3609 If the tab was tapped, and no one else was around to handle + // it, then ask our parent to toss focus into the active control. + TabViewItem().Tapped([weakThis{ get_weak() }](auto&&, auto&&) { + if (auto tab{ weakThis.get() }) + { + tab->RequestFocusActiveControl.raise(); + } + }); + + // BODGY: When the tab is drag/dropped, the TabView gets a + // TabDragStarting. However, the way it is implemented[^1], the + // TabViewItem needs either an Item or a Content for the event to + // include the correct TabViewItem. Otherwise, it will just return the + // first TabViewItem in the TabView with the same Content as the dragged + // tab (which, if the Content is null, will be the _first_ tab). + // + // So here, we'll stick an empty border in, just so that every tab has a + // Content which is not equal to the others. + // + // [^1]: microsoft-ui-xaml/blob/92fbfcd55f05c92ac65569f5d284c5b36492091e/dev/TabView/TabView.cpp#L751-L758 + TabViewItem().Content(winrt::WUX::Controls::Border{}); TabViewItem().DoubleTapped([weakThis = get_weak()](auto&& /*s*/, auto&& /*e*/) { if (auto tab{ weakThis.get() }) @@ -145,7 +167,7 @@ namespace winrt::TerminalApp::implementation _RecalculateAndApplyTabColor(); } - void TerminalTab::_UpdateHeaderControlMaxWidth() + void Tab::_UpdateHeaderControlMaxWidth() { try { @@ -164,6 +186,73 @@ namespace winrt::TerminalApp::implementation CATCH_LOG() } + void Tab::SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch) + { + ASSERT_UI_THREAD(); + + _dispatch = dispatch; + } + + void Tab::SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap) + { + ASSERT_UI_THREAD(); + + _actionMap = actionMap; + _UpdateSwitchToTabKeyChord(); + } + + // Method Description: + // - Sets the key chord resulting in switch to the current tab. + // Updates tool tip if required + // Arguments: + // - keyChord - string representation of the key chord that switches to the current tab + // Return Value: + // - + void Tab::_UpdateSwitchToTabKeyChord() + { + const auto id = fmt::format(FMT_COMPILE(L"Terminal.SwitchToTab{}"), _TabViewIndex); + const auto keyChord{ _actionMap.GetKeyBindingForAction(id) }; + const auto keyChordText = keyChord ? KeyChordSerialization::ToString(keyChord) : L""; + + if (_keyChord == keyChordText) + { + return; + } + + _keyChord = keyChordText; + _UpdateToolTip(); + } + + // Method Description: + // - Sets tab tool tip to a concatenation of title and key chord + // Arguments: + // - + // Return Value: + // - + void Tab::_UpdateToolTip() + { + auto titleRun = WUX::Documents::Run(); + titleRun.Text(_CreateToolTipTitle()); + + auto textBlock = WUX::Controls::TextBlock{}; + textBlock.TextWrapping(WUX::TextWrapping::Wrap); + textBlock.TextAlignment(WUX::TextAlignment::Center); + textBlock.Inlines().Append(titleRun); + + if (!_keyChord.empty()) + { + auto keyChordRun = WUX::Documents::Run(); + keyChordRun.Text(_keyChord); + keyChordRun.FontStyle(winrt::Windows::UI::Text::FontStyle::Italic); + textBlock.Inlines().Append(WUX::Documents::LineBreak{}); + textBlock.Inlines().Append(keyChordRun); + } + + WUX::Controls::ToolTip toolTip{}; + toolTip.Content(textBlock); + WUX::Controls::ToolTipService::SetToolTip(TabViewItem(), toolTip); + } + // Method Description: // - Returns nullptr if no children of this tab were the last control to be // focused, the active control of the current pane, or the last active child control @@ -175,7 +264,7 @@ namespace winrt::TerminalApp::implementation // Return Value: // - nullptr if no children were marked `_lastFocused`, else the TermControl // that was last focused. - TermControl TerminalTab::GetActiveTerminalControl() const + TermControl Tab::GetActiveTerminalControl() const { ASSERT_UI_THREAD(); @@ -186,7 +275,7 @@ namespace winrt::TerminalApp::implementation return nullptr; } - IPaneContent TerminalTab::GetActiveContent() const + IPaneContent Tab::GetActiveContent() const { return _activePane ? _activePane->GetContent() : nullptr; } @@ -198,7 +287,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalTab::Initialize() + void Tab::Initialize() { ASSERT_UI_THREAD(); @@ -219,7 +308,7 @@ namespace winrt::TerminalApp::implementation // - focused: our new focus state // Return Value: // - - void TerminalTab::Focus(WUX::FocusState focusState) + void Tab::Focus(WUX::FocusState focusState) { ASSERT_UI_THREAD(); @@ -253,7 +342,7 @@ namespace winrt::TerminalApp::implementation // Return Value: // - nullopt if no children of this tab were the last control to be // focused, else the GUID of the profile of the last control to be focused - Profile TerminalTab::GetFocusedProfile() const noexcept + Profile Tab::GetFocusedProfile() const noexcept { ASSERT_UI_THREAD(); @@ -266,7 +355,7 @@ namespace winrt::TerminalApp::implementation // of the settings that apply to all tabs. // Return Value: // - - void TerminalTab::UpdateSettings(const CascadiaSettings& settings) + void Tab::UpdateSettings(const CascadiaSettings& settings) { ASSERT_UI_THREAD(); @@ -286,7 +375,7 @@ namespace winrt::TerminalApp::implementation // - iconPath: The new path string to use as the IconPath for our TabViewItem // Return Value: // - - void TerminalTab::UpdateIcon(const winrt::hstring& iconPath, const winrt::Microsoft::Terminal::Settings::Model::IconStyle iconStyle) + void Tab::UpdateIcon(const winrt::hstring& iconPath, const winrt::Microsoft::Terminal::Settings::Model::IconStyle iconStyle) { ASSERT_UI_THREAD(); @@ -324,7 +413,7 @@ namespace winrt::TerminalApp::implementation // - Used when we want to show the progress ring, which should replace the icon // Arguments: // - hide: if true, we hide the icon; if false, we show the icon - void TerminalTab::HideIcon(const bool hide) + void Tab::HideIcon(const bool hide) { ASSERT_UI_THREAD(); @@ -348,7 +437,7 @@ namespace winrt::TerminalApp::implementation // - Hide or show the bell indicator in the tab header // Arguments: // - show: if true, we show the indicator; if false, we hide the indicator - void TerminalTab::ShowBellIndicator(const bool show) + void Tab::ShowBellIndicator(const bool show) { ASSERT_UI_THREAD(); @@ -358,14 +447,14 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Activates the timer for the bell indicator in the tab // - Called if a bell raised when the tab already has focus - void TerminalTab::ActivateBellIndicatorTimer() + void Tab::ActivateBellIndicatorTimer() { ASSERT_UI_THREAD(); if (!_bellIndicatorTimer) { _bellIndicatorTimer.Interval(std::chrono::milliseconds(2000)); - _bellIndicatorTimer.Tick({ get_weak(), &TerminalTab::_BellIndicatorTimerTick }); + _bellIndicatorTimer.Tick({ get_weak(), &Tab::_BellIndicatorTimerTick }); } _bellIndicatorTimer.Start(); @@ -378,7 +467,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - the title string of the last focused terminal control in our tree. - winrt::hstring TerminalTab::_GetActiveTitle() const + winrt::hstring Tab::_GetActiveTitle() const { if (!_runtimeTabText.empty()) { @@ -400,7 +489,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalTab::UpdateTitle() + void Tab::UpdateTitle() { ASSERT_UI_THREAD(); @@ -422,7 +511,7 @@ namespace winrt::TerminalApp::implementation // - delta: a number of lines to move the viewport relative to the current viewport. // Return Value: // - - void TerminalTab::Scroll(const int delta) + void Tab::Scroll(const int delta) { ASSERT_UI_THREAD(); @@ -438,7 +527,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - A vector of commands - std::vector TerminalTab::BuildStartupActions(BuildStartupKind kind) const + std::vector Tab::BuildStartupActions(BuildStartupKind kind) const { ASSERT_UI_THREAD(); @@ -525,9 +614,9 @@ namespace winrt::TerminalApp::implementation // could itself be a parent pane/the root node of a tree of panes // Return Value: // - a pair of (the Pane that now holds the original content, the new Pane in the tree) - std::pair, std::shared_ptr> TerminalTab::SplitPane(SplitDirection splitType, - const float splitSize, - std::shared_ptr pane) + std::pair, std::shared_ptr> Tab::SplitPane(SplitDirection splitType, + const float splitSize, + std::shared_ptr pane) { ASSERT_UI_THREAD(); @@ -586,7 +675,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - The removed pane, if the remove succeeded. - std::shared_ptr TerminalTab::DetachPane() + std::shared_ptr Tab::DetachPane() { ASSERT_UI_THREAD(); @@ -615,7 +704,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - The root pane. - std::shared_ptr TerminalTab::DetachRoot() + std::shared_ptr Tab::DetachRoot() { ASSERT_UI_THREAD(); @@ -643,7 +732,7 @@ namespace winrt::TerminalApp::implementation // - pane: The pane to add. // Return Value: // - - void TerminalTab::AttachPane(std::shared_ptr pane) + void Tab::AttachPane(std::shared_ptr pane) { ASSERT_UI_THREAD(); @@ -694,7 +783,7 @@ namespace winrt::TerminalApp::implementation // - colorPicker: The color picker that we should attach to ourselves // Return Value: // - - void TerminalTab::AttachColorPicker(TerminalApp::ColorPickupFlyout& colorPicker) + void Tab::AttachColorPicker(TerminalApp::ColorPickupFlyout& colorPicker) { ASSERT_UI_THREAD(); @@ -734,7 +823,7 @@ namespace winrt::TerminalApp::implementation // its parent. E.g. switch from Horizontal to Vertical. // Return Value: // - - void TerminalTab::ToggleSplitOrientation() + void Tab::ToggleSplitOrientation() { ASSERT_UI_THREAD(); @@ -743,7 +832,7 @@ namespace winrt::TerminalApp::implementation // Method Description: // - See Pane::CalcSnappedDimension - float TerminalTab::CalcSnappedDimension(const bool widthOrHeight, const float dimension) const + float Tab::CalcSnappedDimension(const bool widthOrHeight, const float dimension) const { ASSERT_UI_THREAD(); @@ -757,7 +846,7 @@ namespace winrt::TerminalApp::implementation // - direction: The direction to move the separator in. // Return Value: // - - void TerminalTab::ResizePane(const ResizeDirection& direction) + void Tab::ResizePane(const ResizeDirection& direction) { ASSERT_UI_THREAD(); @@ -774,7 +863,7 @@ namespace winrt::TerminalApp::implementation // Return Value: // - Whether changing the focus succeeded. This allows a keychord to propagate // to the terminal when no other panes are present (GH#6219) - bool TerminalTab::NavigateFocus(const FocusDirection& direction) + bool Tab::NavigateFocus(const FocusDirection& direction) { ASSERT_UI_THREAD(); @@ -806,7 +895,7 @@ namespace winrt::TerminalApp::implementation // - direction: The direction to move the pane in. // Return Value: // - true if two panes were swapped. - bool TerminalTab::SwapPane(const FocusDirection& direction) + bool Tab::SwapPane(const FocusDirection& direction) { ASSERT_UI_THREAD(); @@ -831,7 +920,7 @@ namespace winrt::TerminalApp::implementation return false; } - bool TerminalTab::FocusPane(const uint32_t id) + bool Tab::FocusPane(const uint32_t id) { ASSERT_UI_THREAD(); @@ -847,12 +936,12 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Prepares this tab for being removed from the UI hierarchy by shutting down all active connections. - void TerminalTab::Shutdown() + void Tab::Shutdown() { ASSERT_UI_THREAD(); - // Don't forget to call the overridden function. :) - TabBase::Shutdown(); + // NOTE: `TerminalPage::_HandleCloseTabRequested` relies on the content being null after this call. + Content(nullptr); if (_rootPane) { @@ -868,14 +957,14 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalTab::ClosePane() + void Tab::ClosePane() { ASSERT_UI_THREAD(); _activePane->Close(); } - void TerminalTab::SetTabText(winrt::hstring title) + void Tab::SetTabText(winrt::hstring title) { ASSERT_UI_THREAD(); @@ -883,14 +972,14 @@ namespace winrt::TerminalApp::implementation UpdateTitle(); } - winrt::hstring TerminalTab::GetTabText() const + winrt::hstring Tab::GetTabText() const { ASSERT_UI_THREAD(); return _runtimeTabText; } - void TerminalTab::ResetTabText() + void Tab::ResetTabText() { ASSERT_UI_THREAD(); @@ -905,7 +994,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalTab::ActivateTabRenamer() + void Tab::ActivateTabRenamer() { ASSERT_UI_THREAD(); @@ -921,7 +1010,7 @@ namespace winrt::TerminalApp::implementation // - paneId: The ID of the pane that contains the given content. // Return Value: // - - void TerminalTab::_DetachEventHandlersFromContent(const uint32_t paneId) + void Tab::_DetachEventHandlersFromContent(const uint32_t paneId) { auto it = _contentEvents.find(paneId); if (it != _contentEvents.end()) @@ -943,7 +1032,7 @@ namespace winrt::TerminalApp::implementation // - control: the TermControl to add events to. // Return Value: // - - void TerminalTab::_AttachEventHandlersToContent(const uint32_t paneId, const TerminalApp::IPaneContent& content) + void Tab::_AttachEventHandlersToContent(const uint32_t paneId, const TerminalApp::IPaneContent& content) { auto weakThis{ get_weak() }; auto dispatcher = TabViewItem().Dispatcher(); @@ -1059,7 +1148,7 @@ namespace winrt::TerminalApp::implementation if (const auto& terminal{ content.try_as() }) { - events.RestartTerminalRequested = terminal.RestartTerminalRequested(winrt::auto_revoke, { get_weak(), &TerminalTab::_bubbleRestartTerminalRequested }); + events.RestartTerminalRequested = terminal.RestartTerminalRequested(winrt::auto_revoke, { get_weak(), &Tab::_bubbleRestartTerminalRequested }); } if (_tabStatus.IsInputBroadcastActive()) @@ -1085,7 +1174,7 @@ namespace winrt::TerminalApp::implementation // Return Value: // - A TaskbarState object representing the combined taskbar state and // progress percentage of all our panes. - winrt::TerminalApp::TaskbarState TerminalTab::GetCombinedTaskbarState() const + winrt::TerminalApp::TaskbarState Tab::GetCombinedTaskbarState() const { ASSERT_UI_THREAD(); @@ -1111,7 +1200,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalTab::_UpdateProgressState() + void Tab::_UpdateProgressState() { const auto state{ GetCombinedTaskbarState() }; @@ -1155,7 +1244,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalTab::_UpdateConnectionClosedState() + void Tab::_UpdateConnectionClosedState() { ASSERT_UI_THREAD(); @@ -1176,7 +1265,7 @@ namespace winrt::TerminalApp::implementation } } - void TerminalTab::_RestartActivePaneConnection() + void Tab::_RestartActivePaneConnection() { ActionAndArgs restartConnection{ ShortcutAction::RestartConnection, nullptr }; _dispatch.DoAction(*this, restartConnection); @@ -1190,7 +1279,7 @@ namespace winrt::TerminalApp::implementation // - pane: a Pane to mark as active. // Return Value: // - - void TerminalTab::_UpdateActivePane(std::shared_ptr pane) + void Tab::_UpdateActivePane(std::shared_ptr pane) { // Clear the active state of the entire tree, and mark only the pane as active. _rootPane->ClearActive(); @@ -1255,7 +1344,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalTab::_AttachEventHandlersToPane(std::shared_ptr pane) + void Tab::_AttachEventHandlersToPane(std::shared_ptr pane) { auto weakThis{ get_weak() }; std::weak_ptr weakPane{ pane }; @@ -1369,6 +1458,139 @@ namespace winrt::TerminalApp::implementation }); } + void Tab::_AppendMoveMenuItems(winrt::Windows::UI::Xaml::Controls::MenuFlyout flyout) + { + auto weakThis{ get_weak() }; + + // Move to new window + { + Controls::FontIcon moveTabToNewWindowTabSymbol; + moveTabToNewWindowTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); + moveTabToNewWindowTabSymbol.Glyph(L"\xE8A7"); + + _moveToNewWindowMenuItem.Click([weakThis](auto&&, auto&&) { + if (auto tab{ weakThis.get() }) + { + MoveTabArgs args{ L"new", MoveTabDirection::Forward }; + ActionAndArgs actionAndArgs{ ShortcutAction::MoveTab, args }; + tab->_dispatch.DoAction(*tab, actionAndArgs); + } + }); + _moveToNewWindowMenuItem.Text(RS_(L"MoveTabToNewWindowText")); + _moveToNewWindowMenuItem.Icon(moveTabToNewWindowTabSymbol); + + const auto moveTabToNewWindowToolTip = RS_(L"MoveTabToNewWindowToolTip"); + WUX::Controls::ToolTipService::SetToolTip(_moveToNewWindowMenuItem, box_value(moveTabToNewWindowToolTip)); + Automation::AutomationProperties::SetHelpText(_moveToNewWindowMenuItem, moveTabToNewWindowToolTip); + } + + // Move left + { + _moveLeftMenuItem.Click([weakThis](auto&&, auto&&) { + if (auto tab{ weakThis.get() }) + { + MoveTabArgs args{ hstring{}, MoveTabDirection::Backward }; + ActionAndArgs actionAndArgs{ ShortcutAction::MoveTab, args }; + tab->_dispatch.DoAction(*tab, actionAndArgs); + } + }); + _moveLeftMenuItem.Text(RS_(L"TabMoveLeft")); + } + + // Move right + { + _moveRightMenuItem.Click([weakThis](auto&&, auto&&) { + if (auto tab{ weakThis.get() }) + { + MoveTabArgs args{ hstring{}, MoveTabDirection::Forward }; + ActionAndArgs actionAndArgs{ ShortcutAction::MoveTab, args }; + tab->_dispatch.DoAction(*tab, actionAndArgs); + } + }); + _moveRightMenuItem.Text(RS_(L"TabMoveRight")); + } + + // Create a sub-menu for our extended move tab items. + Controls::MenuFlyoutSubItem moveSubMenu; + moveSubMenu.Text(RS_(L"TabMoveSubMenu")); + moveSubMenu.Items().Append(_moveToNewWindowMenuItem); + moveSubMenu.Items().Append(_moveRightMenuItem); + moveSubMenu.Items().Append(_moveLeftMenuItem); + flyout.Items().Append(moveSubMenu); + } + + // Method Description: + // - Append the close menu items to the context menu flyout + // Arguments: + // - flyout - the menu flyout to which the close items must be appended + // Return Value: + // - the sub-item that we use for all the nested "close" entries. This + // enables subclasses to add their own entries to this menu. + winrt::Windows::UI::Xaml::Controls::MenuFlyoutSubItem Tab::_AppendCloseMenuItems(winrt::Windows::UI::Xaml::Controls::MenuFlyout flyout) + { + auto weakThis{ get_weak() }; + + // Close tabs after + _closeTabsAfterMenuItem.Click([weakThis](auto&&, auto&&) { + if (auto tab{ weakThis.get() }) + { + CloseTabsAfterArgs args{ tab->_TabViewIndex }; + ActionAndArgs closeTabsAfter{ ShortcutAction::CloseTabsAfter, args }; + tab->_dispatch.DoAction(*tab, closeTabsAfter); + } + }); + _closeTabsAfterMenuItem.Text(RS_(L"TabCloseAfter")); + const auto closeTabsAfterToolTip = RS_(L"TabCloseAfterToolTip"); + + WUX::Controls::ToolTipService::SetToolTip(_closeTabsAfterMenuItem, box_value(closeTabsAfterToolTip)); + Automation::AutomationProperties::SetHelpText(_closeTabsAfterMenuItem, closeTabsAfterToolTip); + + // Close other tabs + _closeOtherTabsMenuItem.Click([weakThis](auto&&, auto&&) { + if (auto tab{ weakThis.get() }) + { + CloseOtherTabsArgs args{ tab->_TabViewIndex }; + ActionAndArgs closeOtherTabs{ ShortcutAction::CloseOtherTabs, args }; + tab->_dispatch.DoAction(*tab, closeOtherTabs); + } + }); + _closeOtherTabsMenuItem.Text(RS_(L"TabCloseOther")); + const auto closeOtherTabsToolTip = RS_(L"TabCloseOtherToolTip"); + + WUX::Controls::ToolTipService::SetToolTip(_closeOtherTabsMenuItem, box_value(closeOtherTabsToolTip)); + Automation::AutomationProperties::SetHelpText(_closeOtherTabsMenuItem, closeOtherTabsToolTip); + + // Close + Controls::MenuFlyoutItem closeTabMenuItem; + Controls::FontIcon closeSymbol; + closeSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); + closeSymbol.Glyph(L"\xE711"); + + closeTabMenuItem.Click([weakThis](auto&&, auto&&) { + if (auto tab{ weakThis.get() }) + { + tab->CloseRequested.raise(nullptr, nullptr); + } + }); + closeTabMenuItem.Text(RS_(L"TabClose")); + closeTabMenuItem.Icon(closeSymbol); + const auto closeTabToolTip = RS_(L"TabCloseToolTip"); + + WUX::Controls::ToolTipService::SetToolTip(closeTabMenuItem, box_value(closeTabToolTip)); + Automation::AutomationProperties::SetHelpText(closeTabMenuItem, closeTabToolTip); + + // Create a sub-menu for our extended close items. + Controls::MenuFlyoutSubItem closeSubMenu; + closeSubMenu.Text(RS_(L"TabCloseSubMenu")); + closeSubMenu.Items().Append(_closeTabsAfterMenuItem); + closeSubMenu.Items().Append(_closeOtherTabsMenuItem); + flyout.Items().Append(closeSubMenu); + + flyout.Items().Append(closeTabMenuItem); + + return closeSubMenu; + } + // Method Description: // - Creates a context menu attached to the tab. // Currently contains elements allowing to select or @@ -1377,7 +1599,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalTab::_CreateContextMenu() + void Tab::_CreateContextMenu() { auto weakThis{ get_weak() }; @@ -1388,7 +1610,7 @@ namespace winrt::TerminalApp::implementation colorPickSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); colorPickSymbol.Glyph(L"\xE790"); - chooseColorMenuItem.Click({ get_weak(), &TerminalTab::_chooseColorClicked }); + chooseColorMenuItem.Click({ get_weak(), &Tab::_chooseColorClicked }); chooseColorMenuItem.Text(RS_(L"TabColorChoose")); chooseColorMenuItem.Icon(colorPickSymbol); @@ -1405,7 +1627,7 @@ namespace winrt::TerminalApp::implementation renameTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); renameTabSymbol.Glyph(L"\xE8AC"); // Rename - renameTabMenuItem.Click({ get_weak(), &TerminalTab::_renameTabClicked }); + renameTabMenuItem.Click({ get_weak(), &Tab::_renameTabClicked }); renameTabMenuItem.Text(RS_(L"RenameTabText")); renameTabMenuItem.Icon(renameTabSymbol); @@ -1422,7 +1644,7 @@ namespace winrt::TerminalApp::implementation duplicateTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); duplicateTabSymbol.Glyph(L"\xF5ED"); - duplicateTabMenuItem.Click({ get_weak(), &TerminalTab::_duplicateTabClicked }); + duplicateTabMenuItem.Click({ get_weak(), &Tab::_duplicateTabClicked }); duplicateTabMenuItem.Text(RS_(L"DuplicateTabText")); duplicateTabMenuItem.Icon(duplicateTabSymbol); @@ -1439,7 +1661,7 @@ namespace winrt::TerminalApp::implementation splitTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); splitTabSymbol.Glyph(L"\xF246"); // ViewDashboard - splitTabMenuItem.Click({ get_weak(), &TerminalTab::_splitTabClicked }); + splitTabMenuItem.Click({ get_weak(), &Tab::_splitTabClicked }); splitTabMenuItem.Text(RS_(L"SplitTabText")); splitTabMenuItem.Icon(splitTabSymbol); @@ -1452,7 +1674,7 @@ namespace winrt::TerminalApp::implementation Controls::MenuFlyoutItem closePaneMenuItem = _closePaneMenuItem; { // "Close pane" - closePaneMenuItem.Click({ get_weak(), &TerminalTab::_closePaneClicked }); + closePaneMenuItem.Click({ get_weak(), &Tab::_closePaneClicked }); closePaneMenuItem.Text(RS_(L"ClosePaneText")); const auto closePaneToolTip = RS_(L"ClosePaneToolTip"); @@ -1468,7 +1690,7 @@ namespace winrt::TerminalApp::implementation exportTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); exportTabSymbol.Glyph(L"\xE74E"); // Save - exportTabMenuItem.Click({ get_weak(), &TerminalTab::_exportTextClicked }); + exportTabMenuItem.Click({ get_weak(), &Tab::_exportTextClicked }); exportTabMenuItem.Text(RS_(L"ExportTabText")); exportTabMenuItem.Icon(exportTabSymbol); @@ -1485,7 +1707,7 @@ namespace winrt::TerminalApp::implementation findSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); findSymbol.Glyph(L"\xF78B"); // SearchMedium - findMenuItem.Click({ get_weak(), &TerminalTab::_findClicked }); + findMenuItem.Click({ get_weak(), &Tab::_findClicked }); findMenuItem.Text(RS_(L"FindText")); findMenuItem.Icon(findSymbol); @@ -1556,13 +1778,47 @@ namespace winrt::TerminalApp::implementation TabViewItem().ContextFlyout(contextMenuFlyout); } + // Method Description: + // - Enable menu items based on tab index and total number of tabs + // Arguments: + // - + // Return Value: + // - + void Tab::_EnableMenuItems() + { + const auto tabIndex = TabViewIndex(); + const auto numOfTabs = TabViewNumTabs(); + + // enabled if there are other tabs + _closeOtherTabsMenuItem.IsEnabled(numOfTabs > 1); + + // enabled if there are other tabs on the right + _closeTabsAfterMenuItem.IsEnabled(tabIndex < numOfTabs - 1); + + // enabled if not left-most tab + _moveLeftMenuItem.IsEnabled(tabIndex > 0); + + // enabled if not last tab + _moveRightMenuItem.IsEnabled(tabIndex < numOfTabs - 1); + } + + void Tab::UpdateTabViewIndex(const uint32_t idx, const uint32_t numTabs) + { + ASSERT_UI_THREAD(); + + TabViewIndex(idx); + TabViewNumTabs(numTabs); + _EnableMenuItems(); + _UpdateSwitchToTabKeyChord(); + } + // Method Description: // Returns the tab color, if any // Arguments: // - // Return Value: // - The tab's color, if any - std::optional TerminalTab::GetTabColor() + std::optional Tab::GetTabColor() { ASSERT_UI_THREAD(); @@ -1602,7 +1858,7 @@ namespace winrt::TerminalApp::implementation // - color: the color the user picked for their tab // Return Value: // - - void TerminalTab::SetRuntimeTabColor(const winrt::Windows::UI::Color& color) + void Tab::SetRuntimeTabColor(const winrt::Windows::UI::Color& color) { ASSERT_UI_THREAD(); @@ -1619,7 +1875,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalTab::ResetRuntimeTabColor() + void Tab::ResetRuntimeTabColor() { ASSERT_UI_THREAD(); @@ -1628,7 +1884,7 @@ namespace winrt::TerminalApp::implementation _tabStatus.TabColorIndicator(GetTabColor().value_or(Windows::UI::Colors::Transparent())); } - winrt::Windows::UI::Xaml::Media::Brush TerminalTab::_BackgroundBrush() + winrt::Windows::UI::Xaml::Media::Brush Tab::_BackgroundBrush() { Media::Brush terminalBrush{ nullptr }; if (const auto& c{ GetActiveContent() }) @@ -1644,7 +1900,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - The total number of leaf panes hosted by this tab. - int TerminalTab::GetLeafPaneCount() const noexcept + int Tab::GetLeafPaneCount() const noexcept { ASSERT_UI_THREAD(); @@ -1661,9 +1917,9 @@ namespace winrt::TerminalApp::implementation // Return value: // - This will return nullopt if a split of the given size/direction was not possible, // or it will return the split direction with automatic converted to a cardinal direction. - std::optional TerminalTab::PreCalculateCanSplit(SplitDirection splitType, - const float splitSize, - winrt::Windows::Foundation::Size availableSpace) const + std::optional Tab::PreCalculateCanSplit(SplitDirection splitType, + const float splitSize, + winrt::Windows::Foundation::Size availableSpace) const { ASSERT_UI_THREAD(); @@ -1676,7 +1932,7 @@ namespace winrt::TerminalApp::implementation // - newFocus: the new pane to be zoomed // Return Value: // - - void TerminalTab::UpdateZoom(std::shared_ptr newFocus) + void Tab::UpdateZoom(std::shared_ptr newFocus) { ASSERT_UI_THREAD(); @@ -1698,7 +1954,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - void TerminalTab::ToggleZoom() + void Tab::ToggleZoom() { ASSERT_UI_THREAD(); @@ -1712,7 +1968,7 @@ namespace winrt::TerminalApp::implementation } } - void TerminalTab::EnterZoom() + void Tab::EnterZoom() { ASSERT_UI_THREAD(); @@ -1727,7 +1983,7 @@ namespace winrt::TerminalApp::implementation _tabStatus.IsPaneZoomed(true); Content(_zoomedPane->GetRootElement()); } - void TerminalTab::ExitZoom() + void Tab::ExitZoom() { ASSERT_UI_THREAD(); @@ -1739,7 +1995,7 @@ namespace winrt::TerminalApp::implementation Content(_rootPane->GetRootElement()); } - bool TerminalTab::IsZoomed() + bool Tab::IsZoomed() { ASSERT_UI_THREAD(); @@ -1762,7 +2018,7 @@ namespace winrt::TerminalApp::implementation // - Toggle read-only mode on the active pane // - If a parent pane is selected, this will ensure that all children have // the same read-only status. - void TerminalTab::TogglePaneReadOnly() + void Tab::TogglePaneReadOnly() { ASSERT_UI_THREAD(); @@ -1796,7 +2052,7 @@ namespace winrt::TerminalApp::implementation // - Set read-only mode on the active pane // - If a parent pane is selected, this will ensure that all children have // the same read-only status. - void TerminalTab::SetPaneReadOnly(const bool readOnlyState) + void Tab::SetPaneReadOnly(const bool readOnlyState) { auto hasReadOnly = false; auto allReadOnly = true; @@ -1828,7 +2084,7 @@ namespace winrt::TerminalApp::implementation // - Calculates if the tab is read-only. // The tab is considered read-only if one of the panes is read-only. // If after the calculation the tab is read-only we hide the close button on the tab view item - void TerminalTab::_RecalculateAndApplyReadOnly() + void Tab::_RecalculateAndApplyReadOnly() { const auto control = GetActiveTerminalControl(); if (control) @@ -1845,7 +2101,7 @@ namespace winrt::TerminalApp::implementation _rootPane->WalkTree([](const auto& p) { p->UpdateVisuals(); }); } - std::shared_ptr TerminalTab::GetActivePane() const + std::shared_ptr Tab::GetActivePane() const { ASSERT_UI_THREAD(); @@ -1859,7 +2115,7 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - The value to populate in the title run of the tool tip - winrt::hstring TerminalTab::_CreateToolTipTitle() + winrt::hstring Tab::_CreateToolTipTitle() { if (const auto& control{ GetActiveTerminalControl() }) { @@ -1875,7 +2131,7 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Toggle broadcasting input to all the panes in this tab. - void TerminalTab::ToggleBroadcastInput() + void Tab::ToggleBroadcastInput() { const bool newIsBroadcasting = !_tabStatus.IsInputBroadcastActive(); _tabStatus.IsInputBroadcastActive(newIsBroadcasting); @@ -1914,7 +2170,7 @@ namespace winrt::TerminalApp::implementation }); } - void TerminalTab::_addBroadcastHandlers(const TermControl& termControl, ContentEventTokens& events) + void Tab::_addBroadcastHandlers(const TermControl& termControl, ContentEventTokens& events) { auto weakThis{ get_weak() }; // ADD EVENT HANDLERS HERE @@ -1957,48 +2213,451 @@ namespace winrt::TerminalApp::implementation }); } - void TerminalTab::_chooseColorClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, - const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) + void Tab::ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused, + const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused, + const til::color& tabRowColor) + { + ASSERT_UI_THREAD(); + + _themeColor = focused; + _unfocusedThemeColor = unfocused; + _tabRowColor = tabRowColor; + _RecalculateAndApplyTabColor(); + } + + // Method Description: + // - This function dispatches a function to the UI thread to recalculate + // what this tab's current background color should be. If a color is set, + // it will apply the given color to the tab's background. Otherwise, it + // will clear the tab's background color. + // Arguments: + // - + // Return Value: + // - + void Tab::_RecalculateAndApplyTabColor() + { + // GetTabColor will return the color set by the color picker, or the + // color specified in the profile. If neither of those were set, + // then look to _themeColor to see if there's a value there. + // Otherwise, clear our color, falling back to the TabView defaults. + const auto currentColor = GetTabColor(); + if (currentColor.has_value()) + { + _ApplyTabColorOnUIThread(currentColor.value()); + } + else if (_themeColor != nullptr) + { + // Safely get the active control's brush. + const Media::Brush terminalBrush{ _BackgroundBrush() }; + + if (const auto themeBrush{ _themeColor.Evaluate(Application::Current().Resources(), terminalBrush, false) }) + { + // ThemeColor.Evaluate will get us a Brush (because the + // TermControl could have an acrylic BG, for example). Take + // that brush, and get the color out of it. We don't really + // want to have the tab items themselves be acrylic. + _ApplyTabColorOnUIThread(til::color{ ThemeColor::ColorFromBrush(themeBrush) }); + } + else + { + _ClearTabBackgroundColor(); + } + } + else + { + _ClearTabBackgroundColor(); + } + } + + // Method Description: + // - Applies the given color to the background of this tab's TabViewItem. + // - Sets the tab foreground color depending on the luminance of + // the background color + // - This method should only be called on the UI thread. + // Arguments: + // - color: the color the user picked for their tab + // Return Value: + // - + void Tab::_ApplyTabColorOnUIThread(const winrt::Windows::UI::Color& color) + { + Media::SolidColorBrush selectedTabBrush{}; + Media::SolidColorBrush deselectedTabBrush{}; + Media::SolidColorBrush fontBrush{}; + Media::SolidColorBrush deselectedFontBrush{}; + Media::SolidColorBrush secondaryFontBrush{}; + Media::SolidColorBrush hoverTabBrush{}; + Media::SolidColorBrush subtleFillColorSecondaryBrush; + Media::SolidColorBrush subtleFillColorTertiaryBrush; + + // calculate the luminance of the current color and select a font + // color based on that + // see https://www.w3.org/TR/WCAG20/#relativeluminancedef + if (TerminalApp::ColorHelper::IsBrightColor(color)) + { + auto subtleFillColorSecondary = winrt::Windows::UI::Colors::Black(); + subtleFillColorSecondary.A = 0x09; + subtleFillColorSecondaryBrush.Color(subtleFillColorSecondary); + auto subtleFillColorTertiary = winrt::Windows::UI::Colors::Black(); + subtleFillColorTertiary.A = 0x06; + subtleFillColorTertiaryBrush.Color(subtleFillColorTertiary); + } + else + { + auto subtleFillColorSecondary = winrt::Windows::UI::Colors::White(); + subtleFillColorSecondary.A = 0x0F; + subtleFillColorSecondaryBrush.Color(subtleFillColorSecondary); + auto subtleFillColorTertiary = winrt::Windows::UI::Colors::White(); + subtleFillColorTertiary.A = 0x0A; + subtleFillColorTertiaryBrush.Color(subtleFillColorTertiary); + } + + // The tab font should be based on the evaluated appearance of the tab color layered on tab row. + const auto layeredTabColor = til::color{ color }.layer_over(_tabRowColor); + if (TerminalApp::ColorHelper::IsBrightColor(layeredTabColor)) + { + fontBrush.Color(winrt::Windows::UI::Colors::Black()); + auto secondaryFontColor = winrt::Windows::UI::Colors::Black(); + // For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L269 + secondaryFontColor.A = 0x9E; + secondaryFontBrush.Color(secondaryFontColor); + } + else + { + fontBrush.Color(winrt::Windows::UI::Colors::White()); + auto secondaryFontColor = winrt::Windows::UI::Colors::White(); + // For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L14 + secondaryFontColor.A = 0xC5; + secondaryFontBrush.Color(secondaryFontColor); + } + + selectedTabBrush.Color(color); + + // Start with the current tab color, set to Opacity=.3 + til::color deselectedTabColor{ color }; + deselectedTabColor = deselectedTabColor.with_alpha(77); // 255 * .3 = 77 + + // If we DON'T have a color set from the color picker, or the profile's + // tabColor, but we do have a unfocused color in the theme, use the + // unfocused theme color here instead. + if (!GetTabColor().has_value() && + _unfocusedThemeColor != nullptr) + { + // Safely get the active control's brush. + const Media::Brush terminalBrush{ _BackgroundBrush() }; + + // Get the color of the brush. + if (const auto themeBrush{ _unfocusedThemeColor.Evaluate(Application::Current().Resources(), terminalBrush, false) }) + { + // We did figure out the brush. Get the color out of it. If it + // was "accent" or "terminalBackground", then we're gonna set + // the alpha to .3 manually here. + // (ThemeColor::UnfocusedTabOpacity will do this for us). If the + // user sets both unfocused and focused tab.background to + // terminalBackground, this will allow for some differentiation + // (and is generally just sensible). + deselectedTabColor = til::color{ ThemeColor::ColorFromBrush(themeBrush) }.with_alpha(_unfocusedThemeColor.UnfocusedTabOpacity()); + } + } + + // currently if a tab has a custom color, a deselected state is + // signified by using the same color with a bit of transparency + deselectedTabBrush.Color(deselectedTabColor.with_alpha(255)); + deselectedTabBrush.Opacity(deselectedTabColor.a / 255.f); + + hoverTabBrush.Color(color); + hoverTabBrush.Opacity(0.6); + + // Account for the color of the tab row when setting the color of text + // on inactive tabs. Consider: + // * black active tabs + // * on a white tab row + // * with a transparent inactive tab color + // + // We don't want that to result in white text on a white tab row for + // inactive tabs. + const auto deselectedActualColor = deselectedTabColor.layer_over(_tabRowColor); + if (TerminalApp::ColorHelper::IsBrightColor(deselectedActualColor)) + { + deselectedFontBrush.Color(winrt::Windows::UI::Colors::Black()); + } + else + { + deselectedFontBrush.Color(winrt::Windows::UI::Colors::White()); + } + + // Add the empty theme dictionaries + const auto& tabItemThemeResources{ TabViewItem().Resources().ThemeDictionaries() }; + ResourceDictionary lightThemeDictionary; + ResourceDictionary darkThemeDictionary; + ResourceDictionary highContrastThemeDictionary; + tabItemThemeResources.Insert(winrt::box_value(L"Light"), lightThemeDictionary); + tabItemThemeResources.Insert(winrt::box_value(L"Dark"), darkThemeDictionary); + tabItemThemeResources.Insert(winrt::box_value(L"HighContrast"), highContrastThemeDictionary); + + // Apply the color to the tab + TabViewItem().Background(deselectedTabBrush); + + // Now actually set the resources we want in them. + // Before, we used to put these on the ResourceDictionary directly. + // However, HighContrast mode may require some adjustments. So let's just add + // all three so we can make those adjustments on the HighContrast version. + for (const auto& [k, v] : tabItemThemeResources) + { + const bool isHighContrast = winrt::unbox_value(k) == L"HighContrast"; + const auto& currentDictionary = v.as(); + + // TabViewItem.Background + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackground"), deselectedTabBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackgroundSelected"), selectedTabBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPointerOver"), isHighContrast ? fontBrush : hoverTabBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPressed"), selectedTabBrush); + + // TabViewItem.Foreground (aka text) + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderForeground"), deselectedFontBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderForegroundSelected"), fontBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderForegroundPointerOver"), isHighContrast ? selectedTabBrush : fontBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderForegroundPressed"), fontBrush); + + // TabViewItem.CloseButton.Foreground (aka X) + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForeground"), deselectedFontBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForegroundPressed"), isHighContrast ? deselectedFontBrush : secondaryFontBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForegroundPointerOver"), isHighContrast ? deselectedFontBrush : fontBrush); + + // TabViewItem.CloseButton.Foreground _when_ interacting with the tab + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderPressedCloseButtonForeground"), fontBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderPointerOverCloseButtonForeground"), isHighContrast ? selectedTabBrush : fontBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderSelectedCloseButtonForeground"), fontBrush); + + // TabViewItem.CloseButton.Background (aka X button) + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackgroundPressed"), isHighContrast ? selectedTabBrush : subtleFillColorTertiaryBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackgroundPointerOver"), isHighContrast ? selectedTabBrush : subtleFillColorSecondaryBrush); + + // A few miscellaneous resources that WinUI said may be removed in the future + currentDictionary.Insert(winrt::box_value(L"TabViewButtonForegroundActiveTab"), fontBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewButtonForegroundPressed"), fontBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewButtonForegroundPointerOver"), fontBrush); + + // Add a few extra ones for high contrast mode + // BODGY: contrary to the docs, Insert() seems to throw if the value already exists + // Make sure you don't touch any that already exist here! + if (isHighContrast) + { + // TabViewItem.CloseButton.Border: in HC mode, the border makes the button more clearly visible + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBorderBrushPressed"), fontBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBorderBrushPointerOver"), fontBrush); + currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBorderBrushSelected"), fontBrush); + } + } + + _RefreshVisualState(); + } + + // Method Description: + // - Clear out any color we've set for the TabViewItem. + // - This method should only be called on the UI thread. + // Arguments: + // - + // Return Value: + // - + void Tab::_ClearTabBackgroundColor() + { + static const winrt::hstring keys[] = { + // TabViewItem.Background + L"TabViewItemHeaderBackground", + L"TabViewItemHeaderBackgroundSelected", + L"TabViewItemHeaderBackgroundPointerOver", + L"TabViewItemHeaderBackgroundPressed", + + // TabViewItem.Foreground (aka text) + L"TabViewItemHeaderForeground", + L"TabViewItemHeaderForegroundSelected", + L"TabViewItemHeaderForegroundPointerOver", + L"TabViewItemHeaderForegroundPressed", + + // TabViewItem.CloseButton.Foreground (aka X) + L"TabViewItemHeaderCloseButtonForeground", + L"TabViewItemHeaderForegroundSelected", + L"TabViewItemHeaderCloseButtonForegroundPointerOver", + L"TabViewItemHeaderCloseButtonForegroundPressed", + + // TabViewItem.CloseButton.Foreground _when_ interacting with the tab + L"TabViewItemHeaderPressedCloseButtonForeground", + L"TabViewItemHeaderPointerOverCloseButtonForeground", + L"TabViewItemHeaderSelectedCloseButtonForeground", + + // TabViewItem.CloseButton.Background (aka X button) + L"TabViewItemHeaderCloseButtonBackground", + L"TabViewItemHeaderCloseButtonBackgroundPressed", + L"TabViewItemHeaderCloseButtonBackgroundPointerOver", + + // A few miscellaneous resources that WinUI said may be removed in the future + L"TabViewButtonForegroundActiveTab", + L"TabViewButtonForegroundPressed", + L"TabViewButtonForegroundPointerOver", + + // TabViewItem.CloseButton.Border: in HC mode, the border makes the button more clearly visible + L"TabViewItemHeaderCloseButtonBorderBrushPressed", + L"TabViewItemHeaderCloseButtonBorderBrushPointerOver", + L"TabViewItemHeaderCloseButtonBorderBrushSelected" + }; + + const auto& tabItemThemeResources{ TabViewItem().Resources().ThemeDictionaries() }; + + // simply clear any of the colors in the tab's dict + for (const auto& keyString : keys) + { + const auto key = winrt::box_value(keyString); + for (const auto& [_, v] : tabItemThemeResources) + { + const auto& themeDictionary = v.as(); + themeDictionary.Remove(key); + } + } + + // GH#11382 DON'T set the background to null. If you do that, then the + // tab won't be hit testable at all. Transparent, however, is a totally + // valid hit test target. That makes sense. + TabViewItem().Background(WUX::Media::SolidColorBrush{ Windows::UI::Colors::Transparent() }); + + _RefreshVisualState(); + } + + // Method Description: + // BODGY + // - Toggles the requested theme of the tab view item, + // so that changes to the tab color are reflected immediately + // - Prior to MUX 2.8, we only toggled the visual state here, but that seemingly + // doesn't work in 2.8. + // - Just changing the Theme also doesn't seem to work by itself - there + // seems to be a way for the tab to set the deselected foreground onto + // itself as it becomes selected. If the mouse isn't over the tab, that + // can result in mismatched fg/bg's (see GH#15184). So that's right, we + // need to do both. + // Arguments: + // - + // Return Value: + // - + void Tab::_RefreshVisualState() + { + const auto& item{ TabViewItem() }; + + const auto& reqTheme = TabViewItem().RequestedTheme(); + item.RequestedTheme(ElementTheme::Light); + item.RequestedTheme(ElementTheme::Dark); + item.RequestedTheme(reqTheme); + + if (TabViewItem().IsSelected()) + { + VisualStateManager::GoToState(item, L"Normal", true); + VisualStateManager::GoToState(item, L"Selected", true); + } + else + { + VisualStateManager::GoToState(item, L"Selected", true); + VisualStateManager::GoToState(item, L"Normal", true); + } + } + + TabCloseButtonVisibility Tab::CloseButtonVisibility() + { + return _closeButtonVisibility; + } + + // Method Description: + // - set our internal state to track if we were requested to have a visible + // tab close button or not. + // - This is called every time the active tab changes. That way, the changes + // in focused tab can be reflected for the "ActiveOnly" state. + void Tab::CloseButtonVisibility(TabCloseButtonVisibility visibility) + { + _closeButtonVisibility = visibility; + _updateIsClosable(); + } + + // Method Description: + // - Update our close button's visibility, to reflect both the ReadOnly + // state of the tab content, and also if if we were told to have a visible + // close button at all. + // - the tab being read-only takes precedence. That will always suppress + // the close button. + // - Otherwise we'll use the state set in CloseButtonVisibility to control + // the tab's visibility. + void Tab::_updateIsClosable() + { + bool isClosable = true; + + if (ReadOnly()) + { + isClosable = false; + } + else + { + switch (_closeButtonVisibility) + { + case TabCloseButtonVisibility::Never: + isClosable = false; + break; + case TabCloseButtonVisibility::Hover: + isClosable = true; + break; + case TabCloseButtonVisibility::ActiveOnly: + isClosable = _focused(); + break; + default: + isClosable = true; + break; + } + } + TabViewItem().IsClosable(isClosable); + } + + bool Tab::_focused() const noexcept + { + return _focusState != FocusState::Unfocused; + } + + void Tab::_chooseColorClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, + const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) { _dispatch.DoAction(*this, { ShortcutAction::OpenTabColorPicker, nullptr }); } - void TerminalTab::_renameTabClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, - const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) + void Tab::_renameTabClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, + const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) { ActivateTabRenamer(); } - void TerminalTab::_duplicateTabClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, - const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) + void Tab::_duplicateTabClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, + const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) { ActionAndArgs actionAndArgs{ ShortcutAction::DuplicateTab, nullptr }; _dispatch.DoAction(*this, actionAndArgs); } - void TerminalTab::_splitTabClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, - const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) + void Tab::_splitTabClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, + const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) { ActionAndArgs actionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate } }; _dispatch.DoAction(*this, actionAndArgs); } - void TerminalTab::_closePaneClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, - const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) + void Tab::_closePaneClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, + const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) { ClosePane(); } - void TerminalTab::_exportTextClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, - const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) + void Tab::_exportTextClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, + const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) { ActionAndArgs actionAndArgs{}; actionAndArgs.Action(ShortcutAction::ExportBuffer); _dispatch.DoAction(*this, actionAndArgs); } - void TerminalTab::_findClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, - const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) + void Tab::_findClicked(const winrt::Windows::Foundation::IInspectable& /* sender */, + const winrt::Windows::UI::Xaml::RoutedEventArgs& /* args */) { ActionAndArgs actionAndArgs{ ShortcutAction::Find, nullptr }; _dispatch.DoAction(*this, actionAndArgs); } - void TerminalTab::_bubbleRestartTerminalRequested(TerminalApp::TerminalPaneContent sender, - const winrt::Windows::Foundation::IInspectable& args) + void Tab::_bubbleRestartTerminalRequested(TerminalApp::TerminalPaneContent sender, + const winrt::Windows::Foundation::IInspectable& args) { RestartTerminalRequested.raise(sender, args); } diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/Tab.h similarity index 67% rename from src/cascadia/TerminalApp/TerminalTab.h rename to src/cascadia/TerminalApp/Tab.h index 29cc3d1b5e..be6180586e 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/Tab.h @@ -4,8 +4,8 @@ #pragma once #include "Pane.h" #include "ColorPickupFlyout.h" -#include "TabBase.h" -#include "TerminalTab.g.h" +#include "Tab.h" +#include "Tab.g.h" // fwdecl unittest classes namespace TerminalAppLocalTests @@ -15,10 +15,10 @@ namespace TerminalAppLocalTests namespace winrt::TerminalApp::implementation { - struct TerminalTab : TerminalTabT + struct Tab : TabT { public: - TerminalTab(std::shared_ptr rootPane); + Tab(std::shared_ptr rootPane); // Called after construction to perform the necessary setup, which relies on weak_ptr void Initialize(); @@ -27,7 +27,7 @@ namespace winrt::TerminalApp::implementation winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile() const noexcept; winrt::TerminalApp::IPaneContent GetActiveContent() const; - void Focus(winrt::Windows::UI::Xaml::FocusState focusState) override; + void Focus(winrt::Windows::UI::Xaml::FocusState focusState); void Scroll(const int delta); @@ -61,7 +61,7 @@ namespace winrt::TerminalApp::implementation void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings); void UpdateTitle(); - void Shutdown() override; + void Shutdown(); void ClosePane(); void SetTabText(winrt::hstring title); @@ -69,7 +69,7 @@ namespace winrt::TerminalApp::implementation void ResetTabText(); void ActivateTabRenamer(); - virtual std::optional GetTabColor() override; + std::optional GetTabColor(); void SetRuntimeTabColor(const winrt::Windows::UI::Color& color); void ResetRuntimeTabColor(); @@ -79,7 +79,7 @@ namespace winrt::TerminalApp::implementation void EnterZoom(); void ExitZoom(); - std::vector BuildStartupActions(BuildStartupKind kind) const override; + std::vector BuildStartupActions(BuildStartupKind kind) const; int GetLeafPaneCount() const noexcept; @@ -98,16 +98,62 @@ namespace winrt::TerminalApp::implementation return _tabStatus; } + void SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch); + + void UpdateTabViewIndex(const uint32_t idx, const uint32_t numTabs); + void SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap); + + void ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused, + const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused, + const til::color& tabRowColor); + + Microsoft::Terminal::Settings::Model::TabCloseButtonVisibility CloseButtonVisibility(); + void CloseButtonVisibility(Microsoft::Terminal::Settings::Model::TabCloseButtonVisibility visible); + + til::event> RequestFocusActiveControl; + + til::event> Closed; + til::event> CloseRequested; + til::property_changed_event PropertyChanged; + til::typed_event RestartTerminalRequested; - til::typed_event ActivePaneChanged; + til::typed_event ActivePaneChanged; til::event> TabRaiseVisualBell; til::typed_event TaskbarProgressChanged; + // The TabViewIndex is the index this Tab object resides in TerminalPage's _tabs vector. + WINRT_PROPERTY(uint32_t, TabViewIndex, 0); + // The TabViewNumTabs is the number of Tab objects in TerminalPage's _tabs vector. + WINRT_PROPERTY(uint32_t, TabViewNumTabs, 0); + + WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Title, PropertyChanged.raise); + WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Icon, PropertyChanged.raise); + WINRT_OBSERVABLE_PROPERTY(bool, ReadOnly, PropertyChanged.raise, false); + WINRT_PROPERTY(winrt::Microsoft::UI::Xaml::Controls::TabViewItem, TabViewItem, nullptr); + + WINRT_OBSERVABLE_PROPERTY(winrt::Windows::UI::Xaml::FrameworkElement, Content, PropertyChanged.raise, nullptr); + private: static constexpr double HeaderRenameBoxWidthDefault{ 165 }; static constexpr double HeaderRenameBoxWidthTitleLength{ std::numeric_limits::infinity() }; + winrt::Windows::UI::Xaml::FocusState _focusState{ winrt::Windows::UI::Xaml::FocusState::Unfocused }; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeOtherTabsMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeTabsAfterMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveToNewWindowMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveRightMenuItem{}; + winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveLeftMenuItem{}; + winrt::TerminalApp::ShortcutActionDispatch _dispatch; + Microsoft::Terminal::Settings::Model::IActionMapView _actionMap{ nullptr }; + winrt::hstring _keyChord{}; + + winrt::Microsoft::Terminal::Settings::Model::ThemeColor _themeColor{ nullptr }; + winrt::Microsoft::Terminal::Settings::Model::ThemeColor _unfocusedThemeColor{ nullptr }; + til::color _tabRowColor; + + Microsoft::Terminal::Settings::Model::TabCloseButtonVisibility _closeButtonVisibility{ Microsoft::Terminal::Settings::Model::TabCloseButtonVisibility::Always }; + std::shared_ptr _rootPane{ nullptr }; std::shared_ptr _activePane{ nullptr }; std::shared_ptr _zoomedPane{ nullptr }; @@ -163,12 +209,10 @@ namespace winrt::TerminalApp::implementation SafeDispatcherTimer _bellIndicatorTimer; void _BellIndicatorTimerTick(const Windows::Foundation::IInspectable& sender, const Windows::Foundation::IInspectable& e); - void _MakeTabViewItem() override; - void _UpdateHeaderControlMaxWidth(); - void _CreateContextMenu() override; - virtual winrt::hstring _CreateToolTipTitle() override; + void _CreateContextMenu(); + winrt::hstring _CreateToolTipTitle(); void _DetachEventHandlersFromContent(const uint32_t paneId); void _AttachEventHandlersToContent(const uint32_t paneId, const winrt::TerminalApp::IPaneContent& content); @@ -187,7 +231,23 @@ namespace winrt::TerminalApp::implementation void _DuplicateTab(); - virtual winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush() override; + winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush(); + + void _MakeTabViewItem(); + + void _AppendMoveMenuItems(winrt::Windows::UI::Xaml::Controls::MenuFlyout flyout); + winrt::Windows::UI::Xaml::Controls::MenuFlyoutSubItem _AppendCloseMenuItems(winrt::Windows::UI::Xaml::Controls::MenuFlyout flyout); + void _EnableMenuItems(); + void _UpdateSwitchToTabKeyChord(); + void _UpdateToolTip(); + + void _RecalculateAndApplyTabColor(); + void _ApplyTabColorOnUIThread(const winrt::Windows::UI::Color& color); + void _ClearTabBackgroundColor(); + void _RefreshVisualState(); + + bool _focused() const noexcept; + void _updateIsClosable(); void _addBroadcastHandlers(const winrt::Microsoft::Terminal::Control::TermControl& control, ContentEventTokens& events); diff --git a/src/cascadia/TerminalApp/TabBase.idl b/src/cascadia/TerminalApp/Tab.idl similarity index 78% rename from src/cascadia/TerminalApp/TabBase.idl rename to src/cascadia/TerminalApp/Tab.idl index 20ee8ffa9d..0f214133a6 100644 --- a/src/cascadia/TerminalApp/TabBase.idl +++ b/src/cascadia/TerminalApp/Tab.idl @@ -1,10 +1,11 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. import "ShortcutActionDispatch.idl"; +import "TerminalTabStatus.idl"; namespace TerminalApp { - unsealed runtimeclass TabBase : Windows.UI.Xaml.Data.INotifyPropertyChanged + runtimeclass Tab : Windows.UI.Xaml.Data.INotifyPropertyChanged { String Title { get; }; String Icon { get; }; @@ -14,6 +15,9 @@ namespace TerminalApp Microsoft.UI.Xaml.Controls.TabViewItem TabViewItem { get; }; Windows.UI.Xaml.FrameworkElement Content { get; }; + // May be Null + TerminalTabStatus TabStatus { get; }; + UInt32 TabViewIndex; UInt32 TabViewNumTabs; diff --git a/src/cascadia/TerminalApp/TabBase.cpp b/src/cascadia/TerminalApp/TabBase.cpp deleted file mode 100644 index 60e2e94bc2..0000000000 --- a/src/cascadia/TerminalApp/TabBase.cpp +++ /dev/null @@ -1,753 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "pch.h" -#include -#include "TabBase.h" -#include "TabBase.g.cpp" -#include "Utils.h" -#include "ColorHelper.h" - -using namespace winrt; -using namespace winrt::Windows::UI::Xaml; -using namespace winrt::Windows::UI::Core; -using namespace winrt::Microsoft::Terminal::Control; -using namespace winrt::Microsoft::Terminal::Settings::Model; -using namespace winrt::Windows::System; - -namespace winrt -{ - namespace MUX = Microsoft::UI::Xaml; - namespace WUX = Windows::UI::Xaml; -} - -#define ASSERT_UI_THREAD() assert(TabViewItem().Dispatcher().HasThreadAccess()) - -namespace winrt::TerminalApp::implementation -{ - - // Method Description: - // - Prepares this tab for being removed from the UI hierarchy - void TabBase::Shutdown() - { - ASSERT_UI_THREAD(); - - // NOTE: `TerminalPage::_HandleCloseTabRequested` relies on the content being null after this call. - Content(nullptr); - } - - // Method Description: - // - Creates a context menu attached to the tab. - // Currently contains elements allowing the user to close the selected tab - // Arguments: - // - - // Return Value: - // - - void TabBase::_CreateContextMenu() - { - auto weakThis{ get_weak() }; - - // Build the menu - Controls::MenuFlyout contextMenuFlyout; - // GH#5750 - When the context menu is dismissed with ESC, toss the focus - // back to our control. - contextMenuFlyout.Closed([weakThis](auto&&, auto&&) { - if (auto tab{ weakThis.get() }) - { - tab->RequestFocusActiveControl.raise(); - } - }); - _AppendMoveMenuItems(contextMenuFlyout); - _AppendCloseMenuItems(contextMenuFlyout); - TabViewItem().ContextFlyout(contextMenuFlyout); - } - - void TabBase::_AppendMoveMenuItems(winrt::Windows::UI::Xaml::Controls::MenuFlyout flyout) - { - auto weakThis{ get_weak() }; - - // Move to new window - { - Controls::FontIcon moveTabToNewWindowTabSymbol; - moveTabToNewWindowTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); - moveTabToNewWindowTabSymbol.Glyph(L"\xE8A7"); - - _moveToNewWindowMenuItem.Click([weakThis](auto&&, auto&&) { - if (auto tab{ weakThis.get() }) - { - MoveTabArgs args{ L"new", MoveTabDirection::Forward }; - ActionAndArgs actionAndArgs{ ShortcutAction::MoveTab, args }; - tab->_dispatch.DoAction(*tab, actionAndArgs); - } - }); - _moveToNewWindowMenuItem.Text(RS_(L"MoveTabToNewWindowText")); - _moveToNewWindowMenuItem.Icon(moveTabToNewWindowTabSymbol); - - const auto moveTabToNewWindowToolTip = RS_(L"MoveTabToNewWindowToolTip"); - WUX::Controls::ToolTipService::SetToolTip(_moveToNewWindowMenuItem, box_value(moveTabToNewWindowToolTip)); - Automation::AutomationProperties::SetHelpText(_moveToNewWindowMenuItem, moveTabToNewWindowToolTip); - } - - // Move left - { - _moveLeftMenuItem.Click([weakThis](auto&&, auto&&) { - if (auto tab{ weakThis.get() }) - { - MoveTabArgs args{ hstring{}, MoveTabDirection::Backward }; - ActionAndArgs actionAndArgs{ ShortcutAction::MoveTab, args }; - tab->_dispatch.DoAction(*tab, actionAndArgs); - } - }); - _moveLeftMenuItem.Text(RS_(L"TabMoveLeft")); - } - - // Move right - { - _moveRightMenuItem.Click([weakThis](auto&&, auto&&) { - if (auto tab{ weakThis.get() }) - { - MoveTabArgs args{ hstring{}, MoveTabDirection::Forward }; - ActionAndArgs actionAndArgs{ ShortcutAction::MoveTab, args }; - tab->_dispatch.DoAction(*tab, actionAndArgs); - } - }); - _moveRightMenuItem.Text(RS_(L"TabMoveRight")); - } - - // Create a sub-menu for our extended move tab items. - Controls::MenuFlyoutSubItem moveSubMenu; - moveSubMenu.Text(RS_(L"TabMoveSubMenu")); - moveSubMenu.Items().Append(_moveToNewWindowMenuItem); - moveSubMenu.Items().Append(_moveRightMenuItem); - moveSubMenu.Items().Append(_moveLeftMenuItem); - flyout.Items().Append(moveSubMenu); - } - - // Method Description: - // - Append the close menu items to the context menu flyout - // Arguments: - // - flyout - the menu flyout to which the close items must be appended - // Return Value: - // - the sub-item that we use for all the nested "close" entries. This - // enables subclasses to add their own entries to this menu. - winrt::Windows::UI::Xaml::Controls::MenuFlyoutSubItem TabBase::_AppendCloseMenuItems(winrt::Windows::UI::Xaml::Controls::MenuFlyout flyout) - { - auto weakThis{ get_weak() }; - - // Close tabs after - _closeTabsAfterMenuItem.Click([weakThis](auto&&, auto&&) { - if (auto tab{ weakThis.get() }) - { - CloseTabsAfterArgs args{ tab->_TabViewIndex }; - ActionAndArgs closeTabsAfter{ ShortcutAction::CloseTabsAfter, args }; - tab->_dispatch.DoAction(*tab, closeTabsAfter); - } - }); - _closeTabsAfterMenuItem.Text(RS_(L"TabCloseAfter")); - const auto closeTabsAfterToolTip = RS_(L"TabCloseAfterToolTip"); - - WUX::Controls::ToolTipService::SetToolTip(_closeTabsAfterMenuItem, box_value(closeTabsAfterToolTip)); - Automation::AutomationProperties::SetHelpText(_closeTabsAfterMenuItem, closeTabsAfterToolTip); - - // Close other tabs - _closeOtherTabsMenuItem.Click([weakThis](auto&&, auto&&) { - if (auto tab{ weakThis.get() }) - { - CloseOtherTabsArgs args{ tab->_TabViewIndex }; - ActionAndArgs closeOtherTabs{ ShortcutAction::CloseOtherTabs, args }; - tab->_dispatch.DoAction(*tab, closeOtherTabs); - } - }); - _closeOtherTabsMenuItem.Text(RS_(L"TabCloseOther")); - const auto closeOtherTabsToolTip = RS_(L"TabCloseOtherToolTip"); - - WUX::Controls::ToolTipService::SetToolTip(_closeOtherTabsMenuItem, box_value(closeOtherTabsToolTip)); - Automation::AutomationProperties::SetHelpText(_closeOtherTabsMenuItem, closeOtherTabsToolTip); - - // Close - Controls::MenuFlyoutItem closeTabMenuItem; - Controls::FontIcon closeSymbol; - closeSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }); - closeSymbol.Glyph(L"\xE711"); - - closeTabMenuItem.Click([weakThis](auto&&, auto&&) { - if (auto tab{ weakThis.get() }) - { - tab->CloseRequested.raise(nullptr, nullptr); - } - }); - closeTabMenuItem.Text(RS_(L"TabClose")); - closeTabMenuItem.Icon(closeSymbol); - const auto closeTabToolTip = RS_(L"TabCloseToolTip"); - - WUX::Controls::ToolTipService::SetToolTip(closeTabMenuItem, box_value(closeTabToolTip)); - Automation::AutomationProperties::SetHelpText(closeTabMenuItem, closeTabToolTip); - - // Create a sub-menu for our extended close items. - Controls::MenuFlyoutSubItem closeSubMenu; - closeSubMenu.Text(RS_(L"TabCloseSubMenu")); - closeSubMenu.Items().Append(_closeTabsAfterMenuItem); - closeSubMenu.Items().Append(_closeOtherTabsMenuItem); - flyout.Items().Append(closeSubMenu); - - flyout.Items().Append(closeTabMenuItem); - - return closeSubMenu; - } - - // Method Description: - // - Enable menu items based on tab index and total number of tabs - // Arguments: - // - - // Return Value: - // - - void TabBase::_EnableMenuItems() - { - const auto tabIndex = TabViewIndex(); - const auto numOfTabs = TabViewNumTabs(); - - // enabled if there are other tabs - _closeOtherTabsMenuItem.IsEnabled(numOfTabs > 1); - - // enabled if there are other tabs on the right - _closeTabsAfterMenuItem.IsEnabled(tabIndex < numOfTabs - 1); - - // enabled if not left-most tab - _moveLeftMenuItem.IsEnabled(tabIndex > 0); - - // enabled if not last tab - _moveRightMenuItem.IsEnabled(tabIndex < numOfTabs - 1); - } - - void TabBase::UpdateTabViewIndex(const uint32_t idx, const uint32_t numTabs) - { - ASSERT_UI_THREAD(); - - TabViewIndex(idx); - TabViewNumTabs(numTabs); - _EnableMenuItems(); - _UpdateSwitchToTabKeyChord(); - } - - void TabBase::SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch) - { - ASSERT_UI_THREAD(); - - _dispatch = dispatch; - } - - void TabBase::SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap) - { - ASSERT_UI_THREAD(); - - _actionMap = actionMap; - _UpdateSwitchToTabKeyChord(); - } - - // Method Description: - // - Sets the key chord resulting in switch to the current tab. - // Updates tool tip if required - // Arguments: - // - keyChord - string representation of the key chord that switches to the current tab - // Return Value: - // - - void TabBase::_UpdateSwitchToTabKeyChord() - { - const auto id = fmt::format(FMT_COMPILE(L"Terminal.SwitchToTab{}"), _TabViewIndex); - const auto keyChord{ _actionMap.GetKeyBindingForAction(id) }; - const auto keyChordText = keyChord ? KeyChordSerialization::ToString(keyChord) : L""; - - if (_keyChord == keyChordText) - { - return; - } - - _keyChord = keyChordText; - _UpdateToolTip(); - } - - // Method Description: - // - Creates a text for the title run in the tool tip by returning tab title - // Arguments: - // - - // Return Value: - // - The value to populate in the title run of the tool tip - winrt::hstring TabBase::_CreateToolTipTitle() - { - return _Title; - } - - // Method Description: - // - Sets tab tool tip to a concatenation of title and key chord - // Arguments: - // - - // Return Value: - // - - void TabBase::_UpdateToolTip() - { - auto titleRun = WUX::Documents::Run(); - titleRun.Text(_CreateToolTipTitle()); - - auto textBlock = WUX::Controls::TextBlock{}; - textBlock.TextWrapping(WUX::TextWrapping::Wrap); - textBlock.TextAlignment(WUX::TextAlignment::Center); - textBlock.Inlines().Append(titleRun); - - if (!_keyChord.empty()) - { - auto keyChordRun = WUX::Documents::Run(); - keyChordRun.Text(_keyChord); - keyChordRun.FontStyle(winrt::Windows::UI::Text::FontStyle::Italic); - textBlock.Inlines().Append(WUX::Documents::LineBreak{}); - textBlock.Inlines().Append(keyChordRun); - } - - WUX::Controls::ToolTip toolTip{}; - toolTip.Content(textBlock); - WUX::Controls::ToolTipService::SetToolTip(TabViewItem(), toolTip); - } - - // Method Description: - // - Initializes a TabViewItem for this Tab instance. - // Arguments: - // - - // Return Value: - // - - void TabBase::_MakeTabViewItem() - { - TabViewItem(::winrt::MUX::Controls::TabViewItem{}); - - // GH#3609 If the tab was tapped, and no one else was around to handle - // it, then ask our parent to toss focus into the active control. - TabViewItem().Tapped([weakThis{ get_weak() }](auto&&, auto&&) { - if (auto tab{ weakThis.get() }) - { - tab->RequestFocusActiveControl.raise(); - } - }); - - // BODGY: When the tab is drag/dropped, the TabView gets a - // TabDragStarting. However, the way it is implemented[^1], the - // TabViewItem needs either an Item or a Content for the event to - // include the correct TabViewItem. Otherwise, it will just return the - // first TabViewItem in the TabView with the same Content as the dragged - // tab (which, if the Content is null, will be the _first_ tab). - // - // So here, we'll stick an empty border in, just so that every tab has a - // Content which is not equal to the others. - // - // [^1]: microsoft-ui-xaml/blob/92fbfcd55f05c92ac65569f5d284c5b36492091e/dev/TabView/TabView.cpp#L751-L758 - TabViewItem().Content(winrt::WUX::Controls::Border{}); - } - - std::optional TabBase::GetTabColor() - { - ASSERT_UI_THREAD(); - - return std::nullopt; - } - - void TabBase::ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused, - const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused, - const til::color& tabRowColor) - { - ASSERT_UI_THREAD(); - - _themeColor = focused; - _unfocusedThemeColor = unfocused; - _tabRowColor = tabRowColor; - _RecalculateAndApplyTabColor(); - } - - // Method Description: - // - This function dispatches a function to the UI thread to recalculate - // what this tab's current background color should be. If a color is set, - // it will apply the given color to the tab's background. Otherwise, it - // will clear the tab's background color. - // Arguments: - // - - // Return Value: - // - - void TabBase::_RecalculateAndApplyTabColor() - { - // GetTabColor will return the color set by the color picker, or the - // color specified in the profile. If neither of those were set, - // then look to _themeColor to see if there's a value there. - // Otherwise, clear our color, falling back to the TabView defaults. - const auto currentColor = GetTabColor(); - if (currentColor.has_value()) - { - _ApplyTabColorOnUIThread(currentColor.value()); - } - else if (_themeColor != nullptr) - { - // Safely get the active control's brush. - const Media::Brush terminalBrush{ _BackgroundBrush() }; - - if (const auto themeBrush{ _themeColor.Evaluate(Application::Current().Resources(), terminalBrush, false) }) - { - // ThemeColor.Evaluate will get us a Brush (because the - // TermControl could have an acrylic BG, for example). Take - // that brush, and get the color out of it. We don't really - // want to have the tab items themselves be acrylic. - _ApplyTabColorOnUIThread(til::color{ ThemeColor::ColorFromBrush(themeBrush) }); - } - else - { - _ClearTabBackgroundColor(); - } - } - else - { - _ClearTabBackgroundColor(); - } - } - - // Method Description: - // - Applies the given color to the background of this tab's TabViewItem. - // - Sets the tab foreground color depending on the luminance of - // the background color - // - This method should only be called on the UI thread. - // Arguments: - // - color: the color the user picked for their tab - // Return Value: - // - - void TabBase::_ApplyTabColorOnUIThread(const winrt::Windows::UI::Color& color) - { - Media::SolidColorBrush selectedTabBrush{}; - Media::SolidColorBrush deselectedTabBrush{}; - Media::SolidColorBrush fontBrush{}; - Media::SolidColorBrush deselectedFontBrush{}; - Media::SolidColorBrush secondaryFontBrush{}; - Media::SolidColorBrush hoverTabBrush{}; - Media::SolidColorBrush subtleFillColorSecondaryBrush; - Media::SolidColorBrush subtleFillColorTertiaryBrush; - - // calculate the luminance of the current color and select a font - // color based on that - // see https://www.w3.org/TR/WCAG20/#relativeluminancedef - if (TerminalApp::ColorHelper::IsBrightColor(color)) - { - auto subtleFillColorSecondary = winrt::Windows::UI::Colors::Black(); - subtleFillColorSecondary.A = 0x09; - subtleFillColorSecondaryBrush.Color(subtleFillColorSecondary); - auto subtleFillColorTertiary = winrt::Windows::UI::Colors::Black(); - subtleFillColorTertiary.A = 0x06; - subtleFillColorTertiaryBrush.Color(subtleFillColorTertiary); - } - else - { - auto subtleFillColorSecondary = winrt::Windows::UI::Colors::White(); - subtleFillColorSecondary.A = 0x0F; - subtleFillColorSecondaryBrush.Color(subtleFillColorSecondary); - auto subtleFillColorTertiary = winrt::Windows::UI::Colors::White(); - subtleFillColorTertiary.A = 0x0A; - subtleFillColorTertiaryBrush.Color(subtleFillColorTertiary); - } - - // The tab font should be based on the evaluated appearance of the tab color layered on tab row. - const auto layeredTabColor = til::color{ color }.layer_over(_tabRowColor); - if (TerminalApp::ColorHelper::IsBrightColor(layeredTabColor)) - { - fontBrush.Color(winrt::Windows::UI::Colors::Black()); - auto secondaryFontColor = winrt::Windows::UI::Colors::Black(); - // For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L269 - secondaryFontColor.A = 0x9E; - secondaryFontBrush.Color(secondaryFontColor); - } - else - { - fontBrush.Color(winrt::Windows::UI::Colors::White()); - auto secondaryFontColor = winrt::Windows::UI::Colors::White(); - // For alpha value see: https://github.com/microsoft/microsoft-ui-xaml/blob/7a33ad772d77d908aa6b316ec24e6d2eb3ebf571/dev/CommonStyles/Common_themeresources_any.xaml#L14 - secondaryFontColor.A = 0xC5; - secondaryFontBrush.Color(secondaryFontColor); - } - - selectedTabBrush.Color(color); - - // Start with the current tab color, set to Opacity=.3 - til::color deselectedTabColor{ color }; - deselectedTabColor = deselectedTabColor.with_alpha(77); // 255 * .3 = 77 - - // If we DON'T have a color set from the color picker, or the profile's - // tabColor, but we do have a unfocused color in the theme, use the - // unfocused theme color here instead. - if (!GetTabColor().has_value() && - _unfocusedThemeColor != nullptr) - { - // Safely get the active control's brush. - const Media::Brush terminalBrush{ _BackgroundBrush() }; - - // Get the color of the brush. - if (const auto themeBrush{ _unfocusedThemeColor.Evaluate(Application::Current().Resources(), terminalBrush, false) }) - { - // We did figure out the brush. Get the color out of it. If it - // was "accent" or "terminalBackground", then we're gonna set - // the alpha to .3 manually here. - // (ThemeColor::UnfocusedTabOpacity will do this for us). If the - // user sets both unfocused and focused tab.background to - // terminalBackground, this will allow for some differentiation - // (and is generally just sensible). - deselectedTabColor = til::color{ ThemeColor::ColorFromBrush(themeBrush) }.with_alpha(_unfocusedThemeColor.UnfocusedTabOpacity()); - } - } - - // currently if a tab has a custom color, a deselected state is - // signified by using the same color with a bit of transparency - deselectedTabBrush.Color(deselectedTabColor.with_alpha(255)); - deselectedTabBrush.Opacity(deselectedTabColor.a / 255.f); - - hoverTabBrush.Color(color); - hoverTabBrush.Opacity(0.6); - - // Account for the color of the tab row when setting the color of text - // on inactive tabs. Consider: - // * black active tabs - // * on a white tab row - // * with a transparent inactive tab color - // - // We don't want that to result in white text on a white tab row for - // inactive tabs. - const auto deselectedActualColor = deselectedTabColor.layer_over(_tabRowColor); - if (TerminalApp::ColorHelper::IsBrightColor(deselectedActualColor)) - { - deselectedFontBrush.Color(winrt::Windows::UI::Colors::Black()); - } - else - { - deselectedFontBrush.Color(winrt::Windows::UI::Colors::White()); - } - - // Add the empty theme dictionaries - const auto& tabItemThemeResources{ TabViewItem().Resources().ThemeDictionaries() }; - ResourceDictionary lightThemeDictionary; - ResourceDictionary darkThemeDictionary; - ResourceDictionary highContrastThemeDictionary; - tabItemThemeResources.Insert(winrt::box_value(L"Light"), lightThemeDictionary); - tabItemThemeResources.Insert(winrt::box_value(L"Dark"), darkThemeDictionary); - tabItemThemeResources.Insert(winrt::box_value(L"HighContrast"), highContrastThemeDictionary); - - // Apply the color to the tab - TabViewItem().Background(deselectedTabBrush); - - // Now actually set the resources we want in them. - // Before, we used to put these on the ResourceDictionary directly. - // However, HighContrast mode may require some adjustments. So let's just add - // all three so we can make those adjustments on the HighContrast version. - for (const auto& [k, v] : tabItemThemeResources) - { - const bool isHighContrast = winrt::unbox_value(k) == L"HighContrast"; - const auto& currentDictionary = v.as(); - - // TabViewItem.Background - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackground"), deselectedTabBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackgroundSelected"), selectedTabBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPointerOver"), isHighContrast ? fontBrush : hoverTabBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPressed"), selectedTabBrush); - - // TabViewItem.Foreground (aka text) - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderForeground"), deselectedFontBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderForegroundSelected"), fontBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderForegroundPointerOver"), isHighContrast ? selectedTabBrush : fontBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderForegroundPressed"), fontBrush); - - // TabViewItem.CloseButton.Foreground (aka X) - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForeground"), deselectedFontBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForegroundPressed"), isHighContrast ? deselectedFontBrush : secondaryFontBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonForegroundPointerOver"), isHighContrast ? deselectedFontBrush : fontBrush); - - // TabViewItem.CloseButton.Foreground _when_ interacting with the tab - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderPressedCloseButtonForeground"), fontBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderPointerOverCloseButtonForeground"), isHighContrast ? selectedTabBrush : fontBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderSelectedCloseButtonForeground"), fontBrush); - - // TabViewItem.CloseButton.Background (aka X button) - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackgroundPressed"), isHighContrast ? selectedTabBrush : subtleFillColorTertiaryBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackgroundPointerOver"), isHighContrast ? selectedTabBrush : subtleFillColorSecondaryBrush); - - // A few miscellaneous resources that WinUI said may be removed in the future - currentDictionary.Insert(winrt::box_value(L"TabViewButtonForegroundActiveTab"), fontBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewButtonForegroundPressed"), fontBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewButtonForegroundPointerOver"), fontBrush); - - // Add a few extra ones for high contrast mode - // BODGY: contrary to the docs, Insert() seems to throw if the value already exists - // Make sure you don't touch any that already exist here! - if (isHighContrast) - { - // TabViewItem.CloseButton.Border: in HC mode, the border makes the button more clearly visible - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBorderBrushPressed"), fontBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBorderBrushPointerOver"), fontBrush); - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBorderBrushSelected"), fontBrush); - } - } - - _RefreshVisualState(); - } - - // Method Description: - // - Clear out any color we've set for the TabViewItem. - // - This method should only be called on the UI thread. - // Arguments: - // - - // Return Value: - // - - void TabBase::_ClearTabBackgroundColor() - { - static const winrt::hstring keys[] = { - // TabViewItem.Background - L"TabViewItemHeaderBackground", - L"TabViewItemHeaderBackgroundSelected", - L"TabViewItemHeaderBackgroundPointerOver", - L"TabViewItemHeaderBackgroundPressed", - - // TabViewItem.Foreground (aka text) - L"TabViewItemHeaderForeground", - L"TabViewItemHeaderForegroundSelected", - L"TabViewItemHeaderForegroundPointerOver", - L"TabViewItemHeaderForegroundPressed", - - // TabViewItem.CloseButton.Foreground (aka X) - L"TabViewItemHeaderCloseButtonForeground", - L"TabViewItemHeaderForegroundSelected", - L"TabViewItemHeaderCloseButtonForegroundPointerOver", - L"TabViewItemHeaderCloseButtonForegroundPressed", - - // TabViewItem.CloseButton.Foreground _when_ interacting with the tab - L"TabViewItemHeaderPressedCloseButtonForeground", - L"TabViewItemHeaderPointerOverCloseButtonForeground", - L"TabViewItemHeaderSelectedCloseButtonForeground", - - // TabViewItem.CloseButton.Background (aka X button) - L"TabViewItemHeaderCloseButtonBackground", - L"TabViewItemHeaderCloseButtonBackgroundPressed", - L"TabViewItemHeaderCloseButtonBackgroundPointerOver", - - // A few miscellaneous resources that WinUI said may be removed in the future - L"TabViewButtonForegroundActiveTab", - L"TabViewButtonForegroundPressed", - L"TabViewButtonForegroundPointerOver", - - // TabViewItem.CloseButton.Border: in HC mode, the border makes the button more clearly visible - L"TabViewItemHeaderCloseButtonBorderBrushPressed", - L"TabViewItemHeaderCloseButtonBorderBrushPointerOver", - L"TabViewItemHeaderCloseButtonBorderBrushSelected" - }; - - const auto& tabItemThemeResources{ TabViewItem().Resources().ThemeDictionaries() }; - - // simply clear any of the colors in the tab's dict - for (const auto& keyString : keys) - { - const auto key = winrt::box_value(keyString); - for (const auto& [_, v] : tabItemThemeResources) - { - const auto& themeDictionary = v.as(); - themeDictionary.Remove(key); - } - } - - // GH#11382 DON'T set the background to null. If you do that, then the - // tab won't be hit testable at all. Transparent, however, is a totally - // valid hit test target. That makes sense. - TabViewItem().Background(WUX::Media::SolidColorBrush{ Windows::UI::Colors::Transparent() }); - - _RefreshVisualState(); - } - - // Method Description: - // BODGY - // - Toggles the requested theme of the tab view item, - // so that changes to the tab color are reflected immediately - // - Prior to MUX 2.8, we only toggled the visual state here, but that seemingly - // doesn't work in 2.8. - // - Just changing the Theme also doesn't seem to work by itself - there - // seems to be a way for the tab to set the deselected foreground onto - // itself as it becomes selected. If the mouse isn't over the tab, that - // can result in mismatched fg/bg's (see GH#15184). So that's right, we - // need to do both. - // Arguments: - // - - // Return Value: - // - - void TabBase::_RefreshVisualState() - { - const auto& item{ TabViewItem() }; - - const auto& reqTheme = TabViewItem().RequestedTheme(); - item.RequestedTheme(ElementTheme::Light); - item.RequestedTheme(ElementTheme::Dark); - item.RequestedTheme(reqTheme); - - if (TabViewItem().IsSelected()) - { - VisualStateManager::GoToState(item, L"Normal", true); - VisualStateManager::GoToState(item, L"Selected", true); - } - else - { - VisualStateManager::GoToState(item, L"Selected", true); - VisualStateManager::GoToState(item, L"Normal", true); - } - } - - TabCloseButtonVisibility TabBase::CloseButtonVisibility() - { - return _closeButtonVisibility; - } - - // Method Description: - // - set our internal state to track if we were requested to have a visible - // tab close button or not. - // - This is called every time the active tab changes. That way, the changes - // in focused tab can be reflected for the "ActiveOnly" state. - void TabBase::CloseButtonVisibility(TabCloseButtonVisibility visibility) - { - _closeButtonVisibility = visibility; - _updateIsClosable(); - } - - // Method Description: - // - Update our close button's visibility, to reflect both the ReadOnly - // state of the tab content, and also if if we were told to have a visible - // close button at all. - // - the tab being read-only takes precedence. That will always suppress - // the close button. - // - Otherwise we'll use the state set in CloseButtonVisibility to control - // the tab's visibility. - void TabBase::_updateIsClosable() - { - bool isClosable = true; - - if (ReadOnly()) - { - isClosable = false; - } - else - { - switch (_closeButtonVisibility) - { - case TabCloseButtonVisibility::Never: - isClosable = false; - break; - case TabCloseButtonVisibility::Hover: - isClosable = true; - break; - case TabCloseButtonVisibility::ActiveOnly: - isClosable = _focused(); - break; - default: - isClosable = true; - break; - } - } - TabViewItem().IsClosable(isClosable); - } - - bool TabBase::_focused() const noexcept - { - return _focusState != FocusState::Unfocused; - } - -} diff --git a/src/cascadia/TerminalApp/TabBase.h b/src/cascadia/TerminalApp/TabBase.h deleted file mode 100644 index aa4928c669..0000000000 --- a/src/cascadia/TerminalApp/TabBase.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#pragma once -#include "TabBase.g.h" - -// fwdecl unittest classes -namespace TerminalAppLocalTests -{ - class TabTests; -}; - -namespace winrt::TerminalApp::implementation -{ - struct TabBase : TabBaseT - { - public: - virtual void Focus(winrt::Windows::UI::Xaml::FocusState focusState) = 0; - - virtual void Shutdown(); - void SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch); - - void UpdateTabViewIndex(const uint32_t idx, const uint32_t numTabs); - void SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap); - virtual std::vector BuildStartupActions(BuildStartupKind kind) const = 0; - - virtual std::optional GetTabColor(); - void ThemeColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& focused, - const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& unfocused, - const til::color& tabRowColor); - - Microsoft::Terminal::Settings::Model::TabCloseButtonVisibility CloseButtonVisibility(); - void CloseButtonVisibility(Microsoft::Terminal::Settings::Model::TabCloseButtonVisibility visible); - - til::event> RequestFocusActiveControl; - - til::event> Closed; - til::event> CloseRequested; - til::property_changed_event PropertyChanged; - - // The TabViewIndex is the index this Tab object resides in TerminalPage's _tabs vector. - WINRT_PROPERTY(uint32_t, TabViewIndex, 0); - // The TabViewNumTabs is the number of Tab objects in TerminalPage's _tabs vector. - WINRT_PROPERTY(uint32_t, TabViewNumTabs, 0); - - WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Title, PropertyChanged.raise); - WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Icon, PropertyChanged.raise); - WINRT_OBSERVABLE_PROPERTY(bool, ReadOnly, PropertyChanged.raise, false); - WINRT_PROPERTY(winrt::Microsoft::UI::Xaml::Controls::TabViewItem, TabViewItem, nullptr); - - WINRT_OBSERVABLE_PROPERTY(winrt::Windows::UI::Xaml::FrameworkElement, Content, PropertyChanged.raise, nullptr); - - protected: - winrt::Windows::UI::Xaml::FocusState _focusState{ winrt::Windows::UI::Xaml::FocusState::Unfocused }; - winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeOtherTabsMenuItem{}; - winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeTabsAfterMenuItem{}; - winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveToNewWindowMenuItem{}; - winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveRightMenuItem{}; - winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveLeftMenuItem{}; - winrt::TerminalApp::ShortcutActionDispatch _dispatch; - Microsoft::Terminal::Settings::Model::IActionMapView _actionMap{ nullptr }; - winrt::hstring _keyChord{}; - - winrt::Microsoft::Terminal::Settings::Model::ThemeColor _themeColor{ nullptr }; - winrt::Microsoft::Terminal::Settings::Model::ThemeColor _unfocusedThemeColor{ nullptr }; - til::color _tabRowColor; - - Microsoft::Terminal::Settings::Model::TabCloseButtonVisibility _closeButtonVisibility{ Microsoft::Terminal::Settings::Model::TabCloseButtonVisibility::Always }; - - virtual void _CreateContextMenu(); - virtual winrt::hstring _CreateToolTipTitle(); - - virtual void _MakeTabViewItem(); - - void _AppendMoveMenuItems(winrt::Windows::UI::Xaml::Controls::MenuFlyout flyout); - winrt::Windows::UI::Xaml::Controls::MenuFlyoutSubItem _AppendCloseMenuItems(winrt::Windows::UI::Xaml::Controls::MenuFlyout flyout); - void _EnableMenuItems(); - void _UpdateSwitchToTabKeyChord(); - void _UpdateToolTip(); - - void _RecalculateAndApplyTabColor(); - void _ApplyTabColorOnUIThread(const winrt::Windows::UI::Color& color); - void _ClearTabBackgroundColor(); - void _RefreshVisualState(); - virtual winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush() = 0; - - bool _focused() const noexcept; - void _updateIsClosable(); - - friend class ::TerminalAppLocalTests::TabTests; - }; -} diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index 3b2691df93..b7a3e29e5a 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -99,7 +99,7 @@ namespace winrt::TerminalApp::implementation // Arguments: // - newTabImpl: the uninitialized tab. // - insertPosition: Optional parameter to indicate the position of tab. - void TerminalPage::_InitializeTab(winrt::com_ptr newTabImpl, uint32_t insertPosition) + void TerminalPage::_InitializeTab(winrt::com_ptr newTabImpl, uint32_t insertPosition) { newTabImpl->Initialize(); @@ -206,11 +206,11 @@ namespace winrt::TerminalApp::implementation // Arguments: // - pane: The pane to use as the root. // - insertPosition: Optional parameter to indicate the position of tab. - TerminalApp::TerminalTab TerminalPage::_CreateNewTabFromPane(std::shared_ptr pane, uint32_t insertPosition) + TerminalApp::Tab TerminalPage::_CreateNewTabFromPane(std::shared_ptr pane, uint32_t insertPosition) { if (pane) { - auto newTabImpl = winrt::make_self(pane); + auto newTabImpl = winrt::make_self(pane); _InitializeTab(newTabImpl, insertPosition); return *newTabImpl; } @@ -222,7 +222,7 @@ namespace winrt::TerminalApp::implementation // tab's icon to that icon. // Arguments: // - tab: the Tab to update the title for. - void TerminalPage::_UpdateTabIcon(TerminalTab& tab) + void TerminalPage::_UpdateTabIcon(Tab& tab) { if (const auto content{ tab.GetActiveContent() }) { @@ -272,9 +272,9 @@ namespace winrt::TerminalApp::implementation // - Duplicates the current focused tab void TerminalPage::_DuplicateFocusedTab() { - if (const auto terminalTab{ _GetFocusedTabImpl() }) + if (const auto activeTab{ _GetFocusedTabImpl() }) { - _DuplicateTab(*terminalTab); + _DuplicateTab(*activeTab); } } @@ -282,7 +282,7 @@ namespace winrt::TerminalApp::implementation // - Duplicates specified tab // Arguments: // - tab: tab to duplicate - void TerminalPage::_DuplicateTab(const TerminalTab& tab) + void TerminalPage::_DuplicateTab(const Tab& tab) { try { @@ -315,7 +315,7 @@ namespace winrt::TerminalApp::implementation // - Exports the content of the Terminal Buffer inside the tab // Arguments: // - tab: tab to export - safe_void_coroutine TerminalPage::_ExportTab(const TerminalTab& tab, winrt::hstring filepath) + safe_void_coroutine TerminalPage::_ExportTab(const Tab& tab, winrt::hstring filepath) { // This will be used to set up the file picker "filter", to select .txt // files by default. @@ -401,7 +401,7 @@ namespace winrt::TerminalApp::implementation // - Removes the tab (both TerminalControl and XAML) after prompting for approval // Arguments: // - tab: the tab to remove - winrt::Windows::Foundation::IAsyncAction TerminalPage::_HandleCloseTabRequested(winrt::TerminalApp::TabBase tab) + winrt::Windows::Foundation::IAsyncAction TerminalPage::_HandleCloseTabRequested(winrt::TerminalApp::Tab tab) { if (tab.ReadOnly()) { @@ -414,7 +414,7 @@ namespace winrt::TerminalApp::implementation } } - auto t = winrt::get_self(tab); + auto t = winrt::get_self(tab); auto actions = t->BuildStartupActions(BuildStartupKind::None); _AddPreviouslyClosedPaneOrTab(std::move(actions)); @@ -425,7 +425,7 @@ namespace winrt::TerminalApp::implementation // - Removes the tab (both TerminalControl and XAML) // Arguments: // - tab: the tab to remove - void TerminalPage::_RemoveTab(const winrt::TerminalApp::TabBase& tab) + void TerminalPage::_RemoveTab(const winrt::TerminalApp::Tab& tab) { uint32_t tabIndex{}; if (!_tabs.IndexOf(tab, tabIndex)) @@ -597,7 +597,7 @@ namespace winrt::TerminalApp::implementation // - tab - tab to select // Return Value: // - - void TerminalPage::_OnSwitchToTabRequested(const IInspectable& /*sender*/, const winrt::TerminalApp::TabBase& tab) + void TerminalPage::_OnSwitchToTabRequested(const IInspectable& /*sender*/, const winrt::TerminalApp::Tab& tab) { uint32_t index{}; if (_tabs.IndexOf(tab, index)) @@ -628,7 +628,7 @@ namespace winrt::TerminalApp::implementation // no tab is currently selected, returns nullopt. // Return Value: // - the index of the currently focused tab if there is one, else nullopt - std::optional TerminalPage::_GetTabIndex(const TerminalApp::TabBase& tab) const noexcept + std::optional TerminalPage::_GetTabIndex(const TerminalApp::Tab& tab) const noexcept { uint32_t i; if (_tabs.IndexOf(tab, i)) @@ -641,7 +641,7 @@ namespace winrt::TerminalApp::implementation // Method Description: // - returns the currently focused tab. This might return null, // so make sure to check the result! - winrt::TerminalApp::TabBase TerminalPage::_GetFocusedTab() const noexcept + winrt::TerminalApp::Tab TerminalPage::_GetFocusedTab() const noexcept { if (auto index{ _GetFocusedTabIndex() }) { @@ -653,11 +653,11 @@ namespace winrt::TerminalApp::implementation // Method Description: // - returns a com_ptr to the currently focused tab implementation. This might return null, // so make sure to check the result! - winrt::com_ptr TerminalPage::_GetFocusedTabImpl() const noexcept + winrt::com_ptr TerminalPage::_GetFocusedTabImpl() const noexcept { if (auto tab{ _GetFocusedTab() }) { - return _GetTerminalTabImpl(tab); + return _GetTabImpl(tab); } return nullptr; } @@ -665,7 +665,7 @@ namespace winrt::TerminalApp::implementation // Method Description: // - returns a tab corresponding to a view item. This might return null, // so make sure to check the result! - winrt::TerminalApp::TabBase TerminalPage::_GetTabByTabViewItem(const Microsoft::UI::Xaml::Controls::TabViewItem& tabViewItem) const noexcept + winrt::TerminalApp::Tab TerminalPage::_GetTabByTabViewItem(const Microsoft::UI::Xaml::Controls::TabViewItem& tabViewItem) const noexcept { uint32_t tabIndexFromControl{}; const auto items{ _tabView.TabItems() }; @@ -687,7 +687,7 @@ namespace winrt::TerminalApp::implementation // - tab: tab to focus. // Return Value: // - - safe_void_coroutine TerminalPage::_SetFocusedTab(const winrt::TerminalApp::TabBase tab) + safe_void_coroutine TerminalPage::_SetFocusedTab(const winrt::TerminalApp::Tab tab) { // GH#1117: This is a workaround because _tabView.SelectedIndex(tabIndex) // sometimes set focus to an incorrect tab after removing some tabs @@ -774,11 +774,11 @@ namespace winrt::TerminalApp::implementation // tab's Closed event. safe_void_coroutine TerminalPage::_CloseFocusedPane() { - if (const auto terminalTab{ _GetFocusedTabImpl() }) + if (const auto activeTab{ _GetFocusedTabImpl() }) { _UnZoomIfNeeded(); - if (const auto pane{ terminalTab->GetActivePane() }) + if (const auto pane{ activeTab->GetActivePane() }) { if (co_await _PaneConfirmCloseReadOnly(pane)) { @@ -793,7 +793,7 @@ namespace winrt::TerminalApp::implementation // Arguments: // - weakTab: weak reference to the tab that the pane belongs to. // - paneIds: collection of the IDs of the panes that are marked for removal. - void TerminalPage::_ClosePanes(weak_ref weakTab, std::vector paneIds) + void TerminalPage::_ClosePanes(weak_ref weakTab, std::vector paneIds) { if (auto strongTab{ weakTab.get() }) { @@ -838,7 +838,7 @@ namespace winrt::TerminalApp::implementation // - Closes provided tabs one by one // Arguments: // - tabs - tabs to remove - safe_void_coroutine TerminalPage::_RemoveTabs(const std::vector tabs) + safe_void_coroutine TerminalPage::_RemoveTabs(const std::vector tabs) { for (auto& tab : tabs) { @@ -926,7 +926,7 @@ namespace winrt::TerminalApp::implementation } // WinUI asynchronously updates its tab view items, so it may happen that we're given a - // `TabViewItem` that still contains a `TabBase` which has actually already been removed. + // `TabViewItem` that still contains a `Tab` which has actually already been removed. // First we must yield once, to flush out whatever TabView is currently doing. const auto strong = get_strong(); co_await wil::resume_foreground(Dispatcher()); @@ -966,7 +966,7 @@ namespace winrt::TerminalApp::implementation } } - void TerminalPage::_UpdatedSelectedTab(const winrt::TerminalApp::TabBase& tab) + void TerminalPage::_UpdatedSelectedTab(const winrt::TerminalApp::Tab& tab) { // Unfocus all the tabs. for (const auto& tab : _tabs) @@ -1007,10 +1007,10 @@ namespace winrt::TerminalApp::implementation _updateThemeColors(); - auto tab_impl = _GetTerminalTabImpl(tab); - if (tab_impl) + auto tabImpl = _GetTabImpl(tab); + if (tabImpl) { - auto profile = tab_impl->GetFocusedProfile(); + auto profile = tabImpl->GetFocusedProfile(); _UpdateBackground(profile); } } @@ -1057,7 +1057,7 @@ namespace winrt::TerminalApp::implementation for (uint32_t i = 0; i < size; ++i) { auto tab{ _tabs.GetAt(i) }; - auto tabImpl{ winrt::get_self(tab) }; + auto tabImpl{ winrt::get_self(tab) }; tabImpl->UpdateTabViewIndex(i, size); } } @@ -1068,7 +1068,7 @@ namespace winrt::TerminalApp::implementation // - tab: tab to bump. // Return Value: // - - void TerminalPage::_UpdateMRUTab(const winrt::TerminalApp::TabBase& tab) + void TerminalPage::_UpdateMRUTab(const winrt::TerminalApp::Tab& tab) { uint32_t mruIndex; if (_mruTabs.IndexOf(tab, mruIndex)) diff --git a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj index 5012430884..7e5028167b 100644 --- a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj +++ b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj @@ -99,15 +99,12 @@ Code - - TabBase.idl + + Tab.idl TaskbarState.idl - - TerminalTab.idl - TerminalPage.xaml Code @@ -206,16 +203,13 @@ PaletteItemTemplateSelector.idl Code - - TabBase.idl + + Tab.idl TaskbarState.idl - - TerminalTab.idl - TerminalPage.xaml Code @@ -333,9 +327,8 @@ MinMaxCloseControl.xaml Code - + - TerminalPage.xaml Code diff --git a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters index 52b5113bdb..68c7f8c7a3 100644 --- a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters +++ b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters @@ -81,9 +81,6 @@ settings - - tab - commandPalette @@ -91,7 +88,7 @@ tab - + diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 87ccb19a32..ce8e8762e4 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -59,8 +59,8 @@ namespace winrt namespace winrt::TerminalApp::implementation { TerminalPage::TerminalPage(TerminalApp::WindowProperties properties, const TerminalApp::ContentManager& manager) : - _tabs{ winrt::single_threaded_observable_vector() }, - _mruTabs{ winrt::single_threaded_observable_vector() }, + _tabs{ winrt::single_threaded_observable_vector() }, + _mruTabs{ winrt::single_threaded_observable_vector() }, _manager{ manager }, _hostingHwnd{}, _WindowProperties{ std::move(properties) } @@ -84,9 +84,9 @@ namespace winrt::TerminalApp::implementation // GH#13211 - if we haven't yet set the owning hwnd, reparent all the controls now. for (const auto& tab : _tabs) { - if (auto terminalTab{ _GetTerminalTabImpl(tab) }) + if (auto tabImpl{ _GetTabImpl(tab) }) { - terminalTab->GetRootPane()->WalkTree([&](auto&& pane) { + tabImpl->GetRootPane()->WalkTree([&](auto&& pane) { if (const auto& term{ pane->GetTerminalControl() }) { term.OwningHwnd(reinterpret_cast(hwnd)); @@ -566,9 +566,9 @@ namespace winrt::TerminalApp::implementation // GH#6586: now that we're done processing all startup commands, // focus the active control. This will work as expected for both // commandline invocations and for `wt` action invocations. - if (const auto& terminalTab{ _GetFocusedTabImpl() }) + if (const auto& tabImpl{ _GetFocusedTabImpl() }) { - if (const auto& content{ terminalTab->GetActiveContent() }) + if (const auto& content{ tabImpl->GetActiveContent() }) { content.Focus(FocusState::Programmatic); } @@ -1755,7 +1755,7 @@ namespace winrt::TerminalApp::implementation // TitleChanged event. // Arguments: // - tab: the Tab to update the title for. - void TerminalPage::_UpdateTitle(const TerminalTab& tab) + void TerminalPage::_UpdateTitle(const Tab& tab) { auto newTabTitle = tab.Title(); @@ -1833,13 +1833,13 @@ namespace winrt::TerminalApp::implementation } // Method Description: - // - Connects event handlers to the TerminalTab for events that we want to + // - Connects event handlers to the Tab for events that we want to // handle. This includes: // * the TitleChanged event, for changing the text of the tab // * the Color{Selected,Cleared} events to change the color of a tab. // Arguments: // - hostingTab: The Tab that's hosting this TermControl instance - void TerminalPage::_RegisterTabEvents(TerminalTab& hostingTab) + void TerminalPage::_RegisterTabEvents(Tab& hostingTab) { auto weakTab{ hostingTab.get_weak() }; auto weakThis{ get_weak() }; @@ -1922,9 +1922,9 @@ namespace winrt::TerminalApp::implementation // to the terminal when no other panes are present (GH#6219) bool TerminalPage::_MoveFocus(const FocusDirection& direction) { - if (const auto terminalTab{ _GetFocusedTabImpl() }) + if (const auto tabImpl{ _GetFocusedTabImpl() }) { - return terminalTab->NavigateFocus(direction); + return tabImpl->NavigateFocus(direction); } return false; } @@ -1938,19 +1938,19 @@ namespace winrt::TerminalApp::implementation // - true if panes were swapped. bool TerminalPage::_SwapPane(const FocusDirection& direction) { - if (const auto terminalTab{ _GetFocusedTabImpl() }) + if (const auto tabImpl{ _GetFocusedTabImpl() }) { _UnZoomIfNeeded(); - return terminalTab->SwapPane(direction); + return tabImpl->SwapPane(direction); } return false; } TermControl TerminalPage::_GetActiveControl() { - if (const auto terminalTab{ _GetFocusedTabImpl() }) + if (const auto tabImpl{ _GetFocusedTabImpl() }) { - return terminalTab->GetActiveTerminalControl(); + return tabImpl->GetActiveTerminalControl(); } return nullptr; } @@ -2057,7 +2057,7 @@ namespace winrt::TerminalApp::implementation for (auto tab : _tabs) { - auto t = winrt::get_self(tab); + auto t = winrt::get_self(tab); auto tabActions = t->BuildStartupActions(serializeBuffer ? BuildStartupKind::PersistAll : BuildStartupKind::PersistLayout); actions.insert(actions.end(), std::make_move_iterator(tabActions.begin()), std::make_move_iterator(tabActions.end())); } @@ -2152,14 +2152,14 @@ namespace winrt::TerminalApp::implementation // - rowsToScroll: a number of lines to move the viewport. If not provided we will use a system default. void TerminalPage::_Scroll(ScrollDirection scrollDirection, const Windows::Foundation::IReference& rowsToScroll) { - if (const auto terminalTab{ _GetFocusedTabImpl() }) + if (const auto tabImpl{ _GetFocusedTabImpl() }) { uint32_t realRowsToScroll; if (rowsToScroll == nullptr) { // The magic value of WHEEL_PAGESCROLL indicates that we need to scroll the entire page realRowsToScroll = _systemRowsToScroll == WHEEL_PAGESCROLL ? - terminalTab->GetActiveTerminalControl().ViewHeight() : + tabImpl->GetActiveTerminalControl().ViewHeight() : _systemRowsToScroll; } else @@ -2168,7 +2168,7 @@ namespace winrt::TerminalApp::implementation realRowsToScroll = rowsToScroll.Value(); } auto scrollDelta = _ComputeScrollDelta(scrollDirection, realRowsToScroll); - terminalTab->Scroll(scrollDelta); + tabImpl->Scroll(scrollDelta); } } @@ -2199,9 +2199,9 @@ namespace winrt::TerminalApp::implementation // specified window instead of moving it in our tab row. if (!windowId.empty()) { - if (const auto terminalTab{ _GetFocusedTabImpl() }) + if (const auto tabImpl{ _GetFocusedTabImpl() }) { - if (const auto pane{ terminalTab->GetActivePane() }) + if (const auto pane{ tabImpl->GetActivePane() }) { auto startupActions = pane->BuildStartupActions(0, 1, BuildStartupKind::MovePane); _DetachPaneFromWindow(pane); @@ -2240,7 +2240,7 @@ namespace winrt::TerminalApp::implementation // tab before its index changes. if (tabIdx < _tabs.Size()) { - auto targetTab = _GetTerminalTabImpl(_tabs.GetAt(tabIdx)); + auto targetTab = _GetTabImpl(_tabs.GetAt(tabIdx)); // if the selected tab is not a host of terminals (e.g. settings) // don't attempt to add a pane to it. if (!targetTab) @@ -2288,15 +2288,12 @@ namespace winrt::TerminalApp::implementation }); } - void TerminalPage::_DetachTabFromWindow(const winrt::com_ptr& tab) + void TerminalPage::_DetachTabFromWindow(const winrt::com_ptr& tab) { - if (const auto terminalTab = tab.try_as()) + // Detach the root pane, which will act like the whole tab got detached. + if (const auto rootPane = tab->GetRootPane()) { - // Detach the root pane, which will act like the whole tab got detached. - if (const auto rootPane = terminalTab->GetRootPane()) - { - _DetachPaneFromWindow(rootPane); - } + _DetachPaneFromWindow(rootPane); } } @@ -2324,7 +2321,7 @@ namespace winrt::TerminalApp::implementation RequestMoveContent.raise(*this, *request); } - bool TerminalPage::_MoveTab(winrt::com_ptr tab, MoveTabArgs args) + bool TerminalPage::_MoveTab(winrt::com_ptr tab, MoveTabArgs args) { if (!tab) { @@ -2392,10 +2389,10 @@ namespace winrt::TerminalApp::implementation // When the tab's active pane changes, we'll want to lookup a new icon // for it. The Title change will be propagated upwards through the tab's // PropertyChanged event handler. - void TerminalPage::_activePaneChanged(winrt::TerminalApp::TerminalTab sender, + void TerminalPage::_activePaneChanged(winrt::TerminalApp::Tab sender, Windows::Foundation::IInspectable /*args*/) { - if (const auto tab{ _GetTerminalTabImpl(sender) }) + if (const auto tab{ _GetTabImpl(sender) }) { // Possibly update the icon of the tab. _UpdateTabIcon(*tab); @@ -2484,7 +2481,7 @@ namespace winrt::TerminalApp::implementation // - splitDirection: one value from the TerminalApp::SplitDirection enum, indicating how the // new pane should be split from its parent. // - splitSize: the size of the split - void TerminalPage::_SplitPane(const winrt::com_ptr& tab, + void TerminalPage::_SplitPane(const winrt::com_ptr& tab, const SplitDirection splitDirection, const float splitSize, std::shared_ptr newPane) @@ -2565,10 +2562,10 @@ namespace winrt::TerminalApp::implementation // - void TerminalPage::_ToggleSplitOrientation() { - if (const auto terminalTab{ _GetFocusedTabImpl() }) + if (const auto tabImpl{ _GetFocusedTabImpl() }) { _UnZoomIfNeeded(); - terminalTab->ToggleSplitOrientation(); + tabImpl->ToggleSplitOrientation(); } } @@ -2582,10 +2579,10 @@ namespace winrt::TerminalApp::implementation // - void TerminalPage::_ResizePane(const ResizeDirection& direction) { - if (const auto terminalTab{ _GetFocusedTabImpl() }) + if (const auto tabImpl{ _GetFocusedTabImpl() }) { _UnZoomIfNeeded(); - terminalTab->ResizePane(direction); + tabImpl->ResizePane(direction); } } @@ -2597,23 +2594,23 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_ScrollPage(ScrollDirection scrollDirection) { // Do nothing if for some reason, there's no terminal tab in focus. We don't want to crash. - if (const auto terminalTab{ _GetFocusedTabImpl() }) + if (const auto tabImpl{ _GetFocusedTabImpl() }) { if (const auto& control{ _GetActiveControl() }) { const auto termHeight = control.ViewHeight(); auto scrollDelta = _ComputeScrollDelta(scrollDirection, termHeight); - terminalTab->Scroll(scrollDelta); + tabImpl->Scroll(scrollDelta); } } } void TerminalPage::_ScrollToBufferEdge(ScrollDirection scrollDirection) { - if (const auto terminalTab{ _GetFocusedTabImpl() }) + if (const auto tabImpl{ _GetFocusedTabImpl() }) { auto scrollDelta = _ComputeScrollDelta(scrollDirection, INT_MAX); - terminalTab->Scroll(scrollDelta); + tabImpl->Scroll(scrollDelta); } } @@ -2725,9 +2722,9 @@ namespace winrt::TerminalApp::implementation { if (_settings && _settings.GlobalSettings().SnapToGridOnResize()) { - if (const auto terminalTab{ _GetFocusedTabImpl() }) + if (const auto tabImpl{ _GetFocusedTabImpl() }) { - return terminalTab->CalcSnappedDimension(widthOrHeight, dimension); + return tabImpl->CalcSnappedDimension(widthOrHeight, dimension); } } return dimension; @@ -3343,7 +3340,7 @@ namespace winrt::TerminalApp::implementation // connection, then we'll return nullptr. Otherwise, we'll return a new // Pane for this connection. std::shared_ptr TerminalPage::_MakeTerminalPane(const NewTerminalArgs& newTerminalArgs, - const winrt::TerminalApp::TabBase& sourceTab, + const winrt::TerminalApp::Tab& sourceTab, TerminalConnection::ITerminalConnection existingConnection) { // First things first - Check for making a pane from content ID. @@ -3361,15 +3358,15 @@ namespace winrt::TerminalApp::implementation TerminalSettingsCreateResult controlSettings{ nullptr }; Profile profile{ nullptr }; - if (const auto& terminalTab{ _GetTerminalTabImpl(sourceTab) }) + if (const auto& tabImpl{ _GetTabImpl(sourceTab) }) { - profile = terminalTab->GetFocusedProfile(); + profile = tabImpl->GetFocusedProfile(); if (profile) { // TODO GH#5047 If we cache the NewTerminalArgs, we no longer need to do this. profile = GetClosestProfileForDuplicationOfProfile(profile); controlSettings = TerminalSettings::CreateWithProfile(_settings, profile, *_bindings); - const auto workingDirectory = terminalTab->GetActiveTerminalControl().WorkingDirectory(); + const auto workingDirectory = tabImpl->GetActiveTerminalControl().WorkingDirectory(); const auto validWorkingDirectory = !workingDirectory.empty(); if (validWorkingDirectory) { @@ -3433,7 +3430,7 @@ namespace winrt::TerminalApp::implementation auto debugContent{ winrt::make(profile, _terminalSettingsCache, newControl) }; auto debugPane = std::make_shared(debugContent); - // Since we're doing this split directly on the pane (instead of going through TerminalTab, + // Since we're doing this split directly on the pane (instead of going through Tab, // we need to handle the panes 'active' states // Set the pane we're splitting to active (otherwise Split will not do anything) @@ -3451,7 +3448,7 @@ namespace winrt::TerminalApp::implementation // NOTE: callers of _MakePane should be able to accept nullptr as a return // value gracefully. std::shared_ptr TerminalPage::_MakePane(const INewContentArgs& contentArgs, - const winrt::TerminalApp::TabBase& sourceTab, + const winrt::TerminalApp::Tab& sourceTab, TerminalConnection::ITerminalConnection existingConnection) { @@ -3485,9 +3482,9 @@ namespace winrt::TerminalApp::implementation // Prevent the user from opening a bunch of snippets panes. // // Look at the focused tab, and if it already has one, then just focus it. - if (const auto& focusedTab{ _GetFocusedTab() }) + if (const auto& focusedTab{ _GetFocusedTabImpl() }) { - const auto rootPane{ focusedTab.try_as()->GetRootPane() }; + const auto rootPane{ focusedTab->GetRootPane() }; const bool found = rootPane == nullptr ? false : rootPane->WalkTree([](const auto& p) -> bool { if (const auto& snippets{ p->GetContent().try_as() }) { @@ -3643,21 +3640,21 @@ namespace winrt::TerminalApp::implementation for (const auto& tab : _tabs) { - if (auto terminalTab{ _GetTerminalTabImpl(tab) }) + if (auto tabImpl{ _GetTabImpl(tab) }) { // Let the tab know that there are new settings. It's up to each content to decide what to do with them. - terminalTab->UpdateSettings(_settings); + tabImpl->UpdateSettings(_settings); // Update the icon of the tab for the currently focused profile in that tab. // Only do this for TerminalTabs. Other types of tabs won't have multiple panes // and profiles so the Title and Icon will be set once and only once on init. - _UpdateTabIcon(*terminalTab); + _UpdateTabIcon(*tabImpl); // Force the TerminalTab to re-grab its currently active control's title. - terminalTab->UpdateTitle(); + tabImpl->UpdateTitle(); } - auto tabImpl{ winrt::get_self(tab) }; + auto tabImpl{ winrt::get_self(tab) }; tabImpl->SetActionMap(_settings.ActionMap()); } @@ -3776,7 +3773,7 @@ namespace winrt::TerminalApp::implementation for (const auto& tab : _tabs) { - if (auto tabImpl{ _GetTerminalTabImpl(tab) }) + if (auto tabImpl{ _GetTabImpl(tab) }) { auto tabState{ tabImpl->GetCombinedTaskbarState() }; // lowest priority wins @@ -3819,11 +3816,11 @@ namespace winrt::TerminalApp::implementation _visible = showOrHide; for (const auto& tab : _tabs) { - if (auto terminalTab{ _GetTerminalTabImpl(tab) }) + if (auto tabImpl{ _GetTabImpl(tab) }) { // Manually enumerate the panes in each tab; this will let us recycle TerminalSettings // objects but only have to iterate one time. - terminalTab->GetRootPane()->WalkTree([&](auto&& pane) { + tabImpl->GetRootPane()->WalkTree([&](auto&& pane) { if (auto control = pane->GetTerminalControl()) { control.WindowVisibilityChanged(showOrHide); @@ -3841,7 +3838,7 @@ namespace winrt::TerminalApp::implementation // - tab: the tab where the search box should be created // Return Value: // - - void TerminalPage::_Find(const TerminalTab& tab) + void TerminalPage::_Find(const Tab& tab) { if (const auto& control{ tab.GetActiveTerminalControl() }) { @@ -3959,7 +3956,7 @@ namespace winrt::TerminalApp::implementation _newTabButton.Background(backgroundBrush); _newTabButton.Foreground(foregroundBrush); - // This is just like what we do in TabBase::_RefreshVisualState. We need + // This is just like what we do in Tab::_RefreshVisualState. We need // to manually toggle the visual state, so the setters in the visual // state group will re-apply, and set our currently selected colors in // the resources. @@ -4210,25 +4207,18 @@ namespace winrt::TerminalApp::implementation } // Method Description: - // - Returns a com_ptr to the implementation type of the given tab if it's a TerminalTab. + // - Returns a com_ptr to the implementation type of the given tab if it's a Tab. // If the tab is not a TerminalTab, returns nullptr. // Arguments: // - tab: the projected type of a Tab // Return Value: // - If the tab is a TerminalTab, a com_ptr to the implementation type. // If the tab is not a TerminalTab, nullptr - winrt::com_ptr TerminalPage::_GetTerminalTabImpl(const TerminalApp::TabBase& tab) + winrt::com_ptr TerminalPage::_GetTabImpl(const TerminalApp::Tab& tab) { - if (auto terminalTab = tab.try_as()) - { - winrt::com_ptr tabImpl; - tabImpl.copy_from(winrt::get_self(terminalTab)); - return tabImpl; - } - else - { - return nullptr; - } + winrt::com_ptr tabImpl; + tabImpl.copy_from(winrt::get_self(tab)); + return tabImpl; } // Method Description: @@ -4715,10 +4705,10 @@ namespace winrt::TerminalApp::implementation for (const auto& tab : _tabs) { - if (auto terminalTab{ _GetTerminalTabImpl(tab) }) + if (auto tabImpl{ _GetTabImpl(tab) }) { // The root pane will propagate the theme change to all its children. - if (const auto& rootPane{ terminalTab->GetRootPane() }) + if (const auto& rootPane{ tabImpl->GetRootPane() }) { rootPane->UpdateResources(_paneResources); } @@ -4779,7 +4769,7 @@ namespace winrt::TerminalApp::implementation } // Second: Update the colors of our individual TabViewItems. This - // applies tab.background to the tabs via TerminalTab::ThemeColor. + // applies tab.background to the tabs via Tab::ThemeColor. // // Do this second, so that we already know the bgColor of the titlebar. { @@ -4787,8 +4777,8 @@ namespace winrt::TerminalApp::implementation const auto tabUnfocusedBackground = theme.Tab() ? theme.Tab().UnfocusedBackground() : nullptr; for (const auto& tab : _tabs) { - winrt::com_ptr tabImpl; - tabImpl.copy_from(winrt::get_self(tab)); + winrt::com_ptr tabImpl; + tabImpl.copy_from(winrt::get_self(tab)); tabImpl->ThemeColor(tabBackground, tabUnfocusedBackground, bgColor); } } @@ -5257,8 +5247,8 @@ namespace winrt::TerminalApp::implementation // Get the tab impl from this event. const auto eventTab = e.Tab(); const auto tabBase = _GetTabByTabViewItem(eventTab); - winrt::com_ptr tabImpl; - tabImpl.copy_from(winrt::get_self(tabBase)); + winrt::com_ptr tabImpl; + tabImpl.copy_from(winrt::get_self(tabBase)); if (tabImpl) { // First: stash the tab we started dragging. diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 4879f65fc6..e4bf6efa1e 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -4,7 +4,7 @@ #pragma once #include "TerminalPage.g.h" -#include "TerminalTab.h" +#include "Tab.h" #include "AppKeyBindings.h" #include "AppCommandlineArgs.h" #include "RenameWindowRequestedArgs.g.h" @@ -219,13 +219,13 @@ namespace winrt::TerminalApp::implementation Microsoft::Terminal::Settings::Model::CascadiaSettings _settings{ nullptr }; - Windows::Foundation::Collections::IObservableVector _tabs; - Windows::Foundation::Collections::IObservableVector _mruTabs; - static winrt::com_ptr _GetTerminalTabImpl(const TerminalApp::TabBase& tab); + Windows::Foundation::Collections::IObservableVector _tabs; + Windows::Foundation::Collections::IObservableVector _mruTabs; + static winrt::com_ptr _GetTabImpl(const TerminalApp::Tab& tab); void _UpdateTabIndices(); - TerminalApp::TerminalTab _settingsTab{ nullptr }; + TerminalApp::Tab _settingsTab{ nullptr }; bool _isInFocusMode{ false }; bool _isFullscreen{ false }; @@ -277,7 +277,7 @@ namespace winrt::TerminalApp::implementation struct StashedDragData { - winrt::com_ptr draggedTab{ nullptr }; + winrt::com_ptr draggedTab{ nullptr }; winrt::Windows::Foundation::Point dragOffset{ 0, 0 }; } _stashed; @@ -305,7 +305,7 @@ namespace winrt::TerminalApp::implementation void _OpenNewTabDropdown(); HRESULT _OpenNewTab(const Microsoft::Terminal::Settings::Model::INewContentArgs& newContentArgs); - TerminalApp::TerminalTab _CreateNewTabFromPane(std::shared_ptr pane, uint32_t insertPosition = -1); + TerminalApp::Tab _CreateNewTabFromPane(std::shared_ptr pane, uint32_t insertPosition = -1); std::wstring _evaluatePathForCwd(std::wstring_view path); @@ -328,25 +328,25 @@ namespace winrt::TerminalApp::implementation void _HookupKeyBindings(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap) noexcept; void _RegisterActionCallbacks(); - void _UpdateTitle(const TerminalTab& tab); - void _UpdateTabIcon(TerminalTab& tab); + void _UpdateTitle(const Tab& tab); + void _UpdateTabIcon(Tab& tab); void _UpdateTabView(); void _UpdateTabWidthMode(); void _SetBackgroundImage(const winrt::Microsoft::Terminal::Settings::Model::IAppearanceConfig& newAppearance); void _DuplicateFocusedTab(); - void _DuplicateTab(const TerminalTab& tab); + void _DuplicateTab(const Tab& tab); - safe_void_coroutine _ExportTab(const TerminalTab& tab, winrt::hstring filepath); + safe_void_coroutine _ExportTab(const Tab& tab, winrt::hstring filepath); - winrt::Windows::Foundation::IAsyncAction _HandleCloseTabRequested(winrt::TerminalApp::TabBase tab); + winrt::Windows::Foundation::IAsyncAction _HandleCloseTabRequested(winrt::TerminalApp::Tab tab); void _CloseTabAtIndex(uint32_t index); - void _RemoveTab(const winrt::TerminalApp::TabBase& tab); - safe_void_coroutine _RemoveTabs(const std::vector tabs); + void _RemoveTab(const winrt::TerminalApp::Tab& tab); + safe_void_coroutine _RemoveTabs(const std::vector tabs); - void _InitializeTab(winrt::com_ptr newTabImpl, uint32_t insertPosition = -1); + void _InitializeTab(winrt::com_ptr newTabImpl, uint32_t insertPosition = -1); void _RegisterTerminalEvents(Microsoft::Terminal::Control::TermControl term); - void _RegisterTabEvents(TerminalTab& hostingTab); + void _RegisterTabEvents(Tab& hostingTab); void _DismissTabContextMenus(); void _FocusCurrentTab(const bool focusAlways); @@ -357,7 +357,7 @@ namespace winrt::TerminalApp::implementation bool _MoveFocus(const Microsoft::Terminal::Settings::Model::FocusDirection& direction); bool _SwapPane(const Microsoft::Terminal::Settings::Model::FocusDirection& direction); bool _MovePane(const Microsoft::Terminal::Settings::Model::MovePaneArgs args); - bool _MoveTab(winrt::com_ptr tab, const Microsoft::Terminal::Settings::Model::MoveTabArgs args); + bool _MoveTab(winrt::com_ptr tab, const Microsoft::Terminal::Settings::Model::MoveTabArgs args); template bool _ApplyToActiveControls(F f) @@ -381,21 +381,21 @@ namespace winrt::TerminalApp::implementation winrt::Microsoft::Terminal::Control::TermControl _GetActiveControl(); std::optional _GetFocusedTabIndex() const noexcept; - std::optional _GetTabIndex(const TerminalApp::TabBase& tab) const noexcept; - TerminalApp::TabBase _GetFocusedTab() const noexcept; - winrt::com_ptr _GetFocusedTabImpl() const noexcept; - TerminalApp::TabBase _GetTabByTabViewItem(const Microsoft::UI::Xaml::Controls::TabViewItem& tabViewItem) const noexcept; + std::optional _GetTabIndex(const TerminalApp::Tab& tab) const noexcept; + TerminalApp::Tab _GetFocusedTab() const noexcept; + winrt::com_ptr _GetFocusedTabImpl() const noexcept; + TerminalApp::Tab _GetTabByTabViewItem(const Microsoft::UI::Xaml::Controls::TabViewItem& tabViewItem) const noexcept; void _HandleClosePaneRequested(std::shared_ptr pane); - safe_void_coroutine _SetFocusedTab(const winrt::TerminalApp::TabBase tab); + safe_void_coroutine _SetFocusedTab(const winrt::TerminalApp::Tab tab); safe_void_coroutine _CloseFocusedPane(); - void _ClosePanes(weak_ref weakTab, std::vector paneIds); + void _ClosePanes(weak_ref weakTab, std::vector paneIds); winrt::Windows::Foundation::IAsyncOperation _PaneConfirmCloseReadOnly(std::shared_ptr pane); void _AddPreviouslyClosedPaneOrTab(std::vector&& args); void _Scroll(ScrollDirection scrollDirection, const Windows::Foundation::IReference& rowsToScroll); - void _SplitPane(const winrt::com_ptr& tab, + void _SplitPane(const winrt::com_ptr& tab, const Microsoft::Terminal::Settings::Model::SplitDirection splitType, const float splitSize, std::shared_ptr newPane); @@ -439,14 +439,14 @@ namespace winrt::TerminalApp::implementation void _OnTabItemsChanged(const IInspectable& sender, const Windows::Foundation::Collections::IVectorChangedEventArgs& eventArgs); void _OnTabCloseRequested(const IInspectable& sender, const Microsoft::UI::Xaml::Controls::TabViewTabCloseRequestedEventArgs& eventArgs); void _OnFirstLayout(const IInspectable& sender, const IInspectable& eventArgs); - void _UpdatedSelectedTab(const winrt::TerminalApp::TabBase& tab); + void _UpdatedSelectedTab(const winrt::TerminalApp::Tab& tab); void _UpdateBackground(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile); void _OnDispatchCommandRequested(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::Command& command); void _OnCommandLineExecutionRequested(const IInspectable& sender, const winrt::hstring& commandLine); - void _OnSwitchToTabRequested(const IInspectable& sender, const winrt::TerminalApp::TabBase& tab); + void _OnSwitchToTabRequested(const IInspectable& sender, const winrt::TerminalApp::Tab& tab); - void _Find(const TerminalTab& tab); + void _Find(const Tab& tab); winrt::Microsoft::Terminal::Control::TermControl _CreateNewControlAndContent(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings, const winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection& connection); @@ -455,10 +455,10 @@ namespace winrt::TerminalApp::implementation TerminalApp::IPaneContent _makeSettingsContent(); std::shared_ptr _MakeTerminalPane(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr, - const winrt::TerminalApp::TabBase& sourceTab = nullptr, + const winrt::TerminalApp::Tab& sourceTab = nullptr, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); std::shared_ptr _MakePane(const Microsoft::Terminal::Settings::Model::INewContentArgs& newContentArgs = nullptr, - const winrt::TerminalApp::TabBase& sourceTab = nullptr, + const winrt::TerminalApp::Tab& sourceTab = nullptr, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); void _RefreshUIForSettingsReload(); @@ -475,7 +475,7 @@ namespace winrt::TerminalApp::implementation static int _ComputeScrollDelta(ScrollDirection scrollDirection, const uint32_t rowsToScroll); static uint32_t _ReadSystemRowsToScroll(); - void _UpdateMRUTab(const winrt::TerminalApp::TabBase& tab); + void _UpdateMRUTab(const winrt::TerminalApp::Tab& tab); void _TryMoveTab(const uint32_t currentTabIndex, const int32_t suggestedNewTabIndex); @@ -534,7 +534,7 @@ namespace winrt::TerminalApp::implementation void _onTabDroppedOutside(winrt::Windows::Foundation::IInspectable sender, winrt::Microsoft::UI::Xaml::Controls::TabViewTabDroppedOutsideEventArgs e); void _DetachPaneFromWindow(std::shared_ptr pane); - void _DetachTabFromWindow(const winrt::com_ptr& terminalTab); + void _DetachTabFromWindow(const winrt::com_ptr& tabImpl); void _MoveContent(std::vector&& actions, const winrt::hstring& windowName, const uint32_t tabIndex, @@ -546,9 +546,9 @@ namespace winrt::TerminalApp::implementation winrt::Windows::UI::Xaml::Controls::MenuFlyout _CreateRunAsAdminFlyout(int profileIndex); winrt::Microsoft::Terminal::Control::TermControl _senderOrActiveControl(const winrt::Windows::Foundation::IInspectable& sender); - winrt::com_ptr _senderOrFocusedTab(const IInspectable& sender); + winrt::com_ptr _senderOrFocusedTab(const IInspectable& sender); - void _activePaneChanged(winrt::TerminalApp::TerminalTab tab, Windows::Foundation::IInspectable args); + void _activePaneChanged(winrt::TerminalApp::Tab tab, Windows::Foundation::IInspectable args); safe_void_coroutine _doHandleSuggestions(Microsoft::Terminal::Settings::Model::SuggestionsArgs realArgs); #pragma region ActionHandlers diff --git a/src/cascadia/TerminalApp/TerminalTab.idl b/src/cascadia/TerminalApp/TerminalTab.idl deleted file mode 100644 index 5dbd845d49..0000000000 --- a/src/cascadia/TerminalApp/TerminalTab.idl +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -import "TabBase.idl"; -import "TerminalTabStatus.idl"; - -namespace TerminalApp -{ - [default_interface] runtimeclass TerminalTab : TabBase - { - TerminalTabStatus TabStatus { get; }; - } -} diff --git a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj index 6a20f0ac9b..282f68a589 100644 --- a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj +++ b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj @@ -36,7 +36,6 @@ -