mirror of
https://github.com/microsoft/terminal.git
synced 2026-02-04 03:05:08 -06:00
commit
82487d029b
3
.github/actions/spelling/excludes.txt
vendored
3
.github/actions/spelling/excludes.txt
vendored
@ -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\.
|
||||
|
||||
@ -4,12 +4,13 @@
|
||||
#include "pch.h"
|
||||
#include "App.h"
|
||||
|
||||
#include "TerminalPage.h"
|
||||
#include "ScratchpadContent.h"
|
||||
#include "../WinRTUtils/inc/WtExeUtils.h"
|
||||
#include "TerminalPage.h"
|
||||
#include "TmuxControl.h"
|
||||
#include "Utils.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "../TerminalSettingsAppAdapterLib/TerminalSettings.h"
|
||||
#include "Utils.h"
|
||||
#include "../WinRTUtils/inc/WtExeUtils.h"
|
||||
|
||||
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
@ -284,6 +285,15 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
const auto& activeTab{ _senderOrFocusedTab(sender) };
|
||||
|
||||
if constexpr (Feature_TmuxControl::IsEnabled())
|
||||
{
|
||||
//Tmux control takes over
|
||||
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(activeTab))
|
||||
{
|
||||
return _tmuxControl->SplitPane(activeTab, realArgs.SplitDirection());
|
||||
}
|
||||
}
|
||||
|
||||
_SplitPane(activeTab,
|
||||
realArgs.SplitDirection(),
|
||||
// This is safe, we're already filtering so the value is (0, 1)
|
||||
|
||||
@ -1306,10 +1306,10 @@ void Pane::UpdateSettings(const CascadiaSettings& settings)
|
||||
// - splitType: How the pane should be attached
|
||||
// Return Value:
|
||||
// - the new reference to the child created from the current pane.
|
||||
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType)
|
||||
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType, const float splitSize)
|
||||
{
|
||||
// Splice the new pane into the tree
|
||||
const auto [first, _] = _Split(splitType, .5, pane);
|
||||
const auto [first, _] = _Split(splitType, splitSize, pane);
|
||||
|
||||
// If the new pane has a child that was the focus, re-focus it
|
||||
// to steal focus from the currently focused pane.
|
||||
@ -2298,8 +2298,7 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
|
||||
_firstChild->Closed(_firstClosedToken);
|
||||
_secondChild->Closed(_secondClosedToken);
|
||||
// If we are not a leaf we should create a new pane that contains our children
|
||||
auto first = std::make_shared<Pane>(_firstChild, _secondChild, _splitState, _desiredSplitPosition);
|
||||
_firstChild = first;
|
||||
_firstChild = std::make_shared<Pane>(_firstChild, _secondChild, _splitState, _desiredSplitPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -131,7 +131,8 @@ public:
|
||||
void Close();
|
||||
|
||||
std::shared_ptr<Pane> AttachPane(std::shared_ptr<Pane> pane,
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType);
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const float splitSize = .5);
|
||||
std::shared_ptr<Pane> DetachPane(std::shared_ptr<Pane> pane);
|
||||
|
||||
int GetLeafPaneCount() const noexcept;
|
||||
|
||||
@ -923,4 +923,11 @@
|
||||
<data name="InvalidRegex" xml:space="preserve">
|
||||
<value>An invalid regular expression was found.</value>
|
||||
</data>
|
||||
</root>
|
||||
<data name="TmuxControlInfo" xml:space="preserve">
|
||||
<value>Running in tmux control mode; Press 'q' to detach:</value>
|
||||
<comment>{Locked="'q'"}</comment>
|
||||
</data>
|
||||
<data name="NewTmuxControlTab.Text" xml:space="preserve">
|
||||
<value>Tmux Control Tab</value>
|
||||
</data>
|
||||
</root>
|
||||
@ -173,6 +173,8 @@
|
||||
<ClInclude Include="SettingsPaneContent.h">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TmuxConnection.h" />
|
||||
<ClInclude Include="TmuxControl.h" />
|
||||
<ClInclude Include="Toast.h" />
|
||||
<ClInclude Include="TerminalSettingsCache.h" />
|
||||
<ClInclude Include="SuggestionsControl.h">
|
||||
@ -286,6 +288,8 @@
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="TmuxConnection.cpp" />
|
||||
<ClCompile Include="TmuxControl.cpp" />
|
||||
<ClCompile Include="Toast.cpp" />
|
||||
<ClCompile Include="TerminalSettingsCache.cpp" />
|
||||
<ClCompile Include="SuggestionsControl.cpp">
|
||||
@ -295,7 +299,6 @@
|
||||
<DependentUpon>MarkdownPaneContent.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClCompile>
|
||||
|
||||
</ItemGroup>
|
||||
<!-- ========================= idl Files ======================== -->
|
||||
<ItemGroup>
|
||||
@ -422,7 +425,6 @@
|
||||
<Private>true</Private>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- This is a hack to get the ARM64 CI build working. See
|
||||
@ -516,4 +518,4 @@
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
@ -2,7 +2,6 @@
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\en-US\Resources.resw" />
|
||||
@ -33,8 +32,9 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="Toast.cpp" />
|
||||
<ClCompile Include="LanguageProfileNotifier.cpp" />
|
||||
<ClCompile Include="Monarch.cpp" />
|
||||
<ClCompile Include="Peasant.cpp" />
|
||||
<ClCompile Include="TerminalSettingsCache.cpp" />
|
||||
<ClCompile Include="TmuxConnection.cpp" />
|
||||
<ClCompile Include="TmuxControl.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
@ -60,14 +60,12 @@
|
||||
<ClInclude Include="fzf/fzf.h">
|
||||
<Filter>fzf</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="fzf/LICENSE">
|
||||
<Filter>fzf</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Toast.h" />
|
||||
<ClInclude Include="LanguageProfileNotifier.h" />
|
||||
<ClInclude Include="WindowsPackageManagerFactory.h" />
|
||||
<ClInclude Include="Monarch.h" />
|
||||
<ClInclude Include="Peasant.h" />
|
||||
<ClInclude Include="TerminalSettingsCache.h" />
|
||||
<ClInclude Include="TmuxConnection.h" />
|
||||
<ClInclude Include="TmuxControl.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="AppLogic.idl">
|
||||
@ -90,7 +88,8 @@
|
||||
<Midl Include="TerminalWindow.idl" />
|
||||
<Midl Include="TaskbarState.idl" />
|
||||
<Midl Include="IPaneContent.idl" />
|
||||
<Midl Include="Monarch.idl" />
|
||||
<Midl Include="Remoting.idl" />
|
||||
<Midl Include="HighlightedTextControl.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="MinMaxCloseControl.xaml">
|
||||
@ -123,6 +122,7 @@
|
||||
<Page Include="AboutDialog.xaml" />
|
||||
<Page Include="SuggestionsControl.xaml" />
|
||||
<Page Include="SnippetsPaneContent.xaml" />
|
||||
<Page Include="MarkdownPaneContent.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="app">
|
||||
@ -155,4 +155,4 @@
|
||||
<Filter>app</Filter>
|
||||
</ApplicationDefinition>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@ -23,6 +23,7 @@
|
||||
#include "SnippetsPaneContent.h"
|
||||
#include "TabRowControl.h"
|
||||
#include "TerminalSettingsCache.h"
|
||||
#include "TmuxControl.h"
|
||||
|
||||
#include "LaunchPositionRequest.g.cpp"
|
||||
#include "RenameWindowRequestedArgs.g.cpp"
|
||||
@ -406,6 +407,15 @@ namespace winrt::TerminalApp::implementation
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
if constexpr (Feature_TmuxControl::IsEnabled())
|
||||
{
|
||||
// tmux control takes over
|
||||
if (page->_tmuxControl && page->_tmuxControl->TabIsTmuxControl(page->_GetFocusedTabImpl()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
page->_OpenNewTerminalViaDropdown(NewTerminalArgs());
|
||||
}
|
||||
});
|
||||
@ -1431,6 +1441,15 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
if (altPressed && !debugTap)
|
||||
{
|
||||
// tmux control panes don't share tab with other panes
|
||||
if constexpr (Feature_TmuxControl::IsEnabled())
|
||||
{
|
||||
if (_tmuxControl && _tmuxControl->TabIsTmuxControl(_GetFocusedTabImpl()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this->_SplitPane(_GetFocusedTabImpl(),
|
||||
SplitDirection::Automatic,
|
||||
0.5f,
|
||||
@ -2527,6 +2546,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() };
|
||||
@ -3595,6 +3623,26 @@ namespace winrt::TerminalApp::implementation
|
||||
original->SetActive();
|
||||
}
|
||||
|
||||
if constexpr (Feature_TmuxControl::IsEnabled())
|
||||
{
|
||||
if (!_tmuxControl)
|
||||
{
|
||||
_tmuxControl = std::make_shared<TmuxControl>(*this);
|
||||
}
|
||||
|
||||
control.EnterTmuxControl([tmuxControl = _tmuxControl.get()](auto&& sender, auto&& args) {
|
||||
if (auto control = sender.try_as<TermControl>())
|
||||
{
|
||||
if (tmuxControl->AcquireSingleUseLock(std::move(control)))
|
||||
{
|
||||
args.InputCallback([tmuxControl](auto&& str) {
|
||||
tmuxControl->FeedInput(winrt_array_to_wstring_view(str));
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return resultPane;
|
||||
}
|
||||
|
||||
@ -5500,6 +5548,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;
|
||||
|
||||
@ -37,6 +37,7 @@ namespace winrt::Microsoft::Terminal::Settings
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct TerminalSettingsCache;
|
||||
struct TmuxControl;
|
||||
|
||||
inline constexpr uint32_t DefaultRowsToScroll{ 3 };
|
||||
inline constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
|
||||
@ -256,6 +257,7 @@ namespace winrt::TerminalApp::implementation
|
||||
std::vector<std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>> _previouslyClosedPanesAndTabs{};
|
||||
|
||||
uint32_t _systemRowsToScroll{ DefaultRowsToScroll };
|
||||
std::shared_ptr<TmuxControl> _tmuxControl{ nullptr };
|
||||
|
||||
// use a weak reference to prevent circular dependency with AppLogic
|
||||
winrt::weak_ref<winrt::TerminalApp::IDialogPresenter> _dialogPresenter;
|
||||
@ -580,6 +582,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
friend class TerminalAppLocalTests::TabTests;
|
||||
friend class TerminalAppLocalTests::SettingsTests;
|
||||
friend struct TmuxControl;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
48
src/cascadia/TerminalApp/TmuxConnection.cpp
Normal file
48
src/cascadia/TerminalApp/TmuxConnection.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "TmuxConnection.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
void TmuxConnection::Initialize(const Windows::Foundation::Collections::ValueSet&) const noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void TmuxConnection::Start() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void TmuxConnection::WriteInput(const winrt::array_view<const char16_t> buffer)
|
||||
{
|
||||
TerminalInput.raise(buffer);
|
||||
}
|
||||
|
||||
void TmuxConnection::Resize(uint32_t /*rows*/, uint32_t /*columns*/) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void TmuxConnection::Close() noexcept
|
||||
{
|
||||
StateChanged.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
winrt::guid TmuxConnection::SessionId() const noexcept
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
Microsoft::Terminal::TerminalConnection::ConnectionState TmuxConnection::State() const noexcept
|
||||
{
|
||||
return Microsoft::Terminal::TerminalConnection::ConnectionState::Connected;
|
||||
}
|
||||
|
||||
void TmuxConnection::WriteOutput(const winrt::array_view<const char16_t> wstr)
|
||||
{
|
||||
if (!wstr.empty())
|
||||
{
|
||||
TerminalOutput.raise(wstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/cascadia/TerminalApp/TmuxConnection.h
Normal file
31
src/cascadia/TerminalApp/TmuxConnection.h
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct TmuxConnection : winrt::implements<TmuxConnection, Microsoft::Terminal::TerminalConnection::ITerminalConnection>
|
||||
{
|
||||
// ITerminalConnection methods
|
||||
|
||||
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) const noexcept;
|
||||
|
||||
void Start() noexcept;
|
||||
void WriteInput(winrt::array_view<const char16_t> buffer);
|
||||
void Resize(uint32_t rows, uint32_t columns) noexcept;
|
||||
void Close() noexcept;
|
||||
|
||||
til::event<Microsoft::Terminal::TerminalConnection::TerminalOutputHandler> TerminalOutput;
|
||||
til::typed_event<Microsoft::Terminal::TerminalConnection::ITerminalConnection, IInspectable> StateChanged;
|
||||
|
||||
winrt::guid SessionId() const noexcept;
|
||||
Microsoft::Terminal::TerminalConnection::ConnectionState State() const noexcept;
|
||||
|
||||
// TmuxConnection methods
|
||||
|
||||
void WriteOutput(winrt::array_view<const char16_t> wstr);
|
||||
|
||||
til::event<Microsoft::Terminal::TerminalConnection::TerminalOutputHandler> TerminalInput;
|
||||
};
|
||||
}
|
||||
1401
src/cascadia/TerminalApp/TmuxControl.cpp
Normal file
1401
src/cascadia/TerminalApp/TmuxControl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
180
src/cascadia/TerminalApp/TmuxControl.h
Normal file
180
src/cascadia/TerminalApp/TmuxControl.h
Normal file
@ -0,0 +1,180 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
class Pane;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct Tab;
|
||||
struct TerminalPage;
|
||||
struct TmuxConnection;
|
||||
|
||||
struct TmuxControl : std::enable_shared_from_this<TmuxControl>
|
||||
{
|
||||
TmuxControl(TerminalPage& page);
|
||||
|
||||
bool AcquireSingleUseLock(winrt::Microsoft::Terminal::Control::TermControl control) noexcept;
|
||||
bool TabIsTmuxControl(const winrt::com_ptr<Tab>& tab);
|
||||
void SplitPane(const winrt::com_ptr<Tab>& tab, winrt::Microsoft::Terminal::Settings::Model::SplitDirection direction);
|
||||
void FeedInput(std::wstring_view str);
|
||||
|
||||
private:
|
||||
enum class State
|
||||
{
|
||||
Init,
|
||||
Attaching,
|
||||
Attached,
|
||||
};
|
||||
|
||||
enum class ResponseInfoType
|
||||
{
|
||||
Ignore,
|
||||
DiscoverNewWindow,
|
||||
DiscoverWindows,
|
||||
CapturePane,
|
||||
DiscoverPanes,
|
||||
};
|
||||
|
||||
struct ResponseInfo
|
||||
{
|
||||
ResponseInfoType type;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int64_t paneId;
|
||||
} capturePane;
|
||||
} data;
|
||||
};
|
||||
|
||||
enum class TmuxLayoutType
|
||||
{
|
||||
// A single leaf pane
|
||||
Pane,
|
||||
// Indicates the start of a horizontal split layout
|
||||
PushHorizontal,
|
||||
// Indicates the start of a vertical split layout
|
||||
PushVertical,
|
||||
// Indicates the end of the most recent split layout
|
||||
Pop,
|
||||
};
|
||||
|
||||
struct TmuxLayout
|
||||
{
|
||||
TmuxLayoutType type = TmuxLayoutType::Pane;
|
||||
|
||||
// Only set for: Pane, PushHorizontal, PushVertical
|
||||
til::CoordType width = 0;
|
||||
// Only set for: Pane, PushHorizontal, PushVertical
|
||||
til::CoordType height = 0;
|
||||
// Only set for: Pane
|
||||
int64_t id = -1;
|
||||
};
|
||||
|
||||
struct AttachedPane
|
||||
{
|
||||
AttachedPane() = default;
|
||||
AttachedPane(int64_t paneId, std::wstring outputBacklog);
|
||||
~AttachedPane();
|
||||
|
||||
// Have to redefine them because they get implicitly deleted once a destructor is defined.
|
||||
AttachedPane(AttachedPane&&) = default;
|
||||
AttachedPane& operator=(AttachedPane&&) = default;
|
||||
|
||||
// Why would you want to copy this.
|
||||
AttachedPane(const AttachedPane&) = delete;
|
||||
AttachedPane& operator=(const AttachedPane&) = delete;
|
||||
|
||||
int64_t windowId = -1;
|
||||
int64_t paneId = -1;
|
||||
winrt::com_ptr<TmuxConnection> connection{ nullptr };
|
||||
winrt::Microsoft::Terminal::Control::TermControl control{ nullptr };
|
||||
std::wstring outputBacklog;
|
||||
bool initialized = false;
|
||||
bool ignoreOutput = false;
|
||||
};
|
||||
|
||||
safe_void_coroutine _parseLine(std::wstring line);
|
||||
|
||||
void _handleAttach(); // A special case of _handleResponse()
|
||||
void _handleDetach();
|
||||
void _handleSessionChanged(int64_t sessionId);
|
||||
void _handleWindowAdd(int64_t windowId);
|
||||
void _handleWindowRenamed(int64_t windowId, winrt::hstring name);
|
||||
void _handleWindowClose(int64_t windowId);
|
||||
void _handleWindowPaneChanged(int64_t windowId, int64_t paneId);
|
||||
void _handleLayoutChange(int64_t windowId, std::wstring_view layout);
|
||||
void _handleResponse(std::wstring_view result);
|
||||
|
||||
void _sendSetOption(std::wstring_view option);
|
||||
void _sendDiscoverWindows(int64_t sessionId);
|
||||
void _handleResponseDiscoverWindows(std::wstring_view response);
|
||||
void _sendDiscoverNewWindow(int64_t windowId);
|
||||
void _handleResponseDiscoverNewWindow(std::wstring_view response);
|
||||
void _sendCapturePane(int64_t paneId, til::CoordType history);
|
||||
void _handleResponseCapturePane(const ResponseInfo& info, std::wstring_view response);
|
||||
void _sendDiscoverPanes(int64_t windowId);
|
||||
void _handleResponseDiscoverPanes(std::wstring_view response);
|
||||
void _sendNewWindow();
|
||||
void _sendKillWindow(int64_t windowId);
|
||||
void _sendKillPane(int64_t paneId);
|
||||
void _sendSplitPane(std::shared_ptr<Pane> pane, winrt::Microsoft::Terminal::Settings::Model::SplitDirection direction);
|
||||
void _sendSelectWindow(int64_t windowId);
|
||||
void _sendSelectPane(int64_t paneId);
|
||||
void _sendResizeWindow(int64_t windowId, til::CoordType width, til::CoordType height);
|
||||
void _sendResizePane(int64_t paneId, til::CoordType width, til::CoordType height);
|
||||
void _sendSendKey(int64_t paneId, const std::wstring_view keys);
|
||||
|
||||
void _sendIgnoreResponse(wil::zwstring_view cmd);
|
||||
void _sendWithResponseInfo(wil::zwstring_view cmd, ResponseInfo info);
|
||||
|
||||
std::shared_ptr<Pane> _layoutCreateRecursive(int64_t windowId, std::wstring_view& remaining, TmuxLayout parent);
|
||||
std::wstring_view _layoutStripHash(std::wstring_view str);
|
||||
TmuxLayout _layoutParseNextToken(std::wstring_view& remaining);
|
||||
|
||||
void _deliverOutputToPane(int64_t paneId, const std::wstring_view text);
|
||||
winrt::com_ptr<Tab> _getTab(int64_t windowId) const;
|
||||
void _newTab(int64_t windowId, winrt::hstring name, std::shared_ptr<Pane> pane);
|
||||
std::pair<AttachedPane&, std::shared_ptr<Pane>> _newPane(int64_t windowId, int64_t paneId);
|
||||
void _openNewTerminalViaDropdown();
|
||||
|
||||
TerminalPage& _page; // Non-owning, because TerminalPage owns us
|
||||
winrt::Windows::System::DispatcherQueue _dispatcherQueue{ nullptr };
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _newTabMenu;
|
||||
|
||||
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
|
||||
winrt::com_ptr<Tab> _controlTab{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile _profile{ nullptr };
|
||||
State _state = State::Init;
|
||||
bool _inUse = false;
|
||||
|
||||
std::wstring _lineBuffer;
|
||||
std::wstring _responseBuffer;
|
||||
bool _insideOutputBlock = false;
|
||||
|
||||
winrt::event_token _detachKeyDownRevoker;
|
||||
winrt::event_token _windowSizeChangedRevoker;
|
||||
winrt::event_token _newTabClickRevoker;
|
||||
|
||||
std::deque<ResponseInfo> _commandQueue;
|
||||
std::unordered_map<int64_t, AttachedPane> _attachedPanes;
|
||||
std::unordered_map<int64_t, winrt::com_ptr<Tab>> _attachedWindows;
|
||||
|
||||
int64_t _sessionId = -1;
|
||||
int64_t _activePaneId = -1;
|
||||
int64_t _activeWindowId = -1;
|
||||
|
||||
til::CoordType _terminalWidth = 0;
|
||||
til::CoordType _terminalHeight = 0;
|
||||
winrt::Windows::UI::Xaml::Thickness _thickness{ 0, 0, 0, 0 };
|
||||
float _fontWidth = 0;
|
||||
float _fontHeight = 0;
|
||||
|
||||
std::pair<std::shared_ptr<Pane>, winrt::Microsoft::Terminal::Settings::Model::SplitDirection> _splittingPane{
|
||||
nullptr,
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitDirection::Right,
|
||||
};
|
||||
};
|
||||
}
|
||||
@ -15,6 +15,7 @@
|
||||
#include "../../renderer/atlas/AtlasEngine.h"
|
||||
#include "../../renderer/base/renderer.hpp"
|
||||
#include "../../renderer/uia/UiaRenderer.hpp"
|
||||
#include "../../terminal/adapter/adaptDispatch.hpp"
|
||||
#include "../../types/inc/CodepointWidthDetector.hpp"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
@ -139,6 +140,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
auto pfnWindowSizeChanged = [this](auto&& PH1, auto&& PH2) { _terminalWindowSizeChanged(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2)); };
|
||||
_terminal->SetWindowSizeChangedCallback(pfnWindowSizeChanged);
|
||||
|
||||
_terminal->SetEnterTmuxControlCallback([this]() -> std::function<bool(wchar_t)> {
|
||||
const auto args = winrt::make_self<EnterTmuxControlEventArgs>();
|
||||
EnterTmuxControl.raise(*this, *args);
|
||||
if (auto inputCallback = args->InputCallback())
|
||||
{
|
||||
return [inputCallback = std::move(inputCallback)](wchar_t ch) -> bool {
|
||||
const auto c16 = static_cast<char16_t>(ch);
|
||||
inputCallback({ &c16, 1 });
|
||||
return true;
|
||||
};
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
// MSFT 33353327: Initialize the renderer in the ctor instead of Initialize().
|
||||
// We need the renderer to be ready to accept new engines before the SwapChainPanel is ready to go.
|
||||
// If we wait, a screen reader may try to get the AutomationPeer (aka the UIA Engine), and we won't be able to attach
|
||||
@ -1459,6 +1474,45 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_terminal->TrySnapOnInput();
|
||||
}
|
||||
|
||||
void ControlCore::InjectTextAtCursor(const winrt::hstring& text)
|
||||
{
|
||||
if (text.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto lock = _terminal->LockForWriting();
|
||||
std::wstring_view remaining{ text };
|
||||
|
||||
// Process one line at a time
|
||||
for (;;)
|
||||
{
|
||||
// Get the (CR)LF position
|
||||
const auto lf = std::min(remaining.size(), remaining.find(L'\n'));
|
||||
|
||||
// Strip off the CR
|
||||
auto lineEnd = lf;
|
||||
if (lineEnd != 0 && remaining[lineEnd - 1] == L'\r')
|
||||
{
|
||||
lineEnd -= 1;
|
||||
}
|
||||
|
||||
// Split into line and whatever comes after
|
||||
const auto line = remaining.substr(0, lineEnd);
|
||||
remaining = remaining.substr(std::min(remaining.size(), lf + 1));
|
||||
|
||||
// This will not just print the line but also handle delay wrap, etc.
|
||||
_terminal->GetAdaptDispatch().PrintString(line);
|
||||
|
||||
if (remaining.empty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_terminal->GetAdaptDispatch().LineFeed(DispatchTypes::LineFeedType::DependsOnMode);
|
||||
}
|
||||
}
|
||||
|
||||
FontInfo ControlCore::GetFont() const
|
||||
{
|
||||
return _actualFont;
|
||||
@ -1568,6 +1622,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return _terminal->GetViewport().Height();
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Gets the width of the terminal in lines of text. This is just the
|
||||
// width of the viewport.
|
||||
// Return Value:
|
||||
// - The width of the terminal in lines of text
|
||||
int ControlCore::ViewWidth() const
|
||||
{
|
||||
const auto lock = _terminal->LockForReading();
|
||||
return _terminal->GetViewport().Width();
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Gets the height of the terminal in lines of text. This includes the
|
||||
// history AND the viewport.
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "../../buffer/out/search.h"
|
||||
#include "../../cascadia/TerminalCore/Terminal.hpp"
|
||||
#include "../../renderer/inc/FontInfoDesired.hpp"
|
||||
#include "../../terminal/adapter/ITermDispatch.hpp"
|
||||
|
||||
namespace Microsoft::Console::Render::Atlas
|
||||
{
|
||||
@ -124,6 +125,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void SendInput(std::wstring_view wstr);
|
||||
void PasteText(const winrt::hstring& hstr);
|
||||
void InjectTextAtCursor(const winrt::hstring& text);
|
||||
bool CopySelectionToClipboard(bool singleLine, bool withControlSequences, const CopyFormat formats);
|
||||
void SelectAll();
|
||||
void ClearSelection();
|
||||
@ -172,6 +174,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
int ScrollOffset();
|
||||
int ViewHeight() const;
|
||||
int ViewWidth() const;
|
||||
int BufferHeight() const;
|
||||
|
||||
bool HasSelection() const;
|
||||
@ -295,10 +298,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
til::typed_event<IInspectable, Control::SearchMissingCommandEventArgs> SearchMissingCommand;
|
||||
til::typed_event<> RefreshQuickFixUI;
|
||||
til::typed_event<IInspectable, Control::WindowSizeChangedEventArgs> WindowSizeChanged;
|
||||
|
||||
til::typed_event<IInspectable, Control::EnterTmuxControlEventArgs> EnterTmuxControl;
|
||||
til::typed_event<> CloseTerminalRequested;
|
||||
til::typed_event<> RestartTerminalRequested;
|
||||
|
||||
til::typed_event<> Attached;
|
||||
// clang-format on
|
||||
|
||||
|
||||
@ -128,6 +128,7 @@ namespace Microsoft.Terminal.Control
|
||||
Microsoft.Terminal.Core.ControlKeyStates modifiers);
|
||||
void SendInput(String text);
|
||||
void PasteText(String text);
|
||||
void InjectTextAtCursor(String text);
|
||||
void SelectAll();
|
||||
void ClearSelection();
|
||||
Boolean ToggleBlockSelection();
|
||||
@ -198,6 +199,7 @@ namespace Microsoft.Terminal.Control
|
||||
event Windows.Foundation.TypedEventHandler<Object, SearchMissingCommandEventArgs> SearchMissingCommand;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> RefreshQuickFixUI;
|
||||
event Windows.Foundation.TypedEventHandler<Object, WindowSizeChangedEventArgs> WindowSizeChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, EnterTmuxControlEventArgs> EnterTmuxControl;
|
||||
|
||||
// These events are always called from the UI thread (bugs aside)
|
||||
event Windows.Foundation.TypedEventHandler<Object, FontSizeChangedArgs> FontSizeChanged;
|
||||
|
||||
@ -21,3 +21,4 @@
|
||||
#include "StringSentEventArgs.g.cpp"
|
||||
#include "SearchMissingCommandEventArgs.g.cpp"
|
||||
#include "WindowSizeChangedEventArgs.g.cpp"
|
||||
#include "EnterTmuxControlEventArgs.g.cpp"
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include "StringSentEventArgs.g.h"
|
||||
#include "SearchMissingCommandEventArgs.g.h"
|
||||
#include "WindowSizeChangedEventArgs.g.h"
|
||||
#include "EnterTmuxControlEventArgs.g.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
@ -265,6 +266,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
WINRT_PROPERTY(int32_t, Width);
|
||||
WINRT_PROPERTY(int32_t, Height);
|
||||
};
|
||||
|
||||
struct EnterTmuxControlEventArgs : public EnterTmuxControlEventArgsT<EnterTmuxControlEventArgs>
|
||||
{
|
||||
til::property<TmuxControlInputCallback> InputCallback;
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::factory_implementation
|
||||
|
||||
@ -159,4 +159,11 @@ namespace Microsoft.Terminal.Control
|
||||
Int32 Width;
|
||||
Int32 Height;
|
||||
}
|
||||
|
||||
delegate void TmuxControlInputCallback(Char[] input);
|
||||
|
||||
runtimeclass EnterTmuxControlEventArgs
|
||||
{
|
||||
void InputCallback(TmuxControlInputCallback callback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,6 +40,7 @@ namespace Microsoft.Terminal.Control
|
||||
|
||||
Int32 ScrollOffset { get; };
|
||||
Int32 ViewHeight { get; };
|
||||
Int32 ViewWidth { get; };
|
||||
Int32 BufferHeight { get; };
|
||||
|
||||
Boolean HasSelection { get; };
|
||||
|
||||
@ -330,6 +330,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_revokers.SearchMissingCommand = _core.SearchMissingCommand(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleSearchMissingCommand });
|
||||
_revokers.WindowSizeChanged = _core.WindowSizeChanged(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleWindowSizeChanged });
|
||||
_revokers.WriteToClipboard = _core.WriteToClipboard(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleWriteToClipboard });
|
||||
_revokers.EnterTmuxControl = _core.EnterTmuxControl(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleEnterTmuxControl });
|
||||
|
||||
_revokers.PasteFromClipboard = _interactivity.PasteFromClipboard(winrt::auto_revoke, { get_weak(), &TermControl::_bubblePasteFromClipboard });
|
||||
|
||||
@ -1506,6 +1507,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_core.SendInput(text);
|
||||
}
|
||||
|
||||
void TermControl::InjectTextAtCursor(const winrt::hstring& text)
|
||||
{
|
||||
_core.InjectTextAtCursor(text);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Manually handles key events for certain keys that can't be passed to us
|
||||
// normally. Namely, the keys we're concerned with are F7 down and Alt up.
|
||||
@ -2667,6 +2673,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return _core.ViewHeight();
|
||||
}
|
||||
|
||||
int TermControl::ViewWidth() const
|
||||
{
|
||||
return _core.ViewWidth();
|
||||
}
|
||||
|
||||
int TermControl::BufferHeight() const
|
||||
{
|
||||
return _core.BufferHeight();
|
||||
@ -2866,7 +2877,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
else
|
||||
{
|
||||
// Do we ever get here (= uninitialized terminal)? If so: How?
|
||||
assert(false);
|
||||
// Yes, we can get here, when do Pane._Split, it need to call _SetupEntranceAnimation
|
||||
// which need the control's size, while this size can only be available when the control
|
||||
// is initialized.
|
||||
return { 10, 10 };
|
||||
}
|
||||
}
|
||||
@ -4002,6 +4015,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void TermControl::_bubbleEnterTmuxControl(const IInspectable&, Control::EnterTmuxControlEventArgs args)
|
||||
{
|
||||
EnterTmuxControl.raise(*this, std::move(args));
|
||||
}
|
||||
|
||||
til::CoordType TermControl::_calculateSearchScrollOffset() const
|
||||
{
|
||||
auto result = 0;
|
||||
|
||||
@ -97,6 +97,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
int ScrollOffset() const;
|
||||
int ViewHeight() const;
|
||||
int ViewWidth() const;
|
||||
int BufferHeight() const;
|
||||
|
||||
bool HasSelection() const;
|
||||
@ -182,6 +183,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
bool RawWriteKeyEvent(const WORD vkey, const WORD scanCode, const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown);
|
||||
bool RawWriteChar(const wchar_t character, const WORD scanCode, const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers);
|
||||
void RawWriteString(const winrt::hstring& text);
|
||||
void InjectTextAtCursor(const winrt::hstring& text);
|
||||
|
||||
void ShowContextMenu();
|
||||
bool OpenQuickFixMenu();
|
||||
@ -217,6 +219,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
til::typed_event<IInspectable, Control::StringSentEventArgs> StringSent;
|
||||
til::typed_event<IInspectable, Control::SearchMissingCommandEventArgs> SearchMissingCommand;
|
||||
til::typed_event<IInspectable, Control::WindowSizeChangedEventArgs> WindowSizeChanged;
|
||||
til::typed_event<IInspectable, Control::EnterTmuxControlEventArgs> EnterTmuxControl;
|
||||
|
||||
// UNDER NO CIRCUMSTANCES SHOULD YOU ADD A (PROJECTED_)FORWARDED_TYPED_EVENT HERE
|
||||
// Those attach the handler to the core directly, and will explode if
|
||||
@ -437,6 +440,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void _bubbleSearchMissingCommand(const IInspectable& sender, const Control::SearchMissingCommandEventArgs& args);
|
||||
winrt::fire_and_forget _bubbleWindowSizeChanged(const IInspectable& sender, Control::WindowSizeChangedEventArgs args);
|
||||
void _bubbleEnterTmuxControl(const IInspectable& sender, Control::EnterTmuxControlEventArgs args);
|
||||
til::CoordType _calculateSearchScrollOffset() const;
|
||||
|
||||
void _PasteCommandHandler(const IInspectable& sender, const IInspectable& args);
|
||||
@ -471,6 +475,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
Control::ControlCore::SearchMissingCommand_revoker SearchMissingCommand;
|
||||
Control::ControlCore::RefreshQuickFixUI_revoker RefreshQuickFixUI;
|
||||
Control::ControlCore::WindowSizeChanged_revoker WindowSizeChanged;
|
||||
Control::ControlCore::EnterTmuxControl_revoker EnterTmuxControl;
|
||||
|
||||
// These are set up in _InitializeTerminal
|
||||
Control::ControlCore::RendererWarning_revoker RendererWarning;
|
||||
|
||||
@ -74,6 +74,7 @@ namespace Microsoft.Terminal.Control
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ReadOnlyChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FocusFollowMouseRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, WindowSizeChangedEventArgs> WindowSizeChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, EnterTmuxControlEventArgs> EnterTmuxControl;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, CompletionsChangedEventArgs> CompletionsChanged;
|
||||
|
||||
@ -130,6 +131,7 @@ namespace Microsoft.Terminal.Control
|
||||
Boolean RawWriteKeyEvent(UInt16 vkey, UInt16 scanCode, Microsoft.Terminal.Core.ControlKeyStates modifiers, Boolean keyDown);
|
||||
Boolean RawWriteChar(Char character, UInt16 scanCode, Microsoft.Terminal.Core.ControlKeyStates modifiers);
|
||||
void RawWriteString(String text);
|
||||
void InjectTextAtCursor(String text);
|
||||
|
||||
void BellLightOn();
|
||||
|
||||
|
||||
@ -51,6 +51,7 @@ void Terminal::Create(til::size viewportSize, til::CoordType scrollbackLines, Re
|
||||
_mainBuffer = std::make_unique<TextBuffer>(bufferSize, attr, cursorSize, true, &renderer);
|
||||
|
||||
auto dispatch = std::make_unique<AdaptDispatch>(*this, &renderer, _renderSettings, _terminalInput);
|
||||
_adaptDispatch = dispatch.get();
|
||||
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
|
||||
_stateMachine = std::make_unique<StateMachine>(std::move(engine));
|
||||
}
|
||||
@ -1039,6 +1040,12 @@ bool Terminal::IsFocused() const noexcept
|
||||
return _focused;
|
||||
}
|
||||
|
||||
AdaptDispatch& Microsoft::Terminal::Core::Terminal::GetAdaptDispatch() noexcept
|
||||
{
|
||||
_assertLocked();
|
||||
return *_adaptDispatch;
|
||||
}
|
||||
|
||||
RenderSettings& Terminal::GetRenderSettings() noexcept
|
||||
{
|
||||
_assertLocked();
|
||||
@ -1270,6 +1277,11 @@ void Microsoft::Terminal::Core::Terminal::SetSearchMissingCommandCallback(std::f
|
||||
_pfnSearchMissingCommand.swap(pfn);
|
||||
}
|
||||
|
||||
void Terminal::SetEnterTmuxControlCallback(std::function<std::function<bool(wchar_t)>()> pfn) noexcept
|
||||
{
|
||||
_pfnEnterTmuxControl = std::move(pfn);
|
||||
}
|
||||
|
||||
void Microsoft::Terminal::Core::Terminal::SetClearQuickFixCallback(std::function<void()> pfn) noexcept
|
||||
{
|
||||
_pfnClearQuickFix.swap(pfn);
|
||||
|
||||
@ -116,6 +116,7 @@ public:
|
||||
int ViewEndIndex() const noexcept;
|
||||
bool IsFocused() const noexcept;
|
||||
|
||||
::Microsoft::Console::VirtualTerminal::AdaptDispatch& GetAdaptDispatch() noexcept;
|
||||
RenderSettings& GetRenderSettings() noexcept;
|
||||
const RenderSettings& GetRenderSettings() const noexcept;
|
||||
|
||||
@ -153,14 +154,12 @@ public:
|
||||
void ShowWindow(bool showOrHide) override;
|
||||
void UseAlternateScreenBuffer(const TextAttribute& attrs) override;
|
||||
void UseMainScreenBuffer() override;
|
||||
|
||||
bool IsVtInputEnabled() const noexcept override;
|
||||
void NotifyBufferRotation(const int delta) override;
|
||||
void NotifyShellIntegrationMark() override;
|
||||
|
||||
void InvokeCompletions(std::wstring_view menuJson, unsigned int replaceLength) override;
|
||||
|
||||
void SearchMissingCommand(const std::wstring_view command) override;
|
||||
std::function<bool(wchar_t)> EnterTmuxControl() override;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
@ -230,6 +229,7 @@ public:
|
||||
void SetPlayMidiNoteCallback(std::function<void(const int, const int, const std::chrono::microseconds)> pfn) noexcept;
|
||||
void CompletionsChangedCallback(std::function<void(std::wstring_view, unsigned int)> pfn) noexcept;
|
||||
void SetSearchMissingCommandCallback(std::function<void(std::wstring_view, const til::CoordType)> pfn) noexcept;
|
||||
void SetEnterTmuxControlCallback(std::function<std::function<bool(wchar_t)>()> pfn) noexcept;
|
||||
void SetClearQuickFixCallback(std::function<void()> pfn) noexcept;
|
||||
void SetWindowSizeChangedCallback(std::function<void(int32_t, int32_t)> pfn) noexcept;
|
||||
void SetSearchHighlights(const std::vector<til::point_span>& highlights) noexcept;
|
||||
@ -338,10 +338,12 @@ private:
|
||||
std::function<void(const int, const int, const std::chrono::microseconds)> _pfnPlayMidiNote;
|
||||
std::function<void(std::wstring_view, unsigned int)> _pfnCompletionsChanged;
|
||||
std::function<void(std::wstring_view, const til::CoordType)> _pfnSearchMissingCommand;
|
||||
std::function<std::function<bool(wchar_t)>()> _pfnEnterTmuxControl;
|
||||
std::function<void()> _pfnClearQuickFix;
|
||||
std::function<void(int32_t, int32_t)> _pfnWindowSizeChanged;
|
||||
|
||||
RenderSettings _renderSettings;
|
||||
::Microsoft::Console::VirtualTerminal::AdaptDispatch* _adaptDispatch = nullptr;
|
||||
std::unique_ptr<::Microsoft::Console::VirtualTerminal::StateMachine> _stateMachine;
|
||||
::Microsoft::Console::VirtualTerminal::TerminalInput _terminalInput;
|
||||
|
||||
|
||||
@ -364,6 +364,11 @@ void Terminal::SearchMissingCommand(const std::wstring_view command)
|
||||
}
|
||||
}
|
||||
|
||||
std::function<bool(wchar_t)> Terminal::EnterTmuxControl()
|
||||
{
|
||||
return _pfnEnterTmuxControl ? _pfnEnterTmuxControl() : nullptr;
|
||||
}
|
||||
|
||||
void Terminal::NotifyBufferRotation(const int delta)
|
||||
{
|
||||
// Update our selection, so it doesn't move as the buffer is cycled
|
||||
|
||||
@ -352,6 +352,7 @@ namespace winrt::Microsoft::Terminal::Settings
|
||||
_AllowVtChecksumReport = profile.AllowVtChecksumReport();
|
||||
_AllowVtClipboardWrite = profile.AllowVtClipboardWrite();
|
||||
_PathTranslationStyle = profile.PathTranslationStyle();
|
||||
_AllowTmuxControl = profile.AllowTmuxControl();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
||||
@ -92,6 +92,7 @@ namespace winrt::Microsoft::Terminal::Settings
|
||||
SIMPLE_OVERRIDABLE_SETTING(bool, Elevate, false);
|
||||
SIMPLE_OVERRIDABLE_SETTING(IEnvironmentVariableMapView, EnvironmentVariables, nullptr);
|
||||
SIMPLE_OVERRIDABLE_SETTING(bool, ReloadEnvironmentVariables, true);
|
||||
SIMPLE_OVERRIDABLE_SETTING(bool, AllowTmuxControl, false);
|
||||
|
||||
public:
|
||||
// TerminalApp overrides these when duplicating a session
|
||||
|
||||
@ -94,6 +94,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
_NotifyChanges(L"Icon", L"IconPath");
|
||||
}
|
||||
|
||||
constexpr bool TmuxControlEnabled() noexcept
|
||||
{
|
||||
return Feature_TmuxControl::IsEnabled();
|
||||
}
|
||||
|
||||
// starting directory
|
||||
hstring CurrentStartingDirectoryPreview() const;
|
||||
bool UseParentProcessDirectory() const;
|
||||
@ -161,6 +166,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, AnswerbackMessage);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, RainbowSuggestions);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, PathTranslationStyle);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, AllowTmuxControl);
|
||||
|
||||
WINRT_PROPERTY(bool, IsBaseLayer, false);
|
||||
WINRT_PROPERTY(bool, FocusDeleteButton, false);
|
||||
|
||||
@ -108,6 +108,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
Boolean UsingBuiltInIcon { get; };
|
||||
Boolean UsingEmojiIcon { get; };
|
||||
Boolean UsingImageIcon { get; };
|
||||
Boolean TmuxControlEnabled { get; };
|
||||
String IconPath;
|
||||
|
||||
EnumEntry CurrentBuiltInIcon;
|
||||
@ -156,5 +157,6 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, RainbowSuggestions);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.PathTranslationStyle, PathTranslationStyle);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AllowVtClipboardWrite);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AllowTmuxControl);
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,6 +82,16 @@
|
||||
<TextBox Style="{StaticResource TextBoxSettingStyle}"
|
||||
Text="{x:Bind Profile.AnswerbackMessage, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Allow Tmux Control -->
|
||||
<local:SettingContainer x:Uid="Profile_AllowTmuxControl"
|
||||
ClearSettingValue="{x:Bind Profile.ClearAllowTmuxControl}"
|
||||
HasSettingValue="{x:Bind Profile.HasAllowTmuxControl, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.AllowTmuxControlOverrideSource, Mode=OneWay}"
|
||||
Visibility="{x:Bind Profile.TmuxControlEnabled, Mode=OneTime}">
|
||||
<ToggleSwitch IsOn="{x:Bind Profile.AllowTmuxControl, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
|
||||
</local:SettingContainer>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
||||
@ -542,6 +542,10 @@
|
||||
<value>Always on top</value>
|
||||
<comment>Header for a control to toggle if the app will always be presented on top of other windows, or is treated normally (when disabled).</comment>
|
||||
</data>
|
||||
<data name="Profile_AllowTmuxControl.Header" xml:space="preserve">
|
||||
<value>Allow Tmux Control</value>
|
||||
<comment>Header for a control to toggle tmux control.</comment>
|
||||
</data>
|
||||
<data name="Profile_ForceVTInput.Header" xml:space="preserve">
|
||||
<value>Use the legacy input encoding</value>
|
||||
<comment>Header for a control to toggle legacy input encoding for the terminal.</comment>
|
||||
|
||||
@ -106,6 +106,7 @@ Author(s):
|
||||
X(bool, AllowVtChecksumReport, "compatibility.allowDECRQCRA", false) \
|
||||
X(bool, AllowVtClipboardWrite, "compatibility.allowOSC52", true) \
|
||||
X(bool, AllowKeypadMode, "compatibility.allowDECNKM", false) \
|
||||
X(bool, AllowTmuxControl, "AllowTmuxControl", false) \
|
||||
X(Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle, "pathTranslationStyle", Microsoft::Terminal::Control::PathTranslationStyle::None)
|
||||
|
||||
// Intentionally omitted Profile settings:
|
||||
|
||||
@ -91,6 +91,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, AllowVtChecksumReport);
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, AllowKeypadMode);
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, AllowVtClipboardWrite);
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, AllowTmuxControl);
|
||||
|
||||
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.PathTranslationStyle, PathTranslationStyle);
|
||||
}
|
||||
|
||||
@ -187,4 +187,16 @@
|
||||
<alwaysDisabledReleaseTokens/>
|
||||
</feature>
|
||||
|
||||
<feature>
|
||||
<name>Feature_TmuxControl</name>
|
||||
<description>Enables Tmux Control</description>
|
||||
<id>3656</id>
|
||||
<stage>AlwaysDisabled</stage>
|
||||
<alwaysEnabledBrandingTokens>
|
||||
<brandingToken>Dev</brandingToken>
|
||||
<brandingToken>Canary</brandingToken>
|
||||
<brandingToken>Preview</brandingToken>
|
||||
</alwaysEnabledBrandingTokens>
|
||||
</feature>
|
||||
|
||||
</featureStaging>
|
||||
|
||||
@ -427,7 +427,14 @@ void ConhostInternalGetSet::InvokeCompletions(std::wstring_view /*menuJson*/, un
|
||||
{
|
||||
// Not implemented for conhost.
|
||||
}
|
||||
|
||||
void ConhostInternalGetSet::SearchMissingCommand(std::wstring_view /*missingCommand*/)
|
||||
{
|
||||
// Not implemented for conhost.
|
||||
}
|
||||
|
||||
std::function<bool(wchar_t)> ConhostInternalGetSet::EnterTmuxControl()
|
||||
{
|
||||
// Not implemented for conhost.
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -71,6 +71,7 @@ public:
|
||||
void InvokeCompletions(std::wstring_view menuJson, unsigned int replaceLength) override;
|
||||
|
||||
void SearchMissingCommand(std::wstring_view missingCommand) override;
|
||||
std::function<bool(wchar_t)> EnterTmuxControl() override;
|
||||
|
||||
private:
|
||||
Microsoft::Console::IIoProvider& _io;
|
||||
|
||||
@ -192,6 +192,8 @@ public:
|
||||
virtual void PlaySounds(const VTParameters parameters) = 0; // DECPS
|
||||
|
||||
virtual void SetOptionalFeatures(const til::enumset<OptionalFeature> features) = 0;
|
||||
|
||||
virtual StringHandler EnterTmuxControl(const VTParameters parameters) = 0; // tmux -CC
|
||||
};
|
||||
inline Microsoft::Console::VirtualTerminal::ITermDispatch::~ITermDispatch() = default;
|
||||
#pragma warning(pop)
|
||||
|
||||
@ -90,5 +90,6 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
virtual void InvokeCompletions(std::wstring_view menuJson, unsigned int replaceLength) = 0;
|
||||
|
||||
virtual void SearchMissingCommand(const std::wstring_view command) = 0;
|
||||
virtual std::function<bool(wchar_t)> EnterTmuxControl() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@ -4760,3 +4760,12 @@ void AdaptDispatch::SetOptionalFeatures(const til::enumset<OptionalFeature> feat
|
||||
{
|
||||
_optionalFeatures = features;
|
||||
}
|
||||
|
||||
ITermDispatch::StringHandler AdaptDispatch::EnterTmuxControl(const VTParameters parameters)
|
||||
{
|
||||
if (parameters.size() != 1 || parameters.at(0).value() != 1000)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return _api.EnterTmuxControl();
|
||||
}
|
||||
|
||||
@ -190,6 +190,8 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
|
||||
void SetOptionalFeatures(const til::enumset<OptionalFeature> features) noexcept override;
|
||||
|
||||
StringHandler EnterTmuxControl(const VTParameters parameters) override; // tmux -CC
|
||||
|
||||
private:
|
||||
enum class Mode
|
||||
{
|
||||
|
||||
@ -179,6 +179,8 @@ public:
|
||||
void PlaySounds(const VTParameters /*parameters*/) override{}; // DECPS
|
||||
|
||||
void SetOptionalFeatures(const til::enumset<OptionalFeature> /*features*/) override{};
|
||||
|
||||
StringHandler EnterTmuxControl(const VTParameters /*parameters*/) override { return nullptr; }; // tmux -CC
|
||||
};
|
||||
|
||||
#pragma warning(default : 26440) // Restore "can be declared noexcept" warning
|
||||
|
||||
@ -224,6 +224,12 @@ public:
|
||||
Log::Comment(L"SearchMissingCommand MOCK called...");
|
||||
}
|
||||
|
||||
std::function<bool(wchar_t)> EnterTmuxControl() override
|
||||
{
|
||||
Log::Comment(L"EnterTmuxControl MOCK called...");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PrepData()
|
||||
{
|
||||
PrepData(CursorDirection::UP); // if called like this, the cursor direction doesn't matter.
|
||||
|
||||
@ -724,6 +724,9 @@ IStateMachineEngine::StringHandler OutputStateMachineEngine::ActionDcsDispatch(c
|
||||
case DcsActionCodes::DECRSPS_RestorePresentationState:
|
||||
handler = _dispatch->RestorePresentationState(parameters.at(0));
|
||||
break;
|
||||
case DcsActionCodes::TMUX_ControlEnter:
|
||||
handler = _dispatch->EnterTmuxControl(parameters);
|
||||
break;
|
||||
default:
|
||||
handler = nullptr;
|
||||
break;
|
||||
|
||||
@ -178,6 +178,7 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
DECRSTS_RestoreTerminalState = VTID("$p"),
|
||||
DECRQSS_RequestSetting = VTID("$q"),
|
||||
DECRSPS_RestorePresentationState = VTID("$t"),
|
||||
TMUX_ControlEnter = VTID("p"),
|
||||
};
|
||||
|
||||
enum Vt52ActionCodes : uint64_t
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user