* Repurposes `_sendInputToConnection` to send output to the connection
no matter whether the terminal is read-only or not.
Now `SendInput` is the function responsible for the UI handling.
* Buffers responses in a VT string into a single string
before sending it as a response all at once.
This reduces the chances for the UI thread to insert cursor positions
and similar into the input pipe, because we're not constantly unlocking
the terminal lock anymore for every response. The only way now that
unrelated inputs are inserted into the input pipe is because the VT
requests (e.g. DA1, DSR, etc.) are broken up across >1 reads.
This also fixes VT responses in read-only panes.
Closes#17775
* Repeatedly run `echo ^[[c` in cmd.
DA1 responses don't stack & always stay the same ✅
* Run nvim in WSL. Doesn't deadlock when pasting 1MB. ✅
* Run the repro from #17775, which requests a ton of OSC 4
(color palette) responses. Jiggle the cursor on top of the window.
Responses never get split up. ✅
(cherry picked from commit b07589e7a87e1d7a2f6144744a59c866c672a78e)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSK_Dw
Service-Version: 1.21
This is fallout from #16937.
* Typing a command then backspacing the chars then asking for
suggestions would think the current commandline ended with spaces,
making filtering very hard.
* The currently typed command would _also_ appear in the command
history, which isn't useful.
I actually did TDD for this and wrote the test first, then confirmed
again running through the build script, I wasn't hitting any of the
earlier issues.
Closes#17241Closes#17243
(cherry picked from commit bf8a647788f2ca9632bb6c9ab508419e79566754)
Service-Card-Id: 92638413
Service-Version: 1.21
We use `if (auto self = weakSelf.get())` in a lot of places.
That assigns the value to `self` and then checks if it's truthy.
Sometimes we need to add a "is (app) closing" check because XAML,
so we wrote something akin to `if (self = ...; !closing)`.
But that's wrong because the correct `if (foo)` is the same as
`if (void; foo)` and not `if (foo; void)` and that meant that
we didn't check for `self`'s truthiness anymore.
This issue became apparent now, because we added a new kind of
delayed callback invocation (which is a lot cheaper).
This made the lack of a `nullptr` check finally obvious.
(cherry picked from commit 6d0342f0bb31bf245843411c6781d6d5399ff651)
Service-Card-Id: 92509288
Service-Version: 1.21
Due to #16821 everything about #16104 broke. This PR rights the wrongs
by rewriting all the `Font`-based code to not use `Font` at all.
Instead we split the font spec once into font families, do a lot of
complex logic to split font axes/features into used and unused ones
and construct all the UI elements. So. much. boilerplate. code.
Closes#16943
## Validation Steps Performed
There are more edge cases than I can list here... Some ideas:
* Edit the settings.json with invalid axis/feature keys ✅
* ...out of range values ✅
* Settings UI reloads when the settings.json changes ✅
* Adding axes/features works ✅
* Removing axes/features works ✅
* Resetting axes/features works ✅
* Axes/features apply in the renderer when saving ✅
I think this subtly regressed in #16611. Jump to
90b8bb7c2d (diff-f9112caf8cb75e7a48a7b84987724d754181227385fbfcc2cc09a879b1f97c12L171-L223)
`Terminal::SelectNewRegion` is the only thing that uses the return value
from `Terminal::_ScrollToPoints`. Before that PR, `_ScrollToPoints` was
just a part of `SelectNewRegion`, and it moved the start & end coords by
the `_VisibleStartIndex`, not the `_scrollOffset`.
Kinda weird there weren't any _other_ tests for `SelectNewRegion`?
I also caught a second bug while I was here - If you had a line with an
exact wrap, and tried to select that like with selectOutput, we'd
explode.
Closes#17131
This addresses a review comment left by tusharsnx in #17092 which I
forgot to fix before merging the PR. The fix itself is somewhat simple:
`Terminal::SetSearchHighlightFocused` triggers a scroll if the target
is outside of the current (scrolled) viewport and avoiding the call
unless necessary fixes it. To do it properly though, I've split up
`Search::ResetIfStale` into `IsStale` and `Reset`. Now we can properly
detect staleness in advance and branch out the search reset cleanly.
Additionally, I've taken the liberty to replace the `IVector` in
`SearchResultRows` with a direct `const std::vector&` into `Searcher`.
This removes a bunch of code and makes it faster to boot.
## Validation Steps Performed
* Print lots of text
* Search a common letter
* Scroll up
* Doesn't scroll back down ✅
* Hold enter to search more occurrences scrolls up as needed ✅
* `showMarksOnScrollbar` still works ✅
These changes were automatically generated by clang-tidy.
```
clang-tidy --checks=modernize-avoid-bind --fix
```
I have not bothered with the test code.
---------
Co-authored-by: Mike Griese <migrie@microsoft.com>
This shouldn't have ever worked...? This looks like it was a typo and
should have been `mark.end`.
Thanks @joadoumie for asking about the moving the cursor in the prompt,
that convo lead to me finding this.
This adds a system message which displays the time at which the
buffer snapshot was written to disk.
Additionally, this PR moves the snapshot loading into a background
thread, so that the UI thread is unblocked and that multiple
tabs/panes can load simultaneously.
Closes#17031Closes#17074
## Validation Steps Performed
Repeatedly closing and opening WT adds more and more messages.
Currently, the messages get somewhat corrupted due to a bug
in our line-wrap handling, or some similar part.
This PR extends `til::throttled_func` to also support debouncing:
* throttling: "At most 1 call every N seconds"
* debouncing: "Exactly 1 call after N seconds of inactivity"
Based on the latter the following series of changes were made:
* An `OutputIdle` event was added to `ControlCore` which is
raised once there hasn't been any incoming data in 100ms.
This also triggers an update of our regex patterns (URL detection).
* The event is then caught by `TermControl` which calls `Search()`.
* `Search()` in turn was modified to return its results by-value
as a struct, which avoids the need for a search-update event
and simplifies how we update the UI.
This architectural change, most importantly the removal of the
`TextLayoutUpdated` event, fixes a DoS bug in Windows Terminal:
As the event leads to UI thread activity, printing lots of text
continuously results in the UI thread becoming unresponsive.
On top of these, a number of improvements were made:
* `IRenderEngine::InvalidateHighlight` was changed to take the
`TextBuffer` by-reference which avoids the need to accumulate the
line renditions in a `std::vector` first. This improves Debug build
performance during reflow by what I guess must be roughly
a magnitude faster. This difference is very noticeable.
* When closing the search box, `ClearSearch()` is called to remove
the highlights. The search text is restored when it's reopened,
however the current search position isn't.
Closes#17073Closes#17089
## Validation Steps Performed
* UIA announcements:
* Pressing Ctrl+Shift+F the first time does not lead to one ✅
* Typing the first letter does ✅
* Closing doesn't ✅
* Reopening does (as it restores the letter) ✅
* Closing the search box dismisses the highlights ✅
* Resizing the window recalculates the highlights ✅
* Changing the terminal output while the box is open
recalculates the highlights ✅
While `double` is probably generally preferable for UI code,
our application is essentially a complex wrapper wrapper around
DWrite, D2D and D3D, all of which use `float` exclusively.
Of course it also uses XAML, but that one uses `float` for roughly
1/3rd of its API functions, so I'm not sure what it prefers.
Additionally, it's mostly a coincidence that we use WinUI/XAML for
Windows Terminal whereas DWrite/D2D/D3D are effectively essential.
This is demonstrated by the fact that we have a `HwndTerminal`,
while there's no alternative to e.g. D3D on Windows.
The goal of this PR is that DIP based calculations never end up
mixing `float` and `double`. This PR also changes opacity-related
values to `float` because I felt like that fits the theme.
Next in the popular series of minor refactorings:
Out with the old, in with the new!
This PR removes all of the existing TSF code, both for conhost and
Windows Terminal. conhost's TSF implementation was awful:
It allocated an entire text buffer _per line_ of input.
Additionally, its implementation spanned a whopping 40 files and
almost 5000 lines of code. Windows Terminal's implementation was
absolutely fine in comparison, but it was user unfriendly due to
two reasons: Its usage of the `CoreTextServices` WinRT API indirectly
meant that it used a non-transitory TSF document, which is not the
right choice for a terminal. A `TF_SS_TRANSITORY` document (-context)
indicates to TSF that it cannot undo a previously completed composition
which is exactly what we need: Once composition has completed we send
the result to the shell and we cannot undo this later on.
The WinRT API does not allow us to use `TF_SS_TRANSITORY` and so it's
unsuitable for our application. Additionally, the implementation used
XAML to render the composition instead of being part of our text
renderer, which resulted in the text looking weird and hard to read.
The new implementation spans just 8 files and is ~1000 lines which
should make it significantly easier to maintain. The architecture is
not particularly great, but it's certainly better than what we had.
The implementation is almost entirely identical between both conhost
and Windows Terminal and thus they both also behave identical.
It fixes an uncountable number of subtle bugs in the conhost TSF
implementation, as it failed to check for status codes after calls.
It also adds several new features, like support for wavy underlines
(as used by the Japanese IME), dashed underlines (the default for
various languages now, like Vietnamese), colored underlines,
colored foreground/background controlled by the IME, and more!
I have tried to replicate the following issues and have a high
confidence that they're resolved now:
Closes#1304Closes#3730Closes#4052Closes#5007 (as it is not applicable anymore)
Closes#5110Closes#6186Closes#6192Closes#13805Closes#14349Closes#14407Closes#16180
For the following issues I'm not entirely sure if it'll fix it,
but I suspect it's somewhat likely:
#13681#16305#16817
Lastly, there's one remaining bug that I don't know how to resolve.
However, that issue also plagues conhost and Windows Terminal
right now, so it's at least not a regression:
* Press Win+. (emoji picker) and close it
* Move the window around
* Press Win+.
This will open the emoji picker at the old window location.
It also occurs when the cursor moves within the window.
While this is super annoying, I could not find a way to fix it.
## Validation Steps Performed
* See the above closed issues
* Use Vietnamese Telex and type "xin choaf"
Results in "xin chào" ✅
* Use the MS Japanese IME and press Alt+`
Toggles between the last 2 modes ✅
* Use the MS Japanese IME, type "kyouhaishaheiku", and press Space
* The text is converted, underlined and the first part is
doubly underlined ✅
* Left/Right moves between the 3 segments ✅
* Home/End moves between start/end ✅
* Esc puts a wavy line under the current segment ✅
* Use the Korean IME, type "gksgks"
This results in "한한" ✅
* Use the Korean IME, type "gks", and press Right Ctrl
Opens a popup which allows you to navigate with Arrow/Tab keys ✅
### The changeset involves:
- Decoupling Selection and Search Highlighting code paths.
- We no longer invalidate search highlights when:
- Left-clicking on terminal
- A new selection is made
- Left-clicking on Search-box
- Dispatching Find Next/Prev Match Action. (The search highlight was
removed after pressing the first key of the Action's key combination)
- And, anything that doesn't change buffer content, shouldn't invalidate
the highlighted region (E.g. Cursor movement)
- Highlighting foreground color is *actually* applied to the highlighted
text.
- Double-clicking on SearchBox no longer starts a text selection in the
terminal.
- Selected text is properly populated in the Search Box (#16355)
Closes: #16355

## Some Implementation Details
### Detecting text layout changes in the Control layer
As Search Highlight regions need to be removed when new text is added,
or the existing text is re-arranged due to window resize or similar
events, a new event `TextLayoutUpdated` is added that notifies
`CoreControl` of any text layout changes. The event is used to
invalidate and remove all search highlight regions from the buffer
(because the regions might not be _fresh_ anymore.
The new event is raised when:
1. `AdaptDispatch` writes new text into the buffer.
2. MainBuffer is switched to AltBuffer or vice-versa.
3. The user resized the window.
4. Font size changed.
5. Zoom level changed.
(Intensionally,) It's not raised when:
1. Buffer is scrolled.
2. The text cursor is moved.
When `ControlCore` receives a `TextLayoutUpdated` event, it clears the
Search Highlights in the *render data*, and raises an
`UpdateSearchResults` event to notify `TermControl` to update the Search
UI (`SearchBoxControl`).
In the future, we can use `TextLayoutUpdated` event to start a new
search which would refresh the results automatically after a slight
delay (throttled). *VSCode already does this today*.
### How does AtlasEngine draw the highlighted regions?
We follow a similar idea as for drawing the Selection region. When new
regions are available, the old+new regions are marked invalidated.
Later, a call to `_drawHighlighted()` is made at the end of
`PaintBufferLine()` to override the highlighted regions' colors with
highlight colors. The highlighting colors replace the buffer colors
while search highlights are active.
Note that to paint search highlights, we currently invalidate the row
completely. This forces text shaping for the rows in the viewport that
have at least one highlighted region. This is done to keep the (already
lengthy) PR... simple. We could take advantage of the fact that only
colors have changed and not the characters (or glyphs). I'm expecting
that this could be improved like:
1. When search regions are added, we add the highlighting colors to the
color bitmaps without causing text shaping.
2. When search regions are removed, we re-fill the color bitmaps with
the original colors from the Buffer.
## Validation Steps:
- New text, window resize, font size changes, zooming, and pasting
content into the terminal removes search highlights.
- highlighting colors override the foreground and background color of
the text (in the rendered output).
- Blinking, faded, reverse video, Intense text is highlighted as
expected.
In the spirit of #15360 this implements the copy part.
The problem is that we have an issue accessing the clipboard while
other applications continue to work just fine. The major difference
between us and the others is that we use the WinRT clipboard APIs.
So, the idea is that we just use the Win32 APIs instead.
The feel-good side-effect is that this is (no joke) 200-1000x faster,
but I suspect no one will notice the -3ms difference down to <0.01ms.
The objective effect however is that it just works.
This may resolve#16982.
## Validation Steps Performed
* Cycle through Text/HTML/RTF-only in the Interaction settings
* Paste the contents into Word each time
* Text is plain and HTML/RTF are colored ✅
Performance of printing enwik8.txt at the following block sizes:
4KiB (printf): 53MB/s -> 58MB/s
128KiB (cat): 170MB/s -> 235MB/s
This commit is imperfect. Support for more than one rendering
engine was "hacked" into `Renderer` and is not quite correct.
As such, this commit cannot fix cursor invalidation correctly either,
and while some bugs are fixed (engines may see highly inconsistent
TextBuffer and Cursor states), it introduces others (an error in the
first engine may result in the second engine not executing).
Neither of those are good and the underlying issue remains to be fixed.
## Validation Steps Performed
* Seems ok? ✅
This is pretty much a huge refactoring of how marks are stored in the
buffer.
Gone is the list of `ScrollMark`s in the buffer that store regions of
text as points marking the ends. Those would be nigh impossible to
reflow nicely.
Instead, we're going to use `TextAttribute`s to store the kind of output
we've got - `Prompt`, `Command`, `Output`, or, the default, `None`.
Those already reflow nicely!
But we also need to store things like, the exit code for the command.
That's why we've now added `ScrollbarData` to `ROW`s. There's really
only going to be one prompt->output on a single row. So, we only need to
store one ScrollbarData per-row. When a command ends, we can just go
update the mark on the row that started that command.
But iterating over the whole buffer to find the next/previous
prompt/command/output region sounds complicated. So, to avoid everyone
needing to do some variant of that, we've added `MarkExtents` (which is
literally just the same mark structure as before). TextBuffer can figure
out where all the mark regions are, and hand that back to callers. This
allows ControlCore to be basically unchanged.
_But collecting up all the regions for all the marks sounds expensive!
We need to update the scrollbar frequently, we can't just collect those
up every time!_ No we can't! But we also don't need to. The scrollbar
doesn't need to know where all the marks start and end and if they have
commands and this and that - no. We only need to know the rows that have
marks on them. So, we've now also got `ScrollMark` to represent just a
mark on a scrollbar at a specific row on the buffer. We can get those
quickly.
* [x] I added a bunch of tests for this.
* [x] I played with it and it feels good, even after a reflow (finally)
* See:
* #11000
* #15057 (I'm not marking this as closed. The stacked PR will close
this, when I move marks to Stable)
This changeset allows Windows Terminal to dump its buffer contents as
UTF-16LE VT text onto disk and restore it later. This functionality is
enabled whenever `persistedWindowLayout` is being used.
Closes#961Closes#16741
## Validation Steps Performed
* Open multiple windows with multiple tabs and restart the app
Everything's restored ✅
* Reopen a tab with output from `RenderingTests.exe`
Everything's restored ✅
* Closing tabs and windows with Ctrl+W deletes their buffer dumps ✅
* Closing tabs doesn't create buffer dumps ✅
This adds support for specifying more than one font family using a
syntax that is similar to CSS' `font-family` property.
The implementation is straight-forward and is effectively
just a wrapper around `IDWriteFontFallbackBuilder`.
Closes#2664
## PR Checklist
* Font fallback
* Write "「猫」"
* Use "Consolas" and remember the shape of the glyphs
* Use "Consolas, MS Gothic" and check that it changed ✅
* Settings UI autocompletion
* It completes ✅
* It filters ✅
* It recognizes commas and starts a new name ✅
* All invalid font names are listed in the warning message ✅
---------
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
This implements `SetForceFullRepaintRendering` and adds a new
`SetGraphicsAPI` function. The former toggles `Present1` on and off
and the latter allows users to explicitly request Direct2D/3D.
On top of these changes I did a minor cleanup of the interface,
because now that DxRenderer is gone we don't need all that anymore.
Closes#14254Closes#16747
## Validation Steps Performed
* Toggling Direct2D on/off changes colored ligature support ✅
* Toggling Present1 on/off can be observed in a debugger ✅
* Toggling WARP on/off changes GPU metrics ✅
---------
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
This PR automagically finds and replaces all[^1] usages of our
TYPED_EVENT macro with `til::event`. Benefits include:
* less macro magic
* editors are more easily able to figure out the relationship between
`til::event<> Foo;`, `Foo.raise(...)`, and `bar.Foo({this,
&Bar::FooHandler})` (whereas before the relationship between
`_FooHandlers(...)` and `bar.Foo({...})`) couldn't be figured out by
vscode & sublime.
Other find & replace work that had to be done:
* I added the `til::typed_event<>` == `<IInspectable, IInspectable>`
thing from #16170, since that is goodness
* I actually fixed `til::property_changed_event`, so you can use that
for your property changed events. They're all the same anyways.
* events had to come before `WINRT_PROPERTY`s, since the latter macro
leaves us in a `private:` block
* `Pane::SetupChildCloseHandlers` I had to swap _back_, because the
script thought that was an event 🤦
* `ProfileViewModel::DeleteProfile` had to be renamed
`DeleteProfileRequested`, since there was already a `DeleteProfile`
method on it.
* WindowManager.cpp was directly wiring up it's `winrt::event`s to the
monarch & peasant. That doesn't work with `til::event`s and I'm kinda
surprised it ever did
<details>
<summary>The script in question</summary>
```py
import os
import re
def replace_in_file(file_path, file_name):
with open(file_path, 'r', encoding="utf8") as file:
content = file.read()
found_matches = False
# Define the pattern for matching
pattern = r' WINRT_CALLBACK\((\w+),\s*(.*?)\);'
event_matches = re.findall(pattern, content)
if event_matches:
found_matches = True
print(f'found events in {file_path}:')
for match in event_matches:
name = match[0]
args = match[1]
if name == "newConnection" and file_name == "ConptyConnection.cpp":
# This one is special
continue
old_declaration = 'WINRT_CALLBACK(' + name + ', ' + args + ');'
new_declaration = 'til::event<' + args + '> ' + name + ';' if name != "PropertyChanged" else 'til::property_changed_event PropertyChanged;'
print(f' {old_declaration} -> {new_declaration}')
content = content.replace(old_declaration, new_declaration)
typed_event_pattern = r' TYPED_EVENT\((\w+),\s*(.*?)\);'
typed_matches = re.findall(typed_event_pattern, content)
if typed_matches:
found_matches = True
print(f'found typed_events in {file_path}:')
for match in typed_matches:
name = match[0]
args = match[1]
if name == "newConnection" and file_name == "ConptyConnection.cpp":
# This one is special
continue
old_declaration = f'TYPED_EVENT({name}, {args});'
was_inspectable = (args == "winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable" ) or (args == "IInspectable, IInspectable" )
new_declaration = f'til::typed_event<{args}> {name};' if not was_inspectable else f"til::typed_event<> {name};"
print(f' {old_declaration} -> {new_declaration}')
content = content.replace(old_declaration, new_declaration)
handlers_pattern = r'_(\w+)Handlers\('
handler_matches = re.findall(handlers_pattern, content)
if handler_matches:
found_matches = True
print(f'found handlers in {file_path}:')
for match in handler_matches:
name = match
if name == "newConnection" and file_name == "ConptyConnection.cpp":
# This one is special
continue
old_declaration = f'_{name}Handlers('
new_declaration = f'{name}.raise('
print(f' {old_declaration} -> {new_declaration}')
content = content.replace(old_declaration, new_declaration)
if found_matches:
with open(file_path, 'w', encoding="utf8") as file:
file.write(content)
def find_and_replace(directory):
for root, dirs, files in os.walk(directory):
if 'Generated Files' in dirs:
dirs.remove('Generated Files') # Exclude the "Generated Files" directory
for file in files:
if file.endswith('.cpp') or file.endswith('.h') or file.endswith('.hpp'):
file_path = os.path.join(root, file)
try:
replace_in_file(file_path, file)
except Exception as e:
print(f"error reading {file_path}")
if file == "TermControl.cpp":
print(e)
# raise e
# Replace in files within a specific directory
directory_path = 'D:\\dev\\public\\terminal\\src'
find_and_replace(directory_path)
```
</details>
[^1]: there are other macros we use that were also using this macro,
those weren't replaced.
---------
Co-authored-by: Dustin Howett <duhowett@microsoft.com>
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
This pull request introduces support for disabling full-color emoji (and
technically other COLR-related font features!)
Full-color emoji don't respond to SGR colors, intensity, faint or blink.
Some users also just prefer the line art ones.
Related to #15979
Refs #1790Closes#956
I realize I might be one of the few developers that care about custom
shader support in terminal but I thought it's worth proposing it and see
what you think.
This is to support custom shaders with custom textures.
I was thinking of exposing the background image to the shader but that
felt complicated after looking into it.
I have tested exploratively. I think the texture loader is possible to
unit test so that is a possible improvement.
The error reporting (as with other custom pixel shader code) is not very
good. That is also an area that I could improve upon.
I do think the risk of adding this is rather low as the new code is only
executed when experimental.pixelShaderImagePath is set.
### Details
Only added to the Atlas engine.
Instead I load the texture using WIC into a shader resource view. When
binding shader resources I test for presence of custom texture and bind
it to register t1.
The image loading code was found in [the D3D Texture documentation].
It's a mouthful but seems rather robust.
Tested setting: "experimental.pixelShaderImagePath"
1. Tested not specifying it.
2. Tested setting it.
3. Tested changing it (the changes are picked up)
4. Tested invalid path
5. Tested a custom shader that made use of the custom texture.
[the D3D Texture documentation]: https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-textures-how-to
Co-authored-by: Mike Griese <migrie@microsoft.com>
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
This adds support for drawing our own box drawing, block element,
and basic Powerline (U+E0Bx) glyphs in AtlasEngine.
This PR consists of 4 parts:
* AtlasEngine was refactored to simplify `_drawGlyph` because I've
wanted to do that for ~1 year now and never got a chance.
Well, now I'm doing it and you all will review it muahahaha.
The good news is that it removes a goto usage that even for my
standards was rather dangerous. Now it's gone and the risk with it.
* AtlasEngine was further refactored to properly parse out text that
we want to handle different from regular text. Previously, we only
did that for soft fonts, but now we want to do that for a lot more,
so a refactor was in order. The new code is still extremely
disgusting, because I now stuff `wchar_t`s into an array that's
intended for glyph indices, but that's the best way to make it fast
and not blow up the complexity of the code even further.
* Finally this adds a huge LUT for all the aforementioned glyphs.
The LUT has 4 "drawing instruction" entries per glyph which describe
the shape (rectangle, circle, lines, etc.) and the start/end coord.
With a lot of bit packing each entry is only 4 bytes large.
* Finally-finally a `builtinGlyphs` setting was added to the font
object and it defaults to `true`.
Closes#5897
## Validation Steps Performed
* RenderingTests with soft fonts ✅
* All the aforementioned glyphs ✅
* ...with color ✅
* `customGlyphs` setting can be toggled on and off ✅
With AtlasEngine being fairly stable at this point and being enabled
by default in the 1.19 branch, this changeset removes DxEngine.
## Validation Steps Performed
* WT builds and runs ✅
* WpfTestNetCore ✅
* Saving the config removes the `useAtlasEngine` key ✅
`TextBuffer::GenHTML` and `TextBuffer::GenRTF` now read directly from
the TextBuffer.
- Since we're reading from the buffer, we can now read _all_ the
attributes saved in the buffer. Formatted copy now copies most (if not
all) font/color attributes in the requested format (RTF/HTML).
- Use `TextBuffer::CopyRequest` to pass all copy-related options into
text generation functions as one unit.
- Helper function `TextBuffer::CopyRequest::FromConfig()` generates a
copy request based on Selection mode and user configuration.
- Both formatted text generation functions now use `std::string` and
`fmt::format_to` to generate the required strings. Previously, we were
using `std::ostringstream` which is not recommended due to its potential
overhead.
- Reading attributes from `ROW`'s attribute RLE simplified the logic as
we don't have to track attribute change between the text.
- On the caller side, we do not have to rebuild the plain text string
from the vector of strings anymore. `TextBuffer::GetPlainText()` returns
the entire text as one `std::string`.
- Removed `TextBuffer::TextAndColors`.
- Removed `TextBuffer::GetText()`. `TextBuffer::GetPlainText()` took its
place.
This PR also fixes two bugs in the formatted copy:
- We were applying line breaks after each selected row, even though the
row could have been a Wrapped row. This caused the wrapped rows to break
when they shouldn't.
- We mishandled Unicode text (\uN) within the RTF copy. Every next
character that uses a surrogate pair or high codepoint was missing in
the copied text when pasted to MSWord. The command `\uc4` should have
been `\uc1`, which is used to tell how many fallback characters are used
for each Unicode codepoint (\u). We always use one `?` character as the
fallback.
Closes#16191
**References and Relevant Issues**
- #16270
**Validation Steps Performed**
- Casual copy-pasting from Terminal or OpenConsole to word editors works
as before.
- Verified HTML copy by copying the generated HTML string and running it
through an HTML viewer.
[Sample](https://codepen.io/tusharvickey/pen/wvNXbVN)
- Verified RTF copy by copy-pasting the generated RTF string into
MSWord.
- SingleLine mode works (<kbd>Shift</kbd>+ copy)
- BlockSelection mode works (<kbd>Alt</kbd> selection)
Avoid generating extra formatted copies when action's `copyFormatting`
is not present and globally set `copyFormatting` is used.
Previously, when the action's `copyFormatting` wasn't set we deferred
the decision of which formats needed to be copied to the
`TerminalPage::CopyToClipboard` handler. This meant we needed to copy
the text in all the available formats and pass it to the handler to copy
the required formats after querying the global `copyFormatting`.
To avoid making extra copies, we'll store the global `copyFormatting` in
TerminalSettings and pass it down to `TermControl`. If
`ControlCore::CopySelectionToClipboard()` doesn't receive action
specific `copyFormatting`, it will fall back to the global one _before
generating the texts_.
## Validation Steps Performed
- no `copyFormatting` set for the copy action: Copies formats according
to the global `copyFormatting`.
- `copyFormatting` is set for the copy action: Copies formats according
to the action's `copyFormatting`.
**FIRST TIME CONTRIBUTOR**
Follows the existing selection code as much as possible.
Updated logic that finds selection rectangles to also identify search
rectangles.
Right now, this feature only works in the new Atlas engine -- it uses
the background and foreground color bitmaps to quickly and efficiently
set the colors of a whole region of text.
Closes#7561
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
This fixes a number of bugs introduced in 4370da9, all of which are of
the same kind: Holding the terminal lock across `WriteFile` calls into
the ConPTY pipe. This is problematic, because the pipe has a tiny buffer
size of just 4KiB and ConPTY may respond on its output pipe, before the
entire buffer given to `WriteFile` has been emptied. When the ConPTY
output thread then tries to acquire the terminal lock to begin parsing
the VT output, we get ourselves a proper deadlock (cross process too!).
The solution is to tease `Terminal` further apart into code that is
thread-safe and code that isn't. Functions like `SendKeyEvent` so far
have mixed them into one, because when they get called by `ControlCore`
they both, processed the data (not thread-safe as it accesses VT state)
and also sent that data back into `ControlCore` through a callback
which then indirectly called into the `ConptyConnection` which calls
`WriteFile`. Instead, we now return the data that needs to be sent from
these functions, and `ControlCore` is free to release the lock and
then call into the connection, which may then block indefinitely.
## Validation Steps Performed
* Start nvim in WSL
* Press `i` to enter the regular Insert mode
* Paste 1MB of text
* Doesn't deadlock ✅
This commit fixes 2 issues:
* `ControlCore::ScrollMarks()` would call `ResetIfStale`
again while the search prompt hasn't changed.
This has been fixed by using `_cachedSearchResultRows` as
the indicator for whether it needs to be recreated or not.
* While typing a search query, the selection would move among the
results with each typed character, because `MovePastCurrentSelection`
would do what its name indicates. It has been renamed and rewritten
to be `MoveToCurrentSelection`. To avoid breaking UIA, the previous
`MovePastPoint` implementation was kept.
Since the new `MoveToCurrentSelection` function would not move past the
current selection anymore, changing the direction would not move past
the current result either. To fix this, we now don't invalidate the
search cache when changing the direction.
Closes#15954
## Validation Steps Performed
* Run ``"helloworld`n"*20`` in pwsh
* Search for "helloworld"
* While typing the characters the selection doesn't move ✅
* ...nor when searching downwards ✅
* ...nor when erasing parts of it ✅
* ...and it behaves identical in conhost ✅
This replaces the use of a `<Canvas>` with an `<Image>` for drawing
scrollbar marks. Otherwise, WinUI struggles with the up to ~9000 UI
elements as they get dirtied every time the scrollbar moves.
(FWIW 9000 is not a lot and it should not struggle with that.)
The `<Image>` element has the benefit that we can get hold of a CPU-side
bitmap which we can manually draw our marks into and then swap them into
the UI tree. It draws the same 9000 elements, but now WinUI doesn't
struggle anymore because only 1 element gets invalidated every time.
Closes#15955
## Validation Steps Performed
* Fill the buffer with "e"
* Searching for "e" fills the entire thumb range with white ✅
* ...doesn't lag when scrolling around ✅
* ...updates quickly when adding newlines at the end ✅
* Marks sort of align with their scroll position ✅
`Terminal` is used concurrently by at least 4 threads. The table
below lists the class members and the threads that access them
to the best of my knowledge. Where:
* UI: UI Thread
* BG: Background worker threads (`winrt::resume_background`)
* RD: Render thread
* VT: VT connection thread
| | UI | BG | RD | VT |
|------------------------------------|----|----|----|----|
| `_pfnWriteInput` | x | x | | x |
| `_pfnWarningBell` | | | | x |
| `_pfnTitleChanged` | | | | x |
| `_pfnCopyToClipboard` | | | | x |
| `_pfnScrollPositionChanged` | x | x | | x |
| `_pfnCursorPositionChanged` | | | | x |
| `_pfnTaskbarProgressChanged` | | | | x |
| `_pfnShowWindowChanged` | | | | x |
| `_pfnPlayMidiNote` | | | | x |
| `_pfnCompletionsChanged` | | | | x |
| `_renderSettings` | x | | x | x |
| `_stateMachine` | x | | | x |
| `_terminalInput` | x | | | x |
| `_title` | x | | x | x |
| `_startingTitle` | x | | x | |
| `_startingTabColor` | x | | | |
| `_defaultCursorShape` | x | | | x |
| `_systemMode` | | x | x | x |
| `_snapOnInput` | x | x | | |
| `_altGrAliasing` | x | | | |
| `_suppressApplicationTitle` | x | | | x |
| `_trimBlockSelection` | x | | | |
| `_autoMarkPrompts` | x | | | |
| `_taskbarState` | x | | | x |
| `_taskbarProgress` | x | | | x |
| `_workingDirectory` | x | | | x |
| `_fontInfo` | x | | x | |
| `_selection` | x | x | x | x |
| `_blockSelection` | x | x | x | |
| `_wordDelimiters` | x | x | | |
| `_multiClickSelectionMode` | x | x | x | |
| `_selectionMode` | x | x | x | |
| `_selectionIsTargetingUrl` | x | x | x | |
| `_selectionEndpoint` | x | x | x | |
| `_anchorInactiveSelectionEndpoint` | x | x | x | |
| `_mainBuffer` | x | x | x | x |
| `_altBuffer` | x | x | x | x |
| `_mutableViewport` | x | | x | x |
| `_scrollbackLines` | x | | | |
| `_detectURLs` | x | | | |
| `_altBufferSize` | x | x | x | x |
| `_deferredResize` | x | | | x |
| `_scrollOffset` | x | x | x | x |
| `_patternIntervalTree` | x | x | x | x |
| `_lastKeyEventCodes` | x | | | |
| `_currentPromptState` | x | | | x |
Only 7 members are specific to one thread and don't require locking.
All other members require some for of locking to be safe for use.
To address the issue this changeset adds `LockForReading/LockForWriting`
calls everywhere `_terminal` is accessed in `ControlCore/HwndTerminal`.
Additionally, to ensure these issues don't pop up anymore, it adds to
all `Terminal` functions a debug assertion that the lock is being held.
Finally, because this changeset started off rather modest, it contains
changes that I initially made without being aware about the extent of
the issue. It simplifies the access around `_patternIntervalTree` by
making `_InvalidatePatternTree()` directly use that member.
Furthermore, it simplifies `_terminal->SetCursorOn(!IsCursorOn())` to
`BlinkCursor()`, allowing the code to be shared with `HwndTerminal`.
Ideally `Terminal` should not be that much of a class so that we don't
need such coarse locking. Splitting out selection and rendering state
should allow deduplicating code with conhost and use finer locking.
Closes#9617
## Validation Steps Performed
I tried to use as many Windows Terminal features as I could and fixed
every occurrence of `_assertLocked()` failures.
## Summary of the Pull Request
Closes#7158
Enabling Acrylic as both an appearance setting (with all the plumbing),
allowing it to be set differently in both focused and unfocused
terminals. EnableUnfocusedAcrylic Global Setting that controls if
unfocused acrylic is possible so that people can disable that behavior.
## References and Relevant Issues
#7158 , references: #15913 , #11092
## Detailed Description of the Pull Request / Additional comments
### Allowing Acrylic to be set differently in both focused and unfocused
terminals:
#### A

