Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/actions/spelling/excludes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ Resources/(?!en)
^NOTICE.md
^oss/.*?/
^samples/PixelShaders/Screenshots/
^src/cascadia/TerminalSettingsEditor/SegoeFluentIconList.h$
^src/cascadia/TerminalApp/TmuxControl\.cpp$
^src/cascadia/TerminalSettingsEditor/SegoeFluentIconList\.h$
^src/interactivity/onecore/BgfxEngine\.
^src/renderer/atlas/
^src/renderer/wddmcon/WddmConRenderer\.
Expand Down
16 changes: 13 additions & 3 deletions src/cascadia/TerminalApp/AppActionHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
#include "pch.h"
#include "App.h"

#include "TerminalPage.h"
#include "ScratchpadContent.h"
#include "../WinRTUtils/inc/WtExeUtils.h"
#include "TerminalPage.h"
#include "TmuxControl.h"
#include "Utils.h"
#include "../../types/inc/utils.hpp"
#include "../TerminalSettingsAppAdapterLib/TerminalSettings.h"
#include "Utils.h"
#include "../WinRTUtils/inc/WtExeUtils.h"

using namespace winrt::Windows::ApplicationModel::DataTransfer;
using namespace winrt::Windows::UI::Xaml;
Expand Down Expand Up @@ -284,6 +285,15 @@ namespace winrt::TerminalApp::implementation

const auto& activeTab{ _senderOrFocusedTab(sender) };

if constexpr (Feature_TmuxControl::IsEnabled())
{
//Tmux control takes over
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(activeTab))
{
return _tmuxControl->SplitPane(activeTab, realArgs.SplitDirection());
}
}

_SplitPane(activeTab,
realArgs.SplitDirection(),
// This is safe, we're already filtering so the value is (0, 1)
Expand Down
7 changes: 3 additions & 4 deletions src/cascadia/TerminalApp/Pane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1306,10 +1306,10 @@ void Pane::UpdateSettings(const CascadiaSettings& settings)
// - splitType: How the pane should be attached
// Return Value:
// - the new reference to the child created from the current pane.
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType)
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType, const float splitSize)
{
// Splice the new pane into the tree
const auto [first, _] = _Split(splitType, .5, pane);
const auto [first, _] = _Split(splitType, splitSize, pane);

// If the new pane has a child that was the focus, re-focus it
// to steal focus from the currently focused pane.
Expand Down Expand Up @@ -2298,8 +2298,7 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
_firstChild->Closed(_firstClosedToken);
_secondChild->Closed(_secondClosedToken);
// If we are not a leaf we should create a new pane that contains our children
auto first = std::make_shared<Pane>(_firstChild, _secondChild, _splitState, _desiredSplitPosition);
_firstChild = first;
_firstChild = std::make_shared<Pane>(_firstChild, _secondChild, _splitState, _desiredSplitPosition);
}
else
{
Expand Down
3 changes: 2 additions & 1 deletion src/cascadia/TerminalApp/Pane.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ class Pane : public std::enable_shared_from_this<Pane>
void Close();

std::shared_ptr<Pane> AttachPane(std::shared_ptr<Pane> pane,
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType);
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
const float splitSize = .5);
std::shared_ptr<Pane> DetachPane(std::shared_ptr<Pane> pane);

