diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
index 9fa780a3a..5f325b1a6 100644
--- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
+++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
@@ -662,10 +662,13 @@
Open a new tab in given starting directory
+
+ Split Tab
+
Open a new window with given starting directory
Split the window and start in given directory
-
\ No newline at end of file
+
diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp
index dd3a7aa7c..b93f50cab 100644
--- a/src/cascadia/TerminalApp/TabManagement.cpp
+++ b/src/cascadia/TerminalApp/TabManagement.cpp
@@ -192,6 +192,16 @@ namespace winrt::TerminalApp::implementation
}
});
+ newTabImpl->SplitTabRequested([weakTab, weakThis{ get_weak() }]() {
+ auto page{ weakThis.get() };
+ auto tab{ weakTab.get() };
+
+ if (page && tab)
+ {
+ page->_SplitTab(*tab);
+ }
+ });
+
auto tabViewItem = newTabImpl->TabViewItem();
_tabView.TabItems().Append(tabViewItem);
@@ -357,6 +367,20 @@ namespace winrt::TerminalApp::implementation
CATCH_LOG();
}
+ // Method Description:
+ // - Sets the specified tab as the focused tab and splits its active pane
+ // Arguments:
+ // - tab: tab to split
+ void TerminalPage::_SplitTab(TerminalTab& tab)
+ {
+ try
+ {
+ _SetFocusedTab(tab);
+ _SplitPane(tab, SplitState::Automatic, SplitType::Duplicate);
+ }
+ CATCH_LOG();
+ }
+
// Method Description:
// - Removes the tab (both TerminalControl and XAML) after prompting for approval
// Arguments:
diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp
index 281189920..96e5f38e0 100644
--- a/src/cascadia/TerminalApp/TerminalPage.cpp
+++ b/src/cascadia/TerminalApp/TerminalPage.cpp
@@ -1238,6 +1238,33 @@ namespace winrt::TerminalApp::implementation
return;
}
+ _SplitPane(*focusedTab, splitType, splitMode, splitSize, newTerminalArgs);
+ }
+
+ // Method Description:
+ // - Split the focused pane of the given tab, either horizontally or vertically, and place the
+ // given TermControl into the newly created pane.
+ // - If splitType == SplitState::None, this method does nothing.
+ // Arguments:
+ // - tab: The tab that is going to be split.
+ // - splitType: one value from the TerminalApp::SplitState enum, indicating how the
+ // new pane should be split from its parent.
+ // - splitMode: value from TerminalApp::SplitType enum, indicating the profile to be used in the newly split pane.
+ // - newTerminalArgs: An object that may contain a blob of parameters to
+ // control which profile is created and with possible other
+ // configurations. See CascadiaSettings::BuildSettings for more details.
+ void TerminalPage::_SplitPane(TerminalTab& tab,
+ const SplitState splitType,
+ const SplitType splitMode,
+ const float splitSize,
+ const NewTerminalArgs& newTerminalArgs)
+ {
+ // Do nothing if we're requesting no split.
+ if (splitType == SplitState::None)
+ {
+ return;
+ }
+
try
{
TerminalSettingsCreateResult controlSettings{ nullptr };
@@ -1246,12 +1273,12 @@ namespace winrt::TerminalApp::implementation
if (splitMode == SplitType::Duplicate)
{
- std::optional current_guid = focusedTab->GetFocusedProfile();
+ std::optional current_guid = tab.GetFocusedProfile();
if (current_guid)
{
profileFound = true;
controlSettings = TerminalSettings::CreateWithProfileByID(_settings, current_guid.value(), *_bindings);
- const auto workingDirectory = focusedTab->GetActiveTerminalControl().WorkingDirectory();
+ const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory();
const auto validWorkingDirectory = !workingDirectory.empty();
if (validWorkingDirectory)
{
@@ -1287,10 +1314,10 @@ namespace winrt::TerminalApp::implementation
auto realSplitType = splitType;
if (realSplitType == SplitState::Automatic)
{
- realSplitType = focusedTab->PreCalculateAutoSplit(availableSpace);
+ realSplitType = tab.PreCalculateAutoSplit(availableSpace);
}
- const auto canSplit = focusedTab->PreCalculateCanSplit(realSplitType, splitSize, availableSpace);
+ const auto canSplit = tab.PreCalculateCanSplit(realSplitType, splitSize, availableSpace);
if (!canSplit)
{
return;
@@ -1299,11 +1326,11 @@ namespace winrt::TerminalApp::implementation
auto newControl = _InitControl(controlSettings, controlConnection);
// Hookup our event handlers to the new terminal
- _RegisterTerminalEvents(newControl, *focusedTab);
+ _RegisterTerminalEvents(newControl, tab);
_UnZoomIfNeeded();
- focusedTab->SplitPane(realSplitType, splitSize, realGuid, newControl);
+ tab.SplitPane(realSplitType, splitSize, realGuid, newControl);
}
CATCH_LOG();
}
diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h
index aa2db9529..d6476b5ad 100644
--- a/src/cascadia/TerminalApp/TerminalPage.h
+++ b/src/cascadia/TerminalApp/TerminalPage.h
@@ -219,6 +219,8 @@ namespace winrt::TerminalApp::implementation
void _DuplicateFocusedTab();
void _DuplicateTab(const TerminalTab& tab);
+ void _SplitTab(TerminalTab& tab);
+
winrt::Windows::Foundation::IAsyncAction _HandleCloseTabRequested(winrt::TerminalApp::TabBase tab);
void _CloseTabAtIndex(uint32_t index);
void _RemoveTab(const winrt::TerminalApp::TabBase& tab);
@@ -254,6 +256,11 @@ namespace winrt::TerminalApp::implementation
const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
const float splitSize = 0.5f,
const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
+ void _SplitPane(TerminalTab& tab,
+ const Microsoft::Terminal::Settings::Model::SplitState splitType,
+ const Microsoft::Terminal::Settings::Model::SplitType splitMode = Microsoft::Terminal::Settings::Model::SplitType::Manual,
+ const float splitSize = 0.5f,
+ const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr);
void _ResizePane(const Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
void _ToggleSplitOrientation();
diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp
index 4e420c5c2..ad4595a1b 100644
--- a/src/cascadia/TerminalApp/TerminalTab.cpp
+++ b/src/cascadia/TerminalApp/TerminalTab.cpp
@@ -936,12 +936,30 @@ namespace winrt::TerminalApp::implementation
duplicateTabMenuItem.Icon(duplicateTabSymbol);
}
+ Controls::MenuFlyoutItem splitTabMenuItem;
+ {
+ // "Split Tab"
+ Controls::FontIcon splitTabSymbol;
+ splitTabSymbol.FontFamily(Media::FontFamily{ L"Segoe MDL2 Assets" });
+ splitTabSymbol.Glyph(L"\xF246"); // ViewDashboard
+
+ splitTabMenuItem.Click([weakThis](auto&&, auto&&) {
+ if (auto tab{ weakThis.get() })
+ {
+ tab->_SplitTabRequestedHandlers();
+ }
+ });
+ splitTabMenuItem.Text(RS_(L"SplitTabText"));
+ splitTabMenuItem.Icon(splitTabSymbol);
+ }
+
// Build the menu
Controls::MenuFlyout contextMenuFlyout;
Controls::MenuFlyoutSeparator menuSeparator;
contextMenuFlyout.Items().Append(chooseColorMenuItem);
contextMenuFlyout.Items().Append(renameTabMenuItem);
contextMenuFlyout.Items().Append(duplicateTabMenuItem);
+ contextMenuFlyout.Items().Append(splitTabMenuItem);
contextMenuFlyout.Items().Append(menuSeparator);
// GH#5750 - When the context menu is dismissed with ESC, toss the focus
@@ -1315,4 +1333,5 @@ namespace winrt::TerminalApp::implementation
DEFINE_EVENT(TerminalTab, ColorCleared, _colorCleared, winrt::delegate<>);
DEFINE_EVENT(TerminalTab, TabRaiseVisualBell, _TabRaiseVisualBellHandlers, winrt::delegate<>);
DEFINE_EVENT(TerminalTab, DuplicateRequested, _DuplicateRequestedHandlers, winrt::delegate<>);
+ DEFINE_EVENT(TerminalTab, SplitTabRequested, _SplitTabRequestedHandlers, winrt::delegate<>);
}
diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h
index 3ef935364..f3cee7555 100644
--- a/src/cascadia/TerminalApp/TerminalTab.h
+++ b/src/cascadia/TerminalApp/TerminalTab.h
@@ -94,6 +94,7 @@ namespace winrt::TerminalApp::implementation
DECLARE_EVENT(ColorCleared, _colorCleared, winrt::delegate<>);
DECLARE_EVENT(TabRaiseVisualBell, _TabRaiseVisualBellHandlers, winrt::delegate<>);
DECLARE_EVENT(DuplicateRequested, _DuplicateRequestedHandlers, winrt::delegate<>);
+ DECLARE_EVENT(SplitTabRequested, _SplitTabRequestedHandlers, winrt::delegate<>);
TYPED_EVENT(TaskbarProgressChanged, IInspectable, IInspectable);
private: