Skip to content

Commit 82487d0

Browse files
committed
PRE-MERGE #18928 Add support for tmux control mode (#3656)
2 parents 3252b7d + 7ec5d91 commit 82487d0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1969
-29
lines changed

.github/actions/spelling/excludes.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ Resources/(?!en)
9999
^NOTICE.md
100100
^oss/.*?/
101101
^samples/PixelShaders/Screenshots/
102-
^src/cascadia/TerminalSettingsEditor/SegoeFluentIconList.h$
102+
^src/cascadia/TerminalApp/TmuxControl\.cpp$
103+
^src/cascadia/TerminalSettingsEditor/SegoeFluentIconList\.h$
103104
^src/interactivity/onecore/BgfxEngine\.
104105
^src/renderer/atlas/
105106
^src/renderer/wddmcon/WddmConRenderer\.

src/cascadia/TerminalApp/AppActionHandlers.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
#include "pch.h"
55
#include "App.h"
66

7-
#include "TerminalPage.h"
87
#include "ScratchpadContent.h"
9-
#include "../WinRTUtils/inc/WtExeUtils.h"
8+
#include "TerminalPage.h"
9+
#include "TmuxControl.h"
10+
#include "Utils.h"
1011
#include "../../types/inc/utils.hpp"
1112
#include "../TerminalSettingsAppAdapterLib/TerminalSettings.h"
12-
#include "Utils.h"
13+
#include "../WinRTUtils/inc/WtExeUtils.h"
1314

1415
using namespace winrt::Windows::ApplicationModel::DataTransfer;
1516
using namespace winrt::Windows::UI::Xaml;
@@ -284,6 +285,15 @@ namespace winrt::TerminalApp::implementation
284285

285286
const auto& activeTab{ _senderOrFocusedTab(sender) };
286287

288+
if constexpr (Feature_TmuxControl::IsEnabled())
289+
{
290+
//Tmux control takes over
291+
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(activeTab))
292+
{
293+
return _tmuxControl->SplitPane(activeTab, realArgs.SplitDirection());
294+
}
295+
}
296+
287297
_SplitPane(activeTab,
288298
realArgs.SplitDirection(),
289299
// This is safe, we're already filtering so the value is (0, 1)

src/cascadia/TerminalApp/Pane.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,10 +1306,10 @@ void Pane::UpdateSettings(const CascadiaSettings& settings)
13061306
// - splitType: How the pane should be attached
13071307
// Return Value:
13081308
// - the new reference to the child created from the current pane.
1309-
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType)
1309+
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType, const float splitSize)
13101310
{
13111311
// Splice the new pane into the tree
1312-
const auto [first, _] = _Split(splitType, .5, pane);
1312+
const auto [first, _] = _Split(splitType, splitSize, pane);
13131313

13141314
// If the new pane has a child that was the focus, re-focus it
13151315
// to steal focus from the currently focused pane.
@@ -2298,8 +2298,7 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
22982298
_firstChild->Closed(_firstClosedToken);
22992299
_secondChild->Closed(_secondClosedToken);
23002300
// If we are not a leaf we should create a new pane that contains our children
2301-
auto first = std::make_shared<Pane>(_firstChild, _secondChild, _splitState, _desiredSplitPosition);
2302-
_firstChild = first;
2301+
_firstChild = std::make_shared<Pane>(_firstChild, _secondChild, _splitState, _desiredSplitPosition);
23032302
}
23042303
else
23052304
{

src/cascadia/TerminalApp/Pane.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ class Pane : public std::enable_shared_from_this<Pane>
131131
void Close();
132132

133133
std::shared_ptr<Pane> AttachPane(std::shared_ptr<Pane> pane,
134-
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType);
134+
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
135+
const float splitSize = .5);
135136
std::shared_ptr<Pane> DetachPane(std::shared_ptr<Pane> pane);
136137

137138
int GetLeafPaneCount() const noexcept;

src/cascadia/TerminalApp/Resources/en-US/Resources.resw

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -923,4 +923,11 @@
923923
<data name="InvalidRegex" xml:space="preserve">
924924
<value>An invalid regular expression was found.</value>
925925
</data>
926-
</root>
926+
<data name="TmuxControlInfo" xml:space="preserve">
927+
<value>Running in tmux control mode; Press 'q' to detach:</value>
928+
<comment>{Locked="'q'"}</comment>
929+
</data>
930+
<data name="NewTmuxControlTab.Text" xml:space="preserve">
931+
<value>Tmux Control Tab</value>
932+
</data>
933+
</root>

