I really shouldn't be doing the throttledfunc thing in this PR
This commit is contained in:
parent
d615ece8c8
commit
04b751faa7
|
@ -23,16 +23,6 @@ using namespace winrt::Windows::Graphics::Display;
|
||||||
using namespace winrt::Windows::System;
|
using namespace winrt::Windows::System;
|
||||||
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
using namespace winrt::Windows::ApplicationModel::DataTransfer;
|
||||||
|
|
||||||
// The minimum delay between updates to the scroll bar's values.
|
|
||||||
// The updates are throttled to limit power usage.
|
|
||||||
constexpr const auto ScrollBarUpdateInterval = std::chrono::milliseconds(8);
|
|
||||||
|
|
||||||
// The minimum delay between updating the TSF input control.
|
|
||||||
constexpr const auto TsfRedrawInterval = std::chrono::milliseconds(100);
|
|
||||||
|
|
||||||
// The minimum delay between updating the locations of regex patterns
|
|
||||||
constexpr const auto UpdatePatternLocationsInterval = std::chrono::milliseconds(500);
|
|
||||||
|
|
||||||
namespace winrt::Microsoft::Terminal::Control::implementation
|
namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
{
|
{
|
||||||
// Helper static function to ensure that all ambiguous-width glyphs are reported as narrow.
|
// Helper static function to ensure that all ambiguous-width glyphs are reported as narrow.
|
||||||
|
@ -104,61 +94,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
auto pfnTerminalTaskbarProgressChanged = std::bind(&ControlCore::_terminalTaskbarProgressChanged, this);
|
auto pfnTerminalTaskbarProgressChanged = std::bind(&ControlCore::_terminalTaskbarProgressChanged, this);
|
||||||
_terminal->TaskbarProgressChangedCallback(pfnTerminalTaskbarProgressChanged);
|
_terminal->TaskbarProgressChangedCallback(pfnTerminalTaskbarProgressChanged);
|
||||||
|
|
||||||
// Get our dispatcher. If we're hosted in-proc with XAML, this will get
|
|
||||||
// us the same dispatcher as TermControl::Dispatcher(). If we're out of
|
|
||||||
// proc, this'll return null. We'll need to instead make a new
|
|
||||||
// DispatcherQueue (on a new thread), so we can use that for throttled
|
|
||||||
// functions.
|
|
||||||
_dispatcher = winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
|
|
||||||
if (!_dispatcher)
|
|
||||||
{
|
|
||||||
auto controller{ winrt::Windows::System::DispatcherQueueController::CreateOnDedicatedThread() };
|
|
||||||
_dispatcher = controller.DispatcherQueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
// A few different events should be throttled, so they don't fire absolutely all the time:
|
|
||||||
// * _tsfTryRedrawCanvas: When the cursor position moves, we need to
|
|
||||||
// inform TSF, so it can move the canvas for the composition. We
|
|
||||||
// throttle this so that we're not hopping across the process boundary
|
|
||||||
// every time that the cursor moves.
|
|
||||||
// * _updatePatternLocations: When there's new output, or we scroll the
|
|
||||||
// viewport, we should re-check if there are any visible hyperlinks.
|
|
||||||
// But we don't really need to do this every single time text is
|
|
||||||
// output, we can limit this update to once every 500ms.
|
|
||||||
// * _updateScrollBar: Same idea as the TSF update - we don't _really_
|
|
||||||
// need to hop across the process boundary every time text is output.
|
|
||||||
// We can throttle this to once every 8ms, which will get us out of
|
|
||||||
// the way of the main output & rendering threads.
|
|
||||||
_tsfTryRedrawCanvas = std::make_shared<ThrottledFuncTrailing<winrt::Windows::System::DispatcherQueue>>(
|
|
||||||
_dispatcher,
|
|
||||||
TsfRedrawInterval,
|
|
||||||
[weakThis = get_weak()]() {
|
|
||||||
if (auto core{ weakThis.get() })
|
|
||||||
{
|
|
||||||
core->_CursorPositionChangedHandlers(*core, nullptr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_updatePatternLocations = std::make_shared<ThrottledFuncTrailing<winrt::Windows::System::DispatcherQueue>>(
|
|
||||||
_dispatcher,
|
|
||||||
UpdatePatternLocationsInterval,
|
|
||||||
[weakThis = get_weak()]() {
|
|
||||||
if (auto core{ weakThis.get() })
|
|
||||||
{
|
|
||||||
core->UpdatePatternLocations();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_updateScrollBar = std::make_shared<ThrottledFuncTrailing<winrt::Windows::System::DispatcherQueue, Control::ScrollPositionChangedArgs>>(
|
|
||||||
_dispatcher,
|
|
||||||
ScrollBarUpdateInterval,
|
|
||||||
[weakThis = get_weak()](const auto& update) {
|
|
||||||
if (auto core{ weakThis.get() })
|
|
||||||
{
|
|
||||||
core->_ScrollPositionChangedHandlers(*core, update);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
UpdateSettings(settings);
|
UpdateSettings(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1141,21 +1076,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
// TODO GH#9617: refine locking around pattern tree
|
// TODO GH#9617: refine locking around pattern tree
|
||||||
_terminal->ClearPatternTree();
|
_terminal->ClearPatternTree();
|
||||||
|
|
||||||
// Start the throttled update of our scrollbar.
|
_ScrollPositionChangedHandlers(*this,
|
||||||
auto update{ winrt::make<ScrollPositionChangedArgs>(viewTop,
|
winrt::make<ScrollPositionChangedArgs>(viewTop,
|
||||||
viewHeight,
|
viewHeight,
|
||||||
bufferSize) };
|
bufferSize));
|
||||||
_updateScrollBar->Run(update);
|
|
||||||
|
|
||||||
// Additionally, start the throttled update of where our links are.
|
|
||||||
_updatePatternLocations->Run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControlCore::_terminalCursorPositionChanged()
|
void ControlCore::_terminalCursorPositionChanged()
|
||||||
{
|
{
|
||||||
// When the buffer's cursor moves, start the throttled func to
|
_CursorPositionChangedHandlers(*this, nullptr);
|
||||||
// eventually dispatch a CursorPositionChanged event.
|
|
||||||
_tsfTryRedrawCanvas->Run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControlCore::_terminalTaskbarProgressChanged()
|
void ControlCore::_terminalTaskbarProgressChanged()
|
||||||
|
@ -1443,8 +1372,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
{
|
{
|
||||||
_terminal->Write(hstr);
|
_terminal->Write(hstr);
|
||||||
|
|
||||||
// Start the throttled update of where our hyperlinks are.
|
// NOTE: We're raising an event here to inform the TermControl that
|
||||||
_updatePatternLocations->Run();
|
// output has been received, so it can queue up a throttled
|
||||||
|
// UpdatePatternLocations call. In the future, we should have the
|
||||||
|
// _updatePatternLocations ThrottledFunc internal to this class, and
|
||||||
|
// run on this object's dispatcher queue.
|
||||||
|
//
|
||||||
|
// We're not doing that quite yet, because the Core will eventually
|
||||||
|
// be out-of-proc from the UI thread, and won't be able to just use
|
||||||
|
// the UI thread as the dispatcher queue thread.
|
||||||
|
//
|
||||||
|
// See TODO: https://github.com/microsoft/terminal/projects/5#card-50760282
|
||||||
|
_ReceivedOutputHandlers(*this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,11 +207,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
double _panelHeight{ 0 };
|
double _panelHeight{ 0 };
|
||||||
double _compositionScale{ 0 };
|
double _compositionScale{ 0 };
|
||||||
|
|
||||||
winrt::Windows::System::DispatcherQueue _dispatcher{ nullptr };
|
|
||||||
std::shared_ptr<ThrottledFuncTrailing<winrt::Windows::System::DispatcherQueue>> _tsfTryRedrawCanvas;
|
|
||||||
std::shared_ptr<ThrottledFuncTrailing<winrt::Windows::System::DispatcherQueue>> _updatePatternLocations;
|
|
||||||
std::shared_ptr<ThrottledFuncTrailing<winrt::Windows::System::DispatcherQueue, Control::ScrollPositionChangedArgs>> _updateScrollBar;
|
|
||||||
|
|
||||||
winrt::fire_and_forget _asyncCloseConnection();
|
winrt::fire_and_forget _asyncCloseConnection();
|
||||||
|
|
||||||
void _setFontSize(int fontSize);
|
void _setFontSize(int fontSize);
|
||||||
|
|
|
@ -67,6 +67,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
_interactivity = winrt::make<implementation::ControlInteractivity>(settings, connection);
|
_interactivity = winrt::make<implementation::ControlInteractivity>(settings, connection);
|
||||||
_core = _interactivity.Core();
|
_core = _interactivity.Core();
|
||||||
|
|
||||||
|
// Use a manual revoker on the output event, so we can immediately stop
|
||||||
|
// worrying about it on destruction.
|
||||||
|
_coreOutputEventToken = _core.ReceivedOutput({ this, &TermControl::_coreReceivedOutput });
|
||||||
|
|
||||||
// These events might all be triggered by the connection, but that
|
// These events might all be triggered by the connection, but that
|
||||||
// should be drained and closed before we complete destruction. So these
|
// should be drained and closed before we complete destruction. So these
|
||||||
// are safe.
|
// are safe.
|
||||||
|
@ -108,7 +112,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
// Core eventually won't have access to. When we get to
|
// Core eventually won't have access to. When we get to
|
||||||
// https://github.com/microsoft/terminal/projects/5#card-50760282
|
// https://github.com/microsoft/terminal/projects/5#card-50760282
|
||||||
// then we'll move the applicable ones.
|
// then we'll move the applicable ones.
|
||||||
_tsfTryRedrawCanvas = std::make_shared<ThrottledFuncTrailing<winrt::Windows::UI::Core::CoreDispatcher>>(
|
_tsfTryRedrawCanvas = std::make_shared<ThrottledFuncTrailing<>>(
|
||||||
Dispatcher(),
|
Dispatcher(),
|
||||||
TsfRedrawInterval,
|
TsfRedrawInterval,
|
||||||
[weakThis = get_weak()]() {
|
[weakThis = get_weak()]() {
|
||||||
|
@ -118,7 +122,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_playWarningBell = std::make_shared<ThrottledFuncLeading<winrt::Windows::UI::Core::CoreDispatcher>>(
|
_updatePatternLocations = std::make_shared<ThrottledFuncTrailing<>>(
|
||||||
|
Dispatcher(),
|
||||||
|
UpdatePatternLocationsInterval,
|
||||||
|
[weakThis = get_weak()]() {
|
||||||
|
if (auto control{ weakThis.get() })
|
||||||
|
{
|
||||||
|
control->_core.UpdatePatternLocations();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_playWarningBell = std::make_shared<ThrottledFuncLeading>(
|
||||||
Dispatcher(),
|
Dispatcher(),
|
||||||
TerminalWarningBellInterval,
|
TerminalWarningBellInterval,
|
||||||
[weakThis = get_weak()]() {
|
[weakThis = get_weak()]() {
|
||||||
|
@ -128,7 +142,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_updateScrollBar = std::make_shared<ThrottledFuncTrailing<winrt::Windows::UI::Core::CoreDispatcher, ScrollBarUpdate>>(
|
_updateScrollBar = std::make_shared<ThrottledFuncTrailing<ScrollBarUpdate>>(
|
||||||
Dispatcher(),
|
Dispatcher(),
|
||||||
ScrollBarUpdateInterval,
|
ScrollBarUpdateInterval,
|
||||||
[weakThis = get_weak()](const auto& update) {
|
[weakThis = get_weak()](const auto& update) {
|
||||||
|
@ -530,7 +544,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
{
|
{
|
||||||
// create a custom automation peer with this code pattern:
|
// create a custom automation peer with this code pattern:
|
||||||
// (https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/custom-automation-peers)
|
// (https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/custom-automation-peers)
|
||||||
if (const auto& interactivityAutoPeer{ _interactivity.OnCreateAutomationPeer() })
|
if (const auto& interactivityAutoPeer = _interactivity.OnCreateAutomationPeer())
|
||||||
{
|
{
|
||||||
auto autoPeer = winrt::make_self<implementation::TermControlAutomationPeer>(this, interactivityAutoPeer);
|
auto autoPeer = winrt::make_self<implementation::TermControlAutomationPeer>(this, interactivityAutoPeer);
|
||||||
_automationPeer = *autoPeer;
|
_automationPeer = *autoPeer;
|
||||||
|
@ -1249,6 +1263,23 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
CATCH_LOG();
|
CATCH_LOG();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TermControl::_coreReceivedOutput(const IInspectable& /*sender*/,
|
||||||
|
const IInspectable& /*args*/)
|
||||||
|
{
|
||||||
|
// Queue up a throttled UpdatePatternLocations call. In the future, we
|
||||||
|
// should have the _updatePatternLocations ThrottledFunc internal to
|
||||||
|
// ControlCore, and run on that object's dispatcher queue.
|
||||||
|
//
|
||||||
|
// We're not doing that quite yet, because the Core will eventually
|
||||||
|
// be out-of-proc from the UI thread, and won't be able to just use
|
||||||
|
// the UI thread as the dispatcher queue thread.
|
||||||
|
//
|
||||||
|
// THIS IS CALLED ON EVERY STRING OF TEXT OUTPUT TO THE TERMINAL. Think
|
||||||
|
// twice before adding anything here.
|
||||||
|
|
||||||
|
_updatePatternLocations->Run();
|
||||||
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Reset the font size of the terminal to its default size.
|
// - Reset the font size of the terminal to its default size.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
@ -1286,6 +1317,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
_updateScrollBar->ModifyPending([](auto& update) {
|
_updateScrollBar->ModifyPending([](auto& update) {
|
||||||
update.newValue.reset();
|
update.newValue.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_updatePatternLocations->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -1623,6 +1656,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
update.newValue = args.ViewTop();
|
update.newValue = args.ViewTop();
|
||||||
|
|
||||||
_updateScrollBar->Run(update);
|
_updateScrollBar->Run(update);
|
||||||
|
_updatePatternLocations->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
@ -1697,6 +1731,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
// has run, we should disconnect them *right now*. If we don't, they may fire between the
|
// has run, we should disconnect them *right now*. If we don't, they may fire between the
|
||||||
// throttle delay (from the final output) and the dtor.
|
// throttle delay (from the final output) and the dtor.
|
||||||
_tsfTryRedrawCanvas.reset();
|
_tsfTryRedrawCanvas.reset();
|
||||||
|
_updatePatternLocations.reset();
|
||||||
_updateScrollBar.reset();
|
_updateScrollBar.reset();
|
||||||
_playWarningBell.reset();
|
_playWarningBell.reset();
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
{
|
{
|
||||||
TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection);
|
TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection);
|
||||||
|
|
||||||
static Control::TermControl FromConnectionInfo(IControlSettings settings, TerminalConnection::ConnectionInformation connectInfo);
|
|
||||||
|
|
||||||
winrt::fire_and_forget UpdateSettings();
|
winrt::fire_and_forget UpdateSettings();
|
||||||
winrt::fire_and_forget UpdateAppearance(const IControlAppearance newAppearance);
|
winrt::fire_and_forget UpdateAppearance(const IControlAppearance newAppearance);
|
||||||
|
|
||||||
|
@ -156,8 +154,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
bool _focused;
|
bool _focused;
|
||||||
bool _initializedTerminal;
|
bool _initializedTerminal;
|
||||||
|
|
||||||
std::shared_ptr<ThrottledFuncTrailing<winrt::Windows::UI::Core::CoreDispatcher>> _tsfTryRedrawCanvas;
|
std::shared_ptr<ThrottledFuncTrailing<>> _tsfTryRedrawCanvas;
|
||||||
std::shared_ptr<ThrottledFuncLeading<winrt::Windows::UI::Core::CoreDispatcher>> _playWarningBell;
|
std::shared_ptr<ThrottledFuncTrailing<>> _updatePatternLocations;
|
||||||
|
std::shared_ptr<ThrottledFuncLeading> _playWarningBell;
|
||||||
|
|
||||||
struct ScrollBarUpdate
|
struct ScrollBarUpdate
|
||||||
{
|
{
|
||||||
|
@ -166,9 +165,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
double newMinimum;
|
double newMinimum;
|
||||||
double newViewportSize;
|
double newViewportSize;
|
||||||
};
|
};
|
||||||
|
std::shared_ptr<ThrottledFuncTrailing<ScrollBarUpdate>> _updateScrollBar;
|
||||||
std::shared_ptr<ThrottledFuncTrailing<winrt::Windows::UI::Core::CoreDispatcher, ScrollBarUpdate>> _updateScrollBar;
|
|
||||||
|
|
||||||
bool _isInternalScrollBarUpdate;
|
bool _isInternalScrollBarUpdate;
|
||||||
|
|
||||||
// Auto scroll occurs when user, while selecting, drags cursor outside viewport. View is then scrolled to 'follow' the cursor.
|
// Auto scroll occurs when user, while selecting, drags cursor outside viewport. View is then scrolled to 'follow' the cursor.
|
||||||
|
@ -260,6 +257,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||||
const int fontHeight,
|
const int fontHeight,
|
||||||
const bool isInitialChange);
|
const bool isInitialChange);
|
||||||
winrt::fire_and_forget _coreTransparencyChanged(IInspectable sender, Control::TransparencyChangedEventArgs args);
|
winrt::fire_and_forget _coreTransparencyChanged(IInspectable sender, Control::TransparencyChangedEventArgs args);
|
||||||
|
void _coreReceivedOutput(const IInspectable& sender, const IInspectable& args);
|
||||||
void _coreRaisedNotice(const IInspectable& s, const Control::NoticeEventArgs& args);
|
void _coreRaisedNotice(const IInspectable& s, const Control::NoticeEventArgs& args);
|
||||||
void _coreWarningBell(const IInspectable& sender, const IInspectable& args);
|
void _coreWarningBell(const IInspectable& sender, const IInspectable& args);
|
||||||
};
|
};
|
||||||
|
|
|
@ -78,13 +78,13 @@ private:
|
||||||
// pending, then the previous call with the previous arguments will be
|
// pending, then the previous call with the previous arguments will be
|
||||||
// cancelled and the call will be made with the new arguments instead.
|
// cancelled and the call will be made with the new arguments instead.
|
||||||
// - The function will be run on the the specified dispatcher.
|
// - The function will be run on the the specified dispatcher.
|
||||||
template<bool leading, typename T, typename... Args>
|
template<bool leading, typename... Args>
|
||||||
class ThrottledFunc : public std::enable_shared_from_this<ThrottledFunc<leading, T, Args...>>
|
class ThrottledFunc : public std::enable_shared_from_this<ThrottledFunc<leading, Args...>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Func = std::function<void(Args...)>;
|
using Func = std::function<void(Args...)>;
|
||||||
|
|
||||||
ThrottledFunc(T dispatcher, winrt::Windows::Foundation::TimeSpan delay, Func func) :
|
ThrottledFunc(winrt::Windows::UI::Core::CoreDispatcher dispatcher, winrt::Windows::Foundation::TimeSpan delay, Func func) :
|
||||||
_dispatcher{ std::move(dispatcher) },
|
_dispatcher{ std::move(dispatcher) },
|
||||||
_delay{ std::move(delay) },
|
_delay{ std::move(delay) },
|
||||||
_func{ std::move(func) }
|
_func{ std::move(func) }
|
||||||
|
@ -174,14 +174,13 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
T _dispatcher;
|
winrt::Windows::UI::Core::CoreDispatcher _dispatcher;
|
||||||
winrt::Windows::Foundation::TimeSpan _delay;
|
winrt::Windows::Foundation::TimeSpan _delay;
|
||||||
Func _func;
|
Func _func;
|
||||||
|
|
||||||
ThrottledFuncStorage<Args...> _storage;
|
ThrottledFuncStorage<Args...> _storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename... Args>
|
||||||
using ThrottledFuncTrailing = ThrottledFunc<false, T, Args...>;
|
using ThrottledFuncTrailing = ThrottledFunc<false, Args...>;
|
||||||
template<typename T, typename... Args>
|
using ThrottledFuncLeading = ThrottledFunc<true>;
|
||||||
using ThrottledFuncLeading = ThrottledFunc<true, T, Args...>;
|
|
||||||
|
|
Loading…
Reference in a new issue