mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-13 17:51:00 +00:00
This PR moves the cursor blinker and VT blink rendition timer into `Renderer`. To do so, this PR introduces a generic timer system with which you can schedule arbitrary timer jobs. Thanks to this, this PR removes a crapton of code, particularly throughout conhost. ## Validation Steps Performed * Focus/unfocus starts/stops blinking ✅ * OS-wide blink settings apply on focus ✅
229 lines
5.0 KiB
C++
229 lines
5.0 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include "precomp.h"
|
|
#include "cursor.h"
|
|
#include "TextBuffer.hpp"
|
|
|
|
#pragma hdrstop
|
|
|
|
// Routine Description:
|
|
// - Constructor to set default properties for Cursor
|
|
// Arguments:
|
|
// - ulSize - The height of the cursor within this buffer
|
|
Cursor::Cursor(const ULONG ulSize, TextBuffer& parentBuffer) noexcept :
|
|
_parentBuffer{ parentBuffer },
|
|
_ulSize(ulSize)
|
|
{
|
|
}
|
|
|
|
til::point Cursor::GetPosition() const noexcept
|
|
{
|
|
return _cPosition;
|
|
}
|
|
|
|
uint64_t Cursor::GetLastMutationId() const noexcept
|
|
{
|
|
return _mutationId;
|
|
}
|
|
|
|
bool Cursor::IsVisible() const noexcept
|
|
{
|
|
return _isVisible;
|
|
}
|
|
|
|
bool Cursor::IsBlinking() const noexcept
|
|
{
|
|
return _isBlinking;
|
|
}
|
|
|
|
bool Cursor::IsDouble() const noexcept
|
|
{
|
|
return _fIsDouble;
|
|
}
|
|
|
|
ULONG Cursor::GetSize() const noexcept
|
|
{
|
|
return _ulSize;
|
|
}
|
|
|
|
void Cursor::SetIsVisible(bool enable) noexcept
|
|
{
|
|
if (_isVisible != enable)
|
|
{
|
|
_isVisible = enable;
|
|
_redrawIfVisible();
|
|
}
|
|
}
|
|
|
|
void Cursor::SetIsBlinking(bool enable) noexcept
|
|
{
|
|
if (_isBlinking != enable)
|
|
{
|
|
_isBlinking = enable;
|
|
_redrawIfVisible();
|
|
}
|
|
}
|
|
|
|
void Cursor::SetIsDouble(const bool fIsDouble) noexcept
|
|
{
|
|
if (_fIsDouble != fIsDouble)
|
|
{
|
|
_fIsDouble = fIsDouble;
|
|
_redrawIfVisible();
|
|
}
|
|
}
|
|
|
|
void Cursor::SetSize(const ULONG ulSize) noexcept
|
|
{
|
|
if (_ulSize != ulSize)
|
|
{
|
|
_ulSize = ulSize;
|
|
_redrawIfVisible();
|
|
}
|
|
}
|
|
|
|
void Cursor::SetStyle(const ULONG ulSize, const CursorType type) noexcept
|
|
{
|
|
if (_ulSize != ulSize || _cursorType != type)
|
|
{
|
|
_ulSize = ulSize;
|
|
_cursorType = type;
|
|
_redrawIfVisible();
|
|
}
|
|
}
|
|
|
|
void Cursor::SetPosition(const til::point cPosition) noexcept
|
|
{
|
|
// The VT code assumes that moving the cursor implicitly resets the delayed EOL wrap,
|
|
// so we call ResetDelayEOLWrap() independent of _cPosition != cPosition.
|
|
// You can see the effect of this with "`e[1;9999Ha`e[1;9999Hb", which should print just "b".
|
|
ResetDelayEOLWrap();
|
|
if (_cPosition != cPosition)
|
|
{
|
|
_cPosition = cPosition;
|
|
_redrawIfVisible();
|
|
}
|
|
}
|
|
|
|
void Cursor::SetXPosition(const til::CoordType NewX) noexcept
|
|
{
|
|
ResetDelayEOLWrap();
|
|
if (_cPosition.x != NewX)
|
|
{
|
|
_cPosition.x = NewX;
|
|
_redrawIfVisible();
|
|
}
|
|
}
|
|
|
|
void Cursor::SetYPosition(const til::CoordType NewY) noexcept
|
|
{
|
|
ResetDelayEOLWrap();
|
|
if (_cPosition.y != NewY)
|
|
{
|
|
_cPosition.y = NewY;
|
|
_redrawIfVisible();
|
|
}
|
|
}
|
|
|
|
void Cursor::IncrementXPosition(const til::CoordType DeltaX) noexcept
|
|
{
|
|
ResetDelayEOLWrap();
|
|
if (DeltaX != 0)
|
|
{
|
|
_cPosition.x = _cPosition.x + DeltaX;
|
|
_redrawIfVisible();
|
|
}
|
|
}
|
|
|
|
void Cursor::IncrementYPosition(const til::CoordType DeltaY) noexcept
|
|
{
|
|
ResetDelayEOLWrap();
|
|
if (DeltaY != 0)
|
|
{
|
|
_cPosition.y = _cPosition.y + DeltaY;
|
|
_redrawIfVisible();
|
|
}
|
|
}
|
|
|
|
void Cursor::DecrementXPosition(const til::CoordType DeltaX) noexcept
|
|
{
|
|
ResetDelayEOLWrap();
|
|
if (DeltaX != 0)
|
|
{
|
|
_cPosition.x = _cPosition.x - DeltaX;
|
|
_redrawIfVisible();
|
|
}
|
|
}
|
|
|
|
void Cursor::DecrementYPosition(const til::CoordType DeltaY) noexcept
|
|
{
|
|
ResetDelayEOLWrap();
|
|
if (DeltaY != 0)
|
|
{
|
|
_cPosition.y = _cPosition.y - DeltaY;
|
|
_redrawIfVisible();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Routine Description:
|
|
// - Copies properties from another cursor into this one.
|
|
// - This is primarily to copy properties that would otherwise not be specified during CreateInstance
|
|
// - NOTE: As of now, this function is specifically used to handle the ResizeWithReflow operation.
|
|
// It will need modification for other future users.
|
|
// Arguments:
|
|
// - OtherCursor - The cursor to copy properties from
|
|
// Return Value:
|
|
// - <none>
|
|
void Cursor::CopyProperties(const Cursor& other) noexcept
|
|
{
|
|
_cPosition = other._cPosition;
|
|
_coordDelayedAt = other._coordDelayedAt;
|
|
_ulSize = other._ulSize;
|
|
_cursorType = other._cursorType;
|
|
_isVisible = other._isVisible;
|
|
_isBlinking = other._isBlinking;
|
|
_fIsDouble = other._fIsDouble;
|
|
}
|
|
|
|
void Cursor::DelayEOLWrap() noexcept
|
|
{
|
|
_coordDelayedAt = _cPosition;
|
|
}
|
|
|
|
void Cursor::ResetDelayEOLWrap() noexcept
|
|
{
|
|
_coordDelayedAt.reset();
|
|
}
|
|
|
|
const std::optional<til::point>& Cursor::GetDelayEOLWrap() const noexcept
|
|
{
|
|
return _coordDelayedAt;
|
|
}
|
|
|
|
CursorType Cursor::GetType() const noexcept
|
|
{
|
|
return _cursorType;
|
|
}
|
|
|
|
void Cursor::SetType(const CursorType type) noexcept
|
|
{
|
|
_cursorType = type;
|
|
}
|
|
|
|
void Cursor::_redrawIfVisible() noexcept
|
|
{
|
|
_mutationId++;
|
|
if (_isVisible)
|
|
{
|
|
_parentBuffer.NotifyPaintFrame();
|
|
}
|
|
}
|
|
|
|
void Cursor::_redraw() noexcept
|
|
{
|
|
_mutationId++;
|
|
_parentBuffer.NotifyPaintFrame();
|
|
}
|