2019-05-03 00:29:04 +02:00
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
#include <intsafe.h>
|
|
|
|
|
|
|
|
#include "misc.h"
|
|
|
|
#include "output.h"
|
|
|
|
#include "srvinit.h"
|
|
|
|
|
2020-11-25 22:02:10 +01:00
|
|
|
#include "../interactivity/inc/ServiceLocator.hpp"
|
|
|
|
#include "../types/inc/convert.hpp"
|
2019-05-03 00:29:04 +02:00
|
|
|
|
2019-05-30 20:14:21 +02:00
|
|
|
using Microsoft::Console::Interactivity::ServiceLocator;
|
Add support for the "blink" graphic rendition attribute (#7490)
This PR adds support for the _blink_ graphic rendition attribute. When a
character is output with this attribute set, it "blinks" at a regular
interval, by cycling its color between the normal rendition and a dimmer
shade of that color.
The majority of the blinking mechanism is encapsulated in a new
`BlinkingState` class, which is shared between the Terminal and Conhost
implementations. This class keeps track of the position in the blinking
cycle, which determines whether characters are rendered as normal or
faint.
In Windows Terminal, the state is stored in the `Terminal` class, and in
Conhost it's stored in the `CONSOLE_INFORMATION` class. In both cases,
the `IsBlinkingFaint` method is used to determine the current blinking
rendition, and that is passed on as a parameter to the
`TextAttribute::CalculateRgbColors` method when these classes are
looking up attribute colors.
Prior to calculating the colors, the current attribute is also passed to
the `RecordBlinkingUsage` method, which keeps track of whether there are
actually any blink attributes in use. This is used to determine whether
the screen needs to be refreshed when the blinking cycle toggles between
the normal and faint renditions.
The refresh itself is handled by the `ToggleBlinkingRendition` method,
which is triggered by a timer. In Conhost this is just piggybacking on
the existing cursor blink timer, but in Windows Terminal it needs to
have its own separate timer, since the cursor timer is reset whenever a
key is pressed, which is not something we want for attribute blinking.
Although the `ToggleBlinkingRendition` is called at the same rate as the
cursor blinking, we actually only want the cells to blink at half that
frequency. We thus have a counter that cycles through four phases, and
blinking is rendered as faint for two of those four. Then every two
cycles - when the state changes - a redraw is triggered, but only if
there are actually blinking attributes in use (as previously recorded).
As mentioned earlier, the blinking frequency is based on the cursor
blink rate, so that means it'll automatically be disabled if a user has
set their cursor blink rate to none. It can also be disabled by turning
off the _Show animations in Windows_ option. In Conhost these settings
take effect immediately, but in Windows Terminal they only apply when a
new tab is opened.
This PR also adds partial support for the `SGR 6` _rapid blink_
attribute. This is not used by DEC terminals, but was defined in the
ECMA/ANSI standards. It's not widely supported, but many terminals just
it implement it as an alias for the regular `SGR 5` blink attribute, so
that's what I've done here too.
## Validation Steps Performed
I've checked the _Graphic rendition test pattern_ in Vttest, and
compared our representation of the blink attribute to that of an actual
DEC VT220 terminal as seen on [YouTube]. With the right color scheme
it's a reasonably close match.
[YouTube]: https://www.youtube.com/watch?v=03Pz5AmxbE4&t=1m55s
Closes #7388
2020-09-22 01:21:33 +02:00
|
|
|
using Microsoft::Console::Render::BlinkingState;
|
2019-05-30 20:14:21 +02:00
|
|
|
using Microsoft::Console::VirtualTerminal::VtIo;
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
CONSOLE_INFORMATION::CONSOLE_INFORMATION() :
|
|
|
|
// ProcessHandleList initializes itself
|
|
|
|
pInputBuffer(nullptr),
|
|
|
|
pCurrentScreenBuffer(nullptr),
|
|
|
|
ScreenBuffers(nullptr),
|
|
|
|
OutputQueue(),
|
|
|
|
// ExeAliasList initialized below
|
|
|
|
_OriginalTitle(),
|
|
|
|
_Title(),
|
|
|
|
_LinkTitle(),
|
|
|
|
Flags(0),
|
|
|
|
PopupCount(0),
|
|
|
|
CP(0),
|
|
|
|
OutputCP(0),
|
|
|
|
CtrlFlags(0),
|
|
|
|
LimitingProcessId(0),
|
|
|
|
// ColorTable initialized below
|
|
|
|
// CPInfo initialized below
|
|
|
|
// OutputCPInfo initialized below
|
|
|
|
_cookedReadData(nullptr),
|
|
|
|
ConsoleIme{},
|
|
|
|
_vtIo(),
|
|
|
|
_blinker{},
|
|
|
|
renderData{}
|
|
|
|
{
|
|
|
|
ZeroMemory((void*)&CPInfo, sizeof(CPInfo));
|
|
|
|
ZeroMemory((void*)&OutputCPInfo, sizeof(OutputCPInfo));
|
|
|
|
InitializeCriticalSection(&_csConsoleLock);
|
|
|
|
}
|
|
|
|
|
|
|
|
CONSOLE_INFORMATION::~CONSOLE_INFORMATION()
|
|
|
|
{
|
|
|
|
DeleteCriticalSection(&_csConsoleLock);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CONSOLE_INFORMATION::IsConsoleLocked() const
|
|
|
|
{
|
|
|
|
// The critical section structure's OwningThread field contains the ThreadId despite having the HANDLE type.
|
|
|
|
// This requires us to hard cast the ID to compare.
|
|
|
|
return _csConsoleLock.OwningThread == (HANDLE)GetCurrentThreadId();
|
|
|
|
}
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
#pragma prefast(suppress : 26135, "Adding lock annotation spills into entire project. Future work.")
|
2019-05-03 00:29:04 +02:00
|
|
|
void CONSOLE_INFORMATION::LockConsole()
|
|
|
|
{
|
|
|
|
EnterCriticalSection(&_csConsoleLock);
|
|
|
|
}
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
#pragma prefast(suppress : 26135, "Adding lock annotation spills into entire project. Future work.")
|
2019-05-03 00:29:04 +02:00
|
|
|
bool CONSOLE_INFORMATION::TryLockConsole()
|
|
|
|
{
|
|
|
|
return !!TryEnterCriticalSection(&_csConsoleLock);
|
|
|
|
}
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
#pragma prefast(suppress : 26135, "Adding lock annotation spills into entire project. Future work.")
|
2019-05-03 00:29:04 +02:00
|
|
|
void CONSOLE_INFORMATION::UnlockConsole()
|
|
|
|
{
|
|
|
|
LeaveCriticalSection(&_csConsoleLock);
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG CONSOLE_INFORMATION::GetCSRecursionCount()
|
|
|
|
{
|
|
|
|
return _csConsoleLock.RecursionCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Routine Description:
|
|
|
|
// - This routine allocates and initialized a console and its associated
|
|
|
|
// data - input buffer and screen buffer.
|
|
|
|
// - NOTE: Will read global ServiceLocator::LocateGlobals().getConsoleInformation expecting Settings to already be filled.
|
|
|
|
// Arguments:
|
|
|
|
// - title - Window Title to display
|
|
|
|
// Return Value:
|
|
|
|
// - STATUS_SUCCESS if successful.
|
2019-06-11 22:27:09 +02:00
|
|
|
[[nodiscard]] NTSTATUS CONSOLE_INFORMATION::AllocateConsole(const std::wstring_view title)
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
|
|
|
// Synchronize flags
|
|
|
|
WI_SetFlagIf(gci.Flags, CONSOLE_AUTO_POSITION, !!gci.GetAutoPosition());
|
|
|
|
WI_SetFlagIf(gci.Flags, CONSOLE_QUICK_EDIT_MODE, !!gci.GetQuickEdit());
|
|
|
|
WI_SetFlagIf(gci.Flags, CONSOLE_HISTORY_NODUP, !!gci.GetHistoryNoDup());
|
|
|
|
|
|
|
|
Selection* const pSelection = &Selection::Instance();
|
|
|
|
pSelection->SetLineSelection(!!gci.GetLineSelection());
|
|
|
|
|
|
|
|
SetConsoleCPInfo(TRUE);
|
|
|
|
SetConsoleCPInfo(FALSE);
|
|
|
|
|
|
|
|
// Initialize input buffer.
|
|
|
|
try
|
|
|
|
{
|
|
|
|
gci.pInputBuffer = new InputBuffer();
|
|
|
|
}
|
2019-06-11 22:27:09 +02:00
|
|
|
catch (...)
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
return NTSTATUS_FROM_HRESULT(wil::ResultFromCaughtException());
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
gci.SetTitle(title);
|
|
|
|
gci.SetOriginalTitle(std::wstring(TranslateConsoleTitle(gci.GetTitle().c_str(), TRUE, FALSE)));
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
return NTSTATUS_FROM_HRESULT(wil::ResultFromCaughtException());
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS Status = DoCreateScreenBuffer();
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
goto ErrorExit2;
|
|
|
|
}
|
|
|
|
|
|
|
|
gci.pCurrentScreenBuffer = gci.ScreenBuffers;
|
|
|
|
|
|
|
|
gci.GetActiveOutputBuffer().ScrollScale = gci.GetScrollScale();
|
|
|
|
|
|
|
|
gci.ConsoleIme.RefreshAreaAttributes();
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
RIPMSG1(RIP_WARNING, "Console init failed with status 0x%x", Status);
|
|
|
|
|
|
|
|
delete gci.ScreenBuffers;
|
|
|
|
gci.ScreenBuffers = nullptr;
|
|
|
|
|
|
|
|
ErrorExit2:
|
|
|
|
delete gci.pInputBuffer;
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
VtIo* CONSOLE_INFORMATION::GetVtIo()
|
|
|
|
{
|
|
|
|
return &_vtIo;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CONSOLE_INFORMATION::IsInVtIoMode() const
|
|
|
|
{
|
|
|
|
return _vtIo.IsUsingVt();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CONSOLE_INFORMATION::HasPendingCookedRead() const noexcept
|
|
|
|
{
|
|
|
|
return _cookedReadData != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const COOKED_READ_DATA& CONSOLE_INFORMATION::CookedReadData() const noexcept
|
|
|
|
{
|
|
|
|
return *_cookedReadData;
|
|
|
|
}
|
|
|
|
|
|
|
|
COOKED_READ_DATA& CONSOLE_INFORMATION::CookedReadData() noexcept
|
|
|
|
{
|
|
|
|
return *_cookedReadData;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CONSOLE_INFORMATION::SetCookedReadData(COOKED_READ_DATA* readData) noexcept
|
|
|
|
{
|
|
|
|
_cookedReadData = readData;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Return the active screen buffer of the console.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - the active screen buffer of the console.
|
|
|
|
SCREEN_INFORMATION& CONSOLE_INFORMATION::GetActiveOutputBuffer()
|
|
|
|
{
|
|
|
|
return *pCurrentScreenBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
const SCREEN_INFORMATION& CONSOLE_INFORMATION::GetActiveOutputBuffer() const
|
|
|
|
{
|
|
|
|
return *pCurrentScreenBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CONSOLE_INFORMATION::HasActiveOutputBuffer() const
|
|
|
|
{
|
|
|
|
return (pCurrentScreenBuffer != nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Return the active input buffer of the console.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - the active input buffer of the console.
|
|
|
|
InputBuffer* const CONSOLE_INFORMATION::GetActiveInputBuffer() const
|
|
|
|
{
|
|
|
|
return pInputBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Return the default foreground color of the console. If the settings are
|
|
|
|
// configured to have a default foreground color (separate from the color
|
|
|
|
// table), this will return that value. Otherwise it will return the value
|
|
|
|
// from the colortable corresponding to our default attributes.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - the default foreground color of the console.
|
|
|
|
COLORREF CONSOLE_INFORMATION::GetDefaultForeground() const noexcept
|
|
|
|
{
|
Add support for the "blink" graphic rendition attribute (#7490)
This PR adds support for the _blink_ graphic rendition attribute. When a
character is output with this attribute set, it "blinks" at a regular
interval, by cycling its color between the normal rendition and a dimmer
shade of that color.
The majority of the blinking mechanism is encapsulated in a new
`BlinkingState` class, which is shared between the Terminal and Conhost
implementations. This class keeps track of the position in the blinking
cycle, which determines whether characters are rendered as normal or
faint.
In Windows Terminal, the state is stored in the `Terminal` class, and in
Conhost it's stored in the `CONSOLE_INFORMATION` class. In both cases,
the `IsBlinkingFaint` method is used to determine the current blinking
rendition, and that is passed on as a parameter to the
`TextAttribute::CalculateRgbColors` method when these classes are
looking up attribute colors.
Prior to calculating the colors, the current attribute is also passed to
the `RecordBlinkingUsage` method, which keeps track of whether there are
actually any blink attributes in use. This is used to determine whether
the screen needs to be refreshed when the blinking cycle toggles between
the normal and faint renditions.
The refresh itself is handled by the `ToggleBlinkingRendition` method,
which is triggered by a timer. In Conhost this is just piggybacking on
the existing cursor blink timer, but in Windows Terminal it needs to
have its own separate timer, since the cursor timer is reset whenever a
key is pressed, which is not something we want for attribute blinking.
Although the `ToggleBlinkingRendition` is called at the same rate as the
cursor blinking, we actually only want the cells to blink at half that
frequency. We thus have a counter that cycles through four phases, and
blinking is rendered as faint for two of those four. Then every two
cycles - when the state changes - a redraw is triggered, but only if
there are actually blinking attributes in use (as previously recorded).
As mentioned earlier, the blinking frequency is based on the cursor
blink rate, so that means it'll automatically be disabled if a user has
set their cursor blink rate to none. It can also be disabled by turning
off the _Show animations in Windows_ option. In Conhost these settings
take effect immediately, but in Windows Terminal they only apply when a
new tab is opened.
This PR also adds partial support for the `SGR 6` _rapid blink_
attribute. This is not used by DEC terminals, but was defined in the
ECMA/ANSI standards. It's not widely supported, but many terminals just
it implement it as an alias for the regular `SGR 5` blink attribute, so
that's what I've done here too.
## Validation Steps Performed
I've checked the _Graphic rendition test pattern_ in Vttest, and
compared our representation of the blink attribute to that of an actual
DEC VT220 terminal as seen on [YouTube]. With the right color scheme
it's a reasonably close match.
[YouTube]: https://www.youtube.com/watch?v=03Pz5AmxbE4&t=1m55s
Closes #7388
2020-09-22 01:21:33 +02:00
|
|
|
const auto fg = GetDefaultForegroundColor();
|
|
|
|
return fg != INVALID_COLOR ? fg : GetColorTableEntry(LOBYTE(GetFillAttribute()) & FG_ATTRS);
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Return the default background color of the console. If the settings are
|
|
|
|
// configured to have a default background color (separate from the color
|
|
|
|
// table), this will return that value. Otherwise it will return the value
|
|
|
|
// from the colortable corresponding to our default attributes.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - the default background color of the console.
|
|
|
|
COLORREF CONSOLE_INFORMATION::GetDefaultBackground() const noexcept
|
|
|
|
{
|
Add support for the "blink" graphic rendition attribute (#7490)
This PR adds support for the _blink_ graphic rendition attribute. When a
character is output with this attribute set, it "blinks" at a regular
interval, by cycling its color between the normal rendition and a dimmer
shade of that color.
The majority of the blinking mechanism is encapsulated in a new
`BlinkingState` class, which is shared between the Terminal and Conhost
implementations. This class keeps track of the position in the blinking
cycle, which determines whether characters are rendered as normal or
faint.
In Windows Terminal, the state is stored in the `Terminal` class, and in
Conhost it's stored in the `CONSOLE_INFORMATION` class. In both cases,
the `IsBlinkingFaint` method is used to determine the current blinking
rendition, and that is passed on as a parameter to the
`TextAttribute::CalculateRgbColors` method when these classes are
looking up attribute colors.
Prior to calculating the colors, the current attribute is also passed to
the `RecordBlinkingUsage` method, which keeps track of whether there are
actually any blink attributes in use. This is used to determine whether
the screen needs to be refreshed when the blinking cycle toggles between
the normal and faint renditions.
The refresh itself is handled by the `ToggleBlinkingRendition` method,
which is triggered by a timer. In Conhost this is just piggybacking on
the existing cursor blink timer, but in Windows Terminal it needs to
have its own separate timer, since the cursor timer is reset whenever a
key is pressed, which is not something we want for attribute blinking.
Although the `ToggleBlinkingRendition` is called at the same rate as the
cursor blinking, we actually only want the cells to blink at half that
frequency. We thus have a counter that cycles through four phases, and
blinking is rendered as faint for two of those four. Then every two
cycles - when the state changes - a redraw is triggered, but only if
there are actually blinking attributes in use (as previously recorded).
As mentioned earlier, the blinking frequency is based on the cursor
blink rate, so that means it'll automatically be disabled if a user has
set their cursor blink rate to none. It can also be disabled by turning
off the _Show animations in Windows_ option. In Conhost these settings
take effect immediately, but in Windows Terminal they only apply when a
new tab is opened.
This PR also adds partial support for the `SGR 6` _rapid blink_
attribute. This is not used by DEC terminals, but was defined in the
ECMA/ANSI standards. It's not widely supported, but many terminals just
it implement it as an alias for the regular `SGR 5` blink attribute, so
that's what I've done here too.
## Validation Steps Performed
I've checked the _Graphic rendition test pattern_ in Vttest, and
compared our representation of the blink attribute to that of an actual
DEC VT220 terminal as seen on [YouTube]. With the right color scheme
it's a reasonably close match.
[YouTube]: https://www.youtube.com/watch?v=03Pz5AmxbE4&t=1m55s
Closes #7388
2020-09-22 01:21:33 +02:00
|
|
|
const auto bg = GetDefaultBackgroundColor();
|
|
|
|
return bg != INVALID_COLOR ? bg : GetColorTableEntry((LOBYTE(GetFillAttribute()) & BG_ATTRS) >> 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Get the colors of a particular text attribute, using our color table,
|
|
|
|
// and our configured default attributes.
|
|
|
|
// Arguments:
|
|
|
|
// - attr: the TextAttribute to retrieve the foreground color of.
|
|
|
|
// Return Value:
|
|
|
|
// - The color values of the attribute's foreground and background.
|
|
|
|
std::pair<COLORREF, COLORREF> CONSOLE_INFORMATION::LookupAttributeColors(const TextAttribute& attr) const noexcept
|
|
|
|
{
|
|
|
|
_blinkingState.RecordBlinkingUsage(attr);
|
|
|
|
return attr.CalculateRgbColors(Get256ColorTable(),
|
|
|
|
GetDefaultForeground(),
|
|
|
|
GetDefaultBackground(),
|
|
|
|
IsScreenReversed(),
|
|
|
|
_blinkingState.IsBlinkingFaint());
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Set the console's title, and trigger a renderer update of the title.
|
|
|
|
// This does not include the title prefix, such as "Mark", "Select", or "Scroll"
|
|
|
|
// Arguments:
|
|
|
|
// - newTitle: The new value to use for the title
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void CONSOLE_INFORMATION::SetTitle(const std::wstring_view newTitle)
|
|
|
|
{
|
|
|
|
_Title = std::wstring{ newTitle.begin(), newTitle.end() };
|
|
|
|
|
|
|
|
auto* const pRender = ServiceLocator::LocateGlobals().pRender;
|
|
|
|
if (pRender)
|
|
|
|
{
|
|
|
|
pRender->TriggerTitleChange();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Set the console title's prefix, and trigger a renderer update of the title.
|
2019-05-29 23:27:30 +02:00
|
|
|
// This is the part of the title such as "Mark", "Select", or "Scroll"
|
2019-05-03 00:29:04 +02:00
|
|
|
// Arguments:
|
|
|
|
// - newTitlePrefix: The new value to use for the title prefix
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void CONSOLE_INFORMATION::SetTitlePrefix(const std::wstring& newTitlePrefix)
|
|
|
|
{
|
|
|
|
_TitlePrefix = newTitlePrefix;
|
|
|
|
|
|
|
|
auto* const pRender = ServiceLocator::LocateGlobals().pRender;
|
|
|
|
if (pRender)
|
|
|
|
{
|
|
|
|
pRender->TriggerTitleChange();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Set the value of the console's original title. This is the title the
|
|
|
|
// console launched with.
|
|
|
|
// Arguments:
|
|
|
|
// - originalTitle: The new value to use for the console's original title
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void CONSOLE_INFORMATION::SetOriginalTitle(const std::wstring& originalTitle)
|
|
|
|
{
|
|
|
|
_OriginalTitle = originalTitle;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Set the value of the console's link title. If the console was launched
|
|
|
|
/// from a shortcut, this value will not be the empty string.
|
|
|
|
// Arguments:
|
|
|
|
// - linkTitle: The new value to use for the console's link title
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void CONSOLE_INFORMATION::SetLinkTitle(const std::wstring& linkTitle)
|
|
|
|
{
|
|
|
|
_LinkTitle = linkTitle;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - return a reference to the console's title.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - a reference to the console's title.
|
|
|
|
const std::wstring& CONSOLE_INFORMATION::GetTitle() const noexcept
|
|
|
|
{
|
|
|
|
return _Title;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Return a new wstring representing the actual display value of the title.
|
|
|
|
// This is the Prefix+Title.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - a new wstring containing the combined prefix and title.
|
|
|
|
const std::wstring CONSOLE_INFORMATION::GetTitleAndPrefix() const
|
|
|
|
{
|
|
|
|
return _TitlePrefix + _Title;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - return a reference to the console's original title.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - a reference to the console's original title.
|
|
|
|
const std::wstring& CONSOLE_INFORMATION::GetOriginalTitle() const noexcept
|
|
|
|
{
|
|
|
|
return _OriginalTitle;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - return a reference to the console's link title.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - a reference to the console's link title.
|
|
|
|
const std::wstring& CONSOLE_INFORMATION::GetLinkTitle() const noexcept
|
|
|
|
{
|
|
|
|
return _LinkTitle;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - return a reference to the console's cursor blinker.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - a reference to the console's cursor blinker.
|
|
|
|
Microsoft::Console::CursorBlinker& CONSOLE_INFORMATION::GetCursorBlinker() noexcept
|
|
|
|
{
|
|
|
|
return _blinker;
|
|
|
|
}
|
|
|
|
|
Add support for the "blink" graphic rendition attribute (#7490)
This PR adds support for the _blink_ graphic rendition attribute. When a
character is output with this attribute set, it "blinks" at a regular
interval, by cycling its color between the normal rendition and a dimmer
shade of that color.
The majority of the blinking mechanism is encapsulated in a new
`BlinkingState` class, which is shared between the Terminal and Conhost
implementations. This class keeps track of the position in the blinking
cycle, which determines whether characters are rendered as normal or
faint.
In Windows Terminal, the state is stored in the `Terminal` class, and in
Conhost it's stored in the `CONSOLE_INFORMATION` class. In both cases,
the `IsBlinkingFaint` method is used to determine the current blinking
rendition, and that is passed on as a parameter to the
`TextAttribute::CalculateRgbColors` method when these classes are
looking up attribute colors.
Prior to calculating the colors, the current attribute is also passed to
the `RecordBlinkingUsage` method, which keeps track of whether there are
actually any blink attributes in use. This is used to determine whether
the screen needs to be refreshed when the blinking cycle toggles between
the normal and faint renditions.
The refresh itself is handled by the `ToggleBlinkingRendition` method,
which is triggered by a timer. In Conhost this is just piggybacking on
the existing cursor blink timer, but in Windows Terminal it needs to
have its own separate timer, since the cursor timer is reset whenever a
key is pressed, which is not something we want for attribute blinking.
Although the `ToggleBlinkingRendition` is called at the same rate as the
cursor blinking, we actually only want the cells to blink at half that
frequency. We thus have a counter that cycles through four phases, and
blinking is rendered as faint for two of those four. Then every two
cycles - when the state changes - a redraw is triggered, but only if
there are actually blinking attributes in use (as previously recorded).
As mentioned earlier, the blinking frequency is based on the cursor
blink rate, so that means it'll automatically be disabled if a user has
set their cursor blink rate to none. It can also be disabled by turning
off the _Show animations in Windows_ option. In Conhost these settings
take effect immediately, but in Windows Terminal they only apply when a
new tab is opened.
This PR also adds partial support for the `SGR 6` _rapid blink_
attribute. This is not used by DEC terminals, but was defined in the
ECMA/ANSI standards. It's not widely supported, but many terminals just
it implement it as an alias for the regular `SGR 5` blink attribute, so
that's what I've done here too.
## Validation Steps Performed
I've checked the _Graphic rendition test pattern_ in Vttest, and
compared our representation of the blink attribute to that of an actual
DEC VT220 terminal as seen on [YouTube]. With the right color scheme
it's a reasonably close match.
[YouTube]: https://www.youtube.com/watch?v=03Pz5AmxbE4&t=1m55s
Closes #7388
2020-09-22 01:21:33 +02:00
|
|
|
// Method Description:
|
|
|
|
// - return a reference to the console's blinking state.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - a reference to the console's blinking state.
|
|
|
|
BlinkingState& CONSOLE_INFORMATION::GetBlinkingState() const noexcept
|
|
|
|
{
|
|
|
|
return _blinkingState;
|
|
|
|
}
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
// Method Description:
|
Improve conpty rendering of default colors in legacy apps (#6698)
Essentially what this does is map the default legacy foreground and
background attributes (typically white on black) to the `IsDefault`
color type in the `TextColor` class. As a result, we can now initialize
the buffer for "legacy" shells (like PowerShell and cmd.exe) with
default colors, instead of white on black. This fixes the startup
rendering in conpty clients, which expect an initial default background
color. It also makes these colors update appropriately when the default
palette values change.
One complication in getting this to work, is that the console permits
users to change which color indices are designated as defaults, so we
can't assume they'll always be white on black. This means that the
legacy-to-`TextAttribute` conversion will need access to those default
values.
Unfortunately the defaults are stored in the conhost `Settings` class
(the `_wFillAttribute` field), which isn't easily accessible to all the
code that needs to construct a `TextAttribute` from a legacy value. The
`OutputCellIterator` is particularly problematic, because some iterator
types need to generate a new `TextAttribute` on every iteration.
So after trying a couple of different approaches, I decided that the
least worst option would be to add a pair of static properties for the
legacy defaults in the `TextAttribute` class itself, then refresh those
values from the `Settings` class whenever the defaults changed (this
only happens on startup, or when the conhost _Properties_ dialog is
edited).
And once the `TextAttribute` class had access to those defaults, it was
fairly easy to adapt the constructor to handle the conversion of default
values to the `IsDefault` color type. I could also then simplify the
`TextAttribute::GetLegacyAttributes` method which does the reverse
mapping, and which previously required the default values to be passed
in as a parameter
VALIDATION
I had to make one small change to the `TestRoundtripExhaustive` unit
test which assumed that all legacy attributes would convert to legacy
color types, which is no longer the case, but otherwise all the existing
tests passed as is. I added a new unit test verifying that the default
legacy attributes correctly mapped to default color types, and the
default color types were mapped back to the correct legacy attributes.
I've manually confirmed that this fixed the issue raised in #5952,
namely that the conhost screen is cleared with the correct default
colors, and also that it is correctly refreshed when changing the
palette from the properties dialog. And I've combined this PR with
#6506, and confirmed that the PowerShell and the cmd shell renderings in
Windows Terminal are at least improved, if not always perfect.
This is a prerequisite for PR #6506
Closes #5952
2020-07-01 20:08:30 +02:00
|
|
|
// - Generates a CHAR_INFO for this output cell, using the TextAttribute
|
|
|
|
// GetLegacyAttributes method to generate the legacy style attributes.
|
2019-05-03 00:29:04 +02:00
|
|
|
// Arguments:
|
|
|
|
// - cell: The cell to get the CHAR_INFO from
|
|
|
|
// Return Value:
|
|
|
|
// - a CHAR_INFO containing legacy information about the cell
|
|
|
|
CHAR_INFO CONSOLE_INFORMATION::AsCharInfo(const OutputCellView& cell) const noexcept
|
|
|
|
{
|
2019-06-11 22:27:09 +02:00
|
|
|
CHAR_INFO ci{ 0 };
|
2019-05-03 00:29:04 +02:00
|
|
|
ci.Char.UnicodeChar = Utf16ToUcs2(cell.Chars());
|
|
|
|
|
|
|
|
// If the current text attributes aren't legacy attributes, then
|
|
|
|
// use gci to look up the correct legacy attributes to use
|
|
|
|
// (for mapping RGB values to the nearest table value)
|
|
|
|
const auto& attr = cell.TextAttr();
|
Improve conpty rendering of default colors in legacy apps (#6698)
Essentially what this does is map the default legacy foreground and
background attributes (typically white on black) to the `IsDefault`
color type in the `TextColor` class. As a result, we can now initialize
the buffer for "legacy" shells (like PowerShell and cmd.exe) with
default colors, instead of white on black. This fixes the startup
rendering in conpty clients, which expect an initial default background
color. It also makes these colors update appropriately when the default
palette values change.
One complication in getting this to work, is that the console permits
users to change which color indices are designated as defaults, so we
can't assume they'll always be white on black. This means that the
legacy-to-`TextAttribute` conversion will need access to those default
values.
Unfortunately the defaults are stored in the conhost `Settings` class
(the `_wFillAttribute` field), which isn't easily accessible to all the
code that needs to construct a `TextAttribute` from a legacy value. The
`OutputCellIterator` is particularly problematic, because some iterator
types need to generate a new `TextAttribute` on every iteration.
So after trying a couple of different approaches, I decided that the
least worst option would be to add a pair of static properties for the
legacy defaults in the `TextAttribute` class itself, then refresh those
values from the `Settings` class whenever the defaults changed (this
only happens on startup, or when the conhost _Properties_ dialog is
edited).
And once the `TextAttribute` class had access to those defaults, it was
fairly easy to adapt the constructor to handle the conversion of default
values to the `IsDefault` color type. I could also then simplify the
`TextAttribute::GetLegacyAttributes` method which does the reverse
mapping, and which previously required the default values to be passed
in as a parameter
VALIDATION
I had to make one small change to the `TestRoundtripExhaustive` unit
test which assumed that all legacy attributes would convert to legacy
color types, which is no longer the case, but otherwise all the existing
tests passed as is. I added a new unit test verifying that the default
legacy attributes correctly mapped to default color types, and the
default color types were mapped back to the correct legacy attributes.
I've manually confirmed that this fixed the issue raised in #5952,
namely that the conhost screen is cleared with the correct default
colors, and also that it is correctly refreshed when changing the
palette from the properties dialog. And I've combined this PR with
#6506, and confirmed that the PowerShell and the cmd shell renderings in
Windows Terminal are at least improved, if not always perfect.
This is a prerequisite for PR #6506
Closes #5952
2020-07-01 20:08:30 +02:00
|
|
|
ci.Attributes = attr.GetLegacyAttributes();
|
2019-05-03 00:29:04 +02:00
|
|
|
ci.Attributes |= cell.DbcsAttr().GeneratePublicApiAttributeFormat();
|
|
|
|
return ci;
|
|
|
|
}
|