int GetLeafPaneCount() const noexcept;
Expand Down
9 changes: 8 additions & 1 deletion src/cascadia/TerminalApp/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -923,4 +923,11 @@
<data name="InvalidRegex" xml:space="preserve">
<value>An invalid regular expression was found.</value>
</data>
</root>
<data name="TmuxControlInfo" xml:space="preserve">
<value>Running in tmux control mode; Press 'q' to detach:</value>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may need to {Lock...} the word tmux in some of these. We also historically made the q an insert from another resource (so that in German for example the Azure Connection can say "Enter Ja/nein [J/n]"

<comment>{Locked="'q'"}</comment>
</data>
<data name="NewTmuxControlTab.Text" xml:space="preserve">
<value>Tmux Control Tab</value>
</data>
</root>
8 changes: 5 additions & 3 deletions src/cascadia/TerminalApp/TerminalAppLib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@
<ClInclude Include="SettingsPaneContent.h">
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
</ClInclude>
<ClInclude Include="TmuxConnection.h" />
<ClInclude Include="TmuxControl.h" />
<ClInclude Include="Toast.h" />
<ClInclude Include="TerminalSettingsCache.h" />
<ClInclude Include="SuggestionsControl.h">
Expand Down Expand Up @@ -286,6 +288,8 @@
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<ClCompile Include="TmuxConnection.cpp" />
<ClCompile Include="TmuxControl.cpp" />
<ClCompile Include="Toast.cpp" />
<ClCompile Include="TerminalSettingsCache.cpp" />
<ClCompile Include="SuggestionsControl.cpp">
Expand All @@ -295,7 +299,6 @@
<DependentUpon>MarkdownPaneContent.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>

</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
Expand Down Expand Up @@ -422,7 +425,6 @@
<Private>true</Private>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>

</ItemGroup>
<PropertyGroup>
<!-- This is a hack to get the ARM64 CI build working. See
Expand Down Expand Up @@ -516,4 +518,4 @@
</ItemGroup>
</Target>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project>
</Project>
6 changes: 5 additions & 1 deletion src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
<ClCompile Include="Toast.cpp" />
<ClCompile Include="LanguageProfileNotifier.cpp" />
<ClCompile Include="TerminalSettingsCache.cpp" />
<ClCompile Include="TmuxConnection.cpp" />
<ClCompile Include="TmuxControl.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
Expand Down Expand Up @@ -62,6 +64,8 @@
<ClInclude Include="LanguageProfileNotifier.h" />
<ClInclude Include="WindowsPackageManagerFactory.h" />
<ClInclude Include="TerminalSettingsCache.h" />
<ClInclude Include="TmuxConnection.h" />
<ClInclude Include="TmuxControl.h" />
</ItemGroup>
<ItemGroup>
<Midl Include="AppLogic.idl">
Expand Down Expand Up @@ -151,4 +155,4 @@
<Filter>app</Filter>
</ApplicationDefinition>
</ItemGroup>
</Project>
</Project>
64 changes: 61 additions & 3 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "SnippetsPaneContent.h"
#include "TabRowControl.h"
#include "TerminalSettingsCache.h"
#include "TmuxControl.h"

#include "LaunchPositionRequest.g.cpp"
#include "RenameWindowRequestedArgs.g.cpp"
Expand Down Expand Up @@ -406,6 +407,15 @@ namespace winrt::TerminalApp::implementation
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));

if constexpr (Feature_TmuxControl::IsEnabled())
{
// tmux control takes over
if (page->_tmuxControl && page->_tmuxControl->TabIsTmuxControl(page->_GetFocusedTabImpl()))
{
return;
}
}

page->_OpenNewTerminalViaDropdown(NewTerminalArgs());
}
});
Expand Down Expand Up @@ -1431,6 +1441,15 @@ namespace winrt::TerminalApp::implementation
}
if (altPressed && !debugTap)
{
// tmux control panes don't share tab with other panes
if constexpr (Feature_TmuxControl::IsEnabled())
{
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(_GetFocusedTabImpl()))
{
return;
}
}

this->_SplitPane(_GetFocusedTabImpl(),
SplitDirection::Automatic,
0.5f,
Expand Down Expand Up @@ -2535,6 +2554,15 @@ namespace winrt::TerminalApp::implementation
return false;
}

if constexpr (Feature_TmuxControl::IsEnabled())
{
//Tmux control tab doesn't support to drag
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(tab))
{
return false;
}
}

// If there was a windowId in the action, try to move it to the
// specified window instead of moving it in our tab row.
const auto windowId{ args.Window() };
Expand Down Expand Up @@ -3598,9 +3626,8 @@ namespace winrt::TerminalApp::implementation
control.RestoreFromPath(path);
}

auto paneContent{ winrt::make<TerminalPaneContent>(profile, _terminalSettingsCache, control) };

auto resultPane = std::make_shared<Pane>(paneContent);
const auto paneContent = winrt::make_self<TerminalPaneContent>(profile, _terminalSettingsCache, control);
auto resultPane = std::make_shared<Pane>(*paneContent);

if (debugConnection) // this will only be set if global debugging is on and tap is active
{
Expand All @@ -3621,6 +3648,28 @@ namespace winrt::TerminalApp::implementation
original->SetActive();
}