src/cascadia/TerminalApp/TerminalAppLib.vcxproj

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@
173173
<ClInclude Include="SettingsPaneContent.h">
174174
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
175175
</ClInclude>
176+
<ClInclude Include="TmuxConnection.h" />
177+
<ClInclude Include="TmuxControl.h" />
176178
<ClInclude Include="Toast.h" />
177179
<ClInclude Include="TerminalSettingsCache.h" />
178180
<ClInclude Include="SuggestionsControl.h">
@@ -286,6 +288,8 @@
286288
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
287289
</ClCompile>
288290
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
291+
<ClCompile Include="TmuxConnection.cpp" />
292+
<ClCompile Include="TmuxControl.cpp" />
289293
<ClCompile Include="Toast.cpp" />
290294
<ClCompile Include="TerminalSettingsCache.cpp" />
291295
<ClCompile Include="SuggestionsControl.cpp">
@@ -295,7 +299,6 @@
295299
<DependentUpon>MarkdownPaneContent.xaml</DependentUpon>
296300
<SubType>Code</SubType>
297301
</ClCompile>
298-
299302
</ItemGroup>
300303
<!-- ========================= idl Files ======================== -->
301304
<ItemGroup>
@@ -422,7 +425,6 @@
422425
<Private>true</Private>
423426
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
424427
</ProjectReference>
425-
426428
</ItemGroup>
427429
<PropertyGroup>
428430
<!-- This is a hack to get the ARM64 CI build working. See
@@ -516,4 +518,4 @@
516518
</ItemGroup>
517519
</Target>
518520
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
519-
</Project>
521+
</Project>

src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
33
<ItemGroup>
44
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
5-
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
65
</ItemGroup>
76
<ItemGroup>
87
<PRIResource Include="Resources\en-US\Resources.resw" />
@@ -33,8 +32,9 @@
3332
</ClCompile>
3433
<ClCompile Include="Toast.cpp" />
3534
<ClCompile Include="LanguageProfileNotifier.cpp" />
36-
<ClCompile Include="Monarch.cpp" />
37-
<ClCompile Include="Peasant.cpp" />
35+
<ClCompile Include="TerminalSettingsCache.cpp" />
36+
<ClCompile Include="TmuxConnection.cpp" />
37+
<ClCompile Include="TmuxControl.cpp" />
3838
</ItemGroup>
3939
<ItemGroup>
4040
<ClInclude Include="pch.h" />
@@ -60,14 +60,12 @@
6060
<ClInclude Include="fzf/fzf.h">
6161
<Filter>fzf</Filter>
6262
</ClInclude>
63-
<ClInclude Include="fzf/LICENSE">
64-
<Filter>fzf</Filter>
65-
</ClInclude>
6663
<ClInclude Include="Toast.h" />
6764
<ClInclude Include="LanguageProfileNotifier.h" />
6865
<ClInclude Include="WindowsPackageManagerFactory.h" />
69-
<ClInclude Include="Monarch.h" />
70-
<ClInclude Include="Peasant.h" />
66+
<ClInclude Include="TerminalSettingsCache.h" />
67+
<ClInclude Include="TmuxConnection.h" />
68+
<ClInclude Include="TmuxControl.h" />
7169
</ItemGroup>
7270
<ItemGroup>
7371
<Midl Include="AppLogic.idl">
@@ -90,7 +88,8 @@
9088
<Midl Include="TerminalWindow.idl" />
9189
<Midl Include="TaskbarState.idl" />
9290
<Midl Include="IPaneContent.idl" />
93-
<Midl Include="Monarch.idl" />
91+
<Midl Include="Remoting.idl" />
92+
<Midl Include="HighlightedTextControl.idl" />
9493
</ItemGroup>
9594
<ItemGroup>
9695
<Page Include="MinMaxCloseControl.xaml">
@@ -123,6 +122,7 @@
123122
<Page Include="AboutDialog.xaml" />
124123
<Page Include="SuggestionsControl.xaml" />
125124
<Page Include="SnippetsPaneContent.xaml" />
125+
<Page Include="MarkdownPaneContent.xaml" />
126126
</ItemGroup>
127127
<ItemGroup>
128128
<Filter Include="app">
@@ -155,4 +155,4 @@
155155
<Filter>app</Filter>
156156
</ApplicationDefinition>
157157
</ItemGroup>
158-
</Project>
158+
</Project>

src/cascadia/TerminalApp/TerminalPage.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "SnippetsPaneContent.h"
2424
#include "TabRowControl.h"
2525
#include "TerminalSettingsCache.h"
26+
#include "TmuxControl.h"
2627

2728
#include "LaunchPositionRequest.g.cpp"
2829
#include "RenameWindowRequestedArgs.g.cpp"
@@ -406,6 +407,15 @@ namespace winrt::TerminalApp::implementation
406407
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
407408
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
408409

410+
if constexpr (Feature_TmuxControl::IsEnabled())
411+
{
412+
// tmux control takes over
413+
if (page->_tmuxControl && page->_tmuxControl->TabIsTmuxControl(page->_GetFocusedTabImpl()))
414+
{
415+
return;
416+
}
417+
}
418+
409419
page->_OpenNewTerminalViaDropdown(NewTerminalArgs());
410420
}
411421
});
@@ -1431,6 +1441,15 @@ namespace winrt::TerminalApp::implementation
14311441
}
14321442
if (altPressed && !debugTap)
14331443
{
1444+
// tmux control panes don't share tab with other panes
1445+
if constexpr (Feature_TmuxControl::IsEnabled())
1446+
{
1447+
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(_GetFocusedTabImpl()))
1448+
{
1449+
return;
1450+
}
1451+
}
1452+
14341453
this->_SplitPane(_GetFocusedTabImpl(),
14351454
SplitDirection::Automatic,
14361455
0.5f,
@@ -2527,6 +2546,15 @@ namespace winrt::TerminalApp::implementation
25272546
return false;
25282547
}
25292548