#### B

#### C

#### D

``` json
"profiles":
{
"list":
[
{
"commandline": "pwsh.exe",
"name": "A",
"unfocusedAppearance":
{
"useAcrylic": true,
},
"useAcrylic": true,
},
{
"commandline": "pwsh.exe",
"name": "B",
"unfocusedAppearance":
{
"useAcrylic": false,
},
"useAcrylic": true,
},
{
"commandline": "pwsh.exe",
"name": "C",
"unfocusedAppearance":
{
"useAcrylic": true,
},
"useAcrylic": false,
},
{
"commandline": "pwsh.exe",
"name": "D",
"unfocusedAppearance":
{
},
"useAcrylic": false,
},
]
}
```
- **A**: AcrylicBlur always on
- **B**: Acrylic when focused, not acrylic when unfocused
- **C**: Why the hell not. Not Acrylic when focused, Acrylic when
unfocused.
- **D:** Possible today by not using Acrylic.
### EnableUnfocusedACrylic global setting that controls if unfocused
acrylic is possible
So that people can disable that behavior:

### Alternate approaches I considered:
Using `_InitializeBackgroundBrush` call instead of
`_changeBackgroundColor(bg) in
``TermControl::_UpdateAppearanceFromUIThread`. Comments in this function
mentioned:
``` *.cs'
// In the future, this might need to be changed to a
// _InitializeBackgroundBrush call instead, because we may need to
// switch from a solid color brush to an acrylic one.
```
I considered using this to tackle to problem, but don't see the benefit.
The only time we need to update the brush is when the user changes the
`EnableUnfocusedAcrylic ` setting which is already covered by
`fire_and_forget TermControl::UpdateControlSettings`
### Supporting different Opacity in Focused and Unfocused Appearance???
This PR is split up in two parts #7158 covers allowing Acrylic to be set
differently in both focused and unfocused terminals. And
EnableUnfocusedAcrylic Global Setting that controls if unfocused acrylic
is possible so that people can disable that behavior.
#11092 will be about enabling opacity as both an appearance setting,
allowing it to be set differently in both focused and unfocused
terminals.
### Skipping the XAML for now:
“I actually think we may want to skip the XAML on this one for now.
We've been having some discussions about compatibility settings, global
settings, stuff like this, and it might be _more- confusing to have you
do something here. We can always add it in post when we decide where to
put it.”
-- Mike Griese
## Validation Steps Performed
#### When Scrolling Mouse , opacity changes appropriately, on opacity
100 there are no gray lines or artefacts


