mirror of
https://github.com/microsoft/terminal.git
synced 2026-05-18 10:50:44 +00:00
Compare commits
11 Commits
v1.25.1322
...
dev/lhecke
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f144427898 | ||
|
|
5f5a26fe9d | ||
|
|
cb79ab47fe | ||
|
|
671eb19ab8 | ||
|
|
500f4132b7 | ||
|
|
962461df32 | ||
|
|
835467888e | ||
|
|
55abb0ffdf | ||
|
|
d2dc2092a6 | ||
|
|
a804faedda | ||
|
|
ef23e6676c |
@@ -284,6 +284,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)
|
||||
|
||||
@@ -120,9 +120,9 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||
return ConnectionState::Failed;
|
||||
}
|
||||
|
||||
void DebugTapConnection::_OutputHandler(const std::wstring_view str)
|
||||
void DebugTapConnection::_OutputHandler(const winrt::array_view<const char16_t> str)
|
||||
{
|
||||
auto output = til::visualize_control_codes(str);
|
||||
auto output = til::visualize_control_codes(winrt_array_to_wstring_view(str));
|
||||
// To make the output easier to read, we introduce a line break whenever
|
||||
// an LF control is encountered. But at this point, the LF would have
|
||||
// been converted to U+240A (␊), so that's what we need to search for.
|
||||
@@ -130,7 +130,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||
{
|
||||
output.insert(++lfPos, L"\r\n");
|
||||
}
|
||||
TerminalOutput.raise(output);
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(output));
|
||||
}
|
||||
|
||||
// Called by the DebugInputTapConnection to print user input
|
||||
@@ -138,7 +138,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||
{
|
||||
auto clean{ til::visualize_control_codes(str) };
|
||||
auto formatted{ wil::str_printf<std::wstring>(L"\x1b[91m%ls\x1b[m", clean.data()) };
|
||||
TerminalOutput.raise(formatted);
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(formatted));
|
||||
}
|
||||
|
||||
// Wire us up so that we can forward input through
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||
|
||||
private:
|
||||
void _PrintInput(const std::wstring_view data);
|
||||
void _OutputHandler(const std::wstring_view str);
|
||||
void _OutputHandler(const winrt::array_view<const char16_t> str);
|
||||
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection::TerminalOutput_revoker _outputRevoker;
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection::StateChanged_revoker _stateChangedRevoker;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -982,4 +982,10 @@
|
||||
<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>
|
||||
</data>
|
||||
<data name="NewTmuxControlTab.Text" xml:space="preserve">
|
||||
<value>Tmux Control Tab</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -933,6 +933,13 @@ namespace winrt::TerminalApp::implementation
|
||||
return res;
|
||||
}
|
||||
|
||||
void Tab::Close()
|
||||
{
|
||||
ASSERT_UI_THREAD();
|
||||
|
||||
Closed.raise(nullptr, nullptr);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Prepares this tab for being removed from the UI hierarchy by shutting down all active connections.
|
||||
void Tab::Shutdown()
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
|
||||
void UpdateTitle();
|
||||
|
||||
void Close();
|
||||
void Shutdown();
|
||||
void ClosePane();
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace TerminalApp
|
||||
UInt32 TabViewNumTabs;
|
||||
|
||||
void Focus(Windows.UI.Xaml.FocusState focusState);
|
||||
void Close();
|
||||
void Shutdown();
|
||||
|
||||
void SetDispatch(ShortcutActionDispatch dispatch);
|
||||
|
||||
@@ -411,13 +411,11 @@ namespace winrt::TerminalApp::implementation
|
||||
auto actions = t->BuildStartupActions(BuildStartupKind::None);
|
||||
_AddPreviouslyClosedPaneOrTab(std::move(actions));
|
||||
|
||||
_RemoveTab(tab);
|
||||
tab.Close();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Removes the tab (both TerminalControl and XAML)
|
||||
// Arguments:
|
||||
// - tab: the tab to remove
|
||||
// Removes the tab (both TerminalControl and XAML).
|
||||
// NOTE: Don't call this directly, but rather `tab.Close()`.
|
||||
void TerminalPage::_RemoveTab(const winrt::TerminalApp::Tab& tab)
|
||||
{
|
||||
uint32_t tabIndex{};
|
||||
|
||||
@@ -173,6 +173,9 @@
|
||||
<ClInclude Include="SettingsPaneContent.h">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TmuxControl.h">
|
||||
<DependentUpon>TerminalPage.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Toast.h" />
|
||||
<ClInclude Include="TerminalSettingsCache.h" />
|
||||
<ClInclude Include="SuggestionsControl.h">
|
||||
@@ -285,6 +288,9 @@
|
||||
<ClCompile Include="SettingsPaneContent.cpp">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TmuxControl.cpp">
|
||||
<DependentUpon>TerminalPage.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="Toast.cpp" />
|
||||
<ClCompile Include="TerminalSettingsCache.cpp" />
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
|
||||
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natstepfilter" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\en-US\Resources.resw" />
|
||||
@@ -33,8 +34,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="Toast.cpp" />
|
||||
<ClCompile Include="LanguageProfileNotifier.cpp" />
|
||||
<ClCompile Include="Monarch.cpp" />
|
||||
<ClCompile Include="Peasant.cpp" />
|
||||
<ClCompile Include="TerminalSettingsCache.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
@@ -60,14 +60,13 @@
|
||||
<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="TmuxControl.h">
|
||||
<Filter>controls</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="AppLogic.idl">
|
||||
@@ -90,7 +89,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 +123,7 @@
|
||||
<Page Include="AboutDialog.xaml" />
|
||||
<Page Include="SuggestionsControl.xaml" />
|
||||
<Page Include="SnippetsPaneContent.xaml" />
|
||||
<Page Include="MarkdownPaneContent.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="app">
|
||||
@@ -155,4 +156,4 @@
|
||||
<Filter>app</Filter>
|
||||
</ApplicationDefinition>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -5,10 +5,14 @@
|
||||
#include "pch.h"
|
||||
#include "TerminalPage.h"
|
||||
|
||||
#include <TerminalThemeHelpers.h>
|
||||
#include <Utils.h>
|
||||
#include <TerminalCore/ControlKeyStates.hpp>
|
||||
#include <TerminalThemeHelpers.h>
|
||||
#include <til/hash.h>
|
||||
#include <Utils.h>
|
||||
|
||||
#include "../../types/inc/ColorFix.hpp"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "../TerminalSettingsAppAdapterLib/TerminalSettings.h"
|
||||
#include "App.h"
|
||||
#include "DebugTapConnection.h"
|
||||
#include "MarkdownPaneContent.h"
|
||||
@@ -18,9 +22,7 @@
|
||||
#include "SnippetsPaneContent.h"
|
||||
#include "TabRowControl.h"
|
||||
#include "TerminalSettingsCache.h"
|
||||
#include "../../types/inc/ColorFix.hpp"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
#include "../TerminalSettingsAppAdapterLib/TerminalSettings.h"
|
||||
#include "TmuxControl.h"
|
||||
|
||||
#include "LaunchPositionRequest.g.cpp"
|
||||
#include "RenameWindowRequestedArgs.g.cpp"
|
||||
@@ -404,6 +406,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());
|
||||
}
|
||||
});
|
||||
@@ -1429,6 +1440,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,
|
||||
@@ -2525,6 +2545,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() };
|
||||
@@ -3581,6 +3610,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;
|
||||
}
|
||||
|
||||
@@ -5000,9 +5049,10 @@ namespace winrt::TerminalApp::implementation
|
||||
void TerminalPage::_adjustProcessPriority() const
|
||||
{
|
||||
// Windowing is single-threaded, so this will not cause a race condition.
|
||||
static bool supported{ true };
|
||||
static uint64_t s_lastUpdateHash{ 0 };
|
||||
static bool s_supported{ true };
|
||||
|
||||
if (!supported || !_hostingHwnd.has_value())
|
||||
if (!s_supported || !_hostingHwnd.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -5066,11 +5116,20 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
const auto count{ gsl::narrow_cast<DWORD>(it - processes.begin()) };
|
||||
const auto hash = til::hash((void*)processes.data(), count * sizeof(HANDLE));
|
||||
|
||||
if (hash == s_lastUpdateHash)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s_lastUpdateHash = hash;
|
||||
const auto hr = TerminalTrySetWindowAssociatedProcesses(_hostingHwnd.value(), count, count ? processes.data() : nullptr);
|
||||
|
||||
if (S_FALSE == hr)
|
||||
{
|
||||
// Don't bother trying again or logging. The wrapper tells us it's unsupported.
|
||||
supported = false;
|
||||
s_supported = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5468,6 +5527,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;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "RenameWindowRequestedArgs.g.h"
|
||||
#include "RequestMoveContentArgs.g.h"
|
||||
#include "LaunchPositionRequest.g.h"
|
||||
#include "TmuxControl.h"
|
||||
#include "Toast.h"
|
||||
|
||||
#include "WindowsPackageManagerFactory.h"
|
||||
@@ -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 class TmuxControl;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,8 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
_removeControlEvents();
|
||||
|
||||
_control.Close();
|
||||
|
||||
// Clear out our media player callbacks, and stop any playing media. This
|
||||
// will prevent the callback from being triggered after we've closed, and
|
||||
// also make sure that our sound stops when we're closed.
|
||||
|
||||
1392
src/cascadia/TerminalApp/TmuxControl.cpp
Normal file
1392
src/cascadia/TerminalApp/TmuxControl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
183
src/cascadia/TerminalApp/TmuxControl.h
Normal file
183
src/cascadia/TerminalApp/TmuxControl.h
Normal file
@@ -0,0 +1,183 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <til/mutex.h>
|
||||
|
||||
#include "Pane.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct TerminalPage;
|
||||
|
||||
class TmuxControl : public std::enable_shared_from_this<TmuxControl>
|
||||
{
|
||||
public:
|
||||
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;
|
||||
};
|
||||
|
||||
// AttachedPane should not need to be copied. Anything else would be a mistake.
|
||||
// But if we added a constructor to it, we could not use designated initializers anymore.
|
||||
// This marker makes it possible.
|
||||
struct MoveOnlyMarker
|
||||
{
|
||||
MoveOnlyMarker() = default;
|
||||
MoveOnlyMarker(MoveOnlyMarker&&) = default;
|
||||
MoveOnlyMarker& operator=(MoveOnlyMarker&&) = default;
|
||||
MoveOnlyMarker(const MoveOnlyMarker&) = delete;
|
||||
MoveOnlyMarker& operator=(const MoveOnlyMarker&) = delete;
|
||||
};
|
||||
|
||||
struct AttachedPane
|
||||
{
|
||||
int64_t windowId = -1;
|
||||
int64_t paneId = -1;
|
||||
winrt::Microsoft::Terminal::TerminalConnection::TmuxConnection connection{ nullptr };
|
||||
winrt::Microsoft::Terminal::Control::TermControl control{ nullptr };
|
||||
std::wstring outputBacklog;
|
||||
bool initialized = false;
|
||||
bool ignoreOutput = false;
|
||||
|
||||
[[msvc::no_unique_address]] MoveOnlyMarker moveOnlyMarker;
|
||||
};
|
||||
|
||||
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,
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -94,9 +94,15 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
// - helper that will write an unterminated string (generally, from a resource) to the output stream.
|
||||
// Arguments:
|
||||
// - str: the string to write.
|
||||
void AzureConnection::_WriteStringWithNewline(std::wstring str)
|
||||
{
|
||||
str.append(L"\r\n");
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(str));
|
||||
}
|
||||
|
||||
void AzureConnection::_WriteStringWithNewline(const std::wstring_view str)
|
||||
{
|
||||
TerminalOutput.raise(str + L"\r\n");
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(str + L"\r\n"));
|
||||
}
|
||||
|
||||
// Method description:
|
||||
@@ -112,7 +118,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
catch (const std::exception& runtimeException)
|
||||
{
|
||||
// This also catches the AzureException, which has a .what()
|
||||
TerminalOutput.raise(_colorize(91, til::u8u16(std::string{ runtimeException.what() })));
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(_colorize(91, til::u8u16(std::string{ runtimeException.what() }))));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -162,13 +168,13 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
|
||||
_currentInputMode = mode;
|
||||
|
||||
TerminalOutput.raise(L"> \x1b[92m"); // Make prompted user input green
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(L"> \x1b[92m")); // Make prompted user input green
|
||||
|
||||
_inputEvent.wait(inputLock, [this, mode]() {
|
||||
return _currentInputMode != mode || _isStateAtOrBeyond(ConnectionState::Closing);
|
||||
});
|
||||
|
||||
TerminalOutput.raise(L"\x1b[m");
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(L"\x1b[m"));
|
||||
|
||||
if (_isStateAtOrBeyond(ConnectionState::Closing))
|
||||
{
|
||||
@@ -211,19 +217,19 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
if (_userInput.size() > 0)
|
||||
{
|
||||
_userInput.pop_back();
|
||||
TerminalOutput.raise(L"\x08 \x08"); // overstrike the character with a space
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(L"\x08 \x08")); // overstrike the character with a space
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TerminalOutput.raise(data); // echo back
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(data)); // echo back
|
||||
|
||||
switch (_currentInputMode)
|
||||
{
|
||||
case InputMode::Line:
|
||||
if (data.size() > 0 && gsl::at(data, 0) == UNICODE_CARRIAGERETURN)
|
||||
{
|
||||
TerminalOutput.raise(L"\r\n"); // we probably got a \r, so we need to advance to the next line.
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(L"\r\n")); // we probably got a \r, so we need to advance to the next line.
|
||||
_currentInputMode = InputMode::None; // toggling the mode indicates completion
|
||||
_inputEvent.notify_one();
|
||||
break;
|
||||
@@ -429,7 +435,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
}
|
||||
|
||||
// Pass the output to our registered event handlers
|
||||
TerminalOutput.raise(_u16Str);
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(_u16Str));
|
||||
break;
|
||||
}
|
||||
case WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE:
|
||||
@@ -772,7 +778,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
const auto shellType = _ParsePreferredShellType(settingsResponse);
|
||||
_WriteStringWithNewline(RS_(L"AzureRequestingTerminal"));
|
||||
const auto socketUri = _GetTerminal(shellType);
|
||||
TerminalOutput.raise(L"\r\n");
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(L"\r\n"));
|
||||
|
||||
//// Step 8: connecting to said terminal
|
||||
{
|
||||
|
||||
@@ -67,6 +67,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
std::optional<::Microsoft::Terminal::Azure::Tenant> _currentTenant;
|
||||
|
||||
void _writeInput(const std::wstring_view str);
|
||||
void _WriteStringWithNewline(std::wstring str);
|
||||
void _WriteStringWithNewline(const std::wstring_view str);
|
||||
void _WriteCaughtExceptionRecord();
|
||||
winrt::Windows::Data::Json::JsonObject _SendRequestReturningJson(std::wstring_view uri, const winrt::Windows::Web::Http::IHttpContent& content = nullptr, winrt::Windows::Web::Http::HttpMethod method = nullptr, const winrt::Windows::Foundation::Uri referer = nullptr);
|
||||
|
||||
@@ -477,31 +477,28 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
const auto hr = wil::ResultFromCaughtException();
|
||||
|
||||
// GH#11556 - make sure to format the error code to this string as an UNSIGNED int
|
||||
const auto failureText = RS_fmt(L"ProcessFailedToLaunch", _formatStatus(hr), _commandline);
|
||||
TerminalOutput.raise(failureText);
|
||||
auto failureText = RS_fmt(L"ProcessFailedToLaunch", _formatStatus(hr), _commandline);
|
||||
|
||||
// If the path was invalid, let's present an informative message to the user
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_DIRECTORY))
|
||||
{
|
||||
const auto badPathText = RS_fmt(L"BadPathText", _startingDirectory);
|
||||
TerminalOutput.raise(L"\r\n");
|
||||
TerminalOutput.raise(badPathText);
|
||||
failureText.append(L"\r\n");
|
||||
failureText.append(RS_fmt(L"BadPathText", _startingDirectory));
|
||||
}
|
||||
// If the requested action requires elevation, display appropriate message
|
||||
else if (hr == HRESULT_FROM_WIN32(ERROR_ELEVATION_REQUIRED))
|
||||
{
|
||||
const auto elevationText = RS_(L"ElevationRequired");
|
||||
TerminalOutput.raise(L"\r\n");
|
||||
TerminalOutput.raise(elevationText);
|
||||
failureText.append(L"\r\n");
|
||||
failureText.append(RS_(L"ElevationRequired"));
|
||||
}
|
||||
// If the requested executable was not found, display appropriate message
|
||||
else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
|
||||
{
|
||||
const auto fileNotFoundText = RS_(L"FileNotFound");
|
||||
TerminalOutput.raise(L"\r\n");
|
||||
TerminalOutput.raise(fileNotFoundText);
|
||||
failureText.append(L"\r\n");
|
||||
failureText.append(RS_(L"FileNotFound"));
|
||||
}
|
||||
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(failureText));
|
||||
_transitionToState(ConnectionState::Failed);
|
||||
|
||||
// Tear down any state we may have accumulated.
|
||||
@@ -520,7 +517,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
const auto msg1 = RS_fmt(L"ProcessExited", _formatStatus(status));
|
||||
const auto msg2 = RS_(L"CtrlDToClose");
|
||||
const auto msg = fmt::format(FMT_COMPILE(L"\r\n{}\r\n{}\r\n"), msg1, msg2);
|
||||
TerminalOutput.raise(msg);
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(msg));
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
@@ -792,7 +789,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
|
||||
try
|
||||
{
|
||||
TerminalOutput.raise(wstr);
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(wstr));
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
prettyPrint << wch;
|
||||
}
|
||||
}
|
||||
TerminalOutput.raise(prettyPrint.str());
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(prettyPrint.str()));
|
||||
}
|
||||
|
||||
void EchoConnection::Resize(uint32_t /*rows*/, uint32_t /*columns*/) noexcept
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Microsoft.Terminal.TerminalConnection
|
||||
Failed
|
||||
};
|
||||
|
||||
delegate void TerminalOutputHandler(String output);
|
||||
delegate void TerminalOutputHandler(Char[] output);
|
||||
|
||||
interface ITerminalConnection
|
||||
{
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
<ClInclude Include="EchoConnection.h">
|
||||
<DependentUpon>EchoConnection.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TmuxConnection.h">
|
||||
<DependentUpon>TmuxConnection.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CTerminalHandoff.cpp" />
|
||||
@@ -52,6 +55,9 @@
|
||||
<ClCompile Include="ConptyConnection.cpp">
|
||||
<DependentUpon>ConptyConnection.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TmuxConnection.cpp">
|
||||
<DependentUpon>TmuxConnection.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -60,6 +66,7 @@
|
||||
<Midl Include="ConptyConnection.idl" />
|
||||
<Midl Include="EchoConnection.idl" />
|
||||
<Midl Include="AzureConnection.idl" />
|
||||
<Midl Include="TmuxConnection.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\en-US\Resources.resw">
|
||||
@@ -99,4 +106,4 @@
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
<ClCompile Include="AzureConnection.cpp" />
|
||||
<ClCompile Include="init.cpp" />
|
||||
<ClCompile Include="CTerminalHandoff.cpp" />
|
||||
<ClCompile Include="TmuxConnection.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
@@ -27,6 +28,7 @@
|
||||
<ClInclude Include="AzureClientID.h" />
|
||||
<ClInclude Include="CTerminalHandoff.h" />
|
||||
<ClInclude Include="BaseTerminalConnection.h" />
|
||||
<ClInclude Include="TmuxConnection.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="ITerminalConnection.idl" />
|
||||
@@ -34,6 +36,7 @@
|
||||
<Midl Include="AzureConnection.idl" />
|
||||
<Midl Include="ConptyConnection.idl" />
|
||||
<Midl Include="ConnectionInformation.idl" />
|
||||
<Midl Include="TmuxConnection.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
||||
@@ -42,4 +45,4 @@
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\en-US\Resources.resw" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
53
src/cascadia/TerminalConnection/TmuxConnection.cpp
Normal file
53
src/cascadia/TerminalConnection/TmuxConnection.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "TmuxConnection.h"
|
||||
#include <sstream>
|
||||
|
||||
#include "TmuxConnection.g.cpp"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
{
|
||||
TmuxConnection::TmuxConnection() noexcept = default;
|
||||
|
||||
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 {};
|
||||
}
|
||||
|
||||
ConnectionState TmuxConnection::State() const noexcept
|
||||
{
|
||||
return ConnectionState::Connected;
|
||||
}
|
||||
|
||||
void TmuxConnection::WriteOutput(const winrt::array_view<const char16_t> wstr)
|
||||
{
|
||||
if (!wstr.empty())
|
||||
{
|
||||
TerminalOutput.raise(wstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/cascadia/TerminalConnection/TmuxConnection.h
Normal file
40
src/cascadia/TerminalConnection/TmuxConnection.h
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "TmuxConnection.g.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
{
|
||||
struct TmuxConnection : TmuxConnectionT<TmuxConnection>
|
||||
{
|
||||
TmuxConnection() noexcept;
|
||||
|
||||
// ---- ITerminalConnection methods ----
|
||||
|
||||
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) const noexcept;
|
||||
|
||||
void Start() noexcept;
|
||||
void WriteInput(const winrt::array_view<const char16_t> buffer);
|
||||
void Resize(uint32_t rows, uint32_t columns) noexcept;
|
||||
void Close() noexcept;
|
||||
|
||||
til::event<TerminalOutputHandler> TerminalOutput;
|
||||
til::typed_event<ITerminalConnection, IInspectable> StateChanged;
|
||||
|
||||
winrt::guid SessionId() const noexcept;
|
||||
ConnectionState State() const noexcept;
|
||||
|
||||
// ---- TmuxConnection methods ----
|
||||
|
||||
void WriteOutput(const winrt::array_view<const char16_t> wstr);
|
||||
|
||||
til::event<TerminalOutputHandler> TerminalInput;
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(TmuxConnection);
|
||||
}
|
||||
16
src/cascadia/TerminalConnection/TmuxConnection.idl
Normal file
16
src/cascadia/TerminalConnection/TmuxConnection.idl
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "ITerminalConnection.idl";
|
||||
|
||||
namespace Microsoft.Terminal.TerminalConnection
|
||||
{
|
||||
[default_interface]
|
||||
runtimeclass TmuxConnection : ITerminalConnection
|
||||
{
|
||||
TmuxConnection();
|
||||
|
||||
void WriteOutput(Char[] data);
|
||||
event TerminalOutputHandler TerminalInput;
|
||||
};
|
||||
}
|
||||
@@ -10,13 +10,12 @@
|
||||
|
||||
#include <DefaultSettings.h>
|
||||
#include <unicode.hpp>
|
||||
#include <utils.hpp>
|
||||
#include <WinUser.h>
|
||||
|
||||
#include "EventArgs.h"
|
||||
#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"
|
||||
|
||||
@@ -141,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
|
||||
@@ -1461,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;
|
||||
@@ -1570,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.
|
||||
@@ -2238,13 +2301,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
auto noticeArgs = winrt::make<NoticeEventArgs>(NoticeLevel::Info, RS_(L"TermControlReadOnly"));
|
||||
RaiseNotice.raise(*this, std::move(noticeArgs));
|
||||
}
|
||||
void ControlCore::_connectionOutputHandler(const hstring& hstr)
|
||||
void ControlCore::_connectionOutputHandler(const winrt::array_view<const char16_t> str)
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
const auto lock = _terminal->LockForWriting();
|
||||
_terminal->Write(hstr);
|
||||
_terminal->Write(winrt_array_to_wstring_view(str));
|
||||
}
|
||||
|
||||
if (!_pendingResponses.empty())
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -349,7 +351,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void _raiseReadOnlyWarning();
|
||||
void _updateAntiAliasingMode();
|
||||
void _connectionOutputHandler(const hstring& hstr);
|
||||
void _connectionOutputHandler(winrt::array_view<const char16_t> str);
|
||||
void _connectionStateChangedHandler(const TerminalConnection::ITerminalConnection&, const Windows::Foundation::IInspectable&);
|
||||
void _updateHoveredCell(const std::optional<til::point> terminalPosition);
|
||||
void _setOpacity(const float opacity, const bool focused = true);
|
||||
|
||||
@@ -67,6 +67,10 @@ namespace Microsoft.Terminal.Control
|
||||
Boolean SearchRegexInvalid;
|
||||
};
|
||||
|
||||
delegate Boolean TmuxDCSHandler(Char ch);
|
||||
delegate void PrintHandler(String str);
|
||||
delegate TmuxDCSHandler TmuxDCSHandlerProducer(PrintHandler print);
|
||||
|
||||
[default_interface] runtimeclass SelectionColor
|
||||
{
|
||||
SelectionColor();
|
||||
@@ -128,6 +132,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 +203,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^M
|
||||
// which need the control's size, while this size can only be available when the control^M
|
||||
// is initialized.^M
|
||||
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;
|
||||
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
|
||||
|
||||
@@ -28,10 +28,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
PreviewConnection::PreviewConnection() noexcept = default;
|
||||
|
||||
void PreviewConnection::Start() noexcept
|
||||
void PreviewConnection::Start()
|
||||
{
|
||||
// Send the preview text
|
||||
TerminalOutput.raise(fmt::format(PreviewText, _displayPowerlineGlyphs ? PromptTextPowerline : PromptTextPlain));
|
||||
const auto prompt = _displayPowerlineGlyphs ? PromptTextPowerline : PromptTextPlain;
|
||||
const auto text = fmt::format(FMT_COMPILE(PreviewText), prompt);
|
||||
TerminalOutput.raise(winrt_wstring_to_array_view(text));
|
||||
}
|
||||
|
||||
void PreviewConnection::Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) noexcept
|
||||
@@ -50,7 +51,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
}
|
||||
|
||||
void PreviewConnection::DisplayPowerlineGlyphs(bool d) noexcept
|
||||
void PreviewConnection::DisplayPowerlineGlyphs(bool d)
|
||||
{
|
||||
if (_displayPowerlineGlyphs != d)
|
||||
{
|
||||
|
||||
@@ -22,12 +22,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
PreviewConnection() noexcept;
|
||||
|
||||
void Initialize(const Windows::Foundation::Collections::ValueSet& settings) noexcept;
|
||||
void Start() noexcept;
|
||||
void Start();
|
||||
void WriteInput(const winrt::array_view<const char16_t> buffer);
|
||||
void Resize(uint32_t rows, uint32_t columns) noexcept;
|
||||
void Close() noexcept;
|
||||
|
||||
void DisplayPowerlineGlyphs(bool d) noexcept;
|
||||
void DisplayPowerlineGlyphs(bool d);
|
||||
|
||||
winrt::guid SessionId() const noexcept { return {}; }
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState State() const noexcept { return winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::Connected; }
|
||||
|
||||
@@ -188,6 +188,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
_parsedPadding = StringToXamlThickness(_profile.Padding());
|
||||
_defaultAppearanceViewModel.IsDefault(true);
|
||||
|
||||
if constexpr (Feature_TmuxControl::IsEnabled())
|
||||
{
|
||||
TmuxControlEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileViewModel::_UpdateBuiltInIcons()
|
||||
|
||||
@@ -171,9 +171,11 @@ 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);
|
||||
WINRT_PROPERTY(bool, TmuxControlEnabled, false);
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IVector<Windows::Foundation::IInspectable>, IconTypes);
|
||||
GETSET_BINDABLE_ENUM_SETTING(AntiAliasingMode, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode);
|
||||
GETSET_BINDABLE_ENUM_SETTING(CloseOnExitMode, Microsoft::Terminal::Settings::Model::CloseOnExitMode, CloseOnExit);
|
||||
|
||||
@@ -114,6 +114,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
Boolean UsingBuiltInIcon { get; };
|
||||
Boolean UsingEmojiIcon { get; };
|
||||
Boolean UsingImageIcon { get; };
|
||||
Boolean TmuxControlEnabled;
|
||||
String IconPath;
|
||||
|
||||
EnumEntry CurrentBuiltInIcon;
|
||||
@@ -162,5 +163,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,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}">
|
||||
<ToggleSwitch IsOn="{x:Bind Profile.AllowTmuxControl, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
|
||||
</local:SettingContainer>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
||||
@@ -568,6 +568,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);
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
|
||||
<!-- For ALL build types-->
|
||||
<PropertyGroup Label="Configuration">
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<name>Feature_EditableUnfocusedAppearance</name>
|
||||
<description>The unfocused appearance section in profiles in the SUI that allows users to create and edit unfocused appearances.</description>
|
||||
<stage>AlwaysEnabled</stage>
|
||||
<alwaysDisabledReleaseTokens/>
|
||||
<alwaysDisabledReleaseTokens />
|
||||
</feature>
|
||||
|
||||
<feature>
|
||||
@@ -184,7 +184,19 @@
|
||||
<name>Feature_DebugModeUI</name>
|
||||
<description>Enables UI access to the debug mode setting</description>
|
||||
<stage>AlwaysEnabled</stage>
|
||||
<alwaysDisabledReleaseTokens/>
|
||||
<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;
|
||||
|
||||
@@ -168,7 +168,41 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
template<typename T, typename Traits>
|
||||
bool equals(const std::basic_string_view<T, Traits>& lhs, const std::basic_string_view<T, Traits>& rhs) noexcept
|
||||
{
|
||||
return lhs.size() == rhs.size() && __builtin_memcmp(lhs.data(), rhs.data(), lhs.size() * sizeof(T)) == 0;
|
||||
// MSVC can only optimize 1 pattern into a bunch of simple comparison instructions:
|
||||
// size1 == size2 && memcmp(data1, data2, size1/2) == 0
|
||||
// If you introduce a `* sizeof(T)` into the size parameter to memcmp,
|
||||
// it'll refuse to inline the memcmp call, resulting in much worse codegen.
|
||||
// As a trade-off we multiply both sizes by sizeof(T) in advance.
|
||||
// The extra addition instruction is comparatively very cheap.
|
||||
const auto ls = lhs.size() * sizeof(T);
|
||||
const auto rs = rhs.size() * sizeof(T);
|
||||
return ls == rs && __builtin_memcmp(lhs.data(), rhs.data(), ls) == 0;
|
||||
}
|
||||
|
||||
inline bool equals(const std::string_view& lhs, const std::string_view& rhs) noexcept
|
||||
{
|
||||
return equals<>(lhs, rhs);
|
||||
}
|
||||
|
||||
inline bool equals(const std::wstring_view& lhs, const std::wstring_view& rhs) noexcept
|
||||
{
|
||||
return equals<>(lhs, rhs);
|
||||
}
|
||||
|
||||
// An extra overload that undoes the quirk in the main equals() implementation.
|
||||
// It's not really needed, except for being neat. This function in particular
|
||||
// is often the best, easy way to do something like:
|
||||
// match str {
|
||||
// "foo" => ...,
|
||||
// "bar" => ...,
|
||||
// }
|
||||
// with:
|
||||
// if (til::equals(str, "foo")) { ... }
|
||||
// else if (til::equals(str, "bar")) { ... }
|
||||
template<typename T, typename Traits, size_t N>
|
||||
constexpr bool equals(const std::basic_string_view<T, Traits>& lhs, const T (&rhs)[N]) noexcept
|
||||
{
|
||||
return lhs.size() == (N - 1) && __builtin_memcmp(lhs.data(), rhs, (N - 1) * sizeof(T)) == 0;
|
||||
}
|
||||
|
||||
// Just like _memicmp, but without annoying locales.
|
||||
|
||||
@@ -60,32 +60,192 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
template<typename ArgsT>
|
||||
struct event
|
||||
{
|
||||
event<ArgsT>() = default;
|
||||
explicit operator bool() const noexcept { return static_cast<bool>(_handlers); }
|
||||
winrt::event_token operator()(const ArgsT& handler) { return _handlers.add(handler); }
|
||||
void operator()(const winrt::event_token& token) { _handlers.remove(token); }
|
||||
operator bool() const noexcept { return bool(_handlers); }
|
||||
template<typename... Arg>
|
||||
void operator()(winrt::event_token token) { _handlers.remove(token); }
|
||||
|
||||
void raise(auto&&... args)
|
||||
{
|
||||
_handlers(std::forward<decltype(args)>(args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
winrt::event<ArgsT> _handlers;
|
||||
};
|
||||
|
||||
template<typename SenderT = winrt::Windows::Foundation::IInspectable, typename ArgsT = winrt::Windows::Foundation::IInspectable>
|
||||
struct typed_event
|
||||
using typed_event = til::event<winrt::Windows::Foundation::TypedEventHandler<SenderT, ArgsT>>;
|
||||
|
||||
// Unlike winrt::event, this event will only call handlers once at most.
|
||||
// It's otherwise a copy of winrt::event's implementation.
|
||||
template<typename ArgsT>
|
||||
struct fused_event
|
||||
{
|
||||
typed_event<SenderT, ArgsT>() = default;
|
||||
winrt::event_token operator()(const winrt::Windows::Foundation::TypedEventHandler<SenderT, ArgsT>& handler) { return _handlers.add(handler); }
|
||||
void operator()(const winrt::event_token& token) { _handlers.remove(token); }
|
||||
operator bool() const noexcept { return bool(_handlers); }
|
||||
template<typename... Arg>
|
||||
void raise(Arg const&... args)
|
||||
using delegate_type = ArgsT;
|
||||
using delegate_array = winrt::com_ptr<winrt::impl::event_array<delegate_type>>;
|
||||
|
||||
fused_event() = default;
|
||||
fused_event(const fused_event&) = delete;
|
||||
fused_event& operator=(const fused_event&) = delete;
|
||||
|
||||
fused_event(fused_event&& other)
|
||||
{
|
||||
_handlers(std::forward<decltype(args)>(args)...);
|
||||
const winrt::slim_lock_guard change_guard{ other.m_change };
|
||||
if (!other.m_targets)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const winrt::slim_lock_guard swap_guard{ other.m_swap };
|
||||
m_targets = std::move(other.m_targets);
|
||||
}
|
||||
winrt::event<winrt::Windows::Foundation::TypedEventHandler<SenderT, ArgsT>> _handlers;
|
||||
|
||||
fused_event& operator=(fused_event&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
const winrt::slim_lock_guard other_change_guard{ other.m_change };
|
||||
const winrt::slim_lock_guard other_swap_guard{ other.m_swap };
|
||||
const winrt::slim_lock_guard self_change_guard{ m_change };
|
||||
const winrt::slim_lock_guard self_swap_guard{ m_swap };
|
||||
m_targets = std::move(other.m_targets);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return m_targets != nullptr;
|
||||
}
|
||||
|
||||
winrt::event_token operator()(const delegate_type& delegate)
|
||||
{
|
||||
return add_agile(winrt::impl::make_agile_delegate(delegate));
|
||||
}
|
||||
|
||||
void operator()(const winrt::event_token token)
|
||||
{
|
||||
// Extends life of old targets array to release delegates outside of lock.
|
||||
delegate_array temp_targets;
|
||||
|
||||
{
|
||||
const winrt::slim_lock_guard change_guard{ m_change };
|
||||
|
||||
if (!m_targets)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t available_slots = m_targets->size() - 1;
|
||||
delegate_array new_targets;
|
||||
bool removed = false;
|
||||
|
||||
if (available_slots == 0)
|
||||
{
|
||||
if (get_token(*m_targets->begin()) == token)
|
||||
{
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_targets = winrt::impl::make_event_array<delegate_type>(available_slots);
|
||||
auto new_iterator = new_targets->begin();
|
||||
|
||||
for (delegate_type const& element : *m_targets)
|
||||
{
|
||||
if (!removed && token == get_token(element))
|
||||
{
|
||||
removed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (available_slots == 0)
|
||||
{
|
||||
WINRT_ASSERT(!removed);
|
||||
break;
|
||||
}
|
||||
|
||||
*new_iterator = element;
|
||||
++new_iterator;
|
||||
--available_slots;
|
||||
}
|
||||
}
|
||||
|
||||
if (removed)
|
||||
{
|
||||
const winrt::slim_lock_guard swap_guard{ m_swap };
|
||||
temp_targets = std::exchange(m_targets, std::move(new_targets));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Arg>
|
||||
void raise(const Arg&... args)
|
||||
{
|
||||
delegate_array temp_targets;
|
||||
|
||||
{
|
||||
const winrt::slim_lock_guard change_guard{ m_change };
|
||||
|
||||
if (!m_targets)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const winrt::slim_lock_guard swap_guard{ m_swap };
|
||||
temp_targets = std::move(m_targets);
|
||||
}
|
||||
|
||||
if (temp_targets)
|
||||
{
|
||||
for (const auto& element : *temp_targets)
|
||||
{
|
||||
if (!winrt::impl::invoke(element, args...))
|
||||
{
|
||||
operator()(get_token(element));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
WINRT_IMPL_NOINLINE winrt::event_token add_agile(delegate_type delegate)
|
||||
{
|
||||
winrt::event_token token;
|
||||
|
||||
// Extends life of old targets array to release delegates outside of lock.
|
||||
delegate_array temp_targets;
|
||||
|
||||
{
|
||||
const winrt::slim_lock_guard change_guard{ m_change };
|
||||
const auto size = !m_targets ? 0 : m_targets->size();
|
||||
auto new_targets = winrt::impl::make_event_array<delegate_type>(size + 1);
|
||||
|
||||
if (m_targets)
|
||||
{
|
||||
std::copy_n(m_targets->begin(), m_targets->size(), new_targets->begin());
|
||||
}
|
||||
|
||||
new_targets->back() = std::move(delegate);
|
||||
token = get_token(new_targets->back());
|
||||
|
||||
const winrt::slim_lock_guard swap_guard{ m_swap };
|
||||
temp_targets = std::exchange(m_targets, std::move(new_targets));
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
winrt::event_token get_token(delegate_type const& delegate) const noexcept
|
||||
{
|
||||
return winrt::event_token{ reinterpret_cast<int64_t>(WINRT_IMPL_EncodePointer(winrt::get_abi(delegate))) };
|
||||
}
|
||||
|
||||
delegate_array m_targets;
|
||||
winrt::slim_mutex m_swap;
|
||||
winrt::slim_mutex m_change;
|
||||
};
|
||||
|
||||
#endif
|
||||
#ifdef WINRT_Windows_UI_Xaml_Data_H
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace Microsoft::Console::Render
|
||||
TimerHandle _cursorBlinker;
|
||||
uint64_t _cursorBufferMutationId = 0;
|
||||
uint64_t _cursorCursorMutationId = 0; // Stupid name, but it's _cursor related and stores the cursor mutation id.
|
||||
til::enumset<InhibitionSource, uint8_t> _cursorVisibilityInhibitors;
|
||||
til::enumset<InhibitionSource, uint8_t> _cursorVisibilityInhibitors{ InhibitionSource::Host };
|
||||
til::enumset<InhibitionSource, uint8_t> _cursorBlinkingInhibitors;
|
||||
bool _cursorBlinkerOn = false;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user