mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-07 14:50:55 +00:00
Merge commit '6a10ea5' into dev/migrie/fhl/non-terminal-panes-2023
This commit is contained in:
1
.github/actions/spelling/expect/expect.txt
vendored
1
.github/actions/spelling/expect/expect.txt
vendored
@@ -2132,6 +2132,7 @@ WDDMCONSOLECONTEXT
|
||||
wdm
|
||||
webpage
|
||||
websites
|
||||
websockets
|
||||
wekyb
|
||||
wex
|
||||
wextest
|
||||
|
||||
@@ -174,6 +174,9 @@
|
||||
|
||||
<SolidColorBrush x:Key="SettingsUiTabBrush"
|
||||
Color="#0c0c0c" />
|
||||
|
||||
<SolidColorBrush x:Key="BroadcastPaneBorderColor"
|
||||
Color="{StaticResource SystemAccentColorDark2}" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="Light">
|
||||
@@ -190,6 +193,9 @@
|
||||
|
||||
<SolidColorBrush x:Key="SettingsUiTabBrush"
|
||||
Color="#ffffff" />
|
||||
|
||||
<SolidColorBrush x:Key="BroadcastPaneBorderColor"
|
||||
Color="{StaticResource SystemAccentColorLight2}" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
@@ -210,6 +216,9 @@
|
||||
|
||||
<StaticResource x:Key="SettingsUiTabBrush"
|
||||
ResourceKey="SystemControlBackgroundBaseLowBrush" />
|
||||
|
||||
<SolidColorBrush x:Key="BroadcastPaneBorderColor"
|
||||
Color="{StaticResource SystemColorHighlightColor}" />
|
||||
</ResourceDictionary>
|
||||
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
@@ -1272,6 +1272,17 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleToggleBroadcastInput(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (const auto activeTab{ _GetFocusedTabImpl() })
|
||||
{
|
||||
activeTab->ToggleBroadcastInput();
|
||||
args.Handled(true);
|
||||
}
|
||||
// If the focused tab wasn't a TerminalTab, then leave handled=false
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleRestartConnection(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
@@ -1301,4 +1312,5 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
args.Handled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -205,6 +205,13 @@
|
||||
Glyph=""
|
||||
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsReadOnlyActive, Mode=OneWay}" />
|
||||
|
||||
<FontIcon x:Name="HeaderBroadcastIcon"
|
||||
Margin="0,0,8,0"
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="12"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).IsInputBroadcastActive, Mode=OneWay}" />
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
@@ -1221,8 +1221,9 @@ void Pane::UpdateVisuals()
|
||||
{
|
||||
_UpdateBorders();
|
||||
}
|
||||
_borderFirst.BorderBrush(_lastActive ? _themeResources.focusedBorderBrush : _themeResources.unfocusedBorderBrush);
|
||||
_borderSecond.BorderBrush(_lastActive ? _themeResources.focusedBorderBrush : _themeResources.unfocusedBorderBrush);
|
||||
const auto& brush{ _ComputeBorderColor() };
|
||||
_borderFirst.BorderBrush(brush);
|
||||
_borderSecond.BorderBrush(brush);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -2963,3 +2964,79 @@ void Pane::CollectTaskbarStates(std::vector<winrt::TerminalApp::TaskbarState>& s
|
||||
_secondChild->CollectTaskbarStates(states);
|
||||
}
|
||||
}
|
||||
|
||||
void Pane::EnableBroadcast(bool enabled)
|
||||
{
|
||||
if (_IsLeaf())
|
||||
{
|
||||
_broadcastEnabled = enabled;
|
||||
UpdateVisuals();
|
||||
}
|
||||
else
|
||||
{
|
||||
_firstChild->EnableBroadcast(enabled);
|
||||
_secondChild->EnableBroadcast(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void Pane::BroadcastKey(const winrt::Microsoft::Terminal::Control::TermControl& sourceControl,
|
||||
const WORD vkey,
|
||||
const WORD scanCode,
|
||||
const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers,
|
||||
const bool keyDown)
|
||||
{
|
||||
WalkTree([&](const auto& pane) {
|
||||
if (const auto& termControl{ pane->GetTerminalControl() })
|
||||
{
|
||||
if (termControl != sourceControl && !termControl.ReadOnly())
|
||||
{
|
||||
termControl.RawWriteKeyEvent(vkey, scanCode, modifiers, keyDown);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Pane::BroadcastChar(const winrt::Microsoft::Terminal::Control::TermControl& sourceControl,
|
||||
const wchar_t character,
|
||||
const WORD scanCode,
|
||||
const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers)
|
||||
{
|
||||
WalkTree([&](const auto& pane) {
|
||||
if (const auto& termControl{ pane->GetTerminalControl() })
|
||||
{
|
||||
if (termControl != sourceControl && !termControl.ReadOnly())
|
||||
{
|
||||
termControl.RawWriteChar(character, scanCode, modifiers);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Pane::BroadcastString(const winrt::Microsoft::Terminal::Control::TermControl& sourceControl,
|
||||
const winrt::hstring& text)
|
||||
{
|
||||
WalkTree([&](const auto& pane) {
|
||||
if (const auto& termControl{ pane->GetTerminalControl() })
|
||||
{
|
||||
if (termControl != sourceControl && !termControl.ReadOnly())
|
||||
{
|
||||
termControl.RawWriteString(text);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::_ComputeBorderColor()
|
||||
{
|
||||
if (_lastActive)
|
||||
{
|
||||
return _themeResources.focusedBorderBrush;
|
||||
}
|
||||
|
||||
if (_broadcastEnabled && (_IsLeaf() && !_content.ReadOnly()))
|
||||
{
|
||||
return _themeResources.broadcastBorderBrush;
|
||||
}
|
||||
|
||||
return _themeResources.unfocusedBorderBrush;
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ struct PaneResources
|
||||
{
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush focusedBorderBrush{ nullptr };
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush unfocusedBorderBrush{ nullptr };
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush broadcastBorderBrush{ nullptr };
|
||||
};
|
||||
|
||||
class Pane : public std::enable_shared_from_this<Pane>
|
||||
@@ -147,6 +148,11 @@ public:
|
||||
|
||||
bool ContainsReadOnly() const;
|
||||
|
||||
void EnableBroadcast(bool enabled);
|
||||
void BroadcastKey(const winrt::Microsoft::Terminal::Control::TermControl& sourceControl, const WORD vkey, const WORD scanCode, const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown);
|
||||
void BroadcastChar(const winrt::Microsoft::Terminal::Control::TermControl& sourceControl, const wchar_t vkey, const WORD scanCode, const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers);
|
||||
void BroadcastString(const winrt::Microsoft::Terminal::Control::TermControl& sourceControl, const winrt::hstring& text);
|
||||
|
||||
void UpdateResources(const PaneResources& resources);
|
||||
|
||||
// Method Description:
|
||||
@@ -255,6 +261,7 @@ private:
|
||||
Borders _borders{ Borders::None };
|
||||
|
||||
bool _zoomed{ false };
|
||||
bool _broadcastEnabled{ false };
|
||||
|
||||
bool _IsLeaf() const noexcept;
|
||||
bool _HasFocusedChild() const noexcept;
|
||||
@@ -274,6 +281,7 @@ private:
|
||||
void _SetupEntranceAnimation();
|
||||
void _UpdateBorders();
|
||||
Borders _GetCommonBorders();
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush _ComputeBorderColor();
|
||||
|
||||
bool _Resize(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
|
||||
|
||||
|
||||
@@ -43,6 +43,12 @@
|
||||
FontSize="12"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind TabStatus.IsReadOnlyActive, Mode=OneWay}" />
|
||||
<FontIcon x:Name="HeaderBroadcastIcon"
|
||||
Margin="0,0,8,0"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="12"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind TabStatus.IsInputBroadcastActive, Mode=OneWay}" />
|
||||
<TextBlock x:Name="HeaderTextBlock"
|
||||
Text="{x:Bind Title, Mode=OneWay}"
|
||||
Visibility="Visible" />
|
||||
|
||||
@@ -2792,6 +2792,24 @@ namespace winrt::TerminalApp::implementation
|
||||
// - Paste text from the Windows Clipboard to the focused terminal
|
||||
void TerminalPage::_PasteText()
|
||||
{
|
||||
// First, check if we're in broadcast input mode. If so, let's tell all
|
||||
// the controls to paste.
|
||||
if (const auto& tab{ _GetFocusedTabImpl() })
|
||||
{
|
||||
if (tab->TabStatus().IsInputBroadcastActive())
|
||||
{
|
||||
tab->GetRootPane()->WalkTree([](auto&& pane) {
|
||||
if (auto control = pane->GetTerminalControl())
|
||||
{
|
||||
control.PasteTextFromClipboard();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The focused tab wasn't in broadcast mode. No matter. Just ask the
|
||||
// current one to paste.
|
||||
if (const auto& control{ _GetActiveControl() })
|
||||
{
|
||||
control.PasteTextFromClipboard();
|
||||
@@ -4578,6 +4596,21 @@ namespace winrt::TerminalApp::implementation
|
||||
// will eat focus.
|
||||
_paneResources.unfocusedBorderBrush = SolidColorBrush{ Colors::Black() };
|
||||
}
|
||||
|
||||
const auto broadcastColorKey = winrt::box_value(L"BroadcastPaneBorderColor");
|
||||
if (res.HasKey(broadcastColorKey))
|
||||
{
|
||||
// MAKE SURE TO USE ThemeLookup
|
||||
auto obj = ThemeLookup(res, requestedTheme, broadcastColorKey);
|
||||
_paneResources.broadcastBorderBrush = obj.try_as<winrt::Windows::UI::Xaml::Media::SolidColorBrush>();
|
||||
}
|
||||
else
|
||||
{
|
||||
// DON'T use Transparent here - if it's "Transparent", then it won't
|
||||
// be able to hittest for clicks, and then clicking on the border
|
||||
// will eat focus.
|
||||
_paneResources.broadcastBorderBrush = SolidColorBrush{ Colors::Black() };
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::WindowActivated(const bool activated)
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void _ControlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& /*args*/);
|
||||
void _ControlWarningBellHandler(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::Foundation::IInspectable& e);
|
||||
void _ControlReadOnlyChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& e);
|
||||
|
||||
void _controlTitleChanged(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||
void _controlTabColorChanged(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||
|
||||
@@ -515,6 +515,8 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
return false;
|
||||
});
|
||||
pane->EnableBroadcast(_tabStatus.IsInputBroadcastActive());
|
||||
|
||||
// Make sure to take the ID before calling Split() - Split() will clear out the active pane's ID
|
||||
const auto activePaneId = _activePane->Id();
|
||||
// Depending on which direction will be split, the new pane can be
|
||||
@@ -627,7 +629,7 @@ namespace winrt::TerminalApp::implementation
|
||||
_nextPaneId++;
|
||||
}
|
||||
});
|
||||
|
||||
pane->EnableBroadcast(_tabStatus.IsInputBroadcastActive());
|
||||
// pass the old id to the new child
|
||||
const auto previousId = _activePane->Id();
|
||||
|
||||
@@ -975,31 +977,14 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
});
|
||||
|
||||
// Add a PaneRaiseBell event handler to the Pane
|
||||
events.BellRequested = content.BellRequested(
|
||||
winrt::auto_revoke,
|
||||
[weakThis](auto&& /*s*/, auto&& args) {
|
||||
if (auto tab{ weakThis.get() })
|
||||
{
|
||||
if (args.FlashTaskbar())
|
||||
{
|
||||
// If visual is set, we need to bubble this event all the way to app host to flash the taskbar
|
||||
// In this part of the chain we bubble it from the hosting tab to the page
|
||||
tab->_TabRaiseVisualBellHandlers();
|
||||
}
|
||||
if (_tabStatus.IsInputBroadcastActive())
|
||||
{
|
||||
if (const auto& termContent{ content.try_as<TerminalApp::TerminalPaneContent>() })
|
||||
{
|
||||
_addBroadcastHandlers(termContent.GetTerminal(), events);
|
||||
|
||||
// Show the bell indicator in the tab header
|
||||
tab->ShowBellIndicator(true);
|
||||
|
||||
// If this tab is focused, activate the bell indicator timer, which will
|
||||
// remove the bell indicator once it fires
|
||||
// (otherwise, the indicator is removed when the tab gets focus)
|
||||
if (tab->_focusState != WUX::FocusState::Unfocused)
|
||||
{
|
||||
tab->ActivateBellIndicatorTimer();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_contentEvents[paneId] = std::move(events);
|
||||
}
|
||||
@@ -1743,6 +1728,10 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
ReadOnly(_rootPane->ContainsReadOnly());
|
||||
TabViewItem().IsClosable(!ReadOnly());
|
||||
|
||||
// Update all the visuals on all our panes, so they can update their
|
||||
// border colors accordingly.
|
||||
_rootPane->WalkTree([](const auto& p) { p->UpdateVisuals(); });
|
||||
}
|
||||
|
||||
std::shared_ptr<Pane> TerminalTab::GetActivePane() const
|
||||
@@ -1772,4 +1761,88 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
return Title();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Toggle broadcasting input to all the panes in this tab.
|
||||
void TerminalTab::ToggleBroadcastInput()
|
||||
{
|
||||
const bool newIsBroadcasting = !_tabStatus.IsInputBroadcastActive();
|
||||
_tabStatus.IsInputBroadcastActive(newIsBroadcasting);
|
||||
_rootPane->EnableBroadcast(newIsBroadcasting);
|
||||
|
||||
auto weakThis{ get_weak() };
|
||||
|
||||
// When we change the state of broadcasting, add or remove event
|
||||
// handlers appropriately, so that controls won't be propagating events
|
||||
// needlessly if no one is listening.
|
||||
|
||||
_rootPane->WalkTree([&](const auto& p) {
|
||||
const auto paneId = p->Id();
|
||||
if (!paneId.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (const auto& control{ p->GetTerminalControl() })
|
||||
{
|
||||
auto it = _contentEvents.find(*paneId);
|
||||
if (it != _contentEvents.end())
|
||||
{
|
||||
auto& events = it->second;
|
||||
|
||||
// Always clear out old ones, just in case.
|
||||
events.KeySent.revoke();
|
||||
events.CharSent.revoke();
|
||||
events.StringSent.revoke();
|
||||
|
||||
if (newIsBroadcasting)
|
||||
{
|
||||
_addBroadcastHandlers(control, events);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void TerminalTab::_addBroadcastHandlers(const TermControl& termControl, ContentEventTokens& events)
|
||||
{
|
||||
auto weakThis{ get_weak() };
|
||||
// ADD EVENT HANDLERS HERE
|
||||
events.KeySent = termControl.KeySent(winrt::auto_revoke, [weakThis](auto&& sender, auto&& e) {
|
||||
if (const auto tab{ weakThis.get() })
|
||||
{
|
||||
if (tab->_tabStatus.IsInputBroadcastActive())
|
||||
{
|
||||
tab->_rootPane->BroadcastKey(sender.try_as<TermControl>(),
|
||||
e.VKey(),
|
||||
e.ScanCode(),
|
||||
e.Modifiers(),
|
||||
e.KeyDown());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
events.CharSent = termControl.CharSent(winrt::auto_revoke, [weakThis](auto&& sender, auto&& e) {
|
||||
if (const auto tab{ weakThis.get() })
|
||||
{
|
||||
if (tab->_tabStatus.IsInputBroadcastActive())
|
||||
{
|
||||
tab->_rootPane->BroadcastChar(sender.try_as<TermControl>(),
|
||||
e.Character(),
|
||||
e.ScanCode(),
|
||||
e.Modifiers());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
events.StringSent = termControl.StringSent(winrt::auto_revoke, [weakThis](auto&& sender, auto&& e) {
|
||||
if (const auto tab{ weakThis.get() })
|
||||
{
|
||||
if (tab->_tabStatus.IsInputBroadcastActive())
|
||||
{
|
||||
tab->_rootPane->BroadcastString(sender.try_as<TermControl>(),
|
||||
e.Text());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void TogglePaneReadOnly();
|
||||
void SetPaneReadOnly(const bool readOnlyState);
|
||||
void ToggleBroadcastInput();
|
||||
|
||||
std::shared_ptr<Pane> GetActivePane() const;
|
||||
winrt::TerminalApp::TaskbarState GetCombinedTaskbarState() const;
|
||||
@@ -134,6 +135,11 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::TerminalApp::IPaneContent::TaskbarProgressChanged_revoker TaskbarProgressChanged;
|
||||
winrt::TerminalApp::IPaneContent::ReadOnlyChanged_revoker ReadOnlyChanged;
|
||||
winrt::TerminalApp::IPaneContent::FocusRequested_revoker FocusRequested;
|
||||
|
||||
// These events literally only apply if the content is a TermControl.
|
||||
winrt::Microsoft::Terminal::Control::TermControl::KeySent_revoker KeySent;
|
||||
winrt::Microsoft::Terminal::Control::TermControl::CharSent_revoker CharSent;
|
||||
winrt::Microsoft::Terminal::Control::TermControl::StringSent_revoker StringSent;
|
||||
};
|
||||
std::unordered_map<uint32_t, ContentEventTokens> _contentEvents;
|
||||
|
||||
@@ -180,6 +186,8 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
virtual winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush() override;
|
||||
|
||||
void _addBroadcastHandlers(const winrt::Microsoft::Terminal::Control::TermControl& control, ContentEventTokens& events);
|
||||
|
||||
friend class ::TerminalAppLocalTests::TabTests;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace winrt::TerminalApp::implementation
|
||||
WINRT_OBSERVABLE_PROPERTY(bool, BellIndicator, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(bool, IsReadOnlyActive, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(uint32_t, ProgressValue, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(bool, IsInputBroadcastActive, _PropertyChangedHandlers);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -13,5 +13,6 @@ namespace TerminalApp
|
||||
Boolean BellIndicator { get; set; };
|
||||
UInt32 ProgressValue { get; set; };
|
||||
Boolean IsReadOnlyActive { get; set; };
|
||||
Boolean IsInputBroadcastActive { get; set; };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,3 +15,6 @@
|
||||
#include "FoundResultsArgs.g.cpp"
|
||||
#include "ShowWindowArgs.g.cpp"
|
||||
#include "UpdateSelectionMarkersEventArgs.g.cpp"
|
||||
#include "KeySentEventArgs.g.cpp"
|
||||
#include "CharSentEventArgs.g.cpp"
|
||||
#include "StringSentEventArgs.g.cpp"
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#include "FoundResultsArgs.g.h"
|
||||
#include "ShowWindowArgs.g.h"
|
||||
#include "UpdateSelectionMarkersEventArgs.g.h"
|
||||
#include "KeySentEventArgs.g.h"
|
||||
#include "CharSentEventArgs.g.h"
|
||||
#include "StringSentEventArgs.g.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
@@ -179,6 +182,43 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
WINRT_PROPERTY(bool, ClearMarkers, false);
|
||||
};
|
||||
|
||||
struct KeySentEventArgs : public KeySentEventArgsT<KeySentEventArgs>
|
||||
{
|
||||
public:
|
||||
KeySentEventArgs(const WORD vkey, const WORD scanCode, const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown) :
|
||||
_VKey(vkey),
|
||||
_ScanCode(scanCode),
|
||||
_Modifiers(modifiers),
|
||||
_KeyDown(keyDown) {}
|
||||
|
||||
WINRT_PROPERTY(WORD, VKey);
|
||||
WINRT_PROPERTY(WORD, ScanCode);
|
||||
WINRT_PROPERTY(winrt::Microsoft::Terminal::Core::ControlKeyStates, Modifiers);
|
||||
WINRT_PROPERTY(bool, KeyDown, false);
|
||||
};
|
||||
|
||||
struct CharSentEventArgs : public CharSentEventArgsT<CharSentEventArgs>
|
||||
{
|
||||
public:
|
||||
CharSentEventArgs(const wchar_t character, const WORD scanCode, const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers) :
|
||||
_Character(character),
|
||||
_ScanCode(scanCode),
|
||||
_Modifiers(modifiers) {}
|
||||
|
||||
WINRT_PROPERTY(wchar_t, Character);
|
||||
WINRT_PROPERTY(WORD, ScanCode);
|
||||
WINRT_PROPERTY(winrt::Microsoft::Terminal::Core::ControlKeyStates, Modifiers);
|
||||
};
|
||||
|
||||
struct StringSentEventArgs : public StringSentEventArgsT<StringSentEventArgs>
|
||||
{
|
||||
public:
|
||||
StringSentEventArgs(const winrt::hstring& text) :
|
||||
_Text(text) {}
|
||||
|
||||
WINRT_PROPERTY(winrt::hstring, Text);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::factory_implementation
|
||||
|
||||
@@ -89,4 +89,24 @@ namespace Microsoft.Terminal.Control
|
||||
{
|
||||
Boolean ClearMarkers { get; };
|
||||
}
|
||||
|
||||
runtimeclass KeySentEventArgs
|
||||
{
|
||||
UInt16 VKey { get; };
|
||||
UInt16 ScanCode { get; };
|
||||
Microsoft.Terminal.Core.ControlKeyStates Modifiers { get; };
|
||||
Boolean KeyDown { get; };
|
||||
}
|
||||
|
||||
runtimeclass CharSentEventArgs
|
||||
{
|
||||
Char Character { get; };
|
||||
UInt16 ScanCode { get; };
|
||||
Microsoft.Terminal.Core.ControlKeyStates Modifiers { get; };
|
||||
}
|
||||
|
||||
runtimeclass StringSentEventArgs
|
||||
{
|
||||
String Text { get; };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,7 +524,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - <none>
|
||||
void TermControl::SendInput(const winrt::hstring& wstr)
|
||||
{
|
||||
_core.SendInput(wstr);
|
||||
// only broadcast if there's an actual listener. Saves the overhead of some object creation.
|
||||
if (_StringSentHandlers)
|
||||
{
|
||||
_StringSentHandlers(*this, winrt::make<StringSentEventArgs>(wstr));
|
||||
}
|
||||
|
||||
RawWriteString(wstr);
|
||||
}
|
||||
void TermControl::ClearBuffer(Control::ClearBufferType clearType)
|
||||
{
|
||||
@@ -1083,10 +1089,31 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
modifiers |= ControlKeyStates::EnhancedKey;
|
||||
}
|
||||
|
||||
const auto handled = _core.SendCharEvent(ch, scanCode, modifiers);
|
||||
// Broadcast the character to all listeners
|
||||
// only broadcast if there's an actual listener. Saves the overhead of some object creation.
|
||||
if (_CharSentHandlers)
|
||||
{
|
||||
auto charSentArgs = winrt::make<CharSentEventArgs>(ch, scanCode, modifiers);
|
||||
_CharSentHandlers(*this, charSentArgs);
|
||||
}
|
||||
|
||||
const auto handled = RawWriteChar(ch, scanCode, modifiers);
|
||||
|
||||
e.Handled(handled);
|
||||
}
|
||||
|
||||
bool TermControl::RawWriteChar(const wchar_t character,
|
||||
const WORD scanCode,
|
||||
const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers)
|
||||
{
|
||||
return _core.SendCharEvent(character, scanCode, modifiers);
|
||||
}
|
||||
|
||||
void TermControl::RawWriteString(const winrt::hstring& text)
|
||||
{
|
||||
_core.SendInput(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.
|
||||
@@ -1333,6 +1360,22 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
const WORD scanCode,
|
||||
const ControlKeyStates modifiers,
|
||||
const bool keyDown)
|
||||
{
|
||||
// Broadcast the key to all listeners
|
||||
// only broadcast if there's an actual listener. Saves the overhead of some object creation.
|
||||
if (_KeySentHandlers)
|
||||
{
|
||||
auto keySentArgs = winrt::make<KeySentEventArgs>(vkey, scanCode, modifiers, keyDown);
|
||||
_KeySentHandlers(*this, keySentArgs);
|
||||
}
|
||||
|
||||
return RawWriteKeyEvent(vkey, scanCode, modifiers, keyDown);
|
||||
}
|
||||
|
||||
bool TermControl::RawWriteKeyEvent(const WORD vkey,
|
||||
const WORD scanCode,
|
||||
const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers,
|
||||
const bool keyDown)
|
||||
{
|
||||
const auto window = CoreWindow::GetForCurrentThread();
|
||||
|
||||
@@ -2587,7 +2630,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return;
|
||||
}
|
||||
|
||||
_core.SendInput(text);
|
||||
// SendInput will take care of broadcasting for us.
|
||||
SendInput(text);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -2666,7 +2710,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
try
|
||||
{
|
||||
auto link{ co_await e.DataView().GetApplicationLinkAsync() };
|
||||
_core.PasteText(link.AbsoluteUri());
|
||||
_pasteTextWithBroadcast(link.AbsoluteUri());
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
@@ -2675,7 +2719,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
try
|
||||
{
|
||||
auto link{ co_await e.DataView().GetWebLinkAsync() };
|
||||
_core.PasteText(link.AbsoluteUri());
|
||||
_pasteTextWithBroadcast(link.AbsoluteUri());
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
@@ -2684,7 +2728,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
try
|
||||
{
|
||||
auto text{ co_await e.DataView().GetTextAsync() };
|
||||
_core.PasteText(text);
|
||||
_pasteTextWithBroadcast(text);
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
@@ -2812,11 +2856,27 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
allPathsString += fullPath;
|
||||
}
|
||||
|
||||
_core.PasteText(winrt::hstring{ allPathsString });
|
||||
_pasteTextWithBroadcast(winrt::hstring{ allPathsString });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Paste this text, and raise a StringSent, to potentially broadcast this
|
||||
// text to other controls in the app. For certain interactions, like
|
||||
// drag/dropping a file, we want to act like we "pasted" the text (even if
|
||||
// the text didn't come from the clipboard). This lets those interactions
|
||||
// broadcast as well.
|
||||
void TermControl::_pasteTextWithBroadcast(const winrt::hstring& text)
|
||||
{
|
||||
// only broadcast if there's an actual listener. Saves the overhead of some object creation.
|
||||
if (_StringSentHandlers)
|
||||
{
|
||||
_StringSentHandlers(*this, winrt::make<StringSentEventArgs>(text));
|
||||
}
|
||||
_core.PasteText(text);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Handle the DragOver event. We'll signal that the drag operation we
|
||||
// support is the "copy" operation, and we'll also customize the
|
||||
|
||||
@@ -146,6 +146,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void AdjustOpacity(const double opacity, const bool relative);
|
||||
|
||||
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 ShowContextMenu();
|
||||
|
||||
void Detach();
|
||||
@@ -180,7 +184,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
TYPED_EVENT(FocusFollowMouseRequested, IInspectable, IInspectable);
|
||||
TYPED_EVENT(Initialized, Control::TermControl, Windows::UI::Xaml::RoutedEventArgs);
|
||||
TYPED_EVENT(WarningBell, IInspectable, IInspectable);
|
||||
|
||||
TYPED_EVENT(KeySent, IInspectable, Control::KeySentEventArgs);
|
||||
TYPED_EVENT(CharSent, IInspectable, Control::CharSentEventArgs);
|
||||
TYPED_EVENT(StringSent, IInspectable, Control::StringSentEventArgs);
|
||||
// clang-format on
|
||||
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::Windows::UI::Xaml::Media::Brush, BackgroundBrush, _PropertyChangedHandlers, nullptr);
|
||||
@@ -355,6 +361,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
til::point _toPosInDips(const Core::Point terminalCellPos);
|
||||
void _throttledUpdateScrollbar(const ScrollBarUpdate& update);
|
||||
|
||||
void _pasteTextWithBroadcast(const winrt::hstring& text);
|
||||
|
||||
void _contextMenuHandler(IInspectable sender, Control::ContextMenuRequestedEventArgs args);
|
||||
void _showContextMenuAt(const til::point& controlRelativePos);
|
||||
|
||||
|
||||
@@ -53,6 +53,9 @@ namespace Microsoft.Terminal.Control
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TabColorChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ReadOnlyChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FocusFollowMouseRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, KeySentEventArgs> KeySent;
|
||||
event Windows.Foundation.TypedEventHandler<Object, CharSentEventArgs> CharSent;
|
||||
event Windows.Foundation.TypedEventHandler<Object, StringSentEventArgs> StringSent;
|
||||
|
||||
Microsoft.UI.Xaml.Controls.CommandBarFlyout ContextMenu { get; };
|
||||
Microsoft.UI.Xaml.Controls.CommandBarFlyout SelectionContextMenu { get; };
|
||||
@@ -94,6 +97,9 @@ namespace Microsoft.Terminal.Control
|
||||
|
||||
void ToggleShaderEffects();
|
||||
void SendInput(String input);
|
||||
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 BellLightOn();
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ static constexpr std::string_view ColorSelectionKey{ "experimental.colorSelectio
|
||||
static constexpr std::string_view ShowContextMenuKey{ "showContextMenu" };
|
||||
static constexpr std::string_view ExpandSelectionToWordKey{ "expandSelectionToWord" };
|
||||
static constexpr std::string_view RestartConnectionKey{ "restartConnection" };
|
||||
static constexpr std::string_view ToggleBroadcastInputKey{ "toggleBroadcastInput" };
|
||||
|
||||
static constexpr std::string_view ActionKey{ "action" };
|
||||
|
||||
@@ -424,6 +425,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{ ShortcutAction::ShowContextMenu, RS_(L"ShowContextMenuCommandKey") },
|
||||
{ ShortcutAction::ExpandSelectionToWord, RS_(L"ExpandSelectionToWordCommandKey") },
|
||||
{ ShortcutAction::RestartConnection, RS_(L"RestartConnectionKey") },
|
||||
{ ShortcutAction::ToggleBroadcastInput, RS_(L"ToggleBroadcastInputCommandKey") },
|
||||
};
|
||||
}();
|
||||
|
||||
|
||||
@@ -106,7 +106,8 @@
|
||||
ON_ALL_ACTIONS(ShowContextMenu) \
|
||||
ON_ALL_ACTIONS(ExpandSelectionToWord) \
|
||||
ON_ALL_ACTIONS(CloseOtherPanes) \
|
||||
ON_ALL_ACTIONS(RestartConnection)
|
||||
ON_ALL_ACTIONS(RestartConnection) \
|
||||
ON_ALL_ACTIONS(ToggleBroadcastInput)
|
||||
|
||||
#define ALL_SHORTCUT_ACTIONS_WITH_ARGS \
|
||||
ON_ALL_ACTIONS_WITH_ARGS(AdjustFontSize) \
|
||||
|
||||
@@ -684,6 +684,10 @@
|
||||
<data name="CloseOtherPanesCommandKey" xml:space="preserve">
|
||||
<value>Close all other panes</value>
|
||||
</data>
|
||||
<data name="ToggleBroadcastInputCommandKey" xml:space="preserve">
|
||||
<value>Toggle broadcast input to all panes</value>
|
||||
<comment>When enabled, input will go to all panes in this tab simultaneously</comment>
|
||||
</data>
|
||||
<data name="RestartConnectionKey" xml:space="preserve">
|
||||
<value>Restart connection</value>
|
||||
</data>
|
||||
|
||||
Reference in New Issue
Block a user