Add cursor blinking (#686)

It even respects the user's cursor blink speed setting!
This commit is contained in:
David Teresi 2019-05-13 21:25:54 -04:00 committed by Dustin L. Howett (MSFT)
parent 2c1ab620bf
commit 8c177fab4f
4 changed files with 80 additions and 1 deletions

View file

@ -7,6 +7,7 @@
#include <DefaultSettings.h>
#include <unicode.hpp>
#include <Utf16Parser.hpp>
#include <WinUser.h>
#include "..\..\types\inc\GlyphWidth.hpp"
using namespace ::Microsoft::Console::Types;
@ -36,7 +37,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
_desiredFont{ DEFAULT_FONT_FACE.c_str(), 0, 10, { 0, DEFAULT_FONT_SIZE }, CP_UTF8 },
_actualFont{ DEFAULT_FONT_FACE.c_str(), 0, 10, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false },
_touchAnchor{ std::nullopt },
_leadingSurrogate{}
_leadingSurrogate{},
_cursorTimer{}
{
_Create();
}
@ -405,6 +407,24 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
auto pfnScrollPositionChanged = std::bind(&TermControl::_TerminalScrollPositionChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
_terminal->SetScrollPositionChangedCallback(pfnScrollPositionChanged);
// Set up blinking cursor
int blinkTime = GetCaretBlinkTime();
if (blinkTime != INFINITE)
{
// Create a timer
_cursorTimer = std::make_optional(DispatcherTimer());
_cursorTimer.value().Interval(std::chrono::milliseconds(blinkTime));
_cursorTimer.value().Tick({ this, &TermControl::_BlinkCursor });
_controlRoot.GotFocus({ this, &TermControl::_GotFocusHandler });
_controlRoot.LostFocus({ this, &TermControl::_LostFocusHandler });
}
else
{
// The user has disabled cursor blinking
_cursorTimer = std::nullopt;
}
// Focus the control here. If we do it up above (in _Create_), then the
// focus won't actually get passed to us. I believe this is because
// we're not technically a part of the UI tree yet, so focusing us
@ -503,6 +523,14 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
WI_IsFlagSet(modifiers, KeyModifiers::Ctrl),
WI_IsFlagSet(modifiers, KeyModifiers::Alt),
WI_IsFlagSet(modifiers, KeyModifiers::Shift));
if (_cursorTimer.has_value())
{
// Manually show the cursor when a key is pressed. Restarting
// the timer prevents flickering.
_terminal->SetCursorVisible(true);
_cursorTimer.value().Start();
}
}
e.Handled(handled);
@ -794,6 +822,29 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
}
}
// Method Description:
// - Event handler for the GotFocus event. This is used to start
// blinking the cursor when the window is focused.
void TermControl::_GotFocusHandler(Windows::Foundation::IInspectable const& /* sender */,
RoutedEventArgs const& /* args */)
{
if (_cursorTimer.has_value())
_cursorTimer.value().Start();
}
// Method Description:
// - Event handler for the LostFocus event. This is used to hide
// and stop blinking the cursor when the window loses focus.
void TermControl::_LostFocusHandler(Windows::Foundation::IInspectable const& /* sender */,
RoutedEventArgs const& /* args */)
{
if (_cursorTimer.has_value())
{
_cursorTimer.value().Stop();
_terminal->SetCursorVisible(false);
}
}
void TermControl::_SendInputToConnection(const std::wstring& wstr)
{
_connection.WriteInput(wstr);
@ -848,6 +899,17 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
_renderer->TriggerRedrawAll();
}
// Method Description:
// - Toggle the cursor on and off when called by the cursor blink timer.
// Arguments:
// - sender: not used
// - e: not used
void TermControl::_BlinkCursor(Windows::Foundation::IInspectable const& /* sender */,
Windows::Foundation::IInspectable const& /* e */)
{
_terminal->SetCursorVisible(!_terminal->IsCursorVisible());
}
// Method Description:
// - Process a resize event that was initiated by the user. This can either be due to the user resizing the window (causing the swapchain to resize) or due to the DPI changing (causing us to need to resize the buffer to match)
// Arguments:

View file

@ -84,6 +84,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// storage location for the leading surrogate of a utf-16 surrogate pair
std::optional<wchar_t> _leadingSurrogate;
std::optional<Windows::UI::Xaml::DispatcherTimer> _cursorTimer;
// If this is set, then we assume we are in the middle of panning the
// viewport via touch input.
std::optional<winrt::Windows::Foundation::Point> _touchAnchor;
@ -100,7 +102,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
void _PointerReleasedHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
void _MouseWheelHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
void _ScrollbarChangeHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e);
void _GotFocusHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
void _LostFocusHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
void _BlinkCursor(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
void _SendInputToConnection(const std::wstring& wstr);
void _SwapChainSizeChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e);
void _SwapChainScaleChanged(Windows::UI::Xaml::Controls::SwapChainPanel const& sender, Windows::Foundation::IInspectable const& args);

View file

@ -590,3 +590,13 @@ const std::wstring Terminal::RetrieveSelectedTextFromBuffer(bool trimTrailingWhi
return result;
}
// Method Description:
// - Sets the visibility of the text cursor.
// Arguments:
// - isVisible: whether the cursor should be visible
void Terminal::SetCursorVisible(const bool isVisible) noexcept
{
auto& cursor = _buffer->GetCursor();
cursor.SetIsVisible(isVisible);
}

View file

@ -113,6 +113,8 @@ public:
void SetTitleChangedCallback(std::function<void(const std::wstring_view&)> pfn) noexcept;
void SetScrollPositionChangedCallback(std::function<void(const int, const int, const int)> pfn) noexcept;
void SetCursorVisible(const bool isVisible) noexcept;
#pragma region TextSelection
const bool IsSelectionActive() const noexcept;
void SetSelectionAnchor(const COORD position);