#### When Adjusting Opacity through command palette, opacity changes
appropriately, on opacity 100 there are no gray lines or artefacts


#### When opening command palette state goes to unfocused, the acrylic
and color change appropriately


#### Stumbled upon a new bug when performing validation steps #15913

## PR Checklist
- [x] Closes#7158
- [X] Tests added/passed
- [X] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [x] Schema updated (if necessary)
---------
Co-authored-by: Mike Griese <migrie@microsoft.com>
This is a resurrection of #8588. That PR became painfully stale after
the `ControlCore` split. Original description:
> ## Summary of the Pull Request
> This is a PoC for:
> * Search status in SearchBox (aka number of matches + index of the
current match)
> * Live search (aka search upon typing)
> ## Detailed Description of the Pull Request / Additional comments
> * Introduced this optionally (global setting to enable it)
> * The approach is following:
> * Every time the filter changes, enumerate all matches
> * Upon navigation just take the relevant match and select it
>
I cleaned it up a bit, and added support for also displaying the
positions of the matches in the scrollbar (if `showMarksOnScrollbar` is
also turned on).
It's also been made SUBSTANTIALLY easier after #15858 was merged.
Similar to before, searching while there's piles of output running isn't
_perfect_. But it's pretty awful currently, so that's not the end of the
world.
Gifs below.
* closes#8631 (which is a bullet point in #3920)
* closes#6319
Co-authored-by: Don-Vito <khvitaly@gmail.com>
---------
Co-authored-by: khvitaly <khvitaly@gmail.com>
The ultimate goal of this PR was to use ICU for text search to
* Improve Unicode support
Previously we used `towlower` and only supported BMP glphs.
* Improve search performance (10-100x)
This allows us to search for all results in the entire text buffer
at once without having to do so asynchronously.
Unfortunately, this required some significant changes too:
* ICU's search facilities operate on text positions which we need to be
mapped back to buffer coordinates. This required the introduction of
`CharToColumnMapper` to implement sort of a reverse-`_charOffsets`
mapping. It turns text (character) positions back into coordinates.
* Previously search restarted every time you clicked the search button.
It used the current selection as the starting position for the new
search. But since ICU's `uregex` cannot search backwards we're
required to accumulate all results in a vector first and so we
need to cache that vector in between searches.
* We need to know when the cached vector became invalid and so we have
to track any changes made to `TextBuffer`. The way this commit solves
it is by splitting `GetRowByOffset` into `GetRowByOffset` for
`const ROW` access and `GetMutableRowByOffset` which increments a
mutation counter on each call. The `Search` instance can then compare
its cached mutation count against the previous mutation count.
Finally, this commit makes 2 semi-unrelated changes:
* URL search now also uses ICU, since it's closely related to regular
text search anyways. This significantly improves performance at
large window sizes.
* A few minor issues in `UiaTracing` were fixed. In particular
2 functions which passed strings as `wstring` by copy are now
using `wstring_view` and `TraceLoggingCountedWideString`.
Related to #6319 and #8000
## Validation Steps Performed
* Search upward/downward in conhost ✅
* Search upward/downward in WT ✅
* Searching for any of ß, ẞ, ss or SS matches any of the other ✅
* Searching for any of Σ, σ, or ς matches any of the other ✅
I originally just wanted to close#1104, but then discovered that hey,
this event wasn't even used anymore. Excerpts of Teams convo:
* [Snap to character grid when resizing window by mcpiroman · Pull
Request #3181 · microsoft/terminal
(github.com)](https://github.com/microsoft/terminal/pull/3181/files#diff-d7ca72e0d5652fee837c06532efa614191bd5c41b18aa4d3ee6711f40138f04c)
added it to Tab.cpp
* where it was added
* which called `pane->Relayout` which I don't even REMEMBER
* By [Add functionality to open the Settings UI tab through openSettings
by leonMSFT · Pull Request #7802 · microsoft/terminal
(github.com)](https://github.com/microsoft/terminal/pull/7802/files#diff-83d260047bed34d3d9d5a12ac62008b65bd6dc5f3b9642905a007c3efce27efd),
there was seemingly no FontSizeChanged in Tab.cpp (when it got moved to
terminaltab.cpp)
> `Pane::Relayout` functionally did nothing because sizing was switched
to `star` sizing at some point in the past, so it was just deleted.
From [Misc pane refactoring by Rosefield · Pull Request #11373 ·
microsoft/terminal](https://github.com/microsoft/terminal/pull/11373/files#r736900998)
So, great. We can kill part of it, and convert the rest to a
`TypedEvent`, and get rid of `DECLARE_` / `DEFINE_`.
`ScrollPositionChangedEventArgs` was ALSO apparently already promoted to
a typed event, so kill that too.
_targets #14943_
When this is true, this will re-use the existing commandline to
pre-filter the results. This is especially helpful for completing a
suggestion based on the text that's already been typed.
Like with command history, this requires that shell integration is
enabled before it will work.## Summary of the Pull Request
## References and Relevant Issues
See also #13445
As spec'd in #14864
## Validation Steps Performed
Tested manually
This adds support for a new action, `showSuggestions`, as described in
#14864. This adds just one `source` currently, `recentCommands`. This
requires shell integration to be enabled in the shell to work properly.
When it is enabled, activating that action will invoke the suggestions
UI as a palette, populated with `sendInput` actions for each of the
user's recent commands.
* These don't persist across reboots.
* These are per-control.
There's mild plans to remedy that in a follow-up, though that needs a
bit more design consideration.
Closes#14779
## Summary of the Pull Request
This adds a new experimental per-setting to the terminal.
```ts
"experimental.repositionCursorWithMouse": bool
```
When:
* the setting is on
* AND you turn on shell integration (at least `133;B`)
* AND you click is somewhere _after_ the "active command" mark
we'll send a number of simulated keystrokes to the terminal based off
the number of cells between the place clicked and where the current
mouse cursor is.
## PR Checklist
- [ ] Related to #8573. I'm not marking as _closed_, because we should
probably polish this before we close that out. This is more a place to
start.
## Detailed Description of the Pull Request / Additional comments
There was a LOT of discussion in #8573. This is kinda a best effort
feature - it won't always work, but it should improve the experience
_most of the time_. We all kinda agreed that as much as the shell
probably should be responsible for doing this, there's myriad reasons
that won't work in practicality:
* That would also disable selection made by the terminal. That's a hard
sell.
* We'd need to invent some new mouse mode to support
click-to-reposition-but-drags-to-select-I-don't-want
* We'd then need shells to adopt that functionality.
And eventually settled that this was the least horrifying comprimise.
This has _e d g e c a s e s_:
* Does it work for wrapped lines? Well, kinda okay actually.
* Does it work for `vim`/`emacs`? Nope.
* Does it work for emoji/wide glyphs? I wouldn't expect it to! I mean,
emoji input is messed up anyways, right?
* Other characters like `ESC` (which are rendered by the shell as two
cells "^[")? Nope.
* Does it do selections? Nope.
* Clicking across lines with continuation prompts? Nope.
* Tabs? Nope.
* Wraps within tmux/screen? Nope.
https://github.com/xtermjs/xterm.js/blob/master/src/browser/input/MoveToCell.ts
has probably a more complete implementation of how we'd want to generate
the keypresses and such.
There's two parts to this PR that should be considered _separately_.
1. The Suggestions UI, a new graphical menu for displaying suggestions /
completions to the user in the context of the terminal the user is
working in.
2. The VsCode shell completions protocol. This enables the shell to
invoke this UI via a VT sequence.
These are being introduced at the same time, because they both require
one another. However, I need to absolutely emphasize:
### THE FORMAT OF THE COMPLETION PROTOCOL IS EXPERIMENTAL AND SUBJECT TO
CHANGE
This is what we've prototyped with VsCode, but we're still working on
how we want to conclusively define that protocol. However, we can also
refine the Suggestions UI independently of how the protocol is actually
implemented.
This will let us rev the Suggestions UI to support other things like
tooltips, recent commands, tasks, INDEPENDENTLY of us rev'ing the
completion protocol.
So yes, they're both here, but let's not nitpick that protocol for now.
### Checklist
* Doesn't actually close anything
* Heavily related to #3121, but I'm not gonna say that's closed till we
settle on the protocol
* See also:
* #1595
* #14779
* https://github.com/microsoft/vscode/pull/171648
### Detailed Description
#### Suggestions UI
The Suggestions UI is spec'ed over in #14864, so go read that. It's
basically a transient Command Palette, that floats by the user's cursor.
It's heavily forked from the Command Palette code, with all the business
about switching modes removed. The major bit of new code is
`SuggestionsControl::Anchor`. It also supports two "modes":
* A "palette", which is like the command palette - a list with a text
box
* A "menu", which is more like the intellisense flyout. No text box.
This is the mode that the shell completions use
#### Shell Completions Protocol
I literally cannot say this enough times - this protocol is experimental
and subject to change. Build on it at your own peril. It's disabled in
Release builds (but available in preview behind
`globals.experimental.enableShellCompletionMenu`), so that when it
ships, no one can take a dependency on it accidentally.
Right now we're just taking a blob of JSON, passing that up to the App
layer, who asks `Command` to parse it and build a list of `sendInput`
actions to populate the menu with. It's not a particularly elegant
solution, but it's good enough to prototype with.
#### How do I test this?
I've been testing this in two parts. You'll need a snippet in your
powershell profile, and a keybinding in the Terminal settings to trigger
it. The work together by binding <kbd>Ctrl+space</kbd> to _essentially_
send <kbd>F12</kbd><kbd>b</kbd>. Wacky, but it works.
```json
{ "command": { "action": "sendInput","input": "\u001b[24~b" }, "keys": "ctrl+space" },
```
```ps1
function Send-Completions2 {
$commandLine = ""
$cursorIndex = 0
# TODO: Since fuzzy matching exists, should completions be provided only for character after the
# last space and then filter on the client side? That would let you trigger ctrl+space
# anywhere on a word and have full completions available
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$commandLine, [ref]$cursorIndex)
$completionPrefix = $commandLine
# Get completions
$result = "`e]633;Completions"
if ($completionPrefix.Length -gt 0) {
# Get and send completions
$completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex
if ($null -ne $completions.CompletionMatches) {
$result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);"
$result += $completions.CompletionMatches | ConvertTo-Json -Compress
}
}
$result += "`a"
Write-Host -NoNewLine $result
}
function Set-MappedKeyHandlers {
# VS Code send completions request (may override Ctrl+Spacebar)
Set-PSReadLineKeyHandler -Chord 'F12,b' -ScriptBlock {
Send-Completions2
}
}
# Register key handlers if PSReadLine is available
if (Get-Module -Name PSReadLine) {
Set-MappedKeyHandlers
}
```
### TODO
* [x] `(prompt | format-hex).`<kbd>Ctrl+space</kbd> -> This always
throws an exception. Seems like the payload is always clipped to
```{"CompletionText":"Ascii","ListItemText":"Ascii","ResultType":5,"ToolTip":"string
Ascii { get```
and that ain't JSON. Investigate on the pwsh side?
`IInputEvent` makes adding Unicode support to `InputBuffer` more
difficult than necessary as the abstract class makes downcasting
as well as copying quite verbose. I found that using `INPUT_RECORD`s
directly leads to a significantly simplified implementation.
In addition, this commit fixes at least one bug: The previous approach
to detect the null key via `DoActiveModifierKeysMatch` didn't work.
As it compared the modifier keys as a bitset with `==` it failed to
match whenever the numpad key was set, which it usually is.
## Validation Steps Performed
* Unit and feature tests are ✅
Move scroll marks to `TextBuffer`, so they can be cleared by
EraseInDisplay and EraseScrollback.
Also removes the namespacing on them.
## References and Relevant Issues
* see also #11000 and #15057
* Resize/Reflow _doesn't_ work yet and I'm not attempting this here.
## Validation Steps Performed
* `cls` works
* `Clear-Host` works
* `clear` works
* the "Clear buffer" action works
* They work when there's marks above the current viewport, and clear the
scrollback
* they work if you clear multiple "pages" of output, then scroll back to
where marks previously were
* resizing doesn't totally destroy the marks
Closes#15426
`ControlCore` contained two bugs:
* Race condition on access of the 3 throttled funcs which may now
be `reset()` during tear out
* The `ScrollPositionChanged` event emitter was written incorrectly
and would emit the event from the background thread without
throttling during tear out
## Summary of the Pull Request
This was a fever dream I had last July. What if, instead of `WINRT_PROPERTY` magic macros everywhere, we had actual templated versions you could debug into.
So instead of
```c++
WINRT_PROPERTY(bool, Deleted, false);
WINRT_PROPERTY(OriginTag, Origin, OriginTag::None);
WINRT_PROPERTY(guid, Updates);
```
you'd do
```c++
til::property<bool> Deleted{ false };
til::property<OriginTag> Origin{ OriginTag::None };
til::property<guid> Updates;
```
.... and then I just kinda kept doing that. So I did that for `til::event`.
**AND THEN LAST WEEK**
Raymond Chen was like: ["this is a good idea"](https://devblogs.microsoft.com/oldnewthing/20230317-00/?p=107946)
So here it is.
## Validation Steps Performed
Added some simple tests.
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
A different take on #14548.
> We didn't love that a connection could transition back in the state
diagram, from Closed -> Start. That felt wrong. To remedy this, we're
going to allow the ControlCore to...
ASK the app to restart its connection. This is a much more sensible
approach, than leaving the ConnectionInfo in the core and having the
core do the restart itself. That's mental.
Cleanup from #14060Closes#14327
Obsoletes #14548
This bug causes AtlasEngine to render buffer contents with an incorrect
`cellCount`, which may either cause it to draw the contents only
partially, or potentially access the TextBuffer contents out of bounds.
`EnablePainting` sets the `_viewport` to the current viewport for some
unfortunate (and quite buggy/incorrect) caching purposes, which causes
`_CheckViewportAndScroll()` to think that the viewport hasn't changed
in the new window. We can ensure `_CheckViewportAndScroll()` works
by also setting `_forceUpdateViewport` to `true`.
Part of #14957
## PR Checklist
* Tear out a tab from a smaller window to a larger window
* Renderer contents adept to the larger window size ✅
---------
Co-authored-by: Mike Griese <migrie@microsoft.com>
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
Adds a "Select command" and a "Select output" entry to the right-click
context menu when the user has shell integration enabled. This lets the
user quickly right-click on a command and select the entire commandline
or all of its output.
This was a "I'm waiting for reviews" sorta idea. Seemed like a
reasonable combination of features. Related to #13445, #11000.
Tested manually.
---------
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>