2019-05-03 00:29:04 +02:00
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
#include "Terminal.hpp"
|
|
|
|
#include <DefaultSettings.h>
|
|
|
|
using namespace Microsoft::Terminal::Core;
|
|
|
|
using namespace Microsoft::Console::Types;
|
|
|
|
using namespace Microsoft::Console::Render;
|
|
|
|
|
|
|
|
Viewport Terminal::GetViewport() noexcept
|
|
|
|
{
|
|
|
|
return _GetVisibleViewport();
|
|
|
|
}
|
|
|
|
|
Search - add search box control and implement search experience (#3590)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
This is the PR for feature Search: #605
This PR includes the newly introduced SearchBoxControl in TermControl dir, which is the search bar for the search experience. And the codes that enable Search in Windows Terminal.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
The PR that migrates the Conhost search module: https://github.com/microsoft/terminal/pull/3279
Spec (still actively updating): https://github.com/microsoft/terminal/pull/3299
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #605
* [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
These functionalities are included in the search experience.
1. Search in Terminal text buffer.
2. Automatic wrap-around.
3. Search up or down switch by clicking different buttons.
4. Search case sensitively/insensitively by clicking a button. S. Move the search box to the top/bottom by clicking a button.
6. Close by clicking 'X'.
7. Open search by ctrl + F.
When the searchbox is open, the user could still interact with the terminal by clicking the terminal input area.
While I already have the search functionalities, currently there are still some known to-do works and I will keep updating my PR:
1. Optimize the search box UI, this includes:
1) Theme adaptation. The search box background and font color
should change according to the theme,
2) Add background. Currently the elements in search box are all
transparent. However, we need a background.
3) Move button should be highlighted once clicked.
2. Accessibility: search process should be able to performed without mouse. Once the search box is focused, the user should be able to navigate between all interactive elements on the searchbox using keyboard.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
To test:
1. checkout this branch.
2. Build the project.
3. Start Windows Terminal and press Ctrl+F
4. The search box should appear on the top right corner.
2019-12-17 16:52:37 +01:00
|
|
|
COORD Terminal::GetTextBufferEndPosition() const noexcept
|
|
|
|
{
|
|
|
|
// We use the end line of mutableViewport as the end
|
|
|
|
// of the text buffer, it always moves with the written
|
|
|
|
// text
|
|
|
|
COORD endPosition{ _GetMutableViewport().Width() - 1, gsl::narrow<short>(ViewEndIndex()) };
|
|
|
|
return endPosition;
|
|
|
|
}
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
const TextBuffer& Terminal::GetTextBuffer() noexcept
|
|
|
|
{
|
|
|
|
return *_buffer;
|
|
|
|
}
|
|
|
|
|
2020-01-03 19:44:27 +01:00
|
|
|
// Creating a FontInfo can technically throw (on string allocation) and this is noexcept.
|
|
|
|
// That means this will std::terminate. We could come back and make there be a default constructor
|
|
|
|
// backup to FontInfo that throws no exceptions and allocates a default FontInfo structure.
|
|
|
|
#pragma warning(push)
|
|
|
|
#pragma warning(disable : 26447)
|
2019-05-03 00:29:04 +02:00
|
|
|
const FontInfo& Terminal::GetFontInfo() noexcept
|
|
|
|
{
|
|
|
|
// TODO: This font value is only used to check if the font is a raster font.
|
|
|
|
// Otherwise, the font is changed with the renderer via TriggerFontChange.
|
|
|
|
// The renderer never uses any of the other members from the value returned
|
|
|
|
// by this method.
|
|
|
|
// We could very likely replace this with just an IsRasterFont method
|
|
|
|
// (which would return false)
|
2020-01-27 19:23:13 +01:00
|
|
|
static const FontInfo _fakeFontInfo(DEFAULT_FONT_FACE, TMPF_TRUETYPE, 10, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false);
|
2019-05-03 00:29:04 +02:00
|
|
|
return _fakeFontInfo;
|
|
|
|
}
|
2020-01-03 19:44:27 +01:00
|
|
|
#pragma warning(pop)
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
const TextAttribute Terminal::GetDefaultBrushColors() noexcept
|
|
|
|
{
|
|
|
|
return TextAttribute{};
|
|
|
|
}
|
|
|
|
|
Refactor the renderer color calculations (#6853)
This is a refactoring of the renderer color calculations to simplify the
implementation, and to make it easier to support additional
color-altering rendition attributes in the future (e.g. _faint_ and
_conceal_).
## References
* This is a followup to PRs #3817 and #6809, which introduced additional
complexity in the color calculations, and which suggested the need for
refactoring.
## Detailed Description of the Pull Request / Additional comments
When we added support for `DECSCNM`, that required the foreground and
background color lookup methods to be able to return the opposite of
what was requested when the reversed mode was set. That made those
methods unnecessarily complicated, and I thought we could simplify them
considerably just by combining the calculations into a single method
that derived both colors at the same time.
And since both conhost and Windows Terminal needed to perform the same
calculations, it also made sense to move that functionality into the
`TextAttribute` class, where it could easily be shared.
In general this way of doing things is a bit more efficient. However, it
does result in some unnecessary work when only one of the colors is
required, as is the case for the gridline painter. So to make that less
of an issue, I've reordered the gridline code a bit so it at least
avoids looking up the colors when no gridlines are needed.
## Validation Steps Performed
Because of the API changes, quite a lot of the unit tests had to be
updated. For example instead of verifying colors with two separate calls
to `LookupForegroundColor` and `LookupBackgroundColor`, that's now
achieved with a single `LookupAttributeColors` call, comparing against a
pair of values. The specifics of the tests haven't changed though, and
they're all still working as expected.
I've also manually confirmed that the various color sequences and
rendition attributes are rendering correctly with the new refactoring.
2020-07-11 00:26:34 +02:00
|
|
|
std::pair<COLORREF, COLORREF> Terminal::GetAttributeColors(const TextAttribute& attr) const noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
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
|
|
|
_blinkingState.RecordBlinkingUsage(attr);
|
Refactor the renderer color calculations (#6853)
This is a refactoring of the renderer color calculations to simplify the
implementation, and to make it easier to support additional
color-altering rendition attributes in the future (e.g. _faint_ and
_conceal_).
## References
* This is a followup to PRs #3817 and #6809, which introduced additional
complexity in the color calculations, and which suggested the need for
refactoring.
## Detailed Description of the Pull Request / Additional comments
When we added support for `DECSCNM`, that required the foreground and
background color lookup methods to be able to return the opposite of
what was requested when the reversed mode was set. That made those
methods unnecessarily complicated, and I thought we could simplify them
considerably just by combining the calculations into a single method
that derived both colors at the same time.
And since both conhost and Windows Terminal needed to perform the same
calculations, it also made sense to move that functionality into the
`TextAttribute` class, where it could easily be shared.
In general this way of doing things is a bit more efficient. However, it
does result in some unnecessary work when only one of the colors is
required, as is the case for the gridline painter. So to make that less
of an issue, I've reordered the gridline code a bit so it at least
avoids looking up the colors when no gridlines are needed.
## Validation Steps Performed
Because of the API changes, quite a lot of the unit tests had to be
updated. For example instead of verifying colors with two separate calls
to `LookupForegroundColor` and `LookupBackgroundColor`, that's now
achieved with a single `LookupAttributeColors` call, comparing against a
pair of values. The specifics of the tests haven't changed though, and
they're all still working as expected.
I've also manually confirmed that the various color sequences and
rendition attributes are rendering correctly with the new refactoring.
2020-07-11 00:26:34 +02:00
|
|
|
auto colors = attr.CalculateRgbColors({ _colorTable.data(), _colorTable.size() },
|
|
|
|
_defaultFg,
|
|
|
|
_defaultBg,
|
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
|
|
|
_screenReversed,
|
|
|
|
_blinkingState.IsBlinkingFaint());
|
Refactor the renderer color calculations (#6853)
This is a refactoring of the renderer color calculations to simplify the
implementation, and to make it easier to support additional
color-altering rendition attributes in the future (e.g. _faint_ and
_conceal_).
## References
* This is a followup to PRs #3817 and #6809, which introduced additional
complexity in the color calculations, and which suggested the need for
refactoring.
## Detailed Description of the Pull Request / Additional comments
When we added support for `DECSCNM`, that required the foreground and
background color lookup methods to be able to return the opposite of
what was requested when the reversed mode was set. That made those
methods unnecessarily complicated, and I thought we could simplify them
considerably just by combining the calculations into a single method
that derived both colors at the same time.
And since both conhost and Windows Terminal needed to perform the same
calculations, it also made sense to move that functionality into the
`TextAttribute` class, where it could easily be shared.
In general this way of doing things is a bit more efficient. However, it
does result in some unnecessary work when only one of the colors is
required, as is the case for the gridline painter. So to make that less
of an issue, I've reordered the gridline code a bit so it at least
avoids looking up the colors when no gridlines are needed.
## Validation Steps Performed
Because of the API changes, quite a lot of the unit tests had to be
updated. For example instead of verifying colors with two separate calls
to `LookupForegroundColor` and `LookupBackgroundColor`, that's now
achieved with a single `LookupAttributeColors` call, comparing against a
pair of values. The specifics of the tests haven't changed though, and
they're all still working as expected.
I've also manually confirmed that the various color sequences and
rendition attributes are rendering correctly with the new refactoring.
2020-07-11 00:26:34 +02:00
|
|
|
colors.first |= 0xff000000;
|
2019-05-03 00:29:04 +02:00
|
|
|
// We only care about alpha for the default BG (which enables acrylic)
|
Make sure background color is opaque when attrs are reversed (#5509)
In order to support a transparent background for the acrylic effect, the
renderer sets the alpha value to zero for the default background color.
However, when the _reversed video_ attribute is set, the background is
actually filled with the foreground color, and will not be displayed
correctly if it is made transparent. This PR addresses that issue by
making sure the rendered background color is opaque if the reversed
video attribute is set.
## References
* This is not a major issue at the moment, since the _reverse video_
attribute is not typically forwarded though conpty, but that will
change once #2661 is fixed.
## PR Checklist
* [x] Closes #5498
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not
checked, I'm ready to accept this work might be rejected in favor of a
different grand plan. Issue number where discussion took place: #5498
## Detailed Description of the Pull Request / Additional comments
This simply adds an additional check in `Terminal::GetBackgroundColor`
to make sure the returned color is opaque if the _reverse video_
attribute is set. At some point in the future this check may need to be
extended to support the `DECSCNM` reverse screen mode, but for now
that's not an issue.
## Validation Steps Performed
I've run the test case from issue #5498, and confirmed that it now works
as expected. I've also got an experimental fix for #2661 that I've
tested with this patch, and that now displays _reverse video_ attributes
correctly too.
Closes #5498
2020-04-23 23:35:12 +02:00
|
|
|
// If the bg isn't the default bg color, or reverse video is enabled, make it fully opaque.
|
2020-07-09 13:25:30 +02:00
|
|
|
if (!attr.BackgroundIsDefault() || (attr.IsReverseVideo() ^ _screenReversed))
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
Refactor the renderer color calculations (#6853)
This is a refactoring of the renderer color calculations to simplify the
implementation, and to make it easier to support additional
color-altering rendition attributes in the future (e.g. _faint_ and
_conceal_).
## References
* This is a followup to PRs #3817 and #6809, which introduced additional
complexity in the color calculations, and which suggested the need for
refactoring.
## Detailed Description of the Pull Request / Additional comments
When we added support for `DECSCNM`, that required the foreground and
background color lookup methods to be able to return the opposite of
what was requested when the reversed mode was set. That made those
methods unnecessarily complicated, and I thought we could simplify them
considerably just by combining the calculations into a single method
that derived both colors at the same time.
And since both conhost and Windows Terminal needed to perform the same
calculations, it also made sense to move that functionality into the
`TextAttribute` class, where it could easily be shared.
In general this way of doing things is a bit more efficient. However, it
does result in some unnecessary work when only one of the colors is
required, as is the case for the gridline painter. So to make that less
of an issue, I've reordered the gridline code a bit so it at least
avoids looking up the colors when no gridlines are needed.
## Validation Steps Performed
Because of the API changes, quite a lot of the unit tests had to be
updated. For example instead of verifying colors with two separate calls
to `LookupForegroundColor` and `LookupBackgroundColor`, that's now
achieved with a single `LookupAttributeColors` call, comparing against a
pair of values. The specifics of the tests haven't changed though, and
they're all still working as expected.
I've also manually confirmed that the various color sequences and
rendition attributes are rendering correctly with the new refactoring.
2020-07-11 00:26:34 +02:00
|
|
|
colors.second |= 0xff000000;
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
Refactor the renderer color calculations (#6853)
This is a refactoring of the renderer color calculations to simplify the
implementation, and to make it easier to support additional
color-altering rendition attributes in the future (e.g. _faint_ and
_conceal_).
## References
* This is a followup to PRs #3817 and #6809, which introduced additional
complexity in the color calculations, and which suggested the need for
refactoring.
## Detailed Description of the Pull Request / Additional comments
When we added support for `DECSCNM`, that required the foreground and
background color lookup methods to be able to return the opposite of
what was requested when the reversed mode was set. That made those
methods unnecessarily complicated, and I thought we could simplify them
considerably just by combining the calculations into a single method
that derived both colors at the same time.
And since both conhost and Windows Terminal needed to perform the same
calculations, it also made sense to move that functionality into the
`TextAttribute` class, where it could easily be shared.
In general this way of doing things is a bit more efficient. However, it
does result in some unnecessary work when only one of the colors is
required, as is the case for the gridline painter. So to make that less
of an issue, I've reordered the gridline code a bit so it at least
avoids looking up the colors when no gridlines are needed.
## Validation Steps Performed
Because of the API changes, quite a lot of the unit tests had to be
updated. For example instead of verifying colors with two separate calls
to `LookupForegroundColor` and `LookupBackgroundColor`, that's now
achieved with a single `LookupAttributeColors` call, comparing against a
pair of values. The specifics of the tests haven't changed though, and
they're all still working as expected.
I've also manually confirmed that the various color sequences and
rendition attributes are rendering correctly with the new refactoring.
2020-07-11 00:26:34 +02:00
|
|
|
return colors;
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
COORD Terminal::GetCursorPosition() const noexcept
|
|
|
|
{
|
|
|
|
const auto& cursor = _buffer->GetCursor();
|
|
|
|
return cursor.GetPosition();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Terminal::IsCursorVisible() const noexcept
|
|
|
|
{
|
|
|
|
const auto& cursor = _buffer->GetCursor();
|
|
|
|
return cursor.IsVisible() && !cursor.IsPopupShown();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Terminal::IsCursorOn() const noexcept
|
|
|
|
{
|
|
|
|
const auto& cursor = _buffer->GetCursor();
|
|
|
|
return cursor.IsOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG Terminal::GetCursorPixelWidth() const noexcept
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG Terminal::GetCursorHeight() const noexcept
|
|
|
|
{
|
|
|
|
return _buffer->GetCursor().GetSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
CursorType Terminal::GetCursorStyle() const noexcept
|
|
|
|
{
|
|
|
|
return _buffer->GetCursor().GetType();
|
|
|
|
}
|
|
|
|
|
|
|
|
COLORREF Terminal::GetCursorColor() const noexcept
|
|
|
|
{
|
|
|
|
return _buffer->GetCursor().GetColor();
|
|
|
|
}
|
|
|
|
|
Show a double width cursor for double width characters (#5319)
# Summary of the Pull Request
This PR will allow the cursor to be double width when on top of a double width character. This required changing `IsCursorDoubleWidth` to check whether the glyph the cursor's on top of is double width. This code is exactly the same as the original PR that addressed this issue in #2932. That one got reverted at some point due to the crashes related to it, but due to a combination of Terminal having come further since that PR and other changes to address use-after-frees, some of the crashes may/may not be relevant now. The ones that seemed to be relevant/repro-able, I attempt to address in this PR.
The `IsCursorDoubleWidth` check would fail during the `TextBuffer::Reflow` call inside of `Terminal::UserResize` occasionally, particularly when `newCursor.EndDeferDrawing()` is called. This is because when we tell the newCursor to `EndDefer`, the renderer will attempt to redraw the cursor. As part of this redraw, it'll ask if `IsCursorDoubleWidth`, and if the renderer managed to ask this before `UserResize` swapped out the old buffer with the new one from `Reflow`, the renderer will be asking the old buffer if its out-of-bounds cursor is double width. This was pretty easily repro'd using `cmatrix -u0` and resizing the window like a madman.
As a solution, I've moved the Start/End DeferDrawing calls out of `Reflow` and into `UserResize`. This way, I can "clamp" the portion of the code where the newBuffer is getting created and reflowed and swapped into the Terminal buffer, and only allow the renderer to draw once the swap is done. This also means that ConHost's `ResizeWithReflow` needed to change slightly.
In addition, I've added a WriteLock to `SetCursorOn`. It was mentioned as a fix for a crash in #2965 (although I can't repro), and I also figured it would be good to try to emulate where ConHost locks with regards to Cursor operations, and this seemed to be one that we were missing.
## PR Checklist
* [x] Closes #2713
* [x] CLA signed
* [x] Tests added/passed
## Validation Steps Performed
Manual validation that the cursor is indeed chonky, added a test case to check that we are correctly saying that the cursor is double width (not too sure if I put it in the right place). Also open to other test case ideas and thoughts on what else I should be careful for since I am quite nervous about what other crashes might occur.
2020-04-15 21:23:06 +02:00
|
|
|
bool Terminal::IsCursorDoubleWidth() const
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
Show a double width cursor for double width characters (#5319)
# Summary of the Pull Request
This PR will allow the cursor to be double width when on top of a double width character. This required changing `IsCursorDoubleWidth` to check whether the glyph the cursor's on top of is double width. This code is exactly the same as the original PR that addressed this issue in #2932. That one got reverted at some point due to the crashes related to it, but due to a combination of Terminal having come further since that PR and other changes to address use-after-frees, some of the crashes may/may not be relevant now. The ones that seemed to be relevant/repro-able, I attempt to address in this PR.
The `IsCursorDoubleWidth` check would fail during the `TextBuffer::Reflow` call inside of `Terminal::UserResize` occasionally, particularly when `newCursor.EndDeferDrawing()` is called. This is because when we tell the newCursor to `EndDefer`, the renderer will attempt to redraw the cursor. As part of this redraw, it'll ask if `IsCursorDoubleWidth`, and if the renderer managed to ask this before `UserResize` swapped out the old buffer with the new one from `Reflow`, the renderer will be asking the old buffer if its out-of-bounds cursor is double width. This was pretty easily repro'd using `cmatrix -u0` and resizing the window like a madman.
As a solution, I've moved the Start/End DeferDrawing calls out of `Reflow` and into `UserResize`. This way, I can "clamp" the portion of the code where the newBuffer is getting created and reflowed and swapped into the Terminal buffer, and only allow the renderer to draw once the swap is done. This also means that ConHost's `ResizeWithReflow` needed to change slightly.
In addition, I've added a WriteLock to `SetCursorOn`. It was mentioned as a fix for a crash in #2965 (although I can't repro), and I also figured it would be good to try to emulate where ConHost locks with regards to Cursor operations, and this seemed to be one that we were missing.
## PR Checklist
* [x] Closes #2713
* [x] CLA signed
* [x] Tests added/passed
## Validation Steps Performed
Manual validation that the cursor is indeed chonky, added a test case to check that we are correctly saying that the cursor is double width (not too sure if I put it in the right place). Also open to other test case ideas and thoughts on what else I should be careful for since I am quite nervous about what other crashes might occur.
2020-04-15 21:23:06 +02:00
|
|
|
const auto position = _buffer->GetCursor().GetPosition();
|
|
|
|
TextBufferTextIterator it(TextBufferCellIterator(*_buffer, position));
|
|
|
|
return IsGlyphFullWidth(*it);
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const std::vector<RenderOverlay> Terminal::GetOverlays() const noexcept
|
|
|
|
{
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
const bool Terminal::IsGridLineDrawingAllowed() noexcept
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-09-03 19:52:39 +02:00
|
|
|
const std::wstring Microsoft::Terminal::Core::Terminal::GetHyperlinkUri(uint16_t id) const noexcept
|
|
|
|
{
|
|
|
|
return _buffer->GetHyperlinkUriFromId(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::wstring Microsoft::Terminal::Core::Terminal::GetHyperlinkCustomId(uint16_t id) const noexcept
|
|
|
|
{
|
|
|
|
return _buffer->GetCustomIdFromId(id);
|
|
|
|
}
|
|
|
|
|
2020-10-28 21:24:43 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Gets the regex pattern ids of a location
|
|
|
|
// Arguments:
|
|
|
|
// - The location
|
|
|
|
// Return value:
|
|
|
|
// - The pattern IDs of the location
|
|
|
|
const std::vector<size_t> Terminal::GetPatternId(const COORD location) const noexcept
|
|
|
|
{
|
|
|
|
// Look through our interval tree for this location
|
|
|
|
const auto intervals = _patternIntervalTree.findOverlapping(COORD{ location.X + 1, location.Y }, location);
|
|
|
|
if (intervals.size() == 0)
|
|
|
|
{
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::vector<size_t> result{};
|
|
|
|
for (const auto& interval : intervals)
|
|
|
|
{
|
|
|
|
result.emplace_back(interval.value);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
std::vector<Microsoft::Console::Types::Viewport> Terminal::GetSelectionRects() noexcept
|
2020-01-03 19:44:27 +01:00
|
|
|
try
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
std::vector<Viewport> result;
|
|
|
|
|
|
|
|
for (const auto& lineRect : _GetSelectionRects())
|
|
|
|
{
|
|
|
|
result.emplace_back(Viewport::FromInclusive(lineRect));
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2020-01-03 19:44:27 +01:00
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
LOG_CAUGHT_EXCEPTION();
|
|
|
|
return {};
|
|
|
|
}
|
2019-05-03 00:29:04 +02:00
|
|
|
|
Accessibility: Set-up UIA Tree (#1691)
**The Basics of Accessibility**
- [What is a User Interaction Automation (UIA) Tree?](https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-tree-overview)
- Other projects (i.e.: Narrator) can take advantage of this UIA tree and are used to present information within it.
- Some things like XAML already have a UIA Tree. So some UIA tree navigation and features are already there. It's just a matter of getting them hooked up and looking right.
**Accessibility in our Project**
There's a few important classes...
regarding Accessibility...
- **WindowUiaProvider**: This sets up the UIA tree for a window. So this is the top-level for the UIA tree.
- **ScreenInfoUiaProvider**: This sets up the UIA tree for a terminal buffer.
- **UiaTextRange**: This is essential to interacting with the UIA tree for the terminal buffer. Actually gets portions of the buffer and presents them.
regarding the Windows Terminal window...
- **BaseWindow**: The foundation to a window. Deals with HWNDs and that kind of stuff.
- **IslandWindow**: This extends `BaseWindow` and is actually what holds our Windows Terminal
- **NonClientIslandWindow**: An extension of the `IslandWindow`
regarding ConHost...
- **IConsoleWindow**: This is an interface for the console window.
- **Window**: This is the actual window for ConHost. Extends `IConsoleWindow`
- `IConsoleWindow` changes:
- move into `Microsoft::Console::Types` (a shared space)
- Have `IslandWindow` extend it
- `WindowUiaProvider` changes:
- move into `Microsoft::Console::Types` (a shared space)
- Hook up `WindowUiaProvider` to IslandWindow (yay! we now have a tree)
### Changes to the WindowUiaProvider
As mentioned earlier, the WindowUiaProvider is the top-level UIA provider for our projects. To reuse as much code as possible, I created `Microsoft::Console::Types::WindowUiaProviderBase`. Any existing functions that reference a `ScreenInfoUiaProvider` were virtual-ized.
In each project, a `WindowUiaProvider : WindowUiaProviderBase` was created to define those virtual functions. Note that that will be the main difference between ConHost and Windows Terminal moving forward: how many TextBuffers are on the screen.
So, ConHost should be the same as before, with only one `ScreenInfoUiaProvider`, whereas Windows Terminal needs to (1) update which one is on the screen and (2) may have multiple on the screen.
🚨 Windows Terminal doesn't have the `ScreenInfoUiaProvider` hooked up yet. We'll have all the XAML elements in the UIA tree. But, since `TermControl` is a custom XAML Control, I need to hook up the `ScreenInfoUiaProvider` to it. This work will be done in a new PR and resolve GitHub Issue #1352.
### Moved to `Microsoft::Console::Types`
These files got moved to a shared area so that they can be used by both ConHost and Windows Terminal.
This means that any references to the `ServiceLocator` had to be removed.
- `IConsoleWindow`
- Windows Terminal: `IslandWindow : IConsoleWindow`
- `ScreenInfoUiaProvider`
- all references to `ServiceLocator` and `SCREEN_INFORMATION` were removed. `IRenderData` was used to accomplish this. Refer to next section for more details.
- `UiaTextRange`
- all references to `ServiceLocator` and `SCREEN_INFORMATION` were removed. `IRenderData` was used to accomplish this. Refer to next section for more details.
- since most of the functions were `static`, that means that an `IRenderData` had to be added into most of them.
### Changes to IRenderData
Since `IRenderData` is now being used to abstract out `ServiceLocator` and `SCREEN_INFORMATION`, I had to add a few functions here:
- `bool IsAreaSelected()`
- `void ClearSelection()`
- `void SelectNewRegion(...)`
- `HRESULT SearchForText(...)`
`SearchForText()` is a problem here. The overall new design is great! But Windows Terminal doesn't have a way to search for text in the buffer yet, whereas ConHost does. So I'm punting on this issue for now. It looks nasty, but just look at all the other pretty things here. :)
2019-07-30 00:21:15 +02:00
|
|
|
void Terminal::SelectNewRegion(const COORD coordStart, const COORD coordEnd)
|
|
|
|
{
|
2020-01-03 19:44:27 +01:00
|
|
|
#pragma warning(push)
|
|
|
|
#pragma warning(disable : 26496) // cpp core checks wants these const, but they're decremented below.
|
Search - add search box control and implement search experience (#3590)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
This is the PR for feature Search: #605
This PR includes the newly introduced SearchBoxControl in TermControl dir, which is the search bar for the search experience. And the codes that enable Search in Windows Terminal.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
The PR that migrates the Conhost search module: https://github.com/microsoft/terminal/pull/3279
Spec (still actively updating): https://github.com/microsoft/terminal/pull/3299
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #605
* [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
These functionalities are included in the search experience.
1. Search in Terminal text buffer.
2. Automatic wrap-around.
3. Search up or down switch by clicking different buttons.
4. Search case sensitively/insensitively by clicking a button. S. Move the search box to the top/bottom by clicking a button.
6. Close by clicking 'X'.
7. Open search by ctrl + F.
When the searchbox is open, the user could still interact with the terminal by clicking the terminal input area.
While I already have the search functionalities, currently there are still some known to-do works and I will keep updating my PR:
1. Optimize the search box UI, this includes:
1) Theme adaptation. The search box background and font color
should change according to the theme,
2) Add background. Currently the elements in search box are all
transparent. However, we need a background.
3) Move button should be highlighted once clicked.
2. Accessibility: search process should be able to performed without mouse. Once the search box is focused, the user should be able to navigate between all interactive elements on the searchbox using keyboard.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
To test:
1. checkout this branch.
2. Build the project.
3. Start Windows Terminal and press Ctrl+F
4. The search box should appear on the top right corner.
2019-12-17 16:52:37 +01:00
|
|
|
COORD realCoordStart = coordStart;
|
|
|
|
COORD realCoordEnd = coordEnd;
|
2020-01-03 19:44:27 +01:00
|
|
|
#pragma warning(pop)
|
Search - add search box control and implement search experience (#3590)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
This is the PR for feature Search: #605
This PR includes the newly introduced SearchBoxControl in TermControl dir, which is the search bar for the search experience. And the codes that enable Search in Windows Terminal.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
The PR that migrates the Conhost search module: https://github.com/microsoft/terminal/pull/3279
Spec (still actively updating): https://github.com/microsoft/terminal/pull/3299
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #605
* [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
These functionalities are included in the search experience.
1. Search in Terminal text buffer.
2. Automatic wrap-around.
3. Search up or down switch by clicking different buttons.
4. Search case sensitively/insensitively by clicking a button. S. Move the search box to the top/bottom by clicking a button.
6. Close by clicking 'X'.
7. Open search by ctrl + F.
When the searchbox is open, the user could still interact with the terminal by clicking the terminal input area.
While I already have the search functionalities, currently there are still some known to-do works and I will keep updating my PR:
1. Optimize the search box UI, this includes:
1) Theme adaptation. The search box background and font color
should change according to the theme,
2) Add background. Currently the elements in search box are all
transparent. However, we need a background.
3) Move button should be highlighted once clicked.
2. Accessibility: search process should be able to performed without mouse. Once the search box is focused, the user should be able to navigate between all interactive elements on the searchbox using keyboard.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
To test:
1. checkout this branch.
2. Build the project.
3. Start Windows Terminal and press Ctrl+F
4. The search box should appear on the top right corner.
2019-12-17 16:52:37 +01:00
|
|
|
|
|
|
|
bool notifyScrollChange = false;
|
|
|
|
if (coordStart.Y < _VisibleStartIndex())
|
|
|
|
{
|
|
|
|
// recalculate the scrollOffset
|
|
|
|
_scrollOffset = ViewStartIndex() - coordStart.Y;
|
|
|
|
notifyScrollChange = true;
|
|
|
|
}
|
|
|
|
else if (coordEnd.Y > _VisibleEndIndex())
|
|
|
|
{
|
|
|
|
// recalculate the scrollOffset, note that if the found text is
|
|
|
|
// beneath the current visible viewport, it may be within the
|
|
|
|
// current mutableViewport and the scrollOffset will be smaller
|
|
|
|
// than 0
|
|
|
|
_scrollOffset = std::max(0, ViewStartIndex() - coordStart.Y);
|
|
|
|
notifyScrollChange = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (notifyScrollChange)
|
|
|
|
{
|
2020-05-08 23:48:23 +02:00
|
|
|
_buffer->GetRenderTarget().TriggerScroll();
|
Search - add search box control and implement search experience (#3590)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
This is the PR for feature Search: #605
This PR includes the newly introduced SearchBoxControl in TermControl dir, which is the search bar for the search experience. And the codes that enable Search in Windows Terminal.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
The PR that migrates the Conhost search module: https://github.com/microsoft/terminal/pull/3279
Spec (still actively updating): https://github.com/microsoft/terminal/pull/3299
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #605
* [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Requires documentation to be updated
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
These functionalities are included in the search experience.
1. Search in Terminal text buffer.
2. Automatic wrap-around.
3. Search up or down switch by clicking different buttons.
4. Search case sensitively/insensitively by clicking a button. S. Move the search box to the top/bottom by clicking a button.
6. Close by clicking 'X'.
7. Open search by ctrl + F.
When the searchbox is open, the user could still interact with the terminal by clicking the terminal input area.
While I already have the search functionalities, currently there are still some known to-do works and I will keep updating my PR:
1. Optimize the search box UI, this includes:
1) Theme adaptation. The search box background and font color
should change according to the theme,
2) Add background. Currently the elements in search box are all
transparent. However, we need a background.
3) Move button should be highlighted once clicked.
2. Accessibility: search process should be able to performed without mouse. Once the search box is focused, the user should be able to navigate between all interactive elements on the searchbox using keyboard.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
To test:
1. checkout this branch.
2. Build the project.
3. Start Windows Terminal and press Ctrl+F
4. The search box should appear on the top right corner.
2019-12-17 16:52:37 +01:00
|
|
|
_NotifyScrollEvent();
|
|
|
|
}
|
|
|
|
|
|
|
|
realCoordStart.Y -= gsl::narrow<short>(_VisibleStartIndex());
|
|
|
|
realCoordEnd.Y -= gsl::narrow<short>(_VisibleStartIndex());
|
|
|
|
|
|
|
|
SetSelectionAnchor(realCoordStart);
|
2020-02-28 01:42:26 +01:00
|
|
|
SetSelectionEnd(realCoordEnd, SelectionExpansionMode::Cell);
|
Accessibility: Set-up UIA Tree (#1691)
**The Basics of Accessibility**
- [What is a User Interaction Automation (UIA) Tree?](https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-tree-overview)
- Other projects (i.e.: Narrator) can take advantage of this UIA tree and are used to present information within it.
- Some things like XAML already have a UIA Tree. So some UIA tree navigation and features are already there. It's just a matter of getting them hooked up and looking right.
**Accessibility in our Project**
There's a few important classes...
regarding Accessibility...
- **WindowUiaProvider**: This sets up the UIA tree for a window. So this is the top-level for the UIA tree.
- **ScreenInfoUiaProvider**: This sets up the UIA tree for a terminal buffer.
- **UiaTextRange**: This is essential to interacting with the UIA tree for the terminal buffer. Actually gets portions of the buffer and presents them.
regarding the Windows Terminal window...
- **BaseWindow**: The foundation to a window. Deals with HWNDs and that kind of stuff.
- **IslandWindow**: This extends `BaseWindow` and is actually what holds our Windows Terminal
- **NonClientIslandWindow**: An extension of the `IslandWindow`
regarding ConHost...
- **IConsoleWindow**: This is an interface for the console window.
- **Window**: This is the actual window for ConHost. Extends `IConsoleWindow`
- `IConsoleWindow` changes:
- move into `Microsoft::Console::Types` (a shared space)
- Have `IslandWindow` extend it
- `WindowUiaProvider` changes:
- move into `Microsoft::Console::Types` (a shared space)
- Hook up `WindowUiaProvider` to IslandWindow (yay! we now have a tree)
### Changes to the WindowUiaProvider
As mentioned earlier, the WindowUiaProvider is the top-level UIA provider for our projects. To reuse as much code as possible, I created `Microsoft::Console::Types::WindowUiaProviderBase`. Any existing functions that reference a `ScreenInfoUiaProvider` were virtual-ized.
In each project, a `WindowUiaProvider : WindowUiaProviderBase` was created to define those virtual functions. Note that that will be the main difference between ConHost and Windows Terminal moving forward: how many TextBuffers are on the screen.
So, ConHost should be the same as before, with only one `ScreenInfoUiaProvider`, whereas Windows Terminal needs to (1) update which one is on the screen and (2) may have multiple on the screen.
🚨 Windows Terminal doesn't have the `ScreenInfoUiaProvider` hooked up yet. We'll have all the XAML elements in the UIA tree. But, since `TermControl` is a custom XAML Control, I need to hook up the `ScreenInfoUiaProvider` to it. This work will be done in a new PR and resolve GitHub Issue #1352.
### Moved to `Microsoft::Console::Types`
These files got moved to a shared area so that they can be used by both ConHost and Windows Terminal.
This means that any references to the `ServiceLocator` had to be removed.
- `IConsoleWindow`
- Windows Terminal: `IslandWindow : IConsoleWindow`
- `ScreenInfoUiaProvider`
- all references to `ServiceLocator` and `SCREEN_INFORMATION` were removed. `IRenderData` was used to accomplish this. Refer to next section for more details.
- `UiaTextRange`
- all references to `ServiceLocator` and `SCREEN_INFORMATION` were removed. `IRenderData` was used to accomplish this. Refer to next section for more details.
- since most of the functions were `static`, that means that an `IRenderData` had to be added into most of them.
### Changes to IRenderData
Since `IRenderData` is now being used to abstract out `ServiceLocator` and `SCREEN_INFORMATION`, I had to add a few functions here:
- `bool IsAreaSelected()`
- `void ClearSelection()`
- `void SelectNewRegion(...)`
- `HRESULT SearchForText(...)`
`SearchForText()` is a problem here. The overall new design is great! But Windows Terminal doesn't have a way to search for text in the buffer yet, whereas ConHost does. So I'm punting on this issue for now. It looks nasty, but just look at all the other pretty things here. :)
2019-07-30 00:21:15 +02:00
|
|
|
}
|
|
|
|
|
2019-05-03 00:29:04 +02:00
|
|
|
const std::wstring Terminal::GetConsoleTitle() const noexcept
|
2020-01-03 19:44:27 +01:00
|
|
|
try
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
2020-06-09 23:47:13 +02:00
|
|
|
if (_title.has_value())
|
|
|
|
{
|
|
|
|
return _title.value();
|
|
|
|
}
|
|
|
|
return _startingTitle;
|
2019-05-03 00:29:04 +02:00
|
|
|
}
|
2020-01-03 19:44:27 +01:00
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
LOG_CAUGHT_EXCEPTION();
|
|
|
|
return {};
|
|
|
|
}
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Lock the terminal for reading the contents of the buffer. Ensures that the
|
|
|
|
// contents of the terminal won't be changed in the middle of a paint
|
|
|
|
// operation.
|
|
|
|
// Callers should make sure to also call Terminal::UnlockConsole once
|
|
|
|
// they're done with any querying they need to do.
|
2019-06-11 22:27:09 +02:00
|
|
|
void Terminal::LockConsole() noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_readWriteLock.lock_shared();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Unlocks the terminal after a call to Terminal::LockConsole.
|
2019-06-11 22:27:09 +02:00
|
|
|
void Terminal::UnlockConsole() noexcept
|
2019-05-03 00:29:04 +02:00
|
|
|
{
|
|
|
|
_readWriteLock.unlock_shared();
|
|
|
|
}
|
2020-03-13 01:54:43 +01:00
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Returns whether the screen is inverted;
|
|
|
|
// Return Value:
|
|
|
|
// - false.
|
|
|
|
bool Terminal::IsScreenReversed() const noexcept
|
|
|
|
{
|
2020-07-09 13:25:30 +02:00
|
|
|
return _screenReversed;
|
2020-03-13 01:54:43 +01:00
|
|
|
}
|