if constexpr (Feature_TmuxControl::IsEnabled())
{
if (!_tmuxControl)
{
_tmuxControl = std::make_shared<TmuxControl>(*this);
}

// We attach the callback to the control that paneContent owns.
// As such, using a weak-ref here is crucial.
control.EnterTmuxControl([tmuxControl = _tmuxControl.get(), paneContentWeak = winrt::make_weak(paneContent)](auto&&, auto&& args) {
if (const auto paneContent = paneContentWeak.get())
{
if (paneContent->AllowTmuxControl() && tmuxControl->AcquireSingleUseLock(paneContent->GetTermControl()))
{
args.InputCallback([tmuxControl](auto&& str) {
tmuxControl->FeedInput(winrt_array_to_wstring_view(str));
});
}
}
});
}

return resultPane;
}

Expand Down Expand Up @@ -5532,6 +5581,15 @@ namespace winrt::TerminalApp::implementation
tabImpl.copy_from(winrt::get_self<Tab>(tabBase));
if (tabImpl)
{
if constexpr (Feature_TmuxControl::IsEnabled())
{
//Tmux control tab doesn't support to drag
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(tabImpl))
{
return;
}
}

// First: stash the tab we started dragging.
// We're going to be asked for this.
_stashed.draggedTab = tabImpl;
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace winrt::Microsoft::Terminal::Settings
namespace winrt::TerminalApp::implementation
{
struct TerminalSettingsCache;
struct TmuxControl;

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

uint32_t _systemRowsToScroll{ DefaultRowsToScroll };
std::shared_ptr<TmuxControl> _tmuxControl{ nullptr };

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

friend class TerminalAppLocalTests::TabTests;
friend class TerminalAppLocalTests::SettingsTests;
friend struct TmuxControl;
};
}

Expand Down
7 changes: 7 additions & 0 deletions src/cascadia/TerminalApp/TerminalPaneContent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace winrt::TerminalApp::implementation
_cache{ cache },
_profile{ profile }
{
_allowTmuxControl.store(_profile.AllowTmuxControl(), std::memory_order_relaxed);
_setupControlEvents();
}

Expand Down Expand Up @@ -342,6 +343,7 @@ namespace winrt::TerminalApp::implementation
// Reload our profile from the settings model to propagate bell mode, icon, and close on exit mode (anything that uses _profile).
const auto profile{ settings.FindProfile(_profile.Guid()) };
_profile = profile ? profile : settings.ProfileDefaults();
_allowTmuxControl.store(_profile.AllowTmuxControl(), std::memory_order_relaxed);

if (const auto settings{ _cache->TryLookup(_profile) })
{
Expand All @@ -363,6 +365,11 @@ namespace winrt::TerminalApp::implementation
return _control.BackgroundBrush();
}

bool TerminalPaneContent::AllowTmuxControl() const noexcept
{
return _allowTmuxControl.load(std::memory_order_relaxed);
}

float TerminalPaneContent::SnapDownToGrid(const TerminalApp::PaneSnapDirection direction, const float sizeToSnap)
{
return _control.SnapDimensionToGrid(direction == PaneSnapDirection::Width, sizeToSnap);
Expand Down
8 changes: 8 additions & 0 deletions src/cascadia/TerminalApp/TerminalPaneContent.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ namespace winrt::TerminalApp::implementation
winrt::hstring Icon() const;
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept;
winrt::Windows::UI::Xaml::Media::Brush BackgroundBrush();
bool AllowTmuxControl() const noexcept;

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

winrt::Windows::Media::Playback::MediaPlayer _bellPlayer{ nullptr };
bool _bellPlayerCreated{ false };
Expand Down
48 changes: 48 additions & 0 deletions src/cascadia/TerminalApp/TmuxConnection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#include "pch.h"
#include "TmuxConnection.h"

namespace winrt::TerminalApp::implementation
{
void TmuxConnection::Initialize(const Windows::Foundation::Collections::ValueSet&) const noexcept
{
}

void TmuxConnection::Start() noexcept
{
}

void TmuxConnection::WriteInput(const winrt::array_view<const char16_t> buffer)
{
TerminalInput.raise(buffer);
}

void TmuxConnection::Resize(uint32_t /*rows*/, uint32_t /*columns*/) noexcept
{
}

void TmuxConnection::Close() noexcept
{
StateChanged.raise(*this, nullptr);
}

winrt::guid TmuxConnection::SessionId() const noexcept
{
return {};
}

Microsoft::Terminal::TerminalConnection::ConnectionState TmuxConnection::State() const noexcept
{
return Microsoft::Terminal::TerminalConnection::ConnectionState::Connected;
}

void TmuxConnection::WriteOutput(const winrt::array_view<const char16_t> wstr)
{
if (!wstr.empty())
{
TerminalOutput.raise(wstr);
}
}
}
Loading