-
Notifications
You must be signed in to change notification settings - Fork 8.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid timer ticks on frozen windows #16587
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,4 @@ | ||
#include "pch.h" | ||
#include "ColorHelper.h" | ||
#include <limits> | ||
|
||
using namespace winrt::TerminalApp; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,10 +57,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
_isInternalScrollBarUpdate{ false }, | ||
_autoScrollVelocity{ 0 }, | ||
_autoScrollingPointerPoint{ std::nullopt }, | ||
_autoScrollTimer{}, | ||
_lastAutoScrollUpdateTime{ std::nullopt }, | ||
_cursorTimer{}, | ||
_blinkTimer{}, | ||
_searchBox{ nullptr } | ||
{ | ||
InitializeComponent(); | ||
|
@@ -1087,10 +1084,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
if (blinkTime != INFINITE) | ||
{ | ||
// Create a timer | ||
DispatcherTimer cursorTimer; | ||
cursorTimer.Interval(std::chrono::milliseconds(blinkTime)); | ||
cursorTimer.Tick({ get_weak(), &TermControl::_CursorTimerTick }); | ||
_cursorTimer.emplace(std::move(cursorTimer)); | ||
_cursorTimer.Interval(std::chrono::milliseconds(blinkTime)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note to self: |
||
_cursorTimer.Tick({ get_weak(), &TermControl::_CursorTimerTick }); | ||
// As of GH#6586, don't start the cursor timer immediately, and | ||
// don't show the cursor initially. We'll show the cursor and start | ||
// the timer when the control is first focused. | ||
|
@@ -1105,13 +1100,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
_core.CursorOn(_focused || _displayCursorWhileBlurred()); | ||
if (_displayCursorWhileBlurred()) | ||
{ | ||
_cursorTimer->Start(); | ||
_cursorTimer.Start(); | ||
} | ||
} | ||
else | ||
{ | ||
// The user has disabled cursor blinking | ||
_cursorTimer = std::nullopt; | ||
_cursorTimer.Destroy(); | ||
} | ||
|
||
// Set up blinking attributes | ||
|
@@ -1120,16 +1114,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
if (animationsEnabled && blinkTime != INFINITE) | ||
{ | ||
// Create a timer | ||
DispatcherTimer blinkTimer; | ||
blinkTimer.Interval(std::chrono::milliseconds(blinkTime)); | ||
blinkTimer.Tick({ get_weak(), &TermControl::_BlinkTimerTick }); | ||
blinkTimer.Start(); | ||
_blinkTimer.emplace(std::move(blinkTimer)); | ||
_blinkTimer.Interval(std::chrono::milliseconds(blinkTime)); | ||
_blinkTimer.Tick({ get_weak(), &TermControl::_BlinkTimerTick }); | ||
_blinkTimer.Start(); | ||
} | ||
else | ||
{ | ||
// The user has disabled blinking | ||
_blinkTimer = std::nullopt; | ||
_blinkTimer.Destroy(); | ||
} | ||
|
||
// Now that the renderer is set up, update the appearance for initialization | ||
|
@@ -1498,7 +1490,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
// Manually show the cursor when a key is pressed. Restarting | ||
// the timer prevents flickering. | ||
_core.CursorOn(_core.SelectionMode() != SelectionInteractionMode::Mark); | ||
_cursorTimer->Start(); | ||
_cursorTimer.Start(); | ||
} | ||
|
||
return handled; | ||
|
@@ -1973,12 +1965,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
{ | ||
// When the terminal focuses, show the cursor immediately | ||
_core.CursorOn(_core.SelectionMode() != SelectionInteractionMode::Mark); | ||
_cursorTimer->Start(); | ||
_cursorTimer.Start(); | ||
} | ||
|
||
if (_blinkTimer) | ||
{ | ||
_blinkTimer->Start(); | ||
_blinkTimer.Start(); | ||
} | ||
|
||
// Only update the appearance here if an unfocused config exists - if an | ||
|
@@ -2021,13 +2013,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
|
||
if (_cursorTimer && !_displayCursorWhileBlurred()) | ||
{ | ||
_cursorTimer->Stop(); | ||
_cursorTimer.Stop(); | ||
_core.CursorOn(false); | ||
} | ||
|
||
if (_blinkTimer) | ||
{ | ||
_blinkTimer->Stop(); | ||
_blinkTimer.Stop(); | ||
} | ||
|
||
// Check if there is an unfocused config we should set the appearance to | ||
|
@@ -2278,7 +2270,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
|
||
// Disconnect the TSF input control so it doesn't receive EditContext events. | ||
TSFInputControl().Close(); | ||
|
||
// At the time of writing, closing the last tab of a window inexplicably | ||
// does not lead to the destruction of the remaining TermControl instance(s). | ||
// On Win10 we don't destroy window threads due to bugs in DesktopWindowXamlSource. | ||
// In turn, we leak TermControl instances. This results in constant HWND messages | ||
// while the thread is supposed to be idle. Stop these timers avoids this. | ||
_autoScrollTimer.Stop(); | ||
_bellLightTimer.Stop(); | ||
_cursorTimer.Stop(); | ||
_blinkTimer.Stop(); | ||
|
||
if (!_detached) | ||
{ | ||
|
@@ -3129,20 +3130,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
_bellDarkAnimation.Duration(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(TerminalWarningBellInterval))); | ||
} | ||
|
||
// Similar to the animation, only initialize the timer here | ||
if (!_bellLightTimer) | ||
{ | ||
_bellLightTimer = {}; | ||
_bellLightTimer.Interval(std::chrono::milliseconds(TerminalWarningBellInterval)); | ||
_bellLightTimer.Tick({ get_weak(), &TermControl::_BellLightOff }); | ||
} | ||
|
||
Windows::Foundation::Numerics::float2 zeroSize{ 0, 0 }; | ||
// If the grid has 0 size or if the bell timer is | ||
// already active, do nothing | ||
if (RootGrid().ActualSize() != zeroSize && !_bellLightTimer.IsEnabled()) | ||
{ | ||
// Start the timer, when the timer ticks we switch off the light | ||
_bellLightTimer.Interval(std::chrono::milliseconds(TerminalWarningBellInterval)); | ||
_bellLightTimer.Tick({ get_weak(), &TermControl::_BellLightOff }); | ||
_bellLightTimer.Start(); | ||
|
||
// Switch on the light and animate the intensity to fade out | ||
|
@@ -3162,15 +3156,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
void TermControl::_BellLightOff(const Windows::Foundation::IInspectable& /* sender */, | ||
const Windows::Foundation::IInspectable& /* e */) | ||
{ | ||
if (_bellLightTimer) | ||
{ | ||
// Stop the timer and switch off the light | ||
_bellLightTimer.Stop(); | ||
// Stop the timer and switch off the light | ||
_bellLightTimer.Stop(); | ||
|
||
if (!_IsClosing()) | ||
{ | ||
VisualBellLight::SetIsTarget(RootGrid(), false); | ||
} | ||
if (!_IsClosing()) | ||
{ | ||
VisualBellLight::SetIsTarget(RootGrid(), false); | ||
} | ||
} | ||
|
||
|
@@ -3729,9 +3720,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
{ | ||
// If we should be ALWAYS displaying the cursor, turn it on and start blinking. | ||
_core.CursorOn(true); | ||
if (_cursorTimer.has_value()) | ||
if (_cursorTimer) | ||
{ | ||
_cursorTimer->Start(); | ||
_cursorTimer.Start(); | ||
} | ||
} | ||
else | ||
|
@@ -3740,9 +3731,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
// blinking. (if we're focused, then we're already doing the right | ||
// thing) | ||
const auto focused = FocusState() != FocusState::Unfocused; | ||
if (!focused && _cursorTimer.has_value()) | ||
if (!focused && _cursorTimer) | ||
{ | ||
_cursorTimer->Stop(); | ||
_cursorTimer.Stop(); | ||
} | ||
_core.CursorOn(focused); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -236,16 +236,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation | |
// viewport. View is then scrolled to 'follow' the cursor. | ||
double _autoScrollVelocity; | ||
std::optional<Windows::UI::Input::PointerPoint> _autoScrollingPointerPoint; | ||
Windows::UI::Xaml::DispatcherTimer _autoScrollTimer; | ||
SafeDispatcherTimer _autoScrollTimer; | ||
std::optional<std::chrono::high_resolution_clock::time_point> _lastAutoScrollUpdateTime; | ||
bool _pointerPressedInBounds{ false }; | ||
|
||
winrt::Windows::UI::Composition::ScalarKeyFrameAnimation _bellLightAnimation{ nullptr }; | ||
winrt::Windows::UI::Composition::ScalarKeyFrameAnimation _bellDarkAnimation{ nullptr }; | ||
Windows::UI::Xaml::DispatcherTimer _bellLightTimer{ nullptr }; | ||
SafeDispatcherTimer _bellLightTimer; | ||
|
||
std::optional<Windows::UI::Xaml::DispatcherTimer> _cursorTimer; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thank you for killing these |
||
std::optional<Windows::UI::Xaml::DispatcherTimer> _blinkTimer; | ||
SafeDispatcherTimer _cursorTimer; | ||
SafeDispatcherTimer _blinkTimer; | ||
|
||
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker; | ||
bool _showMarksInScrollbar{ false }; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jeepers I don't love this, presumably this should be in the pch for both this project and the tests, but also those tests really haven't had love in years. So, this is fine for now. (I can only hope that it also being in the pch.h for TerminalAppLib means it won't actually get re-parsed here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
Windows.UI
header is a smaller than theWindows.UI.Core
header so this at least makes it a tiny bit better.