2549+
if constexpr (Feature_TmuxControl::IsEnabled())
2550+
{
2551+
//Tmux control tab doesn't support to drag
2552+
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(tab))
2553+
{
2554+
return false;
2555+
}
2556+
}
2557+
25302558
// If there was a windowId in the action, try to move it to the
25312559
// specified window instead of moving it in our tab row.
25322560
const auto windowId{ args.Window() };
@@ -3595,6 +3623,26 @@ namespace winrt::TerminalApp::implementation
35953623
original->SetActive();
35963624
}
35973625

3626+
if constexpr (Feature_TmuxControl::IsEnabled())
3627+
{
3628+
if (!_tmuxControl)
3629+
{
3630+
_tmuxControl = std::make_shared<TmuxControl>(*this);
3631+
}
3632+
3633+
control.EnterTmuxControl([tmuxControl = _tmuxControl.get()](auto&& sender, auto&& args) {
3634+
if (auto control = sender.try_as<TermControl>())
3635+
{
3636+
if (tmuxControl->AcquireSingleUseLock(std::move(control)))
3637+
{
3638+
args.InputCallback([tmuxControl](auto&& str) {
3639+
tmuxControl->FeedInput(winrt_array_to_wstring_view(str));
3640+
});
3641+
}
3642+
}
3643+
});
3644+
}
3645+
35983646
return resultPane;
35993647
}
36003648

@@ -5500,6 +5548,15 @@ namespace winrt::TerminalApp::implementation
55005548
tabImpl.copy_from(winrt::get_self<Tab>(tabBase));
55015549
if (tabImpl)
55025550
{
5551+
if constexpr (Feature_TmuxControl::IsEnabled())
5552+
{
5553+
//Tmux control tab doesn't support to drag
5554+
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(tabImpl))
5555+
{
5556+
return;
5557+
}
5558+
}
5559+
55035560
// First: stash the tab we started dragging.
55045561
// We're going to be asked for this.
55055562
_stashed.draggedTab = tabImpl;

src/cascadia/TerminalApp/TerminalPage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ namespace winrt::Microsoft::Terminal::Settings
3737
namespace winrt::TerminalApp::implementation
3838
{
3939
struct TerminalSettingsCache;
40+
struct TmuxControl;
4041

4142
inline constexpr uint32_t DefaultRowsToScroll{ 3 };
4243
inline constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
@@ -256,6 +257,7 @@ namespace winrt::TerminalApp::implementation
256257
std::vector<std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>> _previouslyClosedPanesAndTabs{};
257258

258259
uint32_t _systemRowsToScroll{ DefaultRowsToScroll };
260+
std::shared_ptr<TmuxControl> _tmuxControl{ nullptr };
259261

260262
// use a weak reference to prevent circular dependency with AppLogic
261263
winrt::weak_ref<winrt::TerminalApp::IDialogPresenter> _dialogPresenter;
@@ -580,6 +582,7 @@ namespace winrt::TerminalApp::implementation
580582

581583
friend class TerminalAppLocalTests::TabTests;
582584
friend class TerminalAppLocalTests::SettingsTests;
585+
friend struct TmuxControl;
583586
};
584587
}
585588

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
#include "pch.h"
5+
#include "TmuxConnection.h"
6+
7+
namespace winrt::TerminalApp::implementation
8+
{
9+
void TmuxConnection::Initialize(const Windows::Foundation::Collections::ValueSet&) const noexcept
10+
{
11+
}
12+
13+
void TmuxConnection::Start() noexcept
14+
{
15+
}
16+
17+
void TmuxConnection::WriteInput(const winrt::array_view<const char16_t> buffer)
18+
{
19+
TerminalInput.raise(buffer);
20+
}
21+
22+
void TmuxConnection::Resize(uint32_t /*rows*/, uint32_t /*columns*/) noexcept
23+
{
24+
}
25+
26+
void TmuxConnection::Close() noexcept
27+
{
28+
StateChanged.raise(*this, nullptr);
29+
}
30+
31+
winrt::guid TmuxConnection::SessionId() const noexcept
32+
{
33+
return {};
34+
}
35+
36+
Microsoft::Terminal::TerminalConnection::ConnectionState TmuxConnection::State() const noexcept
37+
{
38+
return Microsoft::Terminal::TerminalConnection::ConnectionState::Connected;
39+
}
40+
41+
void TmuxConnection::WriteOutput(const winrt::array_view<const char16_t> wstr)
42+
{
43+
if (!wstr.empty())
44+
{
45+
TerminalOutput.raise(wstr);
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)