## Summary of the Pull Request
VC++ v14 Descktop Framework package is required and not installed automatically when installing package manually.
## PR Checklist
* [X] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
While working on #13398 I felt that `TSFInputControl` wasn't up to sniff.
This commit is a minor cleanup of the class:
* default member initializers
* Simplified use of STL classes which already perform boundary checks
* Correctly check text buffer emptiness in `_SendAndClearText`
* Track selection range as mandated by the API
## Validation Steps Performed
* Japanese IME (Full-Width Katakana)
Typing "saitama" produces "サイタマ" ✅
* Korean IME
Typing "gksrmf" produces "한글" ✅
* Vietnamese IME
Typing "xin chaof" continues to produce broken "xin xinchaof"
(It's supposed to produce "xin chào")
* Emoji Picker (Win+.)
✅
## Summary of the Pull Request
- We only ever have 1 color picker now, instead of each tab having its own
- `TerminalPage` constructs this color picker (upon first request for it)
- `TerminalPage` attaches the color picker to the tab that requested for it
- `TerminalTab` detaches the color picker when it is done with it, so that `TerminalPage` can attach it to another tab later on
## References
#5907
## Validation Steps Performed
User-end behaviour is the same
We must use 65535 as `MAX_PARAMETER_VALUE` in order for us to properly parse
win32-input-mode sequences, which transmit UTF-16 characters as parameters.
Closes#12977
## Validation Steps Performed
* Call `SendInput` with 🙁 (`L'\xD83D'`, `L'\xDE41'`)
* 🙁 appears on the input line ✅
## Summary of the Pull Request
In #13560 we added a member to `Pane` that lets it know if it was spawned as a default terminal session, but did not propagate that value when the pane gets split or when the pane closes. This commit fixes that.
## Validation Steps Performed
A session spawned by a def term invocation remembers it even as it goes through splits
## Summary of the Pull Request
In general, when a selection marker is shown, we should scroll to it. The `selectAll` action adds a selection marker, but we don't scroll to it. This PR makes it such that we do do that.
Epic: #4993Closes#13485
Updates the schema such that the scroll mark settings are defined as profile settings instead of global settings (because they're actually profile settings).
Separately (but still relevant), I've also updated the release notes.
Closes#13583
This fixes an issue were overwriting parts of a row would only trigger
that specific portion of the row to be redrawn. This isn't just
problematic for combining characters, but also for things like
the new `TestDbcsBisectWriteCells` test introduced in #13626.
Benchmarks showed no impact on performance whatsoever.
## Validation Steps Performed
* Pick this commit into #13626
* Run the `TestDbcsBisectWriteCells` test and break before OpenConsole exits
* A correct "QいかなZYXWVUTに" output is visible ✅
This commit makes AtlasEngine recognize Powerline glyphs as box drawing ones.
The extra pixel offsets when determining the `scale` caused weird artifacts
and thus were removed. It seems like this causes no noticeable regressions.
Closes#13029
## Validation Steps Performed
* Run all values of `wchar_t` through `isInInversionList`
and ensure it produces the expected value ✅
* Powerline glyphs are correctly scaled with Cascadia Code PL ✅
07d58a8 contains a regression where the settings' `Themes()` property is
accessed without checking whether it's a `nullptr`. This can happen because
the invalid settings modal is shown with a empty settings model object.
This commit fixes the issue by deferring the update of `_settings` until
after we ensured that the `_settings` object is valid (besides warnings).
Closes#13543
## Validation Steps Performed
* Replace any string value with `123`
* Application doesn't crash ✅
## Summary of the Pull Request
- When 'discard changes' is hit, we re-initialize our list of color scheme view models but forgot to tell xaml about it, this commit fixes that.
- Make sure to exit rename mode when 'update settings' gets called
## References
color schemes mvvm added in #13179
## PR Checklist
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [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: #xxx
## Validation Steps Performed
Hitting discard changes doesn't cause an inconsistency with the currently selected scheme anymore
## Summary of the Pull Request
Adds a new mode to `CloseOnExit`: `Automatic`. In this mode, if a process handed off by defterm terminates for whatever reason, we always close (i.e. we treat the mode as `Always`), but for processes launched by Terminal we terminate as with the `Graceful` behaviour.
## PR Checklist
* [x] Closes#13325
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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: #xxx
## Detailed Description of the Pull Request / Additional comments
- Adds a new enum value to `CloseOnExit`
- Adds a new function to `Pane`: `FinalizeConfigurationGivenDefault`: this is a function that should be called when the pane is created via default terminal handoff, and can contain any special configurations we should set given that the pane was created via handoff
## Validation Steps Performed
Curiously, at least on Windows 10 (and rarely on Windows 11), if you minimize the Terminal by clicking on the taskbar, then alt-tab to try and restore the window, the Taskbar will decide to call `SwitchToWindow` on the invisible, owned ConPTY window instead of the main window. When that happens, ConPTY'll get a `WM_SIZE(SIZE_RESTORED, lParam=0)`. The main window will NOT get a `SwitchToWindow` called. If ConPTY doesn't actually inform the hosting process about this, then the main HWND might stay hidden.
* Refer to #13158 where we disabled this.
* Closes#13589
* Closes#13248
* Tested manually on a Windows 10 VM.
* Confirmed that opening tabs while maximized/snapped doesn't restore down.
* `[Native]::ShowWindow([Native]::GetConsoleWindow(), 6)` still works
## Summary of the Pull Request
Adds support for the `tab.showCloseButton` property to themes. This accepts three values:
* `"always"` (default): The close button acts like it does today.
* `"hover"`: The close button is always visible on the active tab. On inactive tabs, the close button only appears on mouse over.
* `"never"`: The close button is never visible. You can't close the tab with middle-click, but you can still use keyboard shortcuts to close the tab.
## References
* See #3327
* ⚠️ targets #13178⚠️
## PR Checklist
* [x] Closes#3335
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated - YUP
## Detailed Description of the Pull Request / Additional comments
See the following two properties in WInUI that we're leveraging here.
* [`TabViewCloseButtonOverlayMode.OnPointerOver`](https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.controls.tabviewclosebuttonoverlaymode?view=winui-2.7&viewFallbackFrom=winui-2.2)
* [`TabViewItem.IsClosable`](https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.controls.tabviewitem.isclosable?view=winui-2.2#microsoft-ui-xaml-controls-tabviewitem-isclosable)
One is a tabview-level property, the other is a per-tab-item property, hence why this code is a little wacky.
## Validation Steps Performed
gifs below
This commit contains 3 improvements for glyph rendering:
* Scale block element and box drawing characters to fit the cell size
"perfectly" without leaving pixel gaps between cells.
* Use `IDWriteTextLayout::GetOverhangMetrics` to determine whether glyphs
are outside the given layout box and if they are, offset their position
to fit them back in. If that still fails to fit, we downscale them.
* Always scale up glyphs that are more than 2 cells wide
This ensures that long ligatures that mimic box drawing characters like
"===" under Cascadia Code are upscaled just like regular box drawings.
Unfortunately this results in ligature-heavy text (like Myanmar) to get an
"uneven" appearance because some ligatures can suddenly appear too large.
It's difficult to come up with a good heuristic here.
Closes#12512
## Validation Steps Performed
* Print UTF-8-demo.txt
* Block characters don't leave gaps ✅
* Print a lorem-ipsum in Myanmar
* Glyphs aren't cut off anymore ✅
* Print a long "===" ligature under Cascadia Code
* The ligature is as wide as the number of cells used ✅
## Summary of the Pull Request
Implements the MVVM style for the Color Schemes editor
## PR Checklist
* [x] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] I work here
## Detailed Description of the Pull Request / Additional comments
Introduces:
- `ColorSchemesPageViewModel`: The view model responsible for the entire color schemes page. Handles what the current scheme is, adding/deleting/renaming schemes
- `ColorSchemeViewModel`: A view model class for individual color schemes
## Validation Steps Performed
Manually tested:
- Edit a color scheme
- Add new color scheme
- Rename a color scheme
- Delete a color scheme
This is an experiment, as discussed in https://github.com/microsoft/terminal/issues/11790#issuecomment-1179143049. We don't know what for sure causes these crashes, but it seems that blindly throwing, so that it gets picked up by Watson, is probably not the move. Instead, we're just gonna do our fallback, REGARDLESS of what the exception was.
See #11790, MSFT:38542548, MSFT:38572983, MSFT:38542574 et. al.
Refer to https://docs.microsoft.com/en-us/windows/win32/rstmgr/guidelines-for-applications
The OS will send us a WM_QUERYENDSESSION when it's preparing an
update for our app. It will then send us a WM_ENDSESSION, which gives
us a small timeout (~30s) to actually shut down gracefully. After
that timeout, it will send us a WM_CLOSE. If we still don't close
after the WM_CLOSE, it'll force-kill us (causing a crash which will be
bucketed to moapphang).
We will manually start a quit, so that we can persist the state. If we refuse to
gracefully shut down, the OS will crash us to focefully terminate us. We
choose to quit here, rather than just close, to skip over any warning dialogs
(e.g. "Are you sure you want to close all tabs?") which might prevent a WM_CLOSE
from cleanly closing the window.
This will cause a appHost._RequestQuitAll, which will notify the
monarch to collect up all the window state and save it.
This "crash" caused by the OS force killing us constitutes 80% of all our crashes. 80%. See MSFT:38947155, MSFT:38877540, MSFT:21058878, MSFT:31710054, MSFT:39764652, MSFT:26883776.
Closes#13569
It also fixes the issue where if you've got Terminal Dev running (outside VS), and you try to Deploy, you have to make sure to close the "Are you sure you want to close all tabs" dialog before the deployment can proceed. A deploy in VS sends the same sequence of messages as a real update.
This commit implements the remaining 5 of 8 grid lines:
left/top/right/bottom (COMMON_LVB) borders and double underline
`AtlasEngine::_resolveFontMetrics` was partially refactored to use `float`s
instead of `double`s, because that's what the remaining code uses as well.
It also helps the new, slightly more complex double underline calculation.
## Validation Steps Performed
* Print characters with the `COMMON_LVB_GRID_HORIZONTAL`, `GRID_LVERTICAL`,
`GRID_RVERTICAL` and `UNDERSCORE` attributes via `WriteConsoleOutputW`
* All 4 grid lines are visible ✅
* Grid lines correctly scale according to the `lineWidth` ✅
* Print a double underline with `printf "\033[21mtest\033[0m"`
* A double underline is fully visible ✅
Cleans up a couple local test failures.
* [x] Closes#13474: So, I clearly hadn't ran the local tests at the end of the themes PR. We needed a sensible fallback to SOME theme, even if there wasn't one provided in the user json. This is only really hit in the tests (that don't also include `defaults.json`.
* [x] Closes#13323: Meh, the ordering of the keys in this test doesn't matter. Ordering is a map implementation detail. This is fine.
* [x] Ran tests locally
We recently figured that we can drop support for Windows 7. Coincidentally
AtlasEngine never actually supported Windows 7 properly, because it called
`ResizeBuffers` with `DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT`
no matter whether the swap chain was created with it enabled.
The new minimally supported version is Windows 8.1.
66f4f9d had another bug: Just like how we scroll our viewport by `memmove`ing
the `_r.cells` array, we also have to `memmove` the new `_r.cellGlyphMapping`.
Without this fix drawing lots of glyphs while only scrolling slightly
(= not invalidating the entire viewport), would erroneously call
`makeNewest` on glyphs now outside of the viewport. This would cause
actually visible glyphs to be recycled and overwritten by new ones.
## Validation Steps Performed
* Switch to Cascadia Code
* Print some text that fills the glyph atlas
* Scroll down by a few rows
* Write a long "==========" ligature (this quickly fills up
any remaining space in the atlas and exacerbates the issue)
* Unrelated rows don't get corrupted ✅
While working on another PR related to this I noticed that my VS
generates `.vcxproj` files that are a bit different to the ones we have.
This commit is a quick search & replace of all our project files to make
(primarily) their `ToolsVersion` more in line with what VS does itself:
No `ToolsVersion` for `.vcxproj`, `ToolsVersion="15.0"`
for `.csproj` and `ToolsVersion="4.0"` for `.filters` files.
## Summary of the Pull Request
The xaml file no longer directly accesses the settings model object, and the settings model object is no longer exposed on the view model
## References
#13377
## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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: #xxx
## Validation Steps Performed
Still works
I was messing around with trying to build & deploy from the commandline. I discovered this, which is progress. However, the inner-loop commandline build for the Terminal is still egregiously long.
* just a docs update
* is EIM work
This change adds support for the `IntenseIsBold` rendering setting.
Windows Terminal for instance defaults to `false` here, causing
intense colors to only be bright but not bold.
## Validation Steps Performed
* Set "Intense text style" to "Bright colors"
* Enable AtlasEngine
* Print ``echo "`e[1mtest`e[0m"``
* "test" appears as bright without being bold ✅
## Summary of the Pull Request
This is a spec specifically dedicated to Mark Mode. It's an addition to the Keyboard Selection spec. I felt that it makes the most sense to make this a separate PR because there's a lot of ideas that are very specific to Mark Mode, and this gives us the space to modify some of that behavior and get a good look at how other terminal emulators designed this feature.
## References
#2840 - Keyboard Selection Spec (base spec/branch/PR)
## PR Checklist
* [X] Contributes to #715
#8000 will change the way we store text from a strict grid/matrix where
one UTF16 character or surrogate pair always equals 1 column with the
possibility of joining exactly 2 to a wide character pair, to a dynamic
buffer where 1 or more characters can form 1 or more columns in any
arbitrary combination. Our long term goal is to properly support both
complex grapheme clusters like Emojis and complex ligatures that a wider
than 2 columns. This change requires us to break our API as
`ReadConsoleOutputA/W` assumes the existence of exactly this grid/matrix
storage. Since we store wide characters like "い" as a single codepoint
that is simply marked as being 2 columns wide in the future, we cannot
reconstruct trailing DBCS characters that were written to the buffer
like we used to. On the other hand this new behavior allows us to
implement better Unicode support and most likely significantly improve
our performance.
### Minor breaking changes
* `ReadConsoleOutputA` will now always **zero** the high byte in
`(CHAR_INFO).Char.UnicodeChar`. Only the `.AsciiChar` can be used
then. This prevents users from storing "additional" data in the
terminal buffer.
* `ReadConsoleOutputA` will now **zero** the `.AsciiChar` if it fails to
convert the Unicode character into an appropriate DBCS.
* Example: It's possible to write "い" into a narrow column despite
being a wide character. In these cases `WriteConsoleOutputA` will
now return `0x00` instead of `0x44` (the lower half of い's code
point `0x3044`).
### Major breaking changes
* `ReadConsoleOutputW` will now repeat the leading Unicode character
twice and ignore the trailing one.
* Example 1: Writing the pair `0x3044 0xabcd` with
`WriteConsoleOutputW` used to yield the same `0x3044 0xabcd` if read
back with `ReadConsoleOutputW`. This worked because conhost
effectively ignored the trailing codepoint, allowing one to
"smuggle" data. In the future this trailing character will be
discarded and produce `0x3044 0x3044` instead.
* Example 2: Writing い with `WriteConsoleOutputA` can be done with
code page 932 (Shift-JIS) and the DBCS `0x82 0xa2`. If read back
with `ReadConsoleOutputW` this would previously yield the two
Unicode characters `0x3044 0xffff`. After this commit it'll yield
`0x3044 0x3044`.
### Alternative approaches
It's possible to "tag"/"mark" written data as originating from
`WriteConsoleOutputA/W` so that it can be reconstructed accurately later
on. However this lead to implementation complexities that we're actively
trying to avoid in the new buffer implementation. Effectively
_everything_ that touches the buffer's text would have to handle these
marks and either write or clear them. Given the most likely small amount
of users who depend on the current quirky behavior, it'd be an
unwarranted maintenance and performance burden and prevent Windows
Terminal to ever truly migrate to full Unicode support.
## Validation Steps Performed
* Adjusted feature tests complete successfully ✅
On occasion, when we submit to the store we get a package rejection
because the app name has changed for the `qps-*` locales. Instead of
constantly reserving new pseudolocalized app names every time the
pseudolocalization seed changes, we should just lock our app name so
that it does not get pseudolocalized.
Upgrade check-spelling to [v0.0.20](https://github.com/check-spelling/check-spelling/releases/tag/v0.0.20)
This upgrade includes a refresh of the workflow
key new features:
* the previous comment is collapsed
* duplicate words are flagged (see `alone` and `the`)
* forbidding patterns (see `nonexistent`, `preexisting`, and `greater than`)
Each of these features can be tuned
- comment collapsing is controlled by the `followup` bits in the workflow-- but I can't imagine why one would want to turn it off
- duplicate words can be masked in `patterns.txt` (see `Guid` and `that`)
- forbidding patterns (especially duplicates) is in `.github/actions/spelling/line_forbidden.patterns`
Fwiw, I'm slowly moving towards not using `.txt` in filenames, but it's a long term project and I have a bunch of other goals for the near term.
The refresh of advice is of course flexible -- I'm still evolving my default text. Note that the default now includes some `curl` and I'm still working on how I want to consume the output. I'm getting close to the point where I might be able to provide a tool that could reliably consume the output (including on Windows).
This code has been used internally for a while, but I tested it for this repository here:
https://github.com/check-spelling/terminal/pull/2
## Summary of the Pull Request
`AdjustIndistinguishableColors` can now be set to:
- `Never`: Never adjust the colors
- `Indexed`: Only adjust colors that are part of the color scheme
- `Always`: Always adjust the colors
## References
#13343
## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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: #xxx
## Detailed Description of the Pull Request / Additional comments
For legacy purposes, `true` and `false` map to `Indexed` and `Never` respectively
## Validation Steps Performed
Setting still works
The behaviour of the 'go back' button in the command palette was changed to return to the previously selected element rather than the root.
Instead of returning to the root, the go back button now returns to the previously selected item in the filtered action list. The previously selected item is selected by default and the view is scoped to the item.
## Validation Steps Performed
Manually tested by going back and forth between nested actions in the command palette.
Closes#13457
<!-- 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)? -->
## Summary of the Pull Request
Added two new buttons to the About dialog. Source Code and Send Feedback buttons link directly to the Terminal project on GitHub and to the Issues page respectively.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#13371
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes#13371
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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: #13371
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Performed manual testing and confirmed that the implementation works.
The current TextBuffer implementation will happily overwrite the
leading/trailing half of a wide glyph with a narrow one without
padding the other half with whitespace. This could crash AtlasEngine
which aggressively guarded against such inconsistencies.
Closes#13522
## Validation Steps Performed
* Run .bat file linked in #13522
(Override wide glyph with a single space.)
* `AtlasEngine` doesn't crash ✅
### Disappearing glyphs
We only process glyphs within the dirtyRect, but glyphs outside of the dirtyRect
are still in use and shouldn't be discarded. This is critical if someone uses
a tool like tmux to split the terminal horizontally. If they then print a lot
of Unicode text on just one side, we have to ensure that the (for example)
plain ASCII glyphs on the other half of the viewport are still retained.
### Black viewport after font changes
The cursor was drawn without a clip rect, causing the entire atlas
texture to be filled with black. This just so happened to work fine
in Windows Terminal but relied on a race condition.
Closes#13490
## Validation Steps Performed
* Disappearing glyphs
* Start `tmux` in `wsl`
* Split horizontally with `Ctrl+B`, `"`
* `cat` a huge Unicode text file on the bottom
* Ensure ASCII glyphs in the top half don't disappear ✅
* Black viewport after font changes
* Start `OpenConsole` with `AtlasEngine`
* Open Properties dialog and click "Ok"
* Viewport content doesn't disappear ✅
2b202ce6 changed this code to fix 2-phase name lookup, but accidentally
changed `&m_tInit` to `&CFuzzType::m_tInit` (pointer-to-member¹)
instead of `&this->m_tInit` (a regular pointer to some value).
This should not be confused with `&(CFuzzType::m_tInit)`
of course which is _not_ a pointer-to-member.
¹ To simplify things, a pointer-to-member is basically the byte offset of a
member within a struct. For instance given `struct T { char a, b, c, d; }` then
`&T::c` would commonly "store" the value 2, equivalent to `offsetof(T, c)`.
Closes#13501
## Summary of the Pull Request
Re-enable the setting to adjust indistinguishable text, with some changes:
- We now pre-calculate the nudged values for 'default bright foreground' as well
- When a color table entry is manually set (i.e. via VT sequences) we re-calculate the nudged values
## References
#11095#12160
## PR Checklist
* [x] Closes#11917
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
## Validation Steps Performed
Indistinguishable text gets adjusted again
The min/max/close buttons now use the same font glyphs used in Windows instead of paths.
They will also look different depending on whether you use Windows 10 or 11.
With certain scaling levels, the new fluent icons are always blurry on titlebars (win32, UWP, terminal).
I didn't check, but I assume that the glyphs will not be blurry on Windows 10 because they use the old font.
However, the glyps seem to have some alignment issues, making them even more blurry, and I'm not sure if I can fix that.
I looked into the minimize button problem:
* The UWP titlebar has 4px/5px, just like Terminal, but win32 titlebars have 5px/4px
* The new fluent icons have rounded caps, but the win32 minimize one doesn't (it's very subtle)
* The win32 minimize button is not blurry when the other buttons are
From this I presume that the minimize button is still using the old icon. So perhaps the Terminal/UWP vertical alignment is correct.
I was able to improve the rendering by wrapping the icon inside a Viewbox.
However, it won't perfectly match UWP, because scaling is calculated differently.
The icon width is 10px, which on 1.25x scaling would become 12.5px.
UWP titlebars truncate that to 12px, while Xaml renders that as 13px.
This is probably the best that can be done for now.
I found these icons [here](https://docs.microsoft.com/en-us/windows/apps/design/style/segoe-fluent-icons-font).
## Summary of the Pull Request
This PR adds support for downloadable soft fonts in the DirectX
renderer, potentially enabling them to be used in Windows Terminal.
## References
Soft fonts were first implemented in conhost (with the GDI renderer) in
PR #10011.
## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema 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
## Detailed Description of the Pull Request / Additional comments
The way the DirectX implementation works is by building up a bitmap
containing all of the glyphs, and then drawing an appropriate subsection
of that bitmap for each character that needs to be rendered. The current
text color is applied with a color matrix effect, and the glyphs are
automatically scaled up to the current font size with a scaling effect.
By default the scaling uses a high quality cubic interpolation, which
gives it a smoother antialiased effect. But if the *Text antialiasing*
option is configured as *Aliased*, we use a simpler nearest-neighbor
interpolation, which more closely matches the rendering of the original
GDI implementation.
## Validation Steps Performed
I've manually tested the renderer in conhost with the `UseDx` registry
entry. I've also tested in Windows Terminal using the experimental
passthrough mode.
## Summary of the Pull Request
The original `DECPS` implementation made use of the Windows MIDI APIs to
generate the sound, but that required a 3MB package dependency for the
GS wavetable DLS. This PR reimplements the `MidiAudio` class using
`DirectSound`, so we can avoid that dependency.
## References
The original `DECPS` implementation was added in PR #13208, but was
hidden behind a velocity flag in #13258.
## PR Checklist
* [x] Closes#13252
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number
where discussion took place: #13252
## Detailed Description of the Pull Request / Additional comments
The way it works is by creating a sound buffer with a single triangle
wave that is played in a loop. We generate different notes simply by
adjusting the frequency at which that buffer is played.
When we need a note to end, we just set the volume to its minimum value
rather than stopping the buffer. If we don't do that, the repeated
starting and stopping tends to produce a lot of static in the output. We
also use two buffers, which we alternate between notes, as another way
to reduce that static.
One other thing worth mentioning is the handling of the buffer position.
At the end of each note we save the current position, and then use an
offset from that position when starting the following note. This helps
produce a clearer separation between tones when repeating sequences of
the same note.
In an ideal world, we should really have something like an attack-decay-
sustain-release envelope for each note, but the above hack seems to work
reasonably well, and keeps the implementation simple.
## Validation Steps Performed
I've manually tested both conhost and Terminal with the sample tunes
listed in issue #8687, as well as a couple of games that I have which
make use of `DECPS` sound effects.
<!-- 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)? -->
## Summary of the Pull Request
Added setting for for hide window when it loses focus.
Works on normal window and quake window.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes#10660
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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 -->
## Detailed Description of the Pull Request / Additional comments
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
- Enable **Settings > Appearance > Automatically hide window**
- Terminal window should be minimized on taskbar when it loses focus
- Quake window should be minimized on system tray when it loses focus
- Enable also **Settings > Appearance > Hide Terminal in the notification area when it is minimized**
- Terminal window should be minimized on system tray when it loses focus
- Quake window should be minimized on system tray when it loses focus
⚠️ This spec is going into the `specs/drafts/` folder, because it's CLEARLY not done yet.
I discussed this a bit with Dustin. We felt it would be valuable to have these thoughts committed as a durable artifact. Better to have our Mica thoughts written down somewhere, with the context they belong in. That of course includes the bigger Theming spec, which never got finished.
I don't think we need to go through the fill spec review for this. Theming is clearly still a WIP. But committing this draft should give a better picture of what the vision is.
See also:
* #3327
* #10509
### TODOs
* [ ] The many that are straight up in the doc
* [ ] The fact that there's multiple Mica's now
* [ ] GO look at MSFT:39027976
Moving to VS 2022 and C++20 in #13368 introduced a new dependency on an
as-yet-nonexistent VC Runtime library: msvcp140_atomic_wait.dll. That
library is not installed on the 21H1 machines that run our PGO tests.
Fortunately, the app platform will--largely--handle this dependency for
us on machines in the wild.
Fixes#13500
The debugging tools folks helpfully published PdbStr and SrcTool as
NuGet packages for us to take a dependency on! Now we can end this
wasteful practice once and for all...
NOTE: This change introduces a harmless error message at the end of
symbol indexing. Instead of printing out the list of mapped sources,
`srctool` will complain that `srcsrv.dll` is missing. This is only cosmetic.
Yep this is my bad. I was trying to fix a bug where only having one of `background` or `unfocusedBackground` would cause the other to never get set to the default. In attempting to force all the logic into an if statement, I messed up the order of operations. My bad 😢
Regressed in #13456
## Summary of the Pull Request
Adds support to navigate to clickable hyperlinks using only the keyboard. When in mark mode, the user can press [shift+]tab to go the previous/next hyperlink in the text buffer. Once a hyperlink is selected, the user can press <kbd>Ctrl+Enter</kbd> to open the hyperlink.
## References
#4993
## PR Checklist
* [x] Closes#6649
* [x] Documentation updated at https://github.com/MicrosoftDocs/terminal/pull/558
## Detailed Description of the Pull Request / Additional comments
- Main change
- The `OpenHyperlink` event needs to be piped down to `ControlCore` now so that we can open a hyperlink at that layer.
- `SelectHyperlink(dir)` searches the buffer in a given direction and finds the first hyperlink, then selects it.
- "finding the hyperlink" is the tough part because the pattern tree takes in buffer coordinates, searches through the buffer in that given space, then stores everything relative to the defined space. Normally, the given buffer coordinates would align with the viewport's start and end. However, we're now trying to search outside of the viewport (sometimes), so we need to manage two coordinate systems at the same time.
- `convertToSearchArea()` lambda was used to convert a given coordinate into the search area coordinate system. So if the search area is the visible viewport, we spit out a viewport position. If the search area is the _next_ viewport, we spit out a position relative to that.
- `extractResultFromList()` lambda takes the list of patterns from the pattern tree and spits out the hyperlink we want. If we're searching forwards, we get the next one. Otherwise, we get the previous one. We explicitly ignore the one we're already on. If we don't find any, we return `nullopt`.
- Now that we have all these cool tools, we use them to progressively search through the buffer to find the next/previous hyperlink. Start by searching the visible viewport _after_ (or _before_) the current selection. If we can't find anything, go to the next "page" (viewport scrolled up/down). Repeat this process until something comes up.
- If we can't find anything, nothing happens. We don't wrap around.
- Other relevant changes
- the `copy` action is no longer bound to `Enter`. Instead, we manually handle it in `ControlCore.cpp`. This also lets us handle <kbd>Shift+Enter</kbd> appropriately without having to take another key binding.
- `_ScrollToPoint` was added. It's a simple function that just scrolls the viewport such that the provided buffer position is in view. This was used to de-duplicate code.
- `_ScrollToPoint` was added into the `ToggleMarkMode()` function. Turns out, we don't scroll to the new selection when we enter mark mode (whoops!). We _should_ do that and we should backport this part of the change too. I'll handle that.
- add some clarity when some functions are using the viewport position vs the buffer position. This is important because the pattern interval tree works in the viewport space.
## Validation Steps Performed
- case: all hyperlinks are in the view
- ✅ get next link
- ✅ get prev link
- ✅ case: need to scroll down for next link
- ✅ case: need to scroll up for next link
Does what it says on the tin. When we get focused, temporarily turn off readonly mode, as to not pop the dialog when the focus sequence is eventually sent to the connection.
* closes#13461
The main fix here is for the caption button colors. If you had a dark OS/app theme, and a light titlebar, we'd end up with light glyphs, so the caption buttons would be impossible to find.
There's also a pile of nits from #12992 in here. Probably enough to close#13456 out, but I'll let Dustin be the judge.
Filing today, to get in for 1.16 selfhost (@DHowett)
`TestDbcsWriteRead` failed to properly test all text input scenarios.
In order to write wide characters with `CHAR_INFO` structs using the `W` APIs
one must still repeat the `CHAR_INFO` twice, once with `COMMON_LVB_LEADING_BYTE`
and once with `COMMON_LVB_TRAILING_BYTE` set in the attributes. This is because
`CHAR_INFO` APIs are column oriented. `TestDbcsWriteRead` on the other hand
only tested the scenario of sending wide characters without those flags.
This commit fixes the problem by introducing a `UnicodeDoubled` mode and
increases the number of test patterns from 14 to 17. Due to the existing
code having been written with the false assumption in mind, a simpler
modification resulted in +1100 LOC. As such I opted to rewrite the code instead
and replaced the potentially buggy output generators with static arrays.
Code page 437 tests were removed, as it contains no DBCS characters anyways.
This is preliminary work for #8000.
## Summary of the Pull Request
When the debug tap converts control characters into visible glyphs, it
ends up losing the structure of the output, and that can sometimes make
things difficult to read. This PR attempts to alleviate that problem by
reinjecting an actual line break in the debug stream whenever an `LF`
control is received.
## PR Checklist
* [x] Closes#12312
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number
where discussion took place: #12312
## Validation Steps Performed
I've tested the updated debug tab with a number of different shells, and
also a couple of different apps. When there aren't many linefeeds in the
output, it's obviously not going to make much of a difference, but when
there are, I think it definitely improves the readability.
If launch mode is set to full screen quake window is opened in full
screen.
## Validation Steps Performed
- Set startup > launch mode > full screen
- Launch quake window
- Quake window shouldn't be opened in full screen
Closes#12894
#13458 added the ability to reuse tiles from our glyph atlas texture
so that we stop running out of GPU memory for complex Unicode.
This however can result in our glyph generation being a performance issue in
edge cases, to the point that the application may feel outright unuseable.
CJK glyphs for instance can easily exceed the maximum atlas texture size
(twice the window size), but take a significant amount of CPU and GPU time to
rasterize and draw, which results in "jelly scrolling" down to ~1 FPS.
This PR improves the situation of the latter half by directly drawing
glyphs into the texture atlas without an intermediate scratchpad texture.
This reduces GPU usage by 96% on my system (33% -> 2%) which improves general
render performance by ~100% (15 -> 30 FPS). CPU usage remains the same however,
but that's not really something we can do anything about at this time.
The atlas texture is already our primary means to reduce the CPU cost after all.
## Validation Steps Performed
* Disable V-Sync for OpenConsole in NVIDIA Control Panel
* Enable `debugGlyphGenerationPerformance`
* Print the entire CJK block U+4E00..U+9FFF
* Measure the above GPU usage and FPS improvements ✅
(Alternatively: Just scroll around and judge the "jellyness".)
## Summary of the Pull Request
When you create a console alias that overrides an existing command, it
should still be possible to execute the original command by prefixing it
with a space. However, at some point in the past, there was an attempt
to improve the usability by trimming leading spaces, and that ended up
breaking this functionality. This PR reverts that change, so leading
spaces can once again be used to bypass an alias.
## PR Checklist
* [x] Closes#4189
* [x] CLA signed.
* [x] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number
where discussion took place: #4189
## Validation Steps Performed
I've updated the existing alias unit test for leading spaces to match
the new behavior, i.e. it now confirms that a command with leading
spaces will not match the alias.
I've also manually confirmed that the `doskey` test case reported in
issue #4189 is now working as expected.
So far AtlasEngine would only grow the backing texture atlas once it gets full,
without the ability to reuse tiles once it gets full. This commit adds LRU
capabilities to the glyph-to-tile hashmap, allowing us to reuse the least
recently used tiles for new ones once the atlas texture is full.
This commit uses a quadratic growth factor with power-of-2 textures,
resulting in a backing atlas of 1x to 2x the size of the window.
While AtlasEngine is still incapable of shrinking the texture, it'll now at
least not grow to 128MB or result in weird glitches under most circumstances.
## Validation Steps Performed
* Print `utf8_sequence_0-0x2ffff_assigned_printable_unseparated.txt`
from https://github.com/bits/UTF-8-Unicode-Test-Documents
* Scroll back up to the top
* PowerShell input line is still there rendering as ASCII. ✅
## Summary of the Pull Request
Implements a `RenderingViewModel` for the Rendering page in the SUI
## PR Checklist
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [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: #xxx
## Validation Steps Performed
Rendering page still works
## Summary of the Pull Request
Implements an `InteractionViewModel` for the Interaction page in the SUI
## PR Checklist
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [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: #xxx
## Validation Steps Performed
Interaction page still works
<!-- 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)? -->
## Summary of the Pull Request
Adds ability to select where new tab will appear: at the end or after currently selected tab.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes#12955
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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 -->
## Detailed Description of the Pull Request / Additional comments
PR adds setting "NewTabPosition" in global appearances with dropdown list and uses it then creating new tabs. This setting does not affect settings tab position (should it?).
There should also be a documentation update, I'm just waiting to see if this change even acceptable.
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
## Summary of the Pull Request
Implements a `GlobalAppearanceViewModel` for the GlobalAppearance page in the SUI
## PR Checklist
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [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: #xxx
## Validation Steps Performed
Global appearance page still works
## Summary of the Pull Request
Implements a `LaunchViewModel` for the Launch page in the SUI
## PR Checklist
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
## Validation Steps Performed
Launch page still works
Adds `tabRow.unfocusedBackground` to the theme properties.
When provided, the window will use this ThemeColor as the color of the tab row when the window is inactive.
When omitted, the window will fall back to the default tab row color, `{"key": "TabViewBackground"}` from our App.xaml.
* [ ] tests added.
* [x] Closes#4862
* [ ] Needs a whole pile of docs updates, which we'll do at the end here.
This actually helped validate #12992 quite a bit. I found a bunch of bugs concerning null colors, null objects. Json parsing is hard 😛
This one's pretty obvious. I added another scrollbar sized grid to the terminal,
but I forgot to collapse it when the user requests `"scrollbarState": "hidden"`.
* [x] Closes#13446
* [x] I work here
## Summary of the Pull Request
Adds support for the `tab.background` property to themes. This is also a ThemeColor, so it accepts, colors, `accent`, and `terminalBackground`, just like everything else.
## References
* See #3327
* ⚠️ targets #12992⚠️
## PR Checklist
* [x] Closes#702
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated - YUP
## Detailed Description of the Pull Request / Additional comments
I apparently left behing an optional color in TerminalTab for theme colors some time ago, just never used it. Crazy, huh?
## Validation Steps Performed
gifs below
##### ⚠️ targeting 1.15
## Summary of the Pull Request
Adds support for Themes, a new type of customization for the Terminal. Themes allow the user to customize elements of the Terminal window itself. In this first iteration, this PR adds support for two main properties:
* enabling Mica as the window backdrop
* changing the tab row color (read: changing the titelbar color)
These represent the most important asks of theming in the Terminal. The properties added in this PR are:
* Theme color variants:
- `"#rrggbb"` or `"#aarrggbb"`
- `"accent"`
- `"terminalBackground"`
* Properties (_listed here in dot notation, but implemented as sub-objects_)
- `tabRow.background`: accepts a ThemeColor (above)
- `window.applicationTheme`: accepts one of `{"system", "light", "dark"}`
- `window.useMica`: accepts a boolean, defaults to false.
## References
* As first described in #3327
* spec'd in #12530
## PR Checklist
* [x] Sorta enables #10509, but doesn't close it. That'll need more comprehensive changes to the titlebar code.
* **update**: I totally disabled mica, but left the serialization code. It just seems silly without #10509.
* [x] Closes#1963
* [x] Closes#3774
* [x] Closes#12939
* [x] Does the bulk of the #3327 work, but I'm going to leave that open since that's become my megathread for everything related to theming.
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - **SURE DOES**
## Detailed Description of the Pull Request / Additional comments
### --> GO READ #12530 <--
Seriously.
These themes aren't customizable in the SUI currently. You can change the active theme, and the UI will show all of the defined themes, but they're not editable there.
They don't layer. You'll need to define your own themes.
Thay can't come from fragments. This is a really cool future idea, but not implemented in this v0.
The sub objects have some gnarly macros to generate a lot of the serialization code for you.
### TODOs
* [x] I still have yet to establish what the accent color algorithm is. This might be proprietary and require a ThemeHelpers workaround.
* [x] Make sure `terminalBackground` & the SUI result in something sensible
* [x] Make sure runtime BG changes work with `terminalBackground`. One time, they didn't. `printf "\x1b]11;rgb:ff/00/ff\x07"`
* [x] Acrylic Terminal BG's look weird, like, the opacity is always 50% or something. And the tab row looks all wrong then.
## Validation Steps Performed
This is the blob I've been testing with:
<details>
```jsonc
// "useAcrylicInTabRow": true,
"theme": "my dark",
// "theme": "Edge",
"theme": "orangey",
"theme": "WHITE",
// "theme": "terminal",
"themes": [
{
"name": "my dark",
"window": {
"applicationTheme": "dark",
"useMica": true,
},
"tabRow": {
"background": "#00000000",
},
},
{
"name": "Edge",
"tabRow": { "background": "accent" },
"window": { "applicationTheme": "system" }
},
{
"name": "orangey",
"window": {
"applicationTheme": "light",
"useMica": true,
},
"tabRow": {
"background": "#ff8800",
},
},
{
"name": "WHITE",
"window": {
"applicationTheme": "dark",
"useMica": true,
},
"tabRow": {
"background": "#FFFFFF",
},
},
{
"name": "terminal",
"window": {
"applicationTheme": "dark",
"useMica": false,
},
"tabRow": {
"background": "terminalBackground",
},
},
]
```
</details>
```
% .\tools\ReleaseEngineering\ServicingPipeline.ps1
Inferred servicing version 1.14
PICK f025c53dba: Remove the fallback to wsl.exe when HKCU\...\Lxss doesn't exist (#13436)
OK
```
The hover tab color used to be generated from the selected tab color, which would end up lighter or darker, and white-gray colors would end up pink.
It is now simply the selected tab color with 60% opacity. This is also how brushes are created for accent buttons and color buttons (although with different opacity levels).
The main result of this fallback is that we attempt to launch wsl.exe
when the user hasn't installed or interacted with WSL. On our test
machines, that results in the creation of a wsl.exe process that tells
us precisely nothing; on WDAC managed machines it results in an Event
Log entry about spawning another (possibly blocked) process.
The registry is more reliable, and if the "API" it provides changes we
can just rev terminal.
Closes#11716
## Summary of the Pull Request
In #13370, we should be notifying the renderer that the selection changed. Minor oversight and simple fix.
## References
#4993#13370Closes#13413
This commit fixes a minor race condition covered as part of #13368.
The member `_pfnHandoff` was read without the mutex `_mtx` being locked first.
The issue was solved by acquiring the lock early and running the entire
`s_StopListening` function with that lock held.
## Summary of the Pull Request
Introduces the `switchSelectionEndpoint` action which switches whichever selection endpoint is targeted when a selection is present. For example, if you are targeting "start", `switchSelectionEndpoint` makes it so that now you are targeting "end". This also updates the selection markers appropriately.
## References
Spec - #5804#13358Closes#3663
## Detailed Description of the Pull Request / Additional comments
Most of the code is just standard code of adding a new action. Other than that, we have...
- if there is no selection, the action fails and the keybinding is passed through (similar to `copy()`)
- when we update the selection endpoint, we need to also update the "pivot". This ensures that future calls of `UpdateSelection()` respect this swap.
- [Corner Case] if the cursor is being moved, we make it so that you basically "anchored" an endpoint and you don't have to hold shift anymore.
## Why is this change being made?
Our conhost OneCore backend isn't as thoroughly tested as our Win32 one and fell victim to the general "bugginess" of our shutdown handling centered around `ServiceLocator::RundownAndExit`. In the past we simply leaked all resources, but changed it so that a cleanup on exit occurs, so that we can track resource leaks for instance. This broke OneCore which has a more delicate shutdown than Win32.
## What changed?
This commit reverts changes being made in 9d7a46f64c and after.
## How was the change tested?
This change was tested in a OneCore VM by repeatedly spawning subprocesses and ensuring they exit in a timely manner and without unexpected crashes.
Related work items: MSFT-40226902, MSFT-22128499
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 0683758a0846aefbbe50730c3cd336623328ddeb
## Summary of the Pull Request
1. [copy on select] when manually copying text (i.e. kbd or right-click) while in mark/quick-edit mode, we now dismiss the selection.
2. `Enter` is now bound to copy by default.
- This works very well with mark mode and provides a more consistent behavior with conhost's selection experience overall.
- "why not hardcode `Enter` as a way to copy when in mark mode?"
- In an effort to make this as configurable as possible, I decided to make it a configurable keybinding, but am open to suggestions.
3. selection markers
a. we now hide the selection markers when multi-clicking the terminal.
b. selection markers are now properly shown when a single cell selection exists
- Prior to this PR, any single cell selection would display both markers. Now, we actually track which endpoint we're moving and display the appropriate one.
4. ensures that when you use keyboard selection to move past the top/bottom of the scroll area, we clamp it to the origin/bottom-right respectively. The fix is also better here in that it provides consistent behavior across all of the `_MoveByX` functions.
5. adds `toggleBlockSelection` to the schema
## References
#13053
## Validation Steps Performed
Did a whole flowchart of expected behavior with copy on select:
- enable `copyOnSelect`
- make a selection with the mouse
- ✅ right-click should copy the text --> clear the selection --> paste
- use keyboard selection to quick-edit the existing selection
- ✅ `copy` action should clear the selection
- ✅ right-click should copy the text --> clear the selection --> paste
Played with selection markers a bit in mark mode and quick edit mode. Markers are updating appropriately.
FabricBot is now a [config-as-code-only] platform. As a result, while
you can still use the [FabricBot Configuration Portal] to modify your
FabricBot configuration, you can no longer save the changes. The only
way to save changes to your configuration at the moment is to _export
configuration_ from the portal and upload the exported configuration to
`.github/fabricbot.json` in your repository. In this pull request, we
are adding your FabricBot configuration to your repository at
`.github/fabricbot.json` so that you can make changes to it going
forward.
While the [FabricBot Configuration Portal] is the *only way* to modify
your FabricBot configuration at the moment, we have a feature on our
backlog to publish the JSON schema defining the structure of the
FabricBot configuration file. With the JSON schema, you can (1) use a
plaintext editor of your choice to modify the FabricBot configuration
file and use the schema to validate the file after editing or (2)
[configure VS Code] to use the schema when editing FabricBot
configuration file to take advantage of convenience features such as
automatic code completion and field description on mouseover.
[config-as-code-only]: https://eng.ms/docs/products/1es-data-insights/merlinbot/extensions/bot-config-as-code
[FabricBot Configuration Portal]: https://portal.fabricbot.ms/bot/?repo=microsoft/terminal
[configure VS Code]: https://code.visualstudio.com/Docs/languages/json#_json-schemas-and-settings
Co-authored-by: msftbot[bot] <48340428+msftbot[bot]@users.noreply.github.com>
Co-authored-by: Dustin Howett <duhowett@microsoft.com>
## Summary of the Pull Request
Replaces most uses of `Viewport::CompareInBounds()` with `til::point`'s `<` and `>` operators. `CompareInBounds` has been the cause of a bunch of UIA crashes over the years. Replacing them entirely ensures that the `FAILFAST_IF` isn't ever touched.
Unfortunately, we still need `IncrementInBounds` and `DecrementInBounds` to have support for that exclusive end.
## References
#13183
This commit fixes a bug causing the OpenConsole to get increasingly larger
every time the font is changed when the AtlasEngine is active.
The only impact this bug had on Windows Terminal is that the
`font-size` in HTML and RTF selection copies are too large.
## Validation Steps Performed
* OpenConsole window size doesn't change when
switching between main and alt buffer ✅
[Git2Git] Merged PR 7517171: Fix a race condition in ServiceLocator::RundownAndExit
The whole premise of RundownAndExit is that one thread enters it, runs
down the console and terminates it. One thread enters, 0 threads leave.
After some recent console locking changes, we found that on OneCore
devices it was possible for two threads (the I/O thread and the coniosrv
Input thread) to try to rundown and exit at the same time.
This SRWLOCK prevents that from happening.
Fixes#40146639
Related work items: #40146639 Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev ff235c6e49e065bccc937dee91f43ff310b5743c
Related work items: #40146639
[Git2Git] Merged PR 7517072: conhost: Force the double-click tests to have a high click timeout
The conhost tests might run somewhere that does not have a double click time.
We should hardcode a value for the purposes of testing.
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 3c2620dab577e16e8672b369e4dfcde7c02881a1
Related work items: MSFT-40150725
This introduces the build rules for midi.lib to the OS!
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev fb066544f112ae491bb1d1f73578bc47fa167b41
In #6810, we introduced a "quirk" for all known versions of PowerShell
that suppressed their requests for black background/gray foreground.
This was done to avoid an [issue in PSReadline] where it would paint
black bars all over the screen if the default background color wasn't
the same as the ANSI black color.
Years have passed since that quirk was introduced. The underlying bug
was fixed, and the fix was released broadly long ago. It's time for us
to remove the quirk... almost.
Terminal still runs on versions of Windows that ship a broken version of
PSReadline. We must maintain the quirk there -- the user can't do
anything about it, and we would make their experience worse if we
removed the quirk entirely.
PowerShell 7.0 also ships a broken version of PSReadline. It is still in
support for another 6 months, but updates have been available for some
time. We can encourage users to update.
Therefore, we only need the quirk for Windows PowerShell, and then only
for specific versions of Windows.
_Inside Windows_, we don't even need that: we're guaranteed to be built
alongside a fixed version of PowerShell!
Closes#6807
[issue in PSReadline]: https://github.com/PowerShell/PSReadLine/issues/830#issuecomment-650508857
## Summary of the Pull Request
Introduced in #10824, this fixes a bug where you could use keyboard selection to move below the scroll area. Instead, we now clamp movement to the mutable viewport (aka the scrollable area). Specifically, we clamp to the corners (i.e. 0,0 or bottom right cell of scroll area).
## Validation Steps Performed
✅ (no output) try to move past bottom of viewport
✅ (with output, at bottom of scroll area) try to move past viewport
✅ (with output, NOT at bottom of scroll area) try to move past viewport
✅ try to move past top of viewport
It's not useful to notify users that WT can be made the default if it's already
clearly being used for handoff. This commit will suppresses the banner then.
## PR Checklist
* [x] Closes#13314
* [x] I work here
## Validation Steps Performed
* Modify `TerminalPage::ShowSetAsDefaultInfoBar` to not check for
`CascadiaSettings::IsDefaultTerminalSet()`
* Set Terminal Dev as the default
* Set incoming connections to open in the latest Terminal window
* Delete `state.json` after every test below
* Launching Terminal Dev shows the banner ✅
Launching `cmd.exe` dismisses the banner in the current Terminal ✅
* Launching `cmd.exe` launches Terminal Dev without banner ✅
These files are vestigial, because we are also shipping (either as loose
files or embedded in resources.pri) precompiled xbf/xaml binary format
files.
This saves us almost 500kb on disk.
Fixes#11687
Validation
----------
I ran a local build and saw that it produced a working Terminal, packaged
and unpackaged.
## Summary of the Pull Request
This introduces a selection marker overlay that tells the user which endpoint is currently being moved by the keyboard. The selection markers are respect font size changes and `cursor` color.
## References
#715 - Keyboard Selection
#2840 - Keyboard Selection Spec
#5804 - Mark Mode Spec
## Detailed Description of the Pull Request / Additional comments
- `TermControl` layer:
- Use a canvas (similar to the one used for hyperlinks) to be able to draw the selection markers.
- If we are notified that the selection changed, update the selection markers appropriately.
- `UpdateSelectionMarkersEventArgs` lets us distinguish between mouse and keyboard selections. `ClearMarkers` is set to true in the following cases...
1. Mouse selection, via SetEndSelectionPoint
2. `LeftClickOnTerminal`, pretty self-explanatory
3. a selection created from searching for text
- `ControlCore` layer:
- Responsible for notifying `TermControl` to update the selection markers when a selection has changed.
- Transfers info (the selection endpoint positions and which endpoint we're moving) from the terminal core to the term control.
- `TerminalCore` layer:
- Provides the viewport position of the selection endpoints.
## Validation Steps Performed
- mouse selection (w/ and w/out shift) --> no markers
- keyboard selection --> markers
- markers update appropriately when we pivot the selection
- markers scroll when you hit a boundary
- markers take the color of the cursor color setting
- markers are resized when the font size changes
## Summary of the Pull Request
When you execute a `cls` in the cmd shell, or `Clear-Host` in
PowerShell, we have a pair of shims that attempt to detect those
operations and forward an `ED3` sequence to conpty to clear the
scrollback.
If there was a linefeed at the bottom of the viewport immediately
prior to those functions being called, that event might still be
pending, and only forwarded to conpty after the `ED3`. The result
then is a line pushed into the scrollback that shouldn't be there.
This PR tries to avoid that situation by forcing the renderer to
flush before the `ED3` sequence is sent.
## References
The `cls` and `Clear-Host` shims were originally added in PR #5627.
## PR Checklist
* [x] Closes#5770
* [x] Closes#13320
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema 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
## Validation Steps Performed
I've manually tested in PowerShell with `echo Hello; Clear-Host` (this
is the only way I could reliably reproduce the original problem), and in
the cmd shell with `cls`. Both cases are now working as expected.
When we send this ShowWindow message, if we send it to it's
going to need to get processed by the window message thread before
returning. We're handling this message under lock. However, the first
thing the conhost message thread does is lock the console. That'll
deadlock us. So unlock here, first, to let the message thread deal with
this message, then re-lock so later on this thread can unlock again
safely.
* [x] Closes#13301
* [x] Tested conhost
* [x] Tested terminal
When I moved this into ControlCore, I forgot that UserScrollViewport is usually triggered by the scrollbar updating, so it doesn't ask the UI to update. Since this logic is in ControlCore, it's sorta in a weird place where it needs to communicate both up and down:
* update the `Terminal`'s viewport position
* update the `TermControl`'s scrollbar position
Checklist:
* [x] Closes a bug bash bug
* [x] Missed in #12948
* See also #11000
ed27737 contains a regression were a `RECT` in `GdiEngine` wasn't properly
initialized anymore. Due to this, rendering during scrolling behaved erratic.
To find other cases of this bug in ed27737 the following regex was used:
```
^-.* = \{\s*\d*\s*\};
```
It appears that only `GdiEngine` was affected by a bug of this kind,
but just to be sure, this PR reverts all other instances.
This bug was likely caused when I tried to undo some of the changes in
ed27737 to make the PR smaller, but failed to revert the code properly.
## PR Checklist
* [x] Closes#13270
* [x] I work here
## Validation Steps Performed
I'm unable to reproduce the issue on my hardware and am unable to test
this change, but the uninitialized struct is clearly a bug regardless.
Co-authored-by: James Holderness <j4_james@hotmail.com>
Adds an accelerator key for the shell extension: `T` for stable, `P` for preview and `D` for dev.
# Validation
Ran a dev build and saw the keyboard accelerator assigned.
Closes#13061
## Summary of the Pull Request
Up to now we haven't supported passing `DCS` sequences over conpty, so
any `DCS` operations would just be ignored in Windows Terminal. This PR
introduces a mechanism whereby we can selectively pass through
operations that could reasonably be handled by the connected terminal
without interfering with the regular conpty renderer. For now this is
just used to support restoring the `DECCTR` color table report.
## References
Support for `DECCTR` was originally added to conhost in PR #13139.
## PR Checklist
* [x] Closes#13223
* [x] CLA signed.
* [x] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema 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
## Detailed Description of the Pull Request / Additional comments
The way this works is we have a helper method in `AdaptDispatch` that
`DCS` operations can use to create a passthrough `StringHandler` for the
incoming data instead of their usual handler. To make this passthrough
process more efficient, the handler buffers the data before forwarding
it to conpty.
However, it's important that we aren't holding back data if output is
paused before the string terminator, so we need to flush the buffer
whenever we reach the end of the current write operation. This is
achieved by querying a new method in the `StateMachine` that lets us
know if we're currently dealing with the last character.
Another issue that came up was with the way the `StateMachine` caches
sequences that it might later need to forward to conpty. In the case of
string sequences like `DCS`, we don't want the actual string data cached
here, because that will just waste memory, and can also result in the
data being mistakenly output. So I've now disabled that caching when
we're in any of the string processing states.
## Validation Steps Performed
I've manually confirmed that the `DECCTR` sequence can now update the
color table in Windows Terminal. I've also added a new unit test in
`ConptyRoundtripTests` to verify the sequence is being passed through
successfully.
As described in #13238. libuv sends a focus event to jiggle the handle. Now that we support focus events as VT input (#12900), we'd translate those focus events to VT input as well. That combination of things caused exiting neovim to emit a `\x1b[O` to the input line of the shell when exited.
To fix this, we're going to secretly filter out any focus events that came from the API, before translating to VT. We're fortunate here, the `FOCUS_EVENT_RECORD` version of the ctor is only called by the API.
* [x] Closes#13238
When loading color schemes from Json, check if GetValueForKey failed. If
it did, and we were searching for the colors "purple"/"brightPurple",
swap out the color name with "magenta"/"brightMagenta" and try again.
This was tested manually by creating a new color scheme using the colors
"magenta"/"brightMagenta" and loading it, then printing colored text in
the terminal to assure that the colors were correctly assigned as
purple.
This changes the color loader to use an index pair table to add support
for alternate color names.
## Validation Steps Performed
- Manually edit settings.json, creating a new color scheme with colors
"magenta" and "brightMagenta"
- View the color scheme in settings - the colors will appear as "purple"
and "brightPurple" in the UI
- Run a program that prints colored text, purple and brightPurple text
will appear in the colors defined as magenta and brightMagenta
- Modify the color scheme in the settings UI and save it, the colors
will be saved as "purple" and "brightPurple" *(I think this is the
right behavior, since calling them "magenta" is technically a
mistake)*
- Repeat the steps above with a normal color scheme - colors named
"purple" and "brightPurple" still load properly
Closes#11456
Windows Terminal Preview gets existing settings from Release build if
Preview settings are empty
This ensures that when settings are empty or not existent, we check if
we're currently in a preview build and if we are, we attempt to grab
settings from the Release build's setting path instead. We tested it
manually by changing settings in Release build and confirming that
changes migrated to Preview when settings are empty or not existent.
Additionally, we tested that settings.json of the running build changed.
We also ran existing TAEF testing locally and it passed.
In LoadAll() function in
src\cascadia\TerminalSettingsModel\CascadiaSettingsSerialization.cpp, we
first checked if the settings file us empty/exists via settingsString.
If it does not and we are in the Preview build, we try loading the
Release build's settings. We created modified versions of
CascadiaSettings::_settingsPath() and GetBaseSettingsPath() to get the
path for the Release build's settings. If the Release build settings do
exist and firstTimeSetup is true, we set it to settingsString so it can
be written to disk via WriteSettingsToDisk(). Note that currently we
hardcode the path of the Release build. This pull request was worked on
with @Dannihu01.
## Validation Steps Performed Test1: Setting to firstTimeSetup is true
and loading settings.json from WT release when release exists -> Result:
settings.json AND GUI reflected WT release’s settings
Test2: Setting to firstTimeSetup is true and loading settings.json from
WT release when release doesn’t exist -> Result: settings.json AND GUI
reflected DEFAULT settings
Test3: (After running Test1) Setting to firstTimeSetup is false and
seeing if current settings.json matches WT release. (See if it doesn’t
change) -> Result: settings.json AND GUI reflected WT release’s settings
Closes#6855
Co-authored-by: Danniell Hu <dannihu@umich.edu>
## Summary of the Pull Request
This fixes the crashes caused by using a screen reader when in an app that uses the alt buffer via two changes:
1. Fix `Terminal::ViewEndIndex()`
- `UiaTextRangeBase` receives a coordinate that is outside of the bounds of the text buffer via the following chain of functions... `_getDocumentEnd()` --> `GetLastNonSpaceCharacter()` --> `_getOptimizedBufferSize()` --> `GetTextBufferEndPoisition()` --> `ViewEndIndex()`
- Since support for the alt buffer was added recently, `ViewEndIndex()` was recently changed, so that explains why this issue came up recently. We were accidentally setting the view end index to `height` instead of `height-1`. Thanks @j4james for finding this!
- The UIA code would get the "exclusive end" of the alt buffer. Since it was using `ViewEndIndex()` to calculate that, it was one more than it should be. The UIA code has explicit allowance for "one past the end of the viewport" in its `IsInBounds()` check. Since the `ViewEndIndex()` is way beyond that, it's not allowed, hitting the fail fast.
2. Replace `FAIL_FAST_IF` with `assert`
- These fail fast calls have caused so many issues with our UIA code. Those checks still provide value, but they shouldn't take the whole app down. This change replaces the `Viewport` and `UiaTextRangeBase` fail fasts with asserts to still perform those checks, but not take down the entire app in release builds.
Closes#13183
## Validation Steps Performed
While using Narrator...
- opened nano in bash
- generated text and scrolled in nano
- generated text and scrolled in PowerShell
See also: #12799, the origin of much of this.
This change evolved over multiple phases.
### Part the first
When we create a defterm connection in `TerminalPage::_OnNewConnection`,
we don't have the hosting HWND yet, so the tab gets created without one.
We'll later get called with the owner, in `Initialize`.
To remedy this, we need to:
* In `Initialize`, make sure to update any existing controls with the
new owner.
* In `ControlCore`, actually propogate the new owner down to the
connection
### Part the second
DefTerm launches don't actually request focus mode, so the Terminal
never sends them focus events. We need those focus events so that the
console can request foreground rights.
To remedy this, we need to:
* pass `--win32input` to the commandline used to initialize OpenConsole
in ConPTY mode. We request focus events at the same time we request
win32-input-mode.
* I also added `--resizeQuirk`, because _by all accounts that should be
there_. Resizing in defterm windows should be _wacky_ without it, and
I'm a little surprised we haven't seen any bugs due to this yet.
### Part the third
`ConsoleSetForeground` expects a `HANDLE` to the process we want to give
foreground rights to. The problem is, the wire format we used _also_
decided that a HANDLE value was a good idea. It's not. If we pass the
literal value of the HANDLE to the process from OpenConsole to conhost,
so conhost can call that API, the value that conhost uses there will
most likely be an invalid handle. The HANDLE's value is its value in
_OpenConsole_, not in conhost.
To remedy this, we need to:
* Just not forward `ConsoleSetForeground`. Turns out, we _can_ just call
that in OpenConsole safely. There's no validation. So just instantiate
a static version of the Win32 version of ConsoleControl, just to use
for SetForeground. (thanks Dustin)
* [x] Tested manually - Win+R `powershell`, `notepad` spawns on top.
Closes#13211
Implements the **FTCS_PROMPT** sequence, `OSC 133 ; A ST`. In this PR, it's just used to set a simple Prompt mark on the current line, in the same way that the iTerm2 sequence works.
There's rumination in #11000 on how to implement the rest of the FTCS sequences.
This is broken into its own PR at the moment. [Quoth j4james](https://github.com/microsoft/terminal/pull/12948#issuecomment-1136360132):
> That should be just as easy, and I've noticed a couple of other terminals that are doing that, so it's not unprecedented. If we don't have any immediate use for the other options, there shouldn't be any harm in ignoring them initially.
>
> And the benefit of going with the more widely supported sequence is that we're more likely to benefit from any shells that have this functionality built in. Otherwise they're forced to try and detect the terminal, which is practically impossible for Windows Terminal. Even iTerm2 supports the `OSC 133` sequence, so we'd probably be the only odd one out.
This part of the plumbing is super easy, so I thought it would be valuable to add regardless if we get to the whole of FTCS in 1.15.
* [x] I work here
* [x] Tested manually - in my pwsh `$PROFILE`:
```pwsh
function prompt {
$loc = $($executionContext.SessionState.Path.CurrentLocation);
$out = "PS $loc$('>' * ($nestedPromptLevel + 1)) ";
$out += "$([char]27)]9;9;`"$loc`"$([char]07)";
$out += "$([char]27)]133;A;$([char]7)"; # add the FTCS_PROMPT to the... well, end, but you get the point
return $out
}
```
* See also #11000
* conhost requires an additional dependency in Windows, which might
cause us trouble in WPG
* Terminal requires an additional *package* dependency, which *will*
cause us trouble in WPG (since GmDls is about 3MB)
I chose to scope the feature checks to MidiOut directly, as I wanted to
keep the delay behavior in MidiAudio::PlayNote. This is negotiable.
References #13252
Adds support for marks in the scrollbar. These marks can be added in 3
ways:
* Via the iterm2 `OSC 1337 ; SetMark` sequence
* Via the `addMark` action
* Automatically when the `experimental.autoMarkPrompts` per-profile
setting is enabled.
#11000 has more tracking for the big-picture for this feature, as well
as additional follow-ups. This set of functionality seemed complete
enough to send a review for now. That issue describes these how I wish
these actions to look in the fullness of time. This is simply the v0.1
from the hackathon last month.
#### Actions
* `addMark`: add a mark to the buffer. If there's a selection, use
place the mark covering at the selection. Otherwise, place the mark
on the cursor row.
- `color`: a color for the scrollbar mark. This is optional - defaults
to the `foreground` color of the current scheme if omitted.
* `scrollToMark`
- `direction`: `["first", "previous", "next", "last"]`
* `clearMark`: Clears marks at the current postition (either the
selection if there is one, or the cursor position.
* `clearAllMarks`: Don't think this needs explanation.
#### Per-profile settings
* `experimental.autoMarkPrompts`: `bool`, default `false`.
* `experimental.showMarksOnScrollbar`: `bool`
## PR Checklist
* [x] Closes#1527
* [x] Closes#6232
## Detailed Description of the Pull Request / Additional comments
This is basically hackathon code. It's experimental! That's okay! We'll
figure the rest of the design in post.
Theoretically, I should make these actions `experimental.` as well, but
it seemed like since the only way to see these guys was via the
`experimental.showMarksOnScrollbar` setting, you've already broken
yourself into experimental jail, and you know what you're doing.
Things that won't work as expected:
* resizing, ESPECIALLY reflowing
* Clearing the buffer with ED sequences / Clear Buffer
I could theoretically add velocity around this in the `TermControl`
layer. Always prevent marks from being visible, ignore all the actions.
Marks could still be set by VT and automark, but they'd be useless.
Next up priorities:
* Making this work with the FinalTerm sequences
* properly speccing
* adding support for `showMarksOnScrollbar: flags(categories)`, so you
can only display errors on the scrollbar
* adding the `category` flag to the `addMark` action
## Validation Steps Performed
I like using it quite a bit. The marks can get noisy if you have them
emitted on every prompt and the buffer has 9000 lines. But that's the
beautiful thing, the actions work even if the marks aren't visible, so
you can still scroll between prompts.
<details>
<summary>Settings blob</summary>
```jsonc
// actions
{ "keys": "ctrl+up", "command": { "action": "scrollToMark", "direction": "previous" }, "name": "Previous mark" },
{ "keys": "ctrl+down", "command": { "action": "scrollToMark", "direction": "next" }, "name": "Next mark" },
{ "keys": "ctrl+pgup", "command": { "action": "scrollToMark", "direction": "first" }, "name": "First mark" },
{ "keys": "ctrl+pgdn", "command": { "action": "scrollToMark", "direction": "last" }, "name": "Last mark" },
{ "command": { "action": "addMark" } },
{ "command": { "action": "addMark", "color": "#ff00ff" } },
{ "command": { "action": "addMark", "color": "#0000ff" } },
{ "command": { "action": "clearAllMarks" } },
// profiles.defaults
"experimental.autoMarkPrompts": true,
"experimental.showMarksOnScrollbar": true,
```
</details>
ed27737 contains a regression where (pseudocode)
```c
unsigned long ulActualDelta;
short ScreenInfo.WheelDelta;
delta *= (ScreenInfo.WheelDelta / (short)ulActualDelta);
// ^^^^^^^
```
was changed to
```c
delta *= (ScreenInfo.WheelDelta / ulActualDelta);
```
Due to `ulActualDelta` being unsigned, the new code casts the signed integer
to a unsigned one first, before doing the division. This causes scrolling
downwards (`WheelDelta` is negative) to appear as a large positive `delta`.
## PR Checklist
* [x] Closes#13253
* [x] I work here
## Validation Steps Performed
* Scrolling up/down works in OpenConsole again ✅
When #13160 introduced a new interface to the IConsoleHandoff idl, it
changed midl's RPC proxy stub lookup algorithm from a direct GUID
comparison to an unrolled binary search. Now, that would ordinarily not
be a problem...
However, in #11610, we took a shortcut and replaced `memcmp` -- used
only by RPC for GUID comparison -- with a direct GUID-only equality
comparator. This worked totally fine, and ordinarily would not be a
problem...
The unrolled binary search unfortunately _relies on memcmp's contract_:
it uses memcmp to match against a fully sorted set. Our memcmp only
returned 0 or 1 (equal or not), and it knew nothing about ordering.
When a package that contains a PackagedCOM proxy stub is installed, it
is selected as the primary proxy stub for any interfaces it can proxy.
After all, interfaces are immutable, so it doesn't matter whose proxy
you're using. Now, given that we installed a *broken* proxy... *all*
IIDs that got whacked by our memcmp issue broke for every consumer.
To fix it: instead of implementing memcmp ourselves, we're just going to
take a page out of WinAppSDK's book and link this binary using the
"Hybrid CRT" model. It will statically link any parts of the STL it uses
(none) and dynamically link the ucrt (which is guaranteed to be present
on Windows.)
Sure, the binary size goes up from 8k to 24k, but... the cost is never
having to worry about this again.
Closes#13251
## Summary of the Pull Request
When a profile gets deleted, we were navigating to the next item assuming it was a profile when it may not be. This commit fixes this by checking the tag of the next menu item before we navigate to it.
## PR Checklist
* [x] Closes#13125
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here
## Validation Steps Performed
Deleting the last profile in the SUI doesn't cause a crash
If we want to make Windows Terminal the default terminal under Windows,
we'll have to make conhost "handoff" incoming connections by default.
But this poses a problem: How can the seldomly updated conhost know
whether the routinely updated Windows Terminal version is actually willing
to accept such handoffs by default (it might be unwilling due to bugs, etc.)?
This commit solves the issue by introducing:
* A marker interface (`IDefaultTerminalMarker`): If it exists,
Windows Terminal indicates its willingness to accept the handoff.
* Turning the all-0 GUID from being synonymous for conhost,
to being synonymous for "Let Windows decide". Without this we wouldn't
be able to differentiate between users who consciously chose conhost
as their default terminal, vs. users who want the standard behavior.
Testing fallback behavior:
* Install "Terminal" 1.13
* Delete the 2 keys below `HKCU\Console\%%Startup`
* Enable `Feature_AttemptHandoff` in `features.xml`
Return `true` from `DefaultApp::CheckShouldTerminalBeDefault`
* Replace `conhost.exe` and `console.dll` with `sfpcopy` after building
* Launching `cmd.exe` launches as a conhost window ✅
(because "Terminal" 1.13 lacks the marker interface)
* Open properties page in `conhost.exe`
"Let Windows decide" is select by default ✅
* Changing the selection writes the new value ✅
Testing the new behavior:
* Delete the 2 keys below `HKCU\Console\%%Startup`
* Enable `Feature_AttemptHandoff` in `features.xml`
Return `true` from `DefaultApp::CheckShouldTerminalBeDefault`
* Use `CLSID_WindowsTerminalConsoleDev` and `CLSID_WindowsTerminalTerminalDev`
for the initialization of `TerminalDelegationPair`
* Replace `conhost.exe` and `console.dll` with `sfpcopy` after building
* Deploy the "Terminal Dev" package
* Launching `cmd.exe` launches "Terminal Dev" ✅
(because "Terminal Dev" has the marker interface)
* Open the settings tab
"Let Windows decide" is select by default ✅
* Changing the selection and saving writes the new value ✅
(cherry picked from commit 1b81c6540f)
Service-Card-Id: 82925080
Service-Version: Inbox
If we want to make Windows Terminal the default terminal under Windows,
we'll have to make conhost "handoff" incoming connections by default.
But this poses a problem: How can the seldomly updated conhost know
whether the routinely updated Windows Terminal version is actually willing
to accept such handoffs by default (it might be unwilling due to bugs, etc.)?
This commit solves the issue by introducing:
* A marker interface (`IDefaultTerminalMarker`): If it exists,
Windows Terminal indicates its willingness to accept the handoff.
* Turning the all-0 GUID from being synonymous for conhost,
to being synonymous for "Let Windows decide". Without this we wouldn't
be able to differentiate between users who consciously chose conhost
as their default terminal, vs. users who want the standard behavior.
## Validation Steps Performed
Testing fallback behavior:
* Install "Terminal" 1.13
* Delete the 2 keys below `HKCU\Console\%%Startup`
* Enable `Feature_AttemptHandoff` in `features.xml`
Return `true` from `DefaultApp::CheckShouldTerminalBeDefault`
* Replace `conhost.exe` and `console.dll` with `sfpcopy` after building
* Launching `cmd.exe` launches as a conhost window ✅
(because "Terminal" 1.13 lacks the marker interface)
* Open properties page in `conhost.exe`
"Let Windows decide" is select by default ✅
* Changing the selection writes the new value ✅
Testing the new behavior:
* Delete the 2 keys below `HKCU\Console\%%Startup`
* Enable `Feature_AttemptHandoff` in `features.xml`
Return `true` from `DefaultApp::CheckShouldTerminalBeDefault`
* Use `CLSID_WindowsTerminalConsoleDev` and `CLSID_WindowsTerminalTerminalDev`
for the initialization of `TerminalDelegationPair`
* Replace `conhost.exe` and `console.dll` with `sfpcopy` after building
* Deploy the "Terminal Dev" package
* Launching `cmd.exe` launches "Terminal Dev" ✅
(because "Terminal Dev" has the marker interface)
* Open the settings tab
"Let Windows decide" is select by default ✅
* Changing the selection and saving writes the new value ✅
## Summary of the Pull Request
This introduced the `toggleBlockSelection` action to allow users to create a block selection using only the keyboard. This is not bound to any keys by default, however it is added to the command palette.
## References
#4993 - Epic
#5804 - Spec
## Validation Steps Performed
- [X] Mark mode always starts in line selection mode
- [X] Mouse selections are always in line selection mode by default
- [X] Can toggle block selection for an existing selection (regardless of how it was created)
- [X] The selection is copied properly (aka, no rendering issues)
Previously this project used a great variety of types to present text buffer
coordinates: `short`, `unsigned short`, `int`, `unsigned int`, `size_t`,
`ptrdiff_t`, `COORD`/`SMALL_RECT` (aka `short`), and more.
This massive commit migrates almost all use of those types over to the
centralized types `til::point`/`size`/`rect`/`inclusive_rect` and their
underlying type `til::CoordType` (aka `int32_t`).
Due to the size of the changeset and statistics I expect it to contain bugs.
The biggest risk I see is that some code potentially, maybe implicitly, expected
arithmetic to be mod 2^16 and that this code now allows it to be mod 2^32.
Any narrowing into `short` later on would then throw exceptions.
## PR Checklist
* [x] Closes#4015
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
Casual usage of OpenConsole and Windows Terminal. ✅
This PR introduces the framework for the `DECRSTS` sequence which is
used to restore terminal state reports. But to start with, I've just
implemented the `DECCTR` color table report, which provides a way for
applications to alter the terminal's color scheme.
## PR Checklist
* [x] Closes#13132
* [x] CLA signed.
* [x] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema 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
## Detailed Description of the Pull Request / Additional comments
I've added the functions for parsing DEC RGB and HLS color formats into
the `Utils` class, where we've got all our other color parsing routines,
since this functionality will eventually be needed in other VT protocols
like Sixel and ReGIS.
Since `DECRSTS` is a `DCS` sequence, this only works in conhost for now,
or when using the experimental passthrough mode in Windows Terminal.
## Validation Steps Performed
I've added a number of unit tests to check that the `DECCTR` report is
being interpreted as expected. This includes various edge cases (e.g.
omitted and out-of-range parameters), which I have confirmed to match
the color parsing on a real VT240 terminal.
## Summary of the Pull Request
The `DECPS` (Play Sound) escape sequence provides applications with a
way to play a basic sequence of musical notes. This emulates
functionality that was originally supported on the DEC VT520 and VT525
hardware terminals.
## PR Checklist
* [x] Closes#8687
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number
where discussion took place: #8687
## Detailed Description of the Pull Request / Additional comments
When a `DECPS` control is executed, any further output is blocked until
all the notes have finished playing. So to prevent the UI from hanging
during this period, we have to temporarily release the console/terminal
lock, and then reacquire it before returning.
The problem we then have is how to deal with the terminal being closed
during that unlocked interval. The way I've dealt with that is with a
promise that is set to indicate a shutdown. This immediately aborts any
sound that is in progress, but also signals the thread that it needs to
exit as soon as possible.
The thread exit is achieved by throwing a custom exception which is
recognised by the state machine and rethrown instead of being logged.
This gets it all the way up to the root of the write operation, so it
won't attempt to process anything further output that might still be
buffered.
## Validation Steps Performed
Thanks to the testing done by @jerch on a real VT525 terminal, we have a
good idea of how this sequence is supposed to work, and I'm fairly
confident that our implementation is reasonably compatible.
The only significant difference I'm aware of is that we support multiple
notes in a sequence. That was a feature that was documented in the
VT520/VT525 manual, but didn't appear to be supported on the actual
device.
MSFT-33471786 is one of the most common crashes we have right now.
Memory dumps suggest that `VtEngine::UpdateViewport` is called with a rectangle
like `(0, 46, 119, 29)` (left, top, right, bottom), which is a rectangle of
negative height. When the `_invalidMap` is resized the negative size gets
turned into a very large unsigned integer, which results in an OOM exception,
crashing OpenConsole.
`VtEngine::UpdateViewport` is called by `Renderer::_CheckViewportAndScroll`
which holds a (cached) old and a new viewport. The old viewport was
`(0, 46, 119, 75)` which is exceedingly similar to the invalid, new viewport.
It's bottom coordinate is also coincidentally larger by exactly 46 (top).
The viewport comes from the `SCREEN_INFORMATION` class whose `SetViewport`
function was highly suspicious as it has a branch which updates the bottom
to be the buffer height, but leaves the top unmodified.
`SCREEN_INFORMATION::SetViewport` is called by `SetConsoleWindowInfo` which
processes user-provided data. A repro of the crash can be constructed with:
```
SMALL_RECT rect{0, 46, 119, 75};
SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &rect);
```
Closes#13193
Closes MSFT-33471786
## Validation Steps Performed
Ensured the following code doesn't crash when run under Windows Terminal:
```
SMALL_RECT rect{0, 46, 119, 75};
SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE), TRUE, &rect);
```
This commit hides the "Open in Terminal" context menu option when the
context menu is opened in a non-filesystem path like "Quick Actions".
Closes#12578
This is a big hammer to put out this fire. We're keeping the hiding around for now, cause we think that's likely the one that the internal tests use that we really care about here. If we need to bring this back, we can.
* [x] Closes#13158
* [x] Closes#13162
* [x] Validated these both manually
* [x] `[Native]::ShowWindow([Native]::GetConsoleWindow(), 6)` still works
Prevents a null pointer dereference when attempting to split a settings tab, due to it not being a terminal tab.
* [x] Closes#13166
## Validation Steps Performed
Manually tested.
This only impacts the UI. We can take a workitem to rename the loc data
later. When the user specifies zh-Hans/zh-Hant, the resource mapper does
the right thing.
Related to #8984
Use a throttled update to update our window state. Throttling should prevent scenarios where the Terminal window state and PTY window state get de-sync'd, and cause the window to minimize/restore constantly in a loop. "Should" is doing a lot of work in this sentence.
A 200ms delay was chosen because it's the typical animation timeout in Windows. This does result in a delay between the PTY requesting a change to the window state and the Terminal realizing it, but should mitigate issues where the Terminal and PTY get desync'd.
I think we're overall not super confident that this fixes the root causes of the issue. Rather, we're hopeful that a small amount of throttling here should leave time for the Terminal and pty to sync back up. We're comfortable enough with that as a bandaid for 1.14 preview, to see how this behaves in the wild.
ThemeResources are a persistent pain.
Regressed in #13083. See also #12775 et. al.
We can't just put those here though as StaticResources, because XAML will evaluate their values when the App is first loaded, and we'll always use the value from the OS theme, regarless of the requested theme. Kinda the same thing we've had to do with TabViewBackground in the past.
* [x] Fixes something we noticed right before shipping
We're doing it this way because ThemeResources are tricky. We
default in XAML to using the appropriate ThemeResource background
color for our TabRow. When tabs in the titlebar are _disabled_,
this will ensure that the tab row has the correct theme-dependent
value. When tabs in the titlebar are _enabled_ (the default),
we'll switch the BG to Transparent, to let the Titlebar Control's
background be used as the BG for the tab row.
We can't do it the other way around (default to Transparent, only
switch to a color when disabling tabs in the titlebar), because
looking up the correct ThemeResource from and App dictionary is a
capital-H Hard problem.
* [x] Closes#13143
* [x] I work here
* [x] validated manually:
- [x] showTabsInTitlebar: false, true
- [x] useAcrylicInTabRow: false, true
- [x] theme: light, dark
* [x] Need to check if this is regressed the same in 1.13. I suspect it is.
## Summary of the Pull Request
Introduces a non-configurable version of mark mode to Windows Terminal. It has the following interactions defined:
- <kbd>ctrl+shift+m</kbd> --> Enter Mark Mode
- when in Mark Mode...
- <kbd>ESC</kbd> --> Exit Mark Mode
- arrow keys --> move "start"
- <kbd>shift</kbd> + arrow keys --> anchor "start", move "end"
- <kbd>ctrl+a</kbd> --> select all
- when a selection is active...
When in mark mode, the cursor does not blink.
## References
#4993 - [Epic] Keyboard Selection
## PR Checklist
* [X] Closes#715
* [X] Provides a resolution for #11985
## Detailed Description of the Pull Request / Additional comments
- `TermControl`:
- `TermControl.cpp` just adds logic to prevent the cursor from blinking when in mark mode
- `ControlCore`
- in the same place we handle quick edit, we add an entry point to mark mode
- `TerminalCore`
- this leverages `UpdateSelection()` and other quick edit functions to make mark mode happen
## Validation Steps Performed
- [x] Make selection, split pane, close pane
- NOTE: A similar scenario caused a crash at one point. Really weird. Keep an eye on it.
- [x] Cursor is off when in mark mode
- [x] general movement/selection
- [x] general movement/selection that forces the viewport to move
- [x] In mark mode, selectAll...
- [x] arrow keys --> move start
- [x] shift + arrow keys --> move end
- [x] (regardless of mark mode) if selection active, enter --> copy to clipboard
Well this one feels dumb.
Make sure to also initially set the visibility of ConPTY windows created for DefTerm connections.
* [x] Closes#13066 for real.
* [x] tested manually.
A bad merge, that actually revealed a horrible bug.
There was a secret conflict between the code in #12526 and #12515. 69b77ca was a bad merge that hid just how bad the issue was. Fixing the one line `nullptr`->`this` in `InteractivityFactory` resulted in a window that would flash uncontrollably, as it minimized and restored itself in a loop. Great.
This can seemingly be fixed by making sure that the conpty window is initially created with the owner already set, rather than relying on a `SetParent` call in post. This does pose some complications for the #1256 future we're approaching. However, this is a blocking bug _now_, and we can figure out the tearout/`SetParent` thing in post.
* fixes#13066.
* Tested with the script in that issue.
* Window doesn't flash uncontrollably.
* `gci | ogv` still works right
* I work here.
* Opening a new tab doesn't spontaneously cause the window to minimize
* Restoring from minimized doesn't yeet focus to an invisible window
* Opening a new tab doesn't yeet focus to an invisible window
* There _is_ a viable way to call `GetAncestor` s.t. it returns the Terminal's hwnd in Terminal, and the console's in Conhost
The `SW_SHOWNOACTIVATE` change is also quite load bearing. With just `SW_NORMAL`, the pseudo window (which is invisible!) gets activated whenever the terminal window is restored from minimized. That's BAD.
There's actually more to this as well.
Calling `SetParent` on a window that is `WS_VISIBLE` will cause the OS to hide the window, make it a _child_ window, then call `SW_SHOW` on the window to re-show it. `SW_SHOW`, however, will cause the OS to also set that window as the _foreground_ window, which would result in the pty's hwnd stealing the foreground away from the owning terminal window. That's bad.
`SetWindowLongPtr` seems to do the job of changing who the window owner is, without all the other side effects of reparenting the window.
Without `SetParent`, however, the pty HWND is no longer a descendant of the Terminal HWND, so that means `GA_ROOT` can no longer be used to find the owner's hwnd. For even more insanity, without `WS_POPUP`, none of the values of `GetAncestor` will actually get the terminal HWND. So, now we also need `WS_POPUP` on the pty hwnd. To get at the Terminal hwnd, you'll need
```c++
GetAncestor(GetConsoleWindow(), GA_ROOTOWNER)
```
This PR adds support for the VT line rendition attributes in the DirectX
renderer, which allows for double-width and double-height line
renditions.
Line renditions were first implemented in conhost (with the GDI
renderer) in PR #8664. Supporting them in the DX renderer now is a
small step towards #11595.
The DX implementation is very similar to the GDI one. When a particular
line rendition is requested, we create a transform that is applied to
the render target. And in the case of double-height renditions, we also
initialize some clipping offsets to allow for the fact that we only
render half of a line at a time.
One additional complication exists when drawing the cursor, which
requires a two part process where it first renders to a command list,
and then draw the command list in a second step. We need to temporarily
reset the transform in that first stage otherwise it ends up being
applied twice.
I've manually tested the renderer in conhost by setting the `UseDx`
registry entry and confirmed that it passes the _Vttest_ double-size
tests as well as several of my own tests. I've also checked that the
renderer can now handle horizontal scrolling, which is a feature we get
for free with the transforms.
## Summary of the Pull Request
When the conpty passthrough mode is enabled, it often needs to send `DSR-CPR` queries (cursor position reports) to the client terminal to obtain the current cursor position. However, the code that originally handled the responses to these queries got broken by the refactoring of the `ConGetSet` API. This PR is an attempt to correct that regression.
## References
The conpty passthrough mode was introduced in PR #11264.
The refactoring that broke the cursor position handling was in PR #12703.
## PR Checklist
* [x] Closes#13106
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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
## Detailed Description of the Pull Request / Additional comments
Prior to the `ConGetSet` refactoring, the code that handled `DSR-CPR` responses (`InteractDispatch::MoveCursor`) would pass the cursor position to `ConGetSet::SetCursorPosition`, which in turn would forward it to the `SetConsoleCursorPositionImpl` API, and from there to the `VtIo` class.
After the refactor, all of those intermediate steps were removed - the cursor was simply updated directly in `InteractDispatch::MoveCursor`, and the `VtIo` call was moved from `SetConsoleCursorPositionImpl` to `InteractDispatch` (since that was the only place it was actually required).
However, when the conpty passthrough mode was introduced - which happened in parallel - it relied on the `SetConsoleCursorPositionImpl` API being called from `InteractDispatch` in order to handle its own `DSR-CPR` responses, and that's why things stopped working when the two PRs merged.
So what I've done now is made `InteractDispatch::MoveCursor` method call `SetConsoleCursorPositionImpl` again (although without the intermediate `ConGetSet` overhead), and moved the `VtIo::SetCursorPosition` call back into `SetConsoleCursorPositionImpl`.
This is not ideal, and there are still a bunch of problems with the `DSR-CPR` handling in passthrough mode, but it's at least as good as it was before.
## Validation Steps Performed
I've just manually tested various shells with passthrough mode enabled, and confirmed that they're working better now. There are still issues, but nothing that wasn't already a problem in the initial implementation, at least as far as I can tell.
This regressed in ad2358d.
We're interested in the size of the viewport only, but it can shift up/down
during scrolling. In these situations we shouldn't resize our buffers of course.
## Validation Steps Performed
* Scroll
* Not setting `ApiInvalidations::Size` ✅
## Summary of the Pull Request
Add `Find` to tab context menu as describe in issue #5633.
## PR Checklist
* [x] Closes#5633
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
## Detailed Description of the Pull Request / Additional comments
Just wanted to solve `Easy Starter` issue, so any corrections/suggestions welcome. There's a couple of points I'm not sure of
* Placement of item within menu, currently it's at the end before close tab block.
* Should it be named longer, something like `Find in Tab` of just `Find` is fine?
* The workaround for focus similar to tab rename is a bit annoying, especially because it required adding a method to `TermControl` but without it find window obviously opens without focus which is bad.
## Validation Steps Performed
Open menu, press menu item try to find things via opened find dialog.
This commit includes various minor improvements to til::hash/point/size/rect
which accumulated while working on #4015.
* Allow xvalue containers and non-`size_t` indices in `til::at`.
* `til::as_unsigned` can be used to reinterpret a potentially signed integer
as a unsigned one. This can potentially enable some optimizations as no sign
extension is needed anymore. `til::hash` can make use of this to drop about
20% of the hashing of signed integers <= 32 bit. On x86 this translates to
a `mov` (virtually no latency) or no instructions at all, instead of
requiring a `movsx` (some latency) for sign extension.
* `til::point` operators that prefer mutability.
This is a opinionated change, but it follows the STL style beter and
generates less assembly.
* Simpler `rect` scale_up/down and `size` divide_ceil.
`scale_up` will not depend on the operator header anymore.
`scale_down` / `divide_ceil` can be implemented without checked numerics,
so I did. It also follows the related GdiEngine code better now, which
makes me confident that we can replace GdiEngine's code with this.
* Removal of rect-size-shift operators.
They were only used in DxEngine and confusing as they weren't commutative.
Adding and then subtracting a size from a rect (and vice versa) didn't do
what you'd intuitively think it'd do. The code was replaced with addition
and clamps in DxEngine.
* Various unsafe `as_` casts for point/size/rect.
This will aid the migration in #4015.
## Validation Steps Performed
* Vertical scrolling works in `DxEngine` ✅
This commit is one of the more difficult rewrites that were necessary as part
of #4015, but still simple enough that it can be done as a separate commit.
The search for the `lastNonSpace` was replaced with a simpler
`std::string_view::find_last_not_of`.
## Validation Steps Performed
ConPTY appears to work ✅
This reverts commit 14098d71f2.
## Summary of the Pull Request
@zadjii-msft found that this is causing persisted windows on a secondary monitor to shrink a little each time. We're choosing to revert this commit until that gets resolved.
## References
#12979
This commit fixes various bugs in our unit/feature test suite:
* 2 tests failed at 150% scale.
* The "null key" (@ on a US keyboard) isn't necessarily Shift+2.
The proper way to get it is with `LOBYTE(VkKeyScanW(0))`
* `InputEngineTest::C0Test` never worked as it overwrote
the loop variable, exiting the loop early
Fixes the following issues:
* `desktopWallpaper` not working
* switching tabs/panes causes the background to flicker
* settings preview having a transparent background
## PR Checklist
* [x] Closes#13002
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
Tested the 3 cases above. ✅
## Summary of the Pull Request
For some reason, the PGO tests (specifically the `RunMakeKillTabs` test) started to fail after #12979 merged. After closer inspection, the test was actually improperly written. We should be using <kbd>ctrl+shift+t</kbd> to open new tabs, not <kbd>alt+shift+t</kbd>. Presumably, the <kbd>alt</kbd> was copied over from the previous test, because they look _very_ similar.
So I went ahead and fixed the test, and it now (1) tests what it's intended to test and (2) doesn't fail. Why did #12979 cause the tests to fail? idk, but it works now.
## References
#10071 - Introduce PGO Tests
## Validation Steps Performed
Ran PGO tests locally and confirmed that it works.
Ran PGO pipeline and confirmed that it works.
When the buffer is resized with a reflow, we were previously calculating
the new virtual bottom based on the position of last non-space
character. If the viewport was largely blank when resized, this could
result in the new virtual bottom being higher than it should be.
This PR attempts to address that problem by restoring the virtual bottom
to a position that is the same distance from the cursor row as it was
prior to the resize.
This was a regression introduced in PR #12972.
We still take the last non-space row into account when determining the
virtual bottom, because if the content of the screen is forced to wrap,
the virtual bottom will need to be lower (relative to the cursor) than
it was before.
We also need to check that we don't overflow the bottom of the buffer,
which can occur when the viewport is at the bottom of the buffer, and
the cursor position is pushed down as a result of content wrapping above
it.
I've manually confirmed that this fixes the problem reported in issue
#13078, and I've also extended the existing `RefreshWithReflow` unit
test to cover that particular scenario.
Closes#13078
The `DECAC` (Assign Colors) escape sequence controls which color table
entries are associated with the default foreground and background
colors. This is how you would change the default colors on the the
original DEC VT525 terminals.
But `DECAC` also allows you to assign the color table entries for the
"window frame", which in our case is mapped to the tab color (just the
background for now). So this now gives us a way to control the tab color
via an escape sequence as well.
DETAILS
-------
The way this works is there are now two new entries in the color table
for the frame colors, and two new aliases in the color alias table that
are mapped to those color table entries. As previously mentioned, only
the background is used for now.
By default, the colors are set to `INVALID_COLOR`, which indicates that
the system colors should be used. But if the user has set a `tabColor`
property in their profile, the frame background will be initialized with
that value instead.
And note that some of the existing color table entries are now
renumbered for compatibility with XTerm, which uses entries 256 to 260
for special colors which we don't yet support. Our default colors are
now at 261 and 262, the frame colors are 263 and 264, and the cursor
color is 265.
So at runtime, you can change the tab color programmatically by setting
the color table entry at index 262 using `OSC 4` (assuming you need a
specific RGB value). Otherwise if you just want to set the tab color to
an existing color index, you can use `DECAC 2`.
You can even make the tab color automatically match background color by
mapping the frame background alias to the color table entry for the
default background, using `DECAC 2;261;262` (technically this is mapping
both the the foreground and background).
This PR doesn't include support for querying the color mapping with
`DECRQSS`, and doesn't support resetting the colors with `RIS`, but
hopefully those can be figured out in a future PR - there are some
complications that'll need to be resolved first.
## Validation Steps Performed
I've added a basic unit test that confirms the `DECAC` escape sequence
updates the color aliases in the render settings as expected. I've also
manually confirmed that the tab color in Windows Terminal is updated by
`DECAC 2`, and the default colors are updated in both conhost and WT
using `DECAC 1`.
Closes#6574
Fixes the SUI background being red in high contrast mode. The issue was
that `SolidBackgroundFillColorTertiary` purposefully has a bad High
Contrast color[^1].
The fix was to be explicit in the theme resources so that
`SolidBackgroundFillColorTertiary` is used in light and dark mode, but
the standard high contrast one is used in high contrast mode. Since the
page is the top-level XAML element in the Editor project, I had to
introduce this in the App.xaml resources so that the page can find the
theme resource.
Closes#13065Closes#13070
[^1]: 40df43a61c/dev/CommonStyles/Common_themeresources_any.xaml (L650-L651)
## Summary of the Pull Request
When calculating the position of the virtual bottom after a resize with
reflow, it was possible for it to end up less than the height of the
viewport. This meant that the top of the virtual viewport would be
negative, which resulted in other operations failing further down the
line. This PR updates the virtual bottom calculation to fix that
scenario.
## References
This was probably a regression introduced in PR #12972.
## PR Checklist
* [x] Closes#13034
* [x] CLA signed.
* [x] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number where discussion took place: #13034
## Validation Steps Performed
I wasn't able to replicate the exact case described in issue #13034,
because I don't have Windows 11, so can't configure the default
terminal. However, I was able to reproduce a similar failure using a
`SetConsoleScreenBufferInfoEx` call, and I've confirmed that this PR
has fixed that.
I've also added another screen buffer test to make sure the
`ResizeWithReflow` method doesn't shrink the virtual bottom when
resizing at the top of the buffer.
When we start up, our window is initially just a frame with a transparent content area. We're gonna do all this startup init on the UI thread, so the UI won't actually paint till it's all done. This results in a few frames where the frame is visible, before the page paints for the first time, before any tabs appears, etc.
To mitigate this, we're gonna wait for the UI thread to finish everything it's gotta do for the initial init, and _then_ fire our Initialized event. By waiting for everything else to finish (`CoreDispatcherPriority::Low`), we let all the tabs and panes actually get created. In the window layer, we're gonna ~cloak~ just not show the window till this event is fired, so we don't actually see this frame until we're actually all ready to go. **This will result in the window seemingly not loading as fast**, but it will actually take exactly the same amount of time before it's usable.
I also experimented with drawing a solid BG color before the initialization is finished. However, there are still a few frames after the frame is displayed before the XAML content first draws, so that didn't actually resolve any issues.
* [x] Closes#11561
* [x] Tested manually
* [x] I work here.
* [x] Accidentally also closes#9053. By switching the initial call from `ShowWindow(SW_SHOW)` to `ShowWindow(SW_SHOWDEFAULT)`, we actually obey the startup info now.
Adds the `selectAll` action which can be used to select all text in the buffer (regardless of whether a selection is present).
## References
#3663 - Mark Mode
#4993 - [Scenario] Keyboard selection
## PR Checklist
* [x] Closes#1469
* [x] Tests added/passed
## Detailed Description of the Pull Request / Additional comments
I've made it such that selecting the "entire buffer" really just selects up to the mutable viewport. This seems like a nice QOL improvement since there's generally nothing past that.
When the user selects all, the viewport does not move. This is consistent with CMD behavior and is intended to allow the user to not lose context when selecting everything.
A minor change had to be made to the DxRenderer because this uncovered an underflow issue. Basically, the selection rects were handed to the DxEngine relative to the viewport (which means that some had a negative y-value). At some point, those rects were stored into `size_t`s, resulting in an underflow issue. This caused the renderer to behave strangely when rendering the selection. Generally, these kinds of issues weren't really noticed because selection would always modify a portion of the viewport.
Funny enough, in a way, this satisfies the "mark mode" scenario because the user now has a way to initiate a selection using only the keyboard. Though this isn't ideal, just a fun thing to point out (that's why I'm not closing the mark mode issue).
## Validation Steps Performed
- Verified using DxEngine and AtlasEngine
- select all --> keyboard selection --> start moving the top-left endpoint (and scroll to there)
- select all --> do not scroll automatically
Turns out if you add that Delete handler there, then every time you navigate to the profile, we'll add another Delete handler to the list of handlers. That's bad - that'll cause us to try and delete the profile multiple times.
The repro I had before was 100%, now it's fixed.
* [x] Closes#13017
`TextAttribute` and `TextColor` are commonly used structures in hot paths.
This commit replaces more complex comparisons where each field is compared
independently with a single call to `memcmp`. This compiles down to just
a few instructions. This reduces code and binary size and improves
performance for paths were `TextAttribute`s need to be compared.
## PR Checklist
* [x] Supports #10563
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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
## Validation Steps Performed
* termbench still works ✔️
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
## Summary of the Pull Request
As discussed in team sync. Ignore `newTab` actions with a profile index greater than the number of profiles.
## PR Checklist
* [x] Closes#11114
* [x] I work here
* [ ] Tests added/passed
* [ ] Requires documentation to be updated - maybe❓
In classic fashion, we never run the LocalTests locally before committing, so stuff breaks from time to time.
This time, the main trick was that the tests had a pretty hardcore dependency on the inner workings of `_PreviewActionHandler`, and when that changed, they broke.
Also, there was a weird crash I saw when I had the default terminal set to the Dev build version. That crash would let the test contents pass, but ultimately fail when TAEF tore down the conhost. Unsetting that fixed the crash 🤷Closes#12158
## Summary of the Pull Request
When `TerminalDispatch` was merged with `AdaptDispatch` in PR #13024,
that broke the Terminal's `EraseAll` operation in the alt buffer. The
problem was that the `EraseAll` implementation makes a call to
`SetViewportPosition` which wasn't taking the alt buffer into account,
and thus modified the main viewport instead.
This PR corrects that mistake. If we're in the alt buffer, the
`SetViewportPosition` method now does nothing, since the alt buffer
viewport should always be at 0,0.
## References
This was a regression introduced in PR #13024.
## PR Checklist
* [x] Closes#13038
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number where discussion took place: #13038
## Validation Steps Performed
I've confirmed that the test case reported in issue #13038 is no longer
failing. I've also made sure the `ED 2` and `ED 3` sequences are still
working correctly in the main buffer.
To quote an internal wiki:
> It generally provides improved footprint and performance over the
> existing default heap for native win32 applications.
It is apparently the default heap on ARM64, and for all UWPs.
This heap has different allocation and compaction characteristics.
I am not sure how it will impact terminal.
## Summary of the Pull Request
Make sure we set `Name` and `FullDescription` on expander-style settings in the SUI
## PR Checklist
* [x] Closes#13019
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here
## Validation Steps Performed
Accessibility insights now shows the name/full description for the expander-style settings
## Summary of the Pull Request
This PR replaces the `TerminalDispatch` class with the `AdaptDispatch` class from conhost, so we're no longer duplicating the VT functionality in two places. It also gives us a more complete VT implementation on the Terminal side, so it should work better in pass-through mode.
## References
This is essentially part two of PR #12703.
## PR Checklist
* [x] Closes#3849
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number where discussion took place: #12662
## Detailed Description of the Pull Request / Additional comments
The first thing was to give the `ConGetSet` interface a new name, since it's now no longer specific to conhost. I went with `ITerminalApi`, since that was the equivalent interface on the terminal side, and it still seemed like a generic enough name. I also changed the way the api is managed by the `AdaptDispatch` class, so it's now stored as a reference rather than a `unique_ptr`, which more closely matches the way the `TerminalDispatch` class worked.
I then had to make sure that `AdaptDispatch` actually included all of the functionality currently in `TerminalDispatch`. That meant copying across the code for bracketed paste mode, the copy to clipboard operation, and the various ConEmu OSC operations. This also required a few new methods to the `ConGetSet`/`ITerminalApi` interface, but for now these are just stubs in conhost.
Then there were a few thing in the api interface that needed cleaning up. The `ReparentWindow` method doesn't belong there, so I've moved that into `PtySignalInputThread` class. And the `WriteInput` method was too low-level for the Terminal requirements, so I've replaced that with a `ReturnResponse` method which takes a `wstring_view`.
It was then a matter of getting the `Terminal` class to implement all the methods in the new `ITerminalApi` interface that it didn't already have. This was mostly mapping to existing functionality, but there are still a number of methods that I've had to leave as stubs for now. However, what we have is still good enough that I could then nuke the `TerminalDispatch` class from the Terminal code and replace it with `AdaptDispatch`.
One oddity that came up in testing, though, was the `AdaptDispatch` implementation of `EraseAll` would push a blank line into the scrollback when called on an empty buffer, whereas the previous terminal implementation did not. That caused problems for the conpty connection, because one of the first things it does on startup is send an `ED 2` sequence. I've now updated the `AdaptDispatch` implementation to match the behavior of the terminal implementation in that regard.
Another problem was that the terminal implementation of the color table commands had special handling for the background color to notify the application window that it needed to repaint the background. I didn't want to have to push the color table operations through the `ITerminalApi` interface, so I've instead moved the handling of the background update into the renderer, initiated by a flag on the `TriggerRefreshAll` method.
## Validation Steps Performed
Surprisingly this PR didn't require a lot of changes to get the unit tests working again. There were just a few methods used from the original `ITerminalApi` that have now been removed, and which needed an equivalent replacement. Also the updated behavior of the `EraseAll` method in conhost resulted in a change to the expected cursor position in one of the screen buffer tests.
In terms of manual testing, I've tried out all the different shells in Windows Terminal to make sure there wasn't anything obviously wrong. And I've run a bunch of the tests from _vttest_ to try and get a wider coverage of the VT functionality, and confirmed everything still works at least as well as it used to. I've also run some of my own tests to verify the operations that had to be copied from `TerminalDispatch` to `AdaptDispatch`.
`InteractivityOneCore` and `RendererWddmCon` were the last two remaining
projects which are relevant for our internal console builds, but couldn't be
easily compiled publicly by users on GitHub. This commit adds all definitions
required to compile the two projects into dysfunctional libraries at least.
(Since the added definitions are deliberately incorrect.)
Additionally this commit fixes the AuditMode build for the two projects.
## Validation Steps Performed
The two new projects compile fine.
As noted in the issue. There's a case where backing up the `lineEnd` can result in the `lineEnd` pointing at exactly the `lineBegin`, which results in an empty view, which causes all sorts of pain later.
Instead, just return early in this case.
* tested with an 80x24 conhost
* tested with an 79x24 conhost
I also tried making this a FAILFAST or a THROW_HR, but the failfast immediately died (of course it did), and the throw would result in a few frames where the composition was just... entirely not displayed? Probably not what we wanted.
* [x] Closes#12730
Modified the scope of input control, it used to be `Text`, now it is
`AlphanumericHalfWidth`. This input scope actually accepts any
characters, but English characters are preferred, and the soft keyboard
also displays English by default.
This should improve user friendliness for users using composition mode
input methods.
As a user who uses the composition mode input method, in applications
like windows terminal that should usually be input in English, it is
always required to manually switch to English mode by pressing Shift
before entering commands.
One keystroke is not a problem, but often for some reason there is no or
no successful switching, and additional more keystrokes are required to
clear the wrong input.
The input method that comes with windows will automatically switch to
English mode for a few programs such as conhost, but windows terminal is
not in this list.
This change should have no negative impact. Even if someone does tend to
use a shell oriented towards composition characters or non-alpha
letters, there should also were more users who in the same language are
more inclined to English characters shells, for example, cmd,
powershell, bash that comes with windows.
If there's any reason to have to keep the Text inputScope, maybe making
this setting customizable via `settings.json` would be a good idea, but
I don't see the need to do this, `AlphanumericHalfWidth` is perfect.
Closes#12731
`_api.cellCount` caches the `TextBuffer` size in AtlasEngine.
Calculating it based on the `_api.sizeInPixel` is incorrect as the
`TextBuffer` size doesn't necessarily have to be the size of the window.
This can occur when the window is resized, as the main thread is receiving its
`WM_SIZE` message and resizing the `TextBuffer` concurrently with the render
thread performing a render pass and AtlasEngine checking the `GetClientRect`.
In order to inform `AtlasEngine` about the initial buffer size, `Renderer`
was modified to also invoke `UpdateViewport()` on the first render cycle.
The only other user of `UpdateViewport()` is `VtEngine` which used to call
`InvalidateAll()` in these situations. In order to prevent the `InvalidateAll()`
call, `VtEngine::UpdateViewport()` was modified to suppress this.
## Validation Steps Performed
* Resizing wide characters doesn't crash the terminal anymore ✅
* The additional call to `UpdateViewport()` doesn't break VtEngine ✅
There are 3 en-dashes`(U+2013)` in the file when they should be hyphen `(U+002D)`.
This character causes the file to fail to compile in a non-utf8 encoding environment.
Just modified 3 characters to make it fall within the scope of ascii and keep it consistent with other files of the project.
The "virtual bottom" marks the last line of the mutable viewport area,
which is the part of the buffer that VT sequences can write to. This
region should typically only move downwards as new lines are added to
the buffer, but there were a number of cases where it was incorrectly
being moved up, or moved down further than necessary. This PR attempts
to fix that.
There was an earlier, unsuccessful attempt to fix this in PR #9770 which
was later reverted (issue #9872 was the reason it had to be reverted).
PRs #2666, #2705, and #5317 were fixes for related virtual viewport
problems, some of which have either been extended or superseded by this
PR.
`SetConsoleCursorPositionImpl` is one of the cases that actually does
need to move the virtual viewport upwards sometimes, in particular when
the cmd shell resets the buffer with a `CLS` command. But when this
operation "snaps" the viewport to the location of the cursor, it needs
to use the virtual viewport as the frame of reference. This was
partially addressed by PR #2705, but that only applied in
terminal-scrolling mode, so I've now applied that fix regardless of the
mode.
`SetViewportOrigin` takes a flag which determines whether it will also
move the virtual bottom to match the visible viewport. In some case this
is appropriate (`SetConsoleCursorPositionImpl` being one example), but
in other cases (e.g. when panning the viewport downwards in the
`AdjustCursorPosition` function), it should only be allowed to move
downwards. We can't just not set the update flag in those cases, because
that also determines whether or not the viewport would be clamped, and
we don't want change that. So what I've done is limit
`SetViewportOrigin` to only move the virtual bottom downwards, and added
an explicit `UpdateBottom` call in those places that may also require
upward movement.
`ResizeWindow` in the `ConhostInternalGetSet` class has a similar
problem to `SetConsoleCursorPositionImpl`, in that it's updating the
viewport to account for the new size, but if that visible viewport is
scrolled back or forward, it would end up placing the virtual viewport
in the wrong place. So again the solution here was to use the virtual
viewport as the frame of reference for the position. However, if the
viewport is being shrunk, this can still result in the cursor falling
below the bottom, so we need an additional check to adjust for that.
This can't be applied in pty mode, though, because that would break the
conpty resizing operation.
`_InternalSetViewportSize` comes into play when resizing the window
manually, and again the viewport after the resize can end up truncating
the virtual bottom if not handled correctly. This was partially
addressed in the original code by clamping the new viewport above the
virtual bottom under certain conditions, and only in terminal scrolling
mode. I've replaced that with a new algorithm which links the virtual
bottom to the visible viewport bottom if the two intersect, but
otherwise leaves it unchanged. This applies regardless of the scrolling
mode.
`ResizeWithReflow` is another sizing operation that can affect the
virtual bottom. This occurs when a change of the window width requires
the buffer to be reflowed, and we need to reposition the viewport in the
newly generated buffer. Previously we were just setting the virtual
bottom to align with the new visible viewport, but that could easily
result in the buffer truncation if the visible viewport was scrolled
back at the time. We now set the virtual bottom to the last non-space
row, or the cursor row (whichever is larger). There'll be edge cases
where this is probably not ideal, but it should still work reasonably
well.
`MakeCursorVisible` was another case where the virtual bottom was being
updated (when requested with a flag) via a `SetViewportOrigin` call.
When I checked all the places it was used, though, none of them actually
required that behavior, and doing so could result in the virtual bottom
being incorrectly positioned, even after `SetViewportOrigin` was limited
to moving the virtual bottom downwards. So I've now made it so that
`MakeCursorVisible` never updates the virtual bottom.
`SelectAll` in the `Selection` class was a similar case. It was calling
`SetViewportOrigin` with the `updateBottom` flag set when that really
wasn't necessary and could result in the virtual bottom being
incorrectly set. I've changed the flag to false now.
## Validation Steps Performed
I've manually confirmed that the test cases in issue #9754 are working
now, except for the one involving margins, which is bigger problem with
`AdjustCursorPosition` which will need to be addressed separately.
I've also double checked the test cases from several other virtual
bottom issues (#1206, #1222, #5302, and #9872), and confirmed that
they're still working correctly with these changes.
And I've added a few screen buffer tests in which I've tried to cover as
many of the problematic code paths as possible.
Closes#9754
## Summary of the Pull Request
Ensures the tab close button color matches the text color.
## PR Checklist
* [x] Closes#13010
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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
## Detailed Description of the Pull Request / Additional comments
Also re-ordered and aligned the properties cleared in the `_ClearTabBackgroundColor()` method to match `_ApplyTabColor()`.
## Validation Steps Performed
Manually tested
This pull request introduces a packaging phase that emits
Microsoft.Windows.Console.ConPTY, a nuget package that contains the
pseudoconsole API as well as the requisite copies of conhost.
* winconpty learned to load a version of OpenConsole.exe specific to the
processor architecture on its hosting machine
* the package, as well as its contents, is signed properly and is nearly
ready for distribution via nuget.org
* the API in conpty-static.h has been adjusted to expose
CreatePseudoConsoleAsUser and stamp out the correct DLL import/export
annotations.
* getting .NET to play right was somewhat challenging, but I tested this
against .NET 6.0 and it seemed to work properly; it shipped conpty.dll
in the right places, and it shipped OpenConsole.exe next to the
published application.
In the future, we could provide an interop assembly for C# consumers;
that is, unfortunately, out of scope today.
Closes#3577Closes#3568
Obsoletes #1130
Propagate show/hide window calls against the ConPTY pseudo window to the Terminal
## PR Checklist
* [x] Closes#12570
* [x] I work here
* [x] Manual Tests passed
* [x] Spec Link: →[Doc Link](https://github.com/microsoft/terminal/blob/dev/miniksa/msgs/doc/specs/%2312570%20-%20Show%20Hide%20operations%20on%20GetConsoleWindow%20via%20PTY.md)←
## Detailed Description of the Pull Request / Additional comments
- See the spec. It's pretty much everything I went through deciding on this.
## Validation Steps Performed
- [x] Manual validation against scratch application calling all of the `::ShowWindow` commands against the pseudo console "fake window" and observing the real terminal window state
If we are building a branch called "release-*", we will also change the
NuGet suffix to "preview". If we don't do that, XES will set the suffix
to "release1" because it truncates the value after the first period. In
general, though, we want to disable the suffix entirely if we're Release
branded while on a release branch.
In effect:
BRANCH / BRANDING | Release | Preview
------------------|------------------------|------------------------
release-* | 1.12.20220427 | 1.13.20220427-preview
all others | 1.14.20220427-mybranch | 1.14.20220427-mybranch
<!-- 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)? -->
## Summary of the Pull Request
Fixes#6028
Setting is "experimental.useBackgroundImageForWindow"
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
https://github.com/microsoft/terminal/issues/6028
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [X] Closes#6028
* [X] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated. I read CONTRIBUTING.md, but I'm not sure if a spec is needed for an experimental feature such as this one.
* [ ] Schema updated. I added a JSON key, not sure where I need to update it.
* [X] I've discussed this with core contributors already. Somewhat discussed in https://github.com/microsoft/terminal/issues/6028
<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here
## Detailed Description of the Pull Request / Additional comments -->
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Set ` "experimental.useBackgroundImageForWindow": true` and a bg image for one profile, then make splits and tabs and make sure the bg updates accordingly:

I also did the same with the setting off to make sure it still works correctly and didn't break. And I made sure opening the settings tab does not crash or show the bg image.
#4015 requires sweeping changes in order to allow a migration of our buffer
coordinates from `int16_t` to `int32_t`. This commit reduces the size of
future commits by using type inference wherever possible, dropping the
need to manually adjust types throughout the project later.
As an added bonus this commit standardizes the alignment of cv qualifiers
to be always left of the type (e.g. `const T&` instead of `T const&`).
The migration to type inference with `auto` was mostly done
using JetBrains Resharper with some manual intervention and the
standardization of cv qualifier alignment using clang-format 14.
## References
This is preparation work for #4015.
## Validation Steps Performed
* Tests pass ✅
Fixed various small issues:
* Made TabView bottom border span the entire window width
* Made ScrollBar inner thumb rounded again
* Made SplitButton look more like the new add tab button
* Adjusted rename box height (24px, like the official compact sizing height)
* Adjusted caption button colors to match Windows 11
* ColorPicker can now escape window bounds
* Tweaked ColorPicker buttons
Further builds on #12799. #12799 assumes that the connection is prepared to receive FocusIn/FocusOut events as input. For ConPTY we can be relatively sure of that, but that's not _technically_ correct. In the hypothetical world where the connection is not a ConPTY connection, then the other side might not be expecting those sequences.
This remedies the issue by
* ConPTY will always request focus event mode (from the terminal) when it starts up
* when a client tries to disable focus events in conpty, conpty is gonna note that internally, but never transmit that to the hosting terminal, to leave the terminal in focus event mode.
* `TerminalDispatch` and `ControlCore` are hooked up now to only send focus events when the Terminal is in focus event mode (which will be always for conpty)
* At this point, it was like, 4LOC in `terminalInput.cpp` to add support for focus events to conhost as well.
## checklist
* [x] closes#11682
* This combined with #12515 will finally close out #2988 as well, but we can do that manually.
* [x] I work here
* [ ] There aren't tests for this. There probably should be.
This commit replaces our use of `size_t` to represent VT parameters with
`int32_t`. While unsigned integers have the inherent benefit of being less
ambiguous and enjoying two's complement, our buffer coordinates use signed
integers. Since a number of VT functions need to convert their parameters
to coordinates, this commit makes the conversion easier.
The benefit of this change becomes even more apparent if one considers
that a number of places performed unsafe conversions
of their size_t parameters to int or short already.
Files that had to be modified were converted to use til
wrappers instead of COORD or SMALL_RECT wherever possible.
## References
This commit contains about 20% of the work for #4015.
## PR Checklist
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
I'm mostly relying on our unit tests here. Both OpenConsole and WT appear to work fine.
#### ⚠️ _Targets #12799_ ⚠️
This is an atomic bit of code that partners with #12799. It's separated as an individual PR to keep diffs more simple.
This ensures that when a terminal tells ConPTY that it's focused, that ConPTY doesn't do the `ConsoleControl(CONSOLE_FOREGROUND` thing unless the terminal application is actually in the foreground. This prevents a trivial exploit whereby a `malicious.exe` could create a PTY, tell ConPTY it has focus (when it doesn't), then use this mechanism to launch an instance of itself into the foreground.
When the terminal tells us it's in the foreground, we're gonna look at the owner of the ConPTY window handle. If that owner has focus, then cool, this is allowed. Otherwise, we won't grant them the FG right. For this to work, the terminal just have already called `ReparentPseudoConsole`.
* built on top of #12799 and #12526
* [x] Part of #2988
* [x] Tested manually.
## Window shenanigans, part the third:
Hooks the Terminal's focus state up to the underlying ConPTY. This is LOAD BEARING for allowing windows created by console applications to bring themselves to the foreground.
We're using the [FocusIn/FocusOut](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-FocusIn_FocusOut) sequences to communicate to ConPTY when a control gains/loses focus. Theoretically, other terminals could do this as well.
## References
#11682 tracks _real_ support for this sequence in Console & conpty. When we do that, we should consider even if a client application disables this mode, the Terminal & conpty should always request this from the hosting terminal (and just ignore internally to ConPTY).
See also #12515, #12526, which are the other two parts of this effort. This was tested with all three merged together, and they worked beautifully for all our scenarios. They are kept separate for ease of review.
## PR Checklist
* [x] This is prototype 3 for #2988
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated
## Detailed Description of the Pull Request / Additional comments
This allows windows spawned by console processes to bring themselves to the foreground _when the console is focused_. (Historically, this is also called in the WndProc, when focus changes).
Notably, before this, ConPTY was _never_ focused, so windows could never bring themselves to the foreground when run from a ConPTY console. We're not blanket granting the SetForeground right to all console apps when run in ConPTY. It's the responsibility of the hosting terminal emulator to always tell ConPTY when a particular instance is focused.
## Validation Steps Performed
(gif below)
This will result in the deletion of the following directories from the OS tree, under `onecore/windows/core/console/open`:
* doc/
* src/tools/MonarchPeasantPackage/
* src/api-ms-win-core-synch-l1-2-0/
* src/tools/ansi-color/
* src/tools/ColorTool/
We have gotten some PoliCheck flags on `doc/` (thanks to Niksa.md), but also the OS build just doesn't need these folders 😄
(cherry picked from commit 27b63ad02a)
Service-Card-Id: 80783789
Service-Version: Inbox
This will result in the deletion of the following directories from the OS tree, under `onecore/windows/core/console/open`:
* doc/
* src/tools/MonarchPeasantPackage/
* src/api-ms-win-core-synch-l1-2-0/
* src/tools/ansi-color/
* src/tools/ColorTool/
We have gotten some PoliCheck flags on `doc/` (thanks to Niksa.md), but also the OS build just doesn't need these folders 😄
#12149 introduced a bug where `ClearCommandline()` is called on any user
profile containing the non-canonical strings "cmd.exe" or "powershell.exe"
in the "commandline" field. If you happen to have set the "commandline"
field in your `profiles.defaults`, this will cause these user profiles
to adopt the base layer command-line instead of the defaults layer one.
This commit fixes the issue, by checking the command-line after the call
to `ClearCommandline()` and ensuring it's the expected string.
Additionally this moves the migration logic to `SettingsLoader` as this allows
us to write the fixed settings to disk, if any fixed had to be applied.
## PR Checklist
* [x] Closes#12842
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* The modified unit test fails without these changes ✅
* The modified unit test succeeds with these changes ✅
* Setting `profiles.defaults.commandline` to "pwsh.exe" and setting
my "...\\powershell.exe" profile to use just "powershell.exe" as
the `commandline`, doesn't cause it to use "pwsh.exe" ✅
The fixed settings are written to settings.json ✅
This is exactly the same as #12855, save for one small difference:
```diff
diff --git a/build/pipelines/ci.yml b/build/pipelines/ci.yml
index e4e53e9b2..dc9040aeb 100644
--- a/build/pipelines/ci.yml
+++ b/build/pipelines/ci.yml
@@ -99,7 +99,6 @@ stages:
- stage: CodeIndexer
displayName: Github CodeNav Indexer
dependsOn: [Build_x64]
- condition: succeeded()
+ condition: and(succeeded(), not(eq(variables['Build.Reason'], 'PullRequest')))
jobs:
- template: ./templates/codenav-indexer.yml
- condition: not(eq(variables['Build.Reason'], 'PullRequest'))
```
Because the first ones failed with an error about a duplicate condition
And that hosed the whole CI
VTE only rewraps the contents of the (normal screen + its scrollback
buffer) on a resize event. It doesn't rewrap the contents of the
alternate screen. The alternate screen is used by applications which
repaint it after a resize event. So, it doesn't really matter. However,
in that short time window, after resizing the terminal but before the
application catches up, this prevents vertical lines
It was really hard to get a gif of this where it happened and was small
enough to upload to GH, but there is one in #12719.
There's something in this branch that fixes a scrolling issue in the
parent PR. I'm partially filing this so I can look at the diffs here and
try and figure out what that is. I kinda want to just take all 3 alt
buffer PRs as a single atomic unit, but splitting them up made sense
from a review standpoint.
Closes#3493
The original research for a solution all the way back in #11032 contained an
unfortunate flaw. The nearby font loading code was written under the assumption
that Cascadia is missing in the system font collection, leading to our issues.
Adding nearby fonts last into the collection would thus ensure that we use
the system fonts whenever possible, but only have nearby fonts as a fallback.
This didn't work and we figured that we'd have to always prefer loading nearby
fonts over system fonts. #12554 tried to achieve this, but failed to change
the order in which the font set is built. In order to prefer nearby fonts
over system ones, we have to add the system font collection last.
## PR Checklist
* [x] Closes#11648
* [x] I work here
* [x] Tests added/passed
* [x] Embarrassment for my incompetence
## Validation Steps Performed
* Put Jetbrains Mono into the AppX directory of the Debug build
* Jetbrains Mono shows up in the font selector and is useable
Additionally a more complex mini-test was built:
Using FontForge I've cloned arial.ttf and removed all characters except for
the letter "0". Afterwards I've build a custom font collection the same way
we do it in Terminal, extracted a `FontFace` named "Arial" and called
`IDWriteFont::HasCharacter` for the letter "1".
Loading the system font collection first results in `TRUE` and loading it last
results in `FALSE` (since my custom arial.ttf doesn't have the letter "1").
This confirms that we need to load the system font collection last.
We discussed this with the GitHub folks. It's pretty cool.
(Rich code nav) brings editor-level navigation capabilities into
GitHub.com for C++ and C# repos
If you want to try it out, you can go to github.dev for this repo.
If you haven't used github.dev before there are two steps to get setup:
1. In the settings file you'll need to enable Rich Code Nav. If you just
search for "rich", there'll be a checkbox to enable it.
2. Refresh the page and you should see a stacked papers icon in the task
bar at the bottom. Click on that and select "Latest Index". Then one
more refresh and you should be good to go with navigation in both C#
and C++ files!
This is an attempt to simplify the `ConGetSet` interface down to the
smallest set of methods necessary to support the `AdaptDispatch` class.
The idea is that it should then be easier to implement that interface in
Windows Terminal, so we can replace the `TerminalDispatch` class with
`AdaptDispatch`.
This is a continuation of the refactoring started in #12247, and a
significant step towards #3849.
## Detailed Description of the Pull Request / Additional comments
The general idea was to give the `AdaptDispatch` class direct access to
the high-level structures on which it needs to operate. Some of these
structures are now passed in when the class is constructed (the
`Renderer`, `RenderSettings`, and `TerminalInput`), and some are exposed
as new methods in `ConGetSet` (`GetStateMachine`, `GetTextBuffer`, and
`GetViewport`).
Many of the existing `ConhostInternalGetSet` methods could easily then
be reimplemented in `AdaptDispatch`, since they were often simply
forwarding to methods in one of the above structures. Some were a little
more complicated, though, and require further explanation.
* `GetConsoleScreenBufferInfoEx`: What we were typically using this for
was to obtain the viewport, although what we really wanted was the
virtual viewport, which is now accessible via the `GetViewport`
method. This was also used to obtain the cursor position and buffer
width, which we can now get via the `GetTextBuffer` method.
* `SetConsoleScreenBufferInfoEx`: This was only really used for the
`AdaptDispatch::SetColumns` implementation (for `DECCOLM` mode), and
that could be replaced with `ResizeWindow`. This is a slight change in
behaviour (it sizes the window rather than the buffer), but neither is
technically correct for `DECCOLM`, so I think it's good enough for
now, and at least it's consistent with the other VT sizing operations.
* `SetCursorPosition`: This could mostly be replaced with direct
manipulation of the `Cursor` object (accessible via the text buffer),
although again this is a slight change in behavior. The original code
would also have made a call to `ConsoleImeResizeCompStrView` (which I
don't think is applicable to VT movement), and would potentially have
moved the viewport (not essential for now, but could later be
supported by `DECHCCM`). It also called `VtIo::SetCursorPosition` to
handle cursor inheritance, but that should only apply to
`InteractDispatch`, so I've moved that to the
`InteractDispatch::MoveCursor` method.
* `ScrollRegion`: This has been replaced by two simple helper methods in
`AdaptDispatch` which better meet the VT requirements -
`_ScrollRectVertically` and `_ScrollRectHorizontally`. Unlike the
original `ScrollRegion` implementation, these don't generate
`EVENT_CONSOLE_UPDATE_SCROLL` events (see #12656 for more details).
* `FillRegion`: This has been replaced by the `_FillRect` helper method
in `AdaptDispatch`. It differs from the original `FillRegion` in that
it takes a rect rather than a start position and length, which gives
us more flexibility for future operations.
* `ReverseLineFeed`: This has been replaced with a somewhat refactored
reimplementation in `AdaptDispatch`, mostly using the
`_ScrollRectVertically` helper described above.
* `EraseAll`: This was previously handled by
`SCREEN_INFORMATION::VtEraseAll`, but has now been entirely
reimplemented in the `AdaptDispatch::_EraseAll` method.
* `DeleteLines`/`InsertLines`/`_modifyLines`: These have been replaced
by the `_InsertDeleteLineHelper` method in `AdaptDispatch`, which
mostly relies on the `_ScrollRectVertically` helper described above.
Finally there were a few methods that weren't actually needed in the
`ConGetSet` interface:
* `MoveToBottom`: This was really just a hack to get the virtual
viewport from `GetConsoleScreenBufferInfoEx`. We may still want
something like in the future (e.g. to support `DECVCCM` or #8879), but
I don't think it's essential for now.
* `SuppressResizeRepaint`: This was only needed in `InteractDispatch`
and `PtySignalInputThread`, and they could easily access the `VtIo`
object to implement it themselves.
* `ClearBuffer`: This was only used in `PtySignalInputThread`, and that
could easily access the buffer directly via the global console
information.
* `WriteControlInput`: This was only used in `InteractDispatch`, and
that could easily be replaced with a direct call to
`HandleGenericKeyEvent`.
As part of these changes, I've also refactored some of the existing
`AdaptDispatch` code:
* `_InsertDeleteHelper` (renamed `_InsertDeleteCharacterHelper`) is now
just a straightforward call to the new `_ScrollRectHorizontally`
helper.
* `EraseInDisplay` and `EraseInLine` have been implemented as a series
of `_FillRect` calls, so `_EraseSingleLineHelper` is no longer
required.
* `_EraseScrollback` is a essentially a special form of scrolling
operation, which mostly depends on the `TextBuffer::ScrollRows`
method, and with the filling now provided by the new `_FillRect`
helper.
* There are quite a few operations now in `AdaptDispatch` that are
affected by the scrolling margins, so I've pulled out the common
margin setup into a new `_GetVerticalMargins` helper method. This also
fixes some edge cases where margins could end up out of range.
## Validation Steps Performed
There were a number of unit tests that needed to be updated to work
around functions that have now been removed, but these substitutions
were fairly straightforward for the most part.
The adapter tests were a different story, though. In that case we were
explicitly testing how operations were passed through to the `ConGetSet`
interface, but with more than half those methods now gone, a significant
rewrite was required.
I've tried to retain the crux of the original tests, but we now have to
validate the state changes on the underlying data structures, where
before that state would have been tracked in the `TestGetSet` mock. And
in some cases we were testing what happened when a method failed, but
since that scenario is no longer possible, I've simply removed those
tests.
I've also tried to manually test all the affected operations to confirm
that they're still working as expected, both in vttest as well as my own
test scripts.
Closes#12662
"Alternate scroll mode" is a neat little mode where the app wants mouse wheel events to come through as arrow keypresses instead, when in the alternate buffer. Now that we've got support for the alt buffer in the Terminal, we can support this as well.
* [x] Closes https://github.com/microsoft/terminal/issues/3321
* [x] I work here
* [ ] Tests would be nice
Tested manually with
```bash
printf "\e[?1007h" ; man ps
```
## Window shenanigans, part the first:
This PR enables terminals to tell ConPTY what the owning window for the
pseudo window should be. This allows thigs like MessageBoxes created by
console applications to work. It also enables console apps to use
`GetAncestor(GetConsoleWindow(), GA_ROOT)` to get directly at the HWND
of the Terminal (but _don't please_).
This is tested with our internal partners and seems to work for their
scenario.
See #2988, #12799, #12515, #12570.
## PR Checklist
This is 1/3 of #2988.
This PR allows the Terminal to actually use the alt buffer
appropriately. Currently, we just render the alt buffer state into the
main buffer and that is wild. It means things like `vim` will let the
user scroll up to see the previous history (which it shouldn't).
Very first thing this PR does: updates the
`{Trigger|Invalidate}Circling` methods to instead be
`{Trigger|Invalidate}Flush(bool circling)`. We need this so that when an
app requests the alt buffer in conpty, we can immediately flush the
frame before asking the Terminal side to switch to the other buffer. The
`Circling` methods was a great place to do this, but we don't actually
want to set the circled flag in VtRenderer when that happens just for a
flush.
The Terminal's implementation is a little different than conhost's.
Conhost's implementation grew organically, so I had it straight up
create an entire new screen buffer for the alt buffer. The Terminal
doesn't need all that! All we need to do is have a separate `TextBuffer`
for the alt buffer contents. This makes other parts easier as well - we
don't really need to do anything with the `_mutableViewport` in the alt
buffer, because it's always in the same place. So, we can just leave it
alone and when we come back to the main buffer, there it is. Helper
methods have been updated to account for this.
* [x] Closes#381
* [x] Closes#3492
* #3686, #3082, #3321, #3493 are all good follow-ups here.
<!-- 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)? -->
## Summary of the Pull Request
Specs for feature request "Theme-controlled color scheme switch".
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
#4066
This is all of course, conjecture. This crash is totally wild and makes no sense at all. But, we're hoping that this fixes it. This should also make calls to the Monarch a little easier.
You may be asking yourself - why aren't I doing this for the Peasant too? Well, because the Peasant simply doesn't crash like the monarch does. I'm not gonna touch something that's not broken _during ask mode_.
References #12774. We can close the bug if it is verified fixed.
855e136 contains a regression which breaks buffer reflow if wide surrogate
characters are present. This happens because we made use of the
`TextBufferCellIterator` whose increment operator skips 2 cells for wide
characters. This created a "misalignment" in the reflow logic which was written
for cell-wise iteration. This commit fixes the issue, by reverting back to the
previous algorithm without iterators.
Closes#12837
Closes MSFT-38904421
## Validation Steps Performed
* Run ``pwsh -noprofile -command echo "`u{D83D}`u{DE43}"``
* Resizing conhost preserves all contents ✅
* Resizing Windows Terminal doesn't crash it ✅
* Added a test covering this issue ✅
(cherry picked from commit 10b9044120)
Service-Card-Id: 80340091
Service-Version: Inbox
855e136 contains a regression which breaks buffer reflow if wide surrogate
characters are present. This happens because we made use of the
`TextBufferCellIterator` whose increment operator skips 2 cells for wide
characters. This created a "misalignment" in the reflow logic which was written
for cell-wise iteration. This commit fixes the issue, by reverting back to the
previous algorithm without iterators.
Closes#12837
Closes MSFT-38904421
## Validation Steps Performed
* Run ``pwsh -noprofile -command echo "`u{D83D}`u{DE43}"``
* Resizing conhost preserves all contents ✅
* Resizing Windows Terminal doesn't crash it ✅
* Added a test covering this issue ✅
If we delete a scheme, and the next scheme we've loaded is an inbox one
that _can't_ be deleted, then we need to toss focus to something
sensible, rather than letting it fall out to the tab item.
When deleting a scheme and the next scheme _is_ deletable, this isn't an
issue, we'll already correctly focus the Delete button.
125e9c4790 focused the SelectionBackground
button, which is the _previous_ focusable control, rather than the
following one.
However, it seems even more useful for focus to ALWAYS land on the
scheme dropdown box. This forces Narrator to read the name of the newly
selected color scheme, which seemed more useful.
I'm waiting on feedback from a11y team to see if this solution is
acceptable.
* [x] Is for #11971
After switching to ControlsV2, it seems that
delay-loading a dialog causes the ContentDialog to be assigned a
Height equal to it's content size. If we DON'T assign the
ContentDialog a Row, I believe it's assigned Row 0 by default. So,
when the dialog gets opened, the dialog seemingly causes a giant
hole to appear in the body of the app.
Assigning all the dialogs to Row 2 (where the rest of the content
is) makes the "hole" appear in the same space as the rest of the
TabContent, fixing the issue.
Note that the actual content in a content dialog gets parented to
the PopupRoot, so it actually always appeared in the correct place, it's
just this weird hole that appeared in Row 0.
* [x] Closes#12775
* See also:
* #12202 was fixed by #12208
* #12447 was fixed by #12517
* [x] Tested manually
* [x] Reverts #12625
* [x] Reverts #12517
You'd think that if a key wasn't present in a ThemeDictionary, it'd fall back to the original value. You'd be wrong - if you provide a Light&dark version of a resource, but not the HighContrast version, the resource loader will fall back to the _Light_ value. Of course.
Before (left top), after (right bottom)

Closes MSFT:38264744
This is like, 2-4% of our crashes. Impossible to say for sure, but this _looks_ like it's the root cause. This is just another one of our `HandleCommandlineArgs` buckets, hopefully the last.
* [x] Hopefully should close out MSFT:38542548
* [ ] No I didn't write tests, impossible to test
* [x] it builds
Replaces all the `RadioButton` expanders with `ComboBox`es, which can have the options inline, as opposed to in the expander content. For example, here's a single commit with the changes for a single one of these settings: 745c77d03e
### Checklist
* [x] Closes#12648
* [x] Actually closes#9566 as well (by just removing all radio buttons)
* [x] I work here
* [x] Tested manually
* [x] I'd love @carlos-zamora to have an a11y pass at this, just to see if it's egregious or not.
### Before, after:

This commit fixes some formatting bugs by upgrading clang-format and ensures
that our code is again formatted the same way Visual Studio 2022 would do it.
This is a crazy idea Dustin and I had.
> we can't repro this at will. But we kinda have an idea of where the deref is. We don't know if the small patch (throw, and try again) will fix it. We're sure that the "just fall back to an isolated monarch" will work. I'd almost rather take a build testing the small patch first, to see if that works
> This might seem crazy
> in 1.12, isolated monarch. In 1.13, "small patch". In 1.14, we can wait and see
I can write more details in the morning. It's 5pm here so if we want this today, here it is.
@dhowett double check my velocity flag logic here. Should be always true for Release, and off for Dev, Preview.
* [x] closes#12774
On certain builds of Windows, when Terminal is set as the default it
will accumulate an unbounded amount of queued animations while the
screen is off and it is servicing window management for console
applications.
This results in Terminal hanging when left overnight, as it has millions
of animations to process.
The new call into TerminalThemeHelpers will tell our compositor to
automatically complete animations that are scheduled while the screen is
off.
Fixes MSFT-38506980
Before #12691, the msixbundle version was of the format YYYY.MM.DD.0.
After #12691, it became the same as the build of Terminal it contained.
This caused some trouble for _some_ systems: major version 1 is much,
much smaller than 2022.
Adding 3000 to the major version component, _only for the bundle_, gets
around this. Ugh.
Fixes#12816.
Adds the common nuget import to the Fuzz project so that it compiles.
## References
Broken in #12778, Issue identified by #12796
## Validation Steps Performed
`Host.FuzzWrapper` project builds.
## Summary of the Pull Request
Prevents the Fuzz pipeline from failing by refactoring the nuget restore pipeline steps.
## References
Broken in #12778.
## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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
Does what it says on the tin. This is maximal BODGE.
`TeachingTip` doesn't provide an `Opened` event.
(https://github.com/microsoft/microsoft-ui-xaml/issues/1607). But we
want to focus the renamer text box when it's opened. We can't do that
immediately, the TextBox technically isn't in the visual tree yet. We
have to wait for it to get added some time after we call IsOpen. How do
we do that reliably? Usually, for this kind of thing, we'd just use a
one-off LayoutUpdated event, as a notification that the TextBox was
added to the tree. HOWEVER:
* The _first_ time this is fired, when the box is _first_ opened,
yeeting focus doesn't work on the first LayoutUpdated. It does work on
the second LayoutUpdated. Okay, so we'll wait for two LayoutUpdated
events, and focus on the second.
* On subsequent opens: We only ever get a single LayoutUpdated. Period.
But, you can successfully focus it on that LayoutUpdated.
So, we'll keep track of how many LayoutUpdated's we've _ever_ gotten. If
we've had at least 2, then we can focus the text box.
We're also not using a ContentDialog for this, because in Xaml Islands a
text box in a ContentDialog won't receive _any_ keypresses. Fun!
## References
* microsoft/microsoft-ui-xaml#1607
* microsoft/microsoft-ui-xaml#6910
* microsoft/microsoft-ui-xaml#3257
* microsoft/terminal#9662
## PR Checklist
* [x] Will close out #12021, but that's an a11y bug that needs secondary
validation
* [x] Closes#11322
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated
## Validation Steps Performed
Tested manually
Make a VTApiRoutines servicer that does minimal translations instead of
environmental simulation for some output methods. Remaining methods are
backed on the existing console host infrastructure (primarily input
related methods).
## PR Checklist
* [x] I work here
* [x] It's Fix-Hack-Learn quality so it's behind a feature gate so we
can keep refining it. But it's a start!
To turn this on, you will have to be in the Dev or Preview rings
(feature staged). Then add `experimental.connection.passthroughMode:
true` to a profile and on the next launch, the flags will propagate down
through the `ConptyConnection` into the underlying `Openconsole.exe`
startup and tell it to use the passthrough mode instead of the full
simulation mode.
## Validation Steps Performed
- Played with it manually in CMD.exe, it seems to work mostly.
- Played with it manually in Ubuntu WSL, it seems to work.
- Played with it manually in Powershell and it's mostly sad. It'll get
there.
Starts #1173
This script takes pull requests from a project board, cherry-picks them,
and updates the project board. It also yells at you if there are
conflicts to resolve, and generally tries to keep track of everything.
It is quite cool.
The `cascadia/` directory straight up isn't checked into the OS. So adding a test dependency on code in there was a BAD IDEA.
(cherry picked from commit 4e61be9cd7)
Service-Card-Id: 79863821
Service-Version: Inbox
If we do not include mp:PhoneIdentity in our AppxManifest, the store
will edit our package and re-sign it for distribution. When that
happens, it creates a divergence: there are now two versions of our
package with the same name and version number, but different contents.
This breaks everything.
**THIS IS LOAD BEARING**
<!-- 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)? -->
## Summary of the Pull Request
This builds on top of #12707. As I understand it the primary motivation for using a git submodule instead of NuGet is just that it is too annoying to have to manage dozens of packages.config files and their corresponding import statements. Now that there is a single global nuget definition that is a nonissue and we can switch over.
This also updates to the latest version of WIL.
Now that the latest version of WIL is available it uses it to replace `winrt::resume_foreground` with `wil::resume_foreground`. See [492c01bb53) for a detailed explanation of the problems with `winrt::resume_foreground` and how WIL addresses them.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes#12776, Closes#12777
* [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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 -->
## Detailed Description of the Pull Request / Additional comments
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Ran `git clean -fdx` to wipe my clone to be completely clean. Opened the solution in Visual Studio 2022 and build it. Used `razzle.cmd`, `b`, and `runut.cmd` to run the tests.
## THE WHITE WHALE
This is a fairly naive fix for this bug. It's not terribly performant,
but neither is resize in the first place.
When the buffer gets resized, typically we only copy the text up to the
`MeasureRight` point, the last printable char in the row. Then we'd just
use the last char's attributes to fill the remainder of the row.
Instead, this PR changes how reflow behaves when it gets to the end of
the row. After we finish copying text, then manually walk through the
attributes at the end of the row, and copy them over. This ensures that
cells that just have a colored space in them get copied into the new
buffer as well, and we don't just blat the last character's attributes
into the rest of the row. We'll do a similar thing once we get to the
last printable char in the buffer, copying the remaining attributes.
This could DEFINITELY be more performant. I think this current
implementation walks the attrs _on every cell_, then appends the new
attrs to the new ATTR_ROW. That could be optimized by just using the
actual iterator. The copy after the last printable char bit is also
especially bad in this regard. That could likely be a blind copy - I
just wanted to get this into the world.
Finally, we now copy the final attributes to the correct buffer: the new
one. We used to copy them to the _old_ buffer, which we were about to
destroy.
## Validation
I'll add more gifs in the morning, not enough time to finish spinning a
release Terminal build with this tonight.
Closes#32🎉🎉🎉🎉🎉🎉🎉🎉🎉Closes#12567
(cherry picked from commit 855e1360c0)
These changes are purely a refactoring of the build files. There should
be no difference to the compiled result or runtime behavior.
Currently there are packages.config files in lots of directories, with
those same projects referencing props/targets from packages/ with a
version string in the path. This is frustrating because version changes
or new dependencies require updating lots and lots of build files
identically. There is also the possibility of error where locations are
missed.
With these changes there is a single canonical nuget configuration that
takes effect for all of OpenConsole.sln. Updating version numbers
should be limited to a single set of global files.
The changes were done incrementally but the result is basically that
dep\nuget\packages.config serves as the global NuGet dependency list. A
pair of common build files (common.nugetversions.props and
common.nugetversions.targets) were added to contain the various imports
and error checks. There is also a special build target to ensure that
the restore happens before builds even though a given directory doesn't
have a packages.config for Visual Studio to observe.
These new *.nugetversions.* files are imported in pretty much every
vcxproj/csproj in the solution in the appropriate place to satisfy the
need for packages. There are opt-in configuration values (e.g.
`TerminalCppWinrt=true`) that must be set to opt into a given
dependency. Adding a new dependency is just a matter of adding a new
opt-in value. The ordering of include does matter, which was a
difficult challenge to realize and address.
There was also a preexisting issue in 3 test projects where
cppwinrt.props was included but not cppwinrt.targets. By consolidating
things globally that "error" was fixed, but broke the build in a way
that was very confusing. Those projects don't need the cppwinrt targets
so they were opted out of the cppwinrt build files entirely to fix the
breaks and get back to previous behavior.
There are two notable exceptions to this canonical versioning. The
first is that there are dueling XAML 2.7 dependencies. I avoided that
by leaving those as per-project package.config entries. The second is
that any projects outside of the .sln (such as the Island samples) were
not touched.
## Validation Steps Performed
The primary validation is that the solution builds without errors. That
is what I'm seeing (x64|Debug). I also ran `git clean -fdx` from the
root of the repo to wipe it to clean and then opened the solution and
was able to build successfully. The project F5 deploys and looks fine
to me with just a cursory glance. The tests also largely pass (7418
pass, 188 fail, 14 other) which is as good or better than the baseline I
established from a clean clone.
Closes#12708
In two instances, the help text for the settings UI refers to _transparency_ when we're really talking about _opacity._ This PR changes those occurences to more accurately reflect the setting being described.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes#12592
Previously we would only call `SetWindowSize` and `TriggerRedrawAll` if the
viewport size in characters changed. This commit removes the limitation.
Since the if-condition limiting full redraws is now gone, this commit
moves the responsibility of limiting the calls up the call chain.
With `_refreshSizeUnderLock` now being a heavier function call
than before, some surrounding code was thus refactored.
## PR Checklist
* [x] Closes#11317
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
Test relevant for #11317:
* Print text, filling the entire window
* Move the window from a 150% scale to a 300% scale monitor
* The application works as expected ✅
Regression tests:
* Text zoom with Ctrl+Plus/Minus/0 works as before ✅
* Resizing a window works as before ✅
* No deadlocks, etc. during settings updates ✅
Changed the default value of `"trimBlockSelection"` to `true`.
* [x] Closes#12536
## Validation Steps Performed
Without editing the setting, the toggle switch was enabled by default in the settings UI.
Since RS1 (CL 3427806), gdi32 has been available on OneCoreUAP-based
editions of Windows. Therefore, we no longer need the indirect call to
TranslateCharsetInfo and without that, IInputServices doesn't have a
reason to exist.
In an ideal world.
Unfortunately, we actually do use IInputServices as a backhanded way to
get at the ConIoSrvComm from other OneCoreInteractivity components...
we also use it in a trick we play in RundownAndExit to make sure that
the ConIoSrv connection tears down at the right time.
I've replaced that trick with an equally dirty trick, but one that is
*very explicit* about what it's doing.
This change would break CJK+Grid Lines and GetConsoleLangID on
OneCore-based editions that do not host the extension apiset
ext-ms-win-gdi-font-l1... so we're falling back to the old ConIoSrvComm
implementation directly in `dbcs.cpp`.
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 74ca635710701c45cda9eefd13dafc6f180feb49
Related work items: MSFT-38632962
5964060 contains a regression were the grayscale blending algorithm used the
gamma corrected foreground color as the pixel color, instead of blending that
color with the background color first. Due to that the background color
got lost / got set to black. This breaks any dark-on-bright outputs.
## PR Checklist
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
All 3 "antialiasing" settings work just like in DxEngine. ✅
## Summary of the Pull Request
Fixes a bug in ConHost where Narrator wouldn't read the deleted letter after the user pressed backspace.
## References
MSFT:31748387
## Detailed Description of the Pull Request / Additional comments
`WriteCharsLegacy()` already calls `NotifyAccessibilityEventing()` when text is inserted into the buffer ([see code](855e1360c0/src/host/_stream.cpp (L559-L563))). However, when backspace is pressed, the entire if-condition is skipped over, resulting in the accessibility event not being fired. `WriteCharsLegacy()` has a separate branch that is dedicated to handling backspace, so I added a call to the relevant logic to notify UIA at the end of that.
## Validation Steps Performed
✅ <kbd>Backspace</kbd> deletes a character and Narrator reads it
✅ <kbd>Backspace</kbd> still works with NVDA and JAWS (unchanged behavior)
✅ if the input buffer had wrapped text, the above scenario works as expected
✅ scenario works for CMD, PowerShell Core, and WSL
PR #12722 introduced a dependency on usp10.dll. The Script* APIs are split
between gdi32 and usp10, so we needed to add a new entry to the sources
files for anybody who consumed the GDI renderer.
## Summary of the Pull Request
Fixes a bug in ConHost where Narrator wouldn't read the deleted letter after the user pressed backspace.
## References
MSFT:31748387
## Detailed Description of the Pull Request / Additional comments
`WriteCharsLegacy()` already calls `NotifyAccessibilityEventing()` when text is inserted into the buffer ([see code](855e1360c0/src/host/_stream.cpp (L559-L563))). However, when backspace is pressed, the entire if-condition is skipped over, resulting in the accessibility event not being fired. `WriteCharsLegacy()` has a separate branch that is dedicated to handling backspace, so I added a call to the relevant logic to notify UIA at the end of that.
## Validation Steps Performed
✅ <kbd>Backspace</kbd> deletes a character and Narrator reads it
✅ <kbd>Backspace</kbd> still works with NVDA and JAWS (unchanged behavior)
✅ if the input buffer had wrapped text, the above scenario works as expected
✅ scenario works for CMD, PowerShell Core, and WSL
Some applications like `vim -H` implement their own BiDi reordering.
Previously we used `PolyTextOutW` which supported such arrangements,
but with a0527a1 and the switch to `ExtTextOutW` we broke such applications.
This commit restores the old behavior by reimplementing the basics
of `ExtTextOutW`'s internal workings while enforcing LTR ordering.
## Validation Steps Performed
* Create a text file with "ץחסק פחופפסנ חס קוח ז׳חסש ץקקטק פחטסץ"
Viewing the text file with `vim -H` presents the contents as expected ✅
* Printing enwik8 is as fast as before ✅
* Font fallback for various eastern scripts in enwik8 works as expected ✅
* `DECDWL` double-width sequences ✅
* Horizontal scrolling (apart from producing expected artifacts) ✅Closes#12294
(cherry picked from commit d97d9f0fcf)
The legacy console used to use case-sensitive history deduplication and
this change reverts the logic to restore ye olde history functionality.
This commit additionally changes the other remaining `std::equal` plus
`std::towlower` check into a `CompareStringOrdinal` call,
just because that's what MSDN suggests to use in such situations.
## PR Checklist
* [x] Closes#4186
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Enter `test /v`
* Enter `test /V`
* Browsing through the history yields both items ✅
(cherry picked from commit 6bc2b4af09)
`WideCharToMultiByte` doesn't write a final null-byte by default.
`til::u16u8` avoids the problem.
## PR Checklist
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Test passes in Debug builds ✅
(cherry picked from commit 5072ee640f)
This removes one source of potential integer overflows from the Viewport class.
Other parts were left untouched, as this entire class of overflow issues gets
fixed all at once, as soon as we replace COORD with til::coord (etc.).
## PR Checklist
* [x] Closes#5271
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Call `ScrollConsoleScreenBufferW` with out of bounds coordinates
* Doesn't crash ✅
(cherry picked from commit a4a6dfcc8d)
As noted in #6759:
> `RtlCreateUnicodeString` creates a copy of the string on the process heap and the `PortName` variable has local-scope. The string doesn't get freed with `RtlFreeUnicodeString` before the function returns creating a memory leak.
> `CIS_ALPC_PORT_NAME` is a constant string and the `PortName` variable should instead be initialized using the `RTL_CONSTANT_STRING` macro:
>
> ```c++
> static UNICODE_STRING PortName = RTL_CONSTANT_STRING(CIS_ALPC_PORT_NAME);
> ```
I actually built this in the OS repo to make sure it'll still build, because this code doesn't even build outside Windows.
* [x] Closes#6759
* I work here.
(cherry picked from commit 349b76795f)
This adds some validation in the `UiaTextRange` ctor for the cursor position.
#8730 was caused by creating a `UiaTextRange` at the cursor position when it was in a delayed state (meaning it's purposefully hanging off of the right edge of the buffer). Normally, `Cursor` maintains a flag to keep track of when that occurs, but Windows Terminal isn't maintaining that properly in `Terminal::WriteBuffer`.
The _correct_ approach would be to fix `WriteBuffer` then leverage that flag for validation in `UiaTextRange`. However, messing with `WriteBuffer` is a little too risky for our comfort right now. So we'll do the second half of that by checking if the cursor position is valid. Since the cursor is really only expected to be out of bounds when it's in that delayed state, we get the same result (just maybe a tad slower than simply checking a flag).
Closes#8730
Filed #12440 to track changes in `Terminal::_WriteBuffer` for delayed EOL wrap.
## Validation Steps Performed
While using magnifier, input/delete wrapped text in input buffer.
(cherry picked from commit 5dcf5262b4)
This commit fixes an issue, where we failed to emit a DECTCEM sequence to hide
the cursor if it was hidden before XtermEngine's first frame was finalized.
Even in such cases we need to emit a DECTCEM sequence
in order to ensure we're in a consistent state.
## Validation Steps Performed
* Added test✅
* Run #12401's repro steps around 30 times✅Closes#12401
(cherry picked from commit dbb70778d4)
The pull request fixes the issue where "sizeof" parameter was use instead of "ARRAYSIZE".
## PR Checklist
* [x] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [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] 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
## Detailed Description of the Pull Request / Additional comments
This was a pretty straight forward issue, i just replace sizeof which gives the byte size with ARRAYSIZE which give the number of elements in the array.
(cherry picked from commit 5fa1ba8dab)
In !1806141, MapVirtualKey and VkKeyScan became part of OneCore (yeah,
in 2018!). GetKeyState I can't quite figure out... but it looks like
the places we would use it (Win32 Window and Selection) already either
don't exist (window) or don't work (selection) in OneCore conhost.
Removing these redirects reduces our maintenance burden quite a bit.
Because we had to run all keyboard code through the service locator,
anything that had a dependency on key translation needed to link the
entire console host. Therefore, for anything that conhost depended upon,
so did the unit test binaries. Ugh.
I chose to keep TranslateCharsetInfo, even though it looks like gdi32 is
hosted in OneCore and the code appears as though it would work. It was
not in my critical path, and is a very basic local lookup that only powers
whether gridlines are available and the console's "Lang ID".
TEST RESULTS FROM ONECORE
Microsoft.Console.Host.FeatureTests.dll
Summary: Total=408, Passed=140, Failed=266, Blocked=0, Not Run=0, Skipped=2
I do not know how to make sure that the feature tests run properly on
OneCore. It looks like ModuleSetup is failing, which is unlikely to be
related to this change (especially given that conhost *does* launch.)
If I re-run the categories individually, they either pass or get marked
as skipped intentionally.
Microsoft.Console.Host.IntegrityTests.dll
Summary: Total=5, Passed=0, Failed=5, Blocked=0, Not Run=0, Skipped=0
Same.
Microsoft.Console.Interactivity.Win32.UnitTests.dll
Summary: Total=392, Passed=392, Failed=0, Blocked=0, Not Run=0, Skipped=0
Microsoft.Console.TextBuffer.UnitTests.dll
Summary: Total=27, Passed=27, Failed=0, Blocked=0, Not Run=0, Skipped=0
Microsoft.Console.Host.UIAutomationTests.dll
Summary: Total=6, Passed=0, Failed=0, Blocked=6, Not Run=0, Skipped=0
Microsoft.Console.Types.UnitTests.dll
Summary: Total=8, Passed=8, Failed=0, Blocked=0, Not Run=0, Skipped=0
Microsoft.Terminal.Til.UnitTests.dll
Summary: Total=290, Passed=290, Failed=0, Blocked=0, Not Run=0, Skipped=0
Microsoft.Console.VirtualTerminal.Parser.UnitTests.dll
Summary: Total=748, Passed=747, Failed=0, Blocked=0, Not Run=0, Skipped=1
Microsoft.Console.VirtualTerminal.Adapter.UnitTests.dll
Summary: Total=222, Passed=222, Failed=0, Blocked=0, Not Run=0, Skipped=0
Microsoft.Console.Host.UnitTests.dll
Summary: Total=5235, Passed=5222, Failed=0, Blocked=12, Not Run=0, Skipped=1
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev c4c0267e1139d8d205bc9995da7906e5b09f03db
Related work items: MSFT-38632962
Some applications like `vim -H` implement their own BiDi reordering.
Previously we used `PolyTextOutW` which supported such arrangements,
but with a0527a1 and the switch to `ExtTextOutW` we broke such applications.
This commit restores the old behavior by reimplementing the basics
of `ExtTextOutW`'s internal workings while enforcing LTR ordering.
## Validation Steps Performed
* Create a text file with "ץחסק פחופפסנ חס קוח ז׳חסש ץקקטק פחטסץ"
Viewing the text file with `vim -H` presents the contents as expected ✅
* Printing enwik8 is as fast as before ✅
* Font fallback for various eastern scripts in enwik8 works as expected ✅
* `DECDWL` double-width sequences ✅
* Horizontal scrolling (apart from producing expected artifacts) ✅Closes#12294
[Git2Git] Merged PR 7088552: Silence TVS by using %d (int) instead of %td (ptrdiff_t)
Silence TVS by using %d (int) instead of %td (ptrdiff_t)
This commit also includes an automatic sources.dep fix.
Fixes MSFT-38106841
Fixes MSFT-38106866
Related work items: #38106841, #38106866 Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 5983633fe90cccdb1165ab28935bd704414bb6f2
Related work items: #38106841, #38106866
## THE WHITE WHALE
This is a fairly naive fix for this bug. It's not terribly performant,
but neither is resize in the first place.
When the buffer gets resized, typically we only copy the text up to the
`MeasureRight` point, the last printable char in the row. Then we'd just
use the last char's attributes to fill the remainder of the row.
Instead, this PR changes how reflow behaves when it gets to the end of
the row. After we finish copying text, then manually walk through the
attributes at the end of the row, and copy them over. This ensures that
cells that just have a colored space in them get copied into the new
buffer as well, and we don't just blat the last character's attributes
into the rest of the row. We'll do a similar thing once we get to the
last printable char in the buffer, copying the remaining attributes.
This could DEFINITELY be more performant. I think this current
implementation walks the attrs _on every cell_, then appends the new
attrs to the new ATTR_ROW. That could be optimized by just using the
actual iterator. The copy after the last printable char bit is also
especially bad in this regard. That could likely be a blind copy - I
just wanted to get this into the world.
Finally, we now copy the final attributes to the correct buffer: the new
one. We used to copy them to the _old_ buffer, which we were about to
destroy.
## Validation
I'll add more gifs in the morning, not enough time to finish spinning a
release Terminal build with this tonight.
Closes#32🎉🎉🎉🎉🎉🎉🎉🎉🎉Closes#12567
The x86 Conhost UTs were failing because--when run in a specific order
(SearchTests, then SelectionInputTests)--PrepareGlobalScreenBuffer would
attempt to enable painting on a renderer that was dead and gone and
pushing up daisies.
The legacy console used to use case-sensitive history deduplication and
this change reverts the logic to restore ye olde history functionality.
This commit additionally changes the other remaining `std::equal` plus
`std::towlower` check into a `CompareStringOrdinal` call,
just because that's what MSDN suggests to use in such situations.
## PR Checklist
* [x] Closes#4186
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Enter `test /v`
* Enter `test /V`
* Browsing through the history yields both items ✅
HLSL uses 32-bit booleans, while C++ uses 8-bit ones aligned by 32-bit.
This meant that the shader was accessing uninitialized memory
forcing ClearType blending to be randomly enabled.
This regressed in commit 5964060.
## PR Checklist
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* ClearType blending works ✅
* Enabling transparent backgrounds forces grayscale blending ✅
`WideCharToMultiByte` doesn't write a final null-byte by default.
`til::u16u8` avoids the problem.
## PR Checklist
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Test passes in Debug builds ✅
`std::basic_string_view::substr` throws an exception if the first argument
(offset) is out of range. If UIA is running, this creates _a lot_ of exceptions
and associated log output. This trivial change takes care of that.
After this commit we only set the default fields of a profile - primarily the
name field - as late as possible, after layering has already completed.
This ensures that we pick up any modifications from fragments.
## PR Checklist
* [x] Closes#12520
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Add a fragment at
`%LocalAppData%\Microsoft\Windows Terminal\Fragments\Fragment\fragment.json`
with
`{"profiles":[{"updates":"{61c54bbd-c2c6-5271-96e7-009a87ff44bf}","name":"NewName"}]}`
* Windows PowerShell profile is created with the name "NewName" in settings.json ✅
* Drop engine support for DirectX 9.1
Practically no one has such old hardware anymore and AtlasEngine additionally
drops support for 10.0. The fallback also didn't work properly,
because the `FeatureLevels` array failed to include 9.2 and 9.3.
We'll simply fall back to WARP on all such devices.
* Optimize shaders during compilation
The two new flags increase shader performance sometimes significantly.
* Fix shader feature level flags
D3D feature level 10.0 only support 4.0 and 10.1 only 4.1 shaders.
## PR Checklist
* [x] Closes#12655
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Add `WindowsTerminal.exe` in `dxcpl.exe`
* Add a basic `experimental.pixelShaderPath`
* All forced feature levels between `9_1` and `11_1` render as expected ✅
## Summary of the Pull Request
The purpose of the `IRenderTarget` interface was to support the concept
of multiple buffers in conhost. When a text buffer needed to trigger a
redraw, the render target implementation would be responsible for
deciding whether to forward that redraw to the renderer, depending on
whether the buffer was active or not.
This PR instead introduces a flag in the `TextBuffer` class to track
whether it is active or not, and it can then simply check the flag to
decide whether it needs to trigger a redraw or not. That way it can work
with the `Renderer` directly, and we can avoid a bunch of virtual calls
for the various redraw methods.
## PR Checklist
* [x] Closes#12551
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number
where discussion took place: #12551
## Detailed Description of the Pull Request / Additional comments
Anywhere that had previously been getting an `IRenderTarget` from the
`TextBuffer` class in order to trigger a redraw, will now just call the
`TriggerRedraw` method on the `TextBuffer` class itself, since that will
handle the active check which used to be the responsibility of the
render target. All the redraw methods that were in `IRenderTarget` are
now exposed in `TextBuffer` instead.
For this to work, though, the `Renderer` needed to be available before
the `TextBuffer` could be constructed, which required a change in the
conhost initialization order. In the `ConsoleInitializeConnectInfo`
function, I had to move the `Renderer` initialization up so it could be
constructed before the call to `SetUpConsole` (which initializes the
buffer). Once both are ready, the `Renderer::EnablePainting` method is
called to start the render thread.
The other catch is that the renderer used to setup its initial viewport
in the constructor, but with the new initialization order, the viewport
size would not be known at that point. I've addressed that problem by
moving the viewport initialization into the `EnablePainting` method,
since that will only be called after the buffer is setup.
## Validation Steps Performed
The changes in architecture required a number of tweaks to the unit
tests. Some were using a dummy `IRenderTarget` implementation which now
needed to be replaced with a full `Renderer` (albeit with mostly null
parameters). In the case of the scroll test, a mock `IRenderTarget` was
used to track the scroll delta, which now had to be replaced with a mock
`RenderEngine` instead.
Some tests previously relied on having just a `TextBuffer` but without a
`Renderer`, and now they require both. And tests that were constructing
the `TextBuffer` and `Renderer` themselves had to be updated to use the
new initialization order, i.e. with the renderer constructed first.
Semantically, though, the tests still essentially work the same way as
they did before, and they all still pass.
## Summary of the Pull Request
Closes#12670
Visual Studio 2022 offered to upgrade .NET Framework from an unsupported 4.5 to a supported 4.8. I let it do its thing (and undid a number of whitespace-only changes that aren't necessary). The project still builds after this. The UIA tests fail to run but I think that is preexisting and will be filing a new issue momentarily.
## PR Checklist
* [x] Closes#12670
* [x] Tests added/passed
## Validation Steps Performed
The solution compiles in VS2022 (except for #12673).
The store did not like when I uploaded two Windows Terminal packages
built on the same date, because the appxbundle version defaulted to
YYYY.MMDD.something.
There was a risk that using *this* version number will fail because it is
thousands of numbers less than "2022". We'll have to see if the store
rolls it out properly. I cannot find any documentation on how the store
rolls out *bundle* versions (it is very aware of .appx versions...).
A local test with 1.14.72x (Preview) published via the store seems to
have worked.
This commit fixes a stray exception during settings loading,
caused by a failure to obtain the app's extension catalog.
## PR Checklist
* [x] Closes#12305
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
I'm unable to replicate the issue. ❌
However an error log was provided in #12305 with which
the function causing the exception could be determined.
This regressed recently in cfaa315.
Initially I tried to migrate TestHostApp to C++/WinRT, but due to the
unbearable compile times I've reverted it back to C++/CX (>20x difference).
Unfortunately I then forgot to fix the underlying issue before submitting a PR.
## PR Checklist
* [x] Closes#12673
* [x] I work here
* [x] Tests added/passed
Many articles I read while writing this engine claimed that GPUs can't
do branches like CPUs can. One common approach to branching in GPUs is
apparently to "mask" out results, a technique called branch predication.
The GPU will simply execute all instructions in your shader linearly,
but if a branch isn't taken, it'll ignore the computation results.
This is unfortunate for our shader, since most branches we have are
only very seldomly taken. The cursor for instance is only drawn
on a single cell and underlines are seldomly used.
But apparently modern GPUs (2010s and later?) are actually entirely
capable of branching, _if_ all lanes ("pixels") processed by a
wave (""GPU core"") take the same branch.
On both my Nvidia GPU (RTX 3080) and Intel iGPU (Intel HD Graphics 530)
this change has a positive impact on power draw. Most noticeably on the
latter this reduces power draw from 900mW down to 600mW at 60 FPS.
## PR Checklist
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
It seems to work fine on Intel and Nvidia GPUs.
Unfortunately I don't have a AMD GPU to test this on, but I suspect it can't be worse.
## Summary of the Pull Request
This change makes Windows Terminal raise a `RaiseNotificationEvent()` ([docs](https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.automation.peers.automationpeer.raisenotificationevent?view=winrt-22000)) for new text output to the buffer.
This is intended to help Narrator identify what new output appears and reduce the workload of diffing the buffer when a `TextChanged` event occurs.
## Detailed Description of the Pull Request / Additional comments
The flow of the event occurs as follows:
- `Terminal::_WriteBuffer()`
- New text is output to the text buffer. Notify the renderer that we have new text (and what that text is).
- `Renderer::TriggerNewTextNotification()`
- Cycle through all the rendering engines and tell them to notify handle the new text output.
- None of the rendering engines _except_ `UiaEngine` has it implemented, so really we're just notifying UIA.
- `UiaEngine::NotifyNewText()`
- Concatenate any new output into a string.
- When we're done painting, tell the notification system to actually notify of new events occurring and clear any stored output text. That way, we're ready for the next renderer frame.
- `InteractivityAutomationPeer::NotifyNewOutput()` --> `TermControlAutomationPeer::NotifyNewOutput`
- NOTE: these are split because of the in-proc and out-of-proc separation of the buffer.
- Actually `RaiseNotificationEvent()` for the new text output.
Additionally, we had to handle the "local echo" problem: when a key is pressed, the character is said twice (once for the keyboard event, and again for the character being written to the buffer). To accomplish this, we did the following:
- `TermControl`:
- here, we already handle keyboard events, so I added a line saying "if we have an automation peer attached, record the keyboard event in the automation peer".
- `TermControlAutomationPeer`:
- just before the notification is dispatched, check if the string of recent keyboard events match the beginning of the string of new output. If that's the case, we can assume that the common prefix was the "local echo".
This is a fairly naive heuristic, but it's been working.
Closes the following ADO bugs:
- https://dev.azure.com/microsoft/OS/_workitems/edit/36506838
- (Probably) https://dev.azure.com/microsoft/OS/_workitems/edit/38011453
## Test cases
- [x] Base case: "echo hello"
- [x] Partial line change
- [x] Scrolling (should be unaffected)
- [x] Large output
- [x] "local echo": keyboard events read input character twice
This sure is bodgy, but it makes sense. Right now, when we delete a profile, we load in a totally new content for the new profile's settings. That one resets the scroll view and the focus, and now the "delete" button is obviously not focused.
Instead, this PR will manually re-focus the delete button of a profile page when the page is navigated to _because we deleted another profile_.
* [x] This will take care of #11971
This removes one source of potential integer overflows from the Viewport class.
Other parts were left untouched, as this entire class of overflow issues gets
fixed all at once, as soon as we replace COORD with til::coord (etc.).
## PR Checklist
* [x] Closes#5271
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Call `ScrollConsoleScreenBufferW` with out of bounds coordinates
* Doesn't crash ✅
This fixes a pair of inbox bugs, hopefully.
* MSFT:35731327
* There's a small window where a peasant is being created when a monarch is exiting. When that happens, the new peasant will try to tell itself (the new monarch) when the peasant was last activated, but because the window hasn't actually finished instantiating, the peasant doesn't yet have a LastActivatedArgs to tell the monarch about.
* MSFT:32518679 (ARM version) / MSFT:32279047 (AMD64 version)
* This one's tricky. Not totally sure this is the fix, bug assuming my hypothesis is correct, this should fix it. Regardless, this does fix a bug that was in the code.
* If the king dies right as another window is starting, right while the new window is starting to ProposeCommandline to the monarch, the monarch could die. If it does, the new window just explodes too. Not what you want.
Vaguely tested the second bug manually, by setting breakpoints in the monarch, starting a defterm, then exiting the monarch while the handoff was in process. That now creates a new window, so that's at least something. `RemotingTests::TestProposeCommandlineWithDeadMonarch` was the closest I could get to testing that.
The first bug only got an eye check. Not sure how to repro, but I figured yeet and hopefully we get it.
* [x] Closes#12624
The `bg != _r.backgroundColor` invalidation check wasn't symmetric with
us setting `_r.backgroundColor` to `bg | _api.backgroundOpaqueMixin`.
Due to this, when the `backgroundOpaqueMixin` changed,
we didn't always update the const buffer appropriately.
## PR Checklist
* [x] Closes#11773
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Enable window transparency (`backgroundOpaqueMixin == 0x00000000`)
* Maximize window (ensure we have gutters in the first place)
* Disable window transparency (`backgroundOpaqueMixin == 0xff000000`)
* Gutters are filled ✅
This commit enables `/std:c++20` for local development under VS17.
Our CIs will continue to use VS16 and C++17 for now in order to reduce
the likelihood of regressions during the current development cycle.
It's expected that we'll migrate to VS17 soon, as this
is what conhost is already being built with anyways.
## PR Checklist
* [x] Closes#12510
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Everything compiles under `/std:c++20` ✅
This regressed in 2b202ce6, which removed `ACTCTX_FLAG_RESOURCE_NAME_VALID`
during `CreateActCtxW` under the assumption that an executable only has
one manifest. conhost has two however and we need to pick the correct one.
On OpenConsole this causes the expected `ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET`.
Closes MSFT:38355907
(cherry picked from commit c820af46b7)
By replacing `IDWriteFontSetBuilder2::AddFontFile` with
`IDWriteFactory5::CreateFontFileReference` and
`IDWriteFontSetBuilder1::AddFontFile` we add nearby
font loading support for Windows 10, build 15021.
This commit also fixes font fallback for AtlasEngine,
which was crashing during testing.
Finally it fixes a bug in DxEngine, where we only created a "nearby" font
collection if we couldn't find the font in the system collection. This doesn't
fix the bug, if the font is locked or broken in the system collection.
This is related to #11648.
## PR Checklist
* [x] Closes#12420
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Build a Debug version of Windows Terminal
* Put Jetbrains Mono into the writeable AppX directory
* Jetbrains Mono is present in the settings UI ✅
* DxEngine works with Jetbrains Mono ✅
* AtlasEngine works with Jetbrains Mono ✅
This regressed in 2b202ce6, which removed `ACTCTX_FLAG_RESOURCE_NAME_VALID`
during `CreateActCtxW` under the assumption that an executable only has
one manifest. conhost has two however and we need to pick the correct one.
On OpenConsole this causes the expected `ERROR_SXS_PROCESS_DEFAULT_ALREADY_SET`.
Closes MSFT:38355907
## Summary of the Pull Request
This makes it so that the settings.json backups are no longer created when the user saves their settings via the Settings UI.
Closes#11703
"Summon" was translated as a synonym for "citation" in Spanish instead
of treating it as a RPG-related word. "Show/Hide" will hopefully
allow an improved automatic translation in the future.
Closes#10691
2b202ce6 introduced a bug, where FreeProcessData was called without the console
lock being held. The previous code can be found in 40e3dea, on line 441-454.
## PR Checklist
* [x] Closes MSFT:21372705
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
None, as this fix is purely theoretic, but it matches the stack trace
and 40e3dea clearly wasn't correctly ported to strict C++ either.
## Summary of the Pull Request
Fixes RTF generation for text with Unicode characters.
## PR Checklist
* [x] Closes#12379
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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
## Validation Steps Performed
Added some unit tests.
Ran the following in PowerShell and copied the emitted text into WordPad.
```pwsh
echo "This is some Ascii \ {}`nLow code units: á é í ó ú `u{2b81} `u{2b82}`nHigh code units: `u{a7b5} `u{a7b7}`nSurrogates: `u{1f366} `u{1f47e} `u{1f440}"
```
2b202ce6 introduced a bug, where FreeProcessData was called without the console
lock being held. The previous code can be found in 40e3dea, on line 441-454.
## PR Checklist
* [x] Closes MSFT:21372705
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
None, as this fix is purely theoretic, but it matches the stack trace
and 40e3dea clearly wasn't correctly ported to strict C++ either.
From MSFT:36797001. Okay so this is only .22% of our crashes, but every little bit helps, right?
Turns out this is also hitting in:
* MSFT:35726322
* MSFT:34662459
and together they're a fairly hot bug.
There's a large class of bugs where we might get a callback to one of our event handlers when we call `app.Close()` in the `AppHost` dtor. This PR adds manual revokers to these events, and makes sure to revoke them BEFORE nulling out the `_window`. That will prevent callbacks during the rest of the dtor, when the `_window` is null.
This is intended to be a PR triggered build that only runs when
features.xml has been touched, to validate that the disabled features do
not cause compilation errors.
Four (4) squashed changes, with messages preserved.
## release: move symbol publication into its own phase
Right now, symbol publication happens every time we produce a final
bundle. In the future, we may be producing multiple bundles from the
same pipeline run, and we need to make sure we only do *one* symbol
publication to MSDL.
When we do that, it will be advantageous for us to have just one phase
that source-indexes and publishes all of the symbols.
## Remove Terminal's built-in copy of the VC Runtime
This removes the trick we pulled in #5661 and saves us ~550kb per arch.
Some of our dependencies still depend on the "app" versions of the
runtime libraries, so we are going to continue shipping the forwarders
in our package. Build rules have been updated to remove the non-Desktop
VCLibs dependency to slim down our package graph.
This is not a problem on Windows 11 -- it looks like it's shipped inbox.
**BREAKING CHANGE**: When launched unpackaged, Terminal now requires the
vcruntime redist to be installed.
## Prepare for toggling XAML between 2.7.0 and -prerelease on Win11
common.openconsole.props is a pretty good place to stash the XAML
version since it is included in every project (including the WAP
project (unlike the C++ build props!)).
I've gone ahead and added a "double dependency" on multiple XAML
versions. We'll toggle them with a build flag.
## Run the release pipeline twice, for Win10 and Win11, at the same time
This required some changes in how we download artifacts to make sure
that we could control which version of Windows we were processing in any
individual step.
We're also going to patch the package manifest on the Windows 11 version
so the store targets it more specifically.
On top of the prior three steps, this lets us ship a Windows 11
package that costs only ~15MB on disk. The Windows 10 version, for
comparison, is about 40.
The previous implementation only inverted the RGB values of the cell,
but failed to account for situations where the `color` is transparent,
which is the case when `backgroundOpaqueMixin` is 0 (for instance if
acrylic backgrounds are enabled). In these situations the alpha
component remained 0 which caused the cursor to be invisible.
For some inexplicable reason this issue is only visible on a HDR display,
even though it should also effect regular ones. God knows why.
With this commit the cursor texture is treated as a mask that inverts the color.
We use branching here, because I couldn't come up with a more clever solution.
## PR Checklist
* [x] Closes#12507
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Cursor is visible on a HDR display with acrylic background ✅
* TBD performance benchmark for `[branch]` ❌
Fixes two crashes amounting to 14% of our crash burden in Simulated
Selfhost. I can't reproduce this organically, but I was able to do so by
forcing the command palette to be empty.
## Summary of the Pull Request
In PR #12462, a new `maxversiontested` entry was added to the
_WindowsTerminal.manifest_ file which now gets propagated to the
_TerminalApp.Unit.Tests.manifest_ file whenever a full build is
executed. This PR is just committing the updated test manifest.
## PR Checklist
* [x] Closes#12543
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number
where discussion took place: #12543
## Summary of the Pull Request
Prevents a crash that could occur when invoking `wt C:\`
## PR Checklist
* [x] Closes#12535
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema 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
## Detailed Description of the Pull Request / Additional comments
Updates `CascadiaSettings::NormalizeCommandLine()` to check that there are a suitable number of command line arguments to be concatenated together, to prevent accessing an array index in `argv` that doesn't exist.
Also prevents a test flake that could occur in `TerminalSettingsTests::CommandLineToArgvW()`, due to generating an empty command line argument.
## Validation Steps Performed
Added a test, and checked that invoking each of the command lines below behaved as expected:
```
wtd C:\ # Window pops up with [error 2147942405 (0x80070005) when launching `C:\']
wtd C:\Program Files # Window pops up with [error 2147942402 (0x80070002) when launching `C:\Program Files']
wtd cmd # cmd profile pops up
wtd C:\Program Files\Powershell\7\pwsh -WorkingDirectory C:\ # PowerShell profile pops up in C:\
wtd "C:\Program Files\Powershell\7\pwsh" -WorkingDirectory C:\ # PowerShell profile pops up in C:\
wtd . # Window pops up with [error 2147942405 (0x80070005) when launching `.']
```
## Summary of the Pull Request
Somehow, the controls v2 update caused an issue where if you as much as _load_ a content dialog when there's already one open, we get holes in the terminal window (#12447)
This commit introduces logic to `TerminalPage` to check whether there is a content dialog open before we try to load another one.
## PR Checklist
* [x] Closes#12447
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here
## Validation Steps Performed
Can no longer repro #12447
"Acrylic material" is the official name as used on Microsoft Docs
and should ensure it gets properly translated in all languages.
## PR Checklist
* [x] Closes#9846
* [x] Closes MSFT:36776499
* [x] I work here
## Detailed Description of the Pull Request / Additional comments
We originally intended to replace the strings with "acrylic transparency",
but "acrylic material" is actually the official term on Microsoft Docs.
<!-- 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)? -->
## Summary of the Pull Request
Fix typos found by codespell. Some of it in documentation and user-visible text, mostly in code comments. While I understand you might not be interested in fixing code comments, one of the reasons being extra noise in git history, kindly note that most spell checking tools do not discriminate between documentation and code comments. So it's easier to fix everything for long maintenance.
<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes #xxx
* [X] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [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: [#501](https://github.com/MicrosoftDocs/terminal/pull/501)
* [ ] Schema 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 -->
## Detailed Description of the Pull Request / Additional comments
<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
I have checked and re-checked all changes.
When the dpi is changed, call `updateFont()` instead of `TriggerFontChange`, this
means that we continue to use the existing font features/axes
Closes#11287
## Summary of the Pull Request
Modifies the OneFuzz CI Job so that it attempts to read the notification config from a file rather than the command line.
## References
Potential oversight in #10431.
## PR Checklist
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
## Detailed Description of the Pull Request / Additional comments
Noticed that the CI job was failing on main, so took a look. According to the [docs](7f7d76fa7f/docs/notifications.md (implementation)), files should be referenced using `@./` notation.
We chose to use the "ContextMenu" resource compartment when we
changed the package name to Terminal in #12264 because it was more
broadly localized than the rest of the application.
It appears as though some platform features have trouble with the
"more qualified" resource paths that #12264 required.
To fix this, we will:
1. Copy all of the ContextMenu localizations into CascadiaPackage's
resource root
2. Switch all manifest resource paths to use resources from the package
root.
Regressed in #12264Closes#12384Closes#12406 (tracked in microsoft/powertoys#16118)
As noted in #6759:
> `RtlCreateUnicodeString` creates a copy of the string on the process heap and the `PortName` variable has local-scope. The string doesn't get freed with `RtlFreeUnicodeString` before the function returns creating a memory leak.
> `CIS_ALPC_PORT_NAME` is a constant string and the `PortName` variable should instead be initialized using the `RTL_CONSTANT_STRING` macro:
>
> ```c++
> static UNICODE_STRING PortName = RTL_CONSTANT_STRING(CIS_ALPC_PORT_NAME);
> ```
I actually built this in the OS repo to make sure it'll still build, because this code doesn't even build outside Windows.
* [x] Closes#6759
* I work here.
I believe this fixes#12383, but I can't seem to find a way to set up a N SKU VM to confirm this.
* [ ] TODO: wait till the morning to finish copying the N vhd I found off the build shares, to confirm this doesn't crash on launch.
This has been a saga.
Basically, any resources in `App.xaml` aren't going to be able to reference other theme-aware resources. We can't change the theme of the app at runtime, only elements within the app. So we can't use `ApplicationPageBackgroundThemeBrush` in app.xaml, because it will ALWAYS be evaluated as the OS theme version of that brush.
* regressed in #12326
* See also #10864
* #3917 CANNOT be fixed in the same way. We're lucky here that the TabView uses a `{ThemeResource TabViewBackground}` in markup to set the bg. We're not similarly lucky with the Pane one.
* [x] closes#12356
* [x] Tested manually. You can confirm, my eyes are bleeding from the OS-wide light mode
#12348 introduced an off-by-one bug. While the `NormalizeCommandLine` loop
should exit early when there aren't at least _two_ arguments to be joined,
the final argument-append needs to happen even if just _one_ argument exists.
This commit fixes the issue and introduces changes to additionally monitor
the early loop exit, as well as the call to `ExpandEnvironmentStringsW`.
## PR Checklist
* [x] Closes#12461
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* All `TerminalSettingsTests` tests pass ✅
* use `FontFamily="{ThemeResource SymbolThemeFontFamily}"` where possible, in XAML
* use `FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" }` in codebehind
Basically just a simple string replace.
* [x] This was a bullet point in #11353
* [x] Confirmed manually on my win10 PC
* see also #12438
Actually, this is the last bullet in #11353, so I'm gonna say closes#11353.
Screenshots below.
AtlasEngine enables various debug options for D2D and D3D in Debug builds.
Among those are resource leak checks, which were broken in OpenConsole
due to the unclean exit in `ServiceLocator::RundownAndExit`.
This commit fixes the issue by running the destructors
of any renderers registered in the Window class first.
## PR Checklist
* [x] Closes#12414
* [x] I work here
## Validation Steps Performed
* Set `HKEY_CURRENT_USER\Console\UseDx` to `2`
* Run `OpenConsole.exe`
* Exit
* No exceptions are thrown ✅
Now that we've figured out how to publish the public symbols to the official Microsoft download server... we may as well embed the source code linking information inside of them given that it's right here on GitHub. This attempts to run our existing source linking scripts against the public copy of the symbols.
## PR Checklist
* [x] Closes#12443
* [x] I work here
* [x] Tested manually
## Validation Steps Performed
* [x] Build with it: https://dev.azure.com/microsoft/Dart/_build/results?buildId=44930661&view=logs&j=8f802011-b567-5b81-5fa6-bce316c020ce
* [x] Point the debugger at them and see if it can find the sources
* [x] Maybe also look at them in a hex editor or whatnot and validate I can see the source paths pointing at GitHub
Updates this narrator announcement message to include the number of results it found. There are two versions:
* one for a singular result
* one for multiple results.
which should help with loc.
We're trying to get this in with the loc hotfix, so 👀 please
* [x] will take care of the last bit of #7907
verified with narrator locally.
We're now building a fully provenance, compliance, and security
validated package (vpack) through our Release pipeline. This attaches
the last phase which automates the submission into the Windows product.
It will also automatically trace back the source, commit SHA, and build
to the submission here from the Windows side.
* [x] Automates a manual activity I performed a few times recently
* [x] I work here
* [x] Ran a test of it against `release-1.12` and it worked
## Summary of the Pull Request
Followup from our discussion during team sync, the 'automatic adjustment of indistinguishable text' setting is going to be enabled for dev builds only.
## References
#12160
## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here
## Validation Steps Performed
Setting appears on dev build and the feature works
## Summary of the Pull Request
The only method that was really needed in the `AdaptDefault` class was
the `PrintString` method, and that could easily be moved into the
`ConGetSet` interface. That lets us get rid of the `AdaptDefault` class
altogether, simplifying the construction of the `AdaptDispatch` class,
and brings us more in line with the `TerminalDispatch` implementation.
## PR Checklist
* [x] Closes#12318
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number
where discussion took place: #12318
## Detailed Description of the Pull Request / Additional comments
The `Execute` method was never used at all, so there was no problem with
losing that. But I also noticed there was an equivalent `ExecuteChar`
method in the `ITerminalApi` interface, which also wasn't being used, so
I've removed that too.
Then there was a `Print` method taking a single `wchar_t` parameter, but
that was ultimately implemented as a `PrintString` call anyway, so that
translation could easily be accomplished in the `AdaptDispatch` calling
code, the same way it's done in `TerminalDispatch`.
That left us with the `PrintString` method, which could simply be moved
into the `ConGetSet` interface, which would then more closely match the
`ITerminalApi` interface.
There was also a `GetResult` method, that returned the status of the
last `PrintString`, but that result was never actually checked anywhere.
What I've done now is make the `PrintString` method throw an exception
on failure, and that will be caught and logged in the `StateMachine`.
## Validation Steps Performed
I've started a bash shell in conhost to verify that it still works.
Since almost everything goes through `PrintString` in VT mode, it should
be obvious if something was broken.
## Summary of the Pull Request
Other than the `s_ResizeWindow` function, the `DispatchCommon` class was
just a couple of static functions indirectly calling the `ConGetSet`
interface. So by moving the `s_ResizeWindow` implementation into the
`ConhostInternalGetSet` class, we could easily replace all usage of
`DispatchCommon` with direct calls to `ConGetSet`.
## PR Checklist
* [x] Closes#12253
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number
where discussion took place: #12253
## Validation Steps Performed
I've manually confirmed the resizing operations still work as expected.
The other functions are harder to test, but were trivial replacements.
Basically, some WSL distros ship fragments that replace the `commandline` with the executable for their distro (`ubuntu.exe`, etc.). We didn't expect that when we changed the `startingDirectory` for them all to `~`.
Unfortunately, `~` is really never a valid path for a process on windows, so those distros would now fail with
```
[error 2147942667 (0x8007010b) when launching `ubuntu1804.exe']
Could not access starting directory "~"
```
If we find that we were unable to mangle `~` into the user's WSL `commandline`, then we will re-evaluate that `startingDirectory` as `%USERPROFILE%`, which is at least something sensible, if albeit not what they wanted.
* regressed in #12315
* [x] Closes#12353
* [x] Tested with a (`ubuntu1804.exe`, `~`) profile - launched successfully, where 1.13 in market fails.
* [x] added tests
We absolutely cannot allow a defterm connection to
auto-elevate. Defterm doesn't work for elevated senarios in the
first place. If we try accepting the connection, the spawning an
elevated version of the Terminal with that profile... that's a
recipe for disaster. We won't ever open up a tab in this window.
* [x] Closes#12370
* [x] Tested manually, since there's not a great way to add defterm tests
This PR updates the `ITerminalApi` and `TerminalDispatch` classes to
allow exceptions to be thrown in case of errors instead of using boolean
return values.
## References
This brings the Terminal code into alignment with the `AdaptDispatch`
and `ConGetSet` changes made in PR #12247.
And while this isn't exactly a fix for #12378, it does at least stop the
app from crashing now.
## Detailed Description of the Pull Request / Additional comments
All the `TerminalDispatch` methods have had their `noexcept` specifiers
dropped, and any `try`/`catch` wrapping removed, so exceptions will now
fall through to the `StateMachine` class where they should be safely
caught and logged.
The same goes for the `ITerminalApi` interface and its implementation in
the `Terminal` class. And many of the methods in this interface have
also had their `bool` return values changed to `void`, since there is
usually not a need for error return values now.
## Validation Steps Performed
I've manually tested the `OSC 9;9` sequence described in #12378 and
confirmed that it no longer crashes.
This adds some validation in the `UiaTextRange` ctor for the cursor position.
#8730 was caused by creating a `UiaTextRange` at the cursor position when it was in a delayed state (meaning it's purposefully hanging off of the right edge of the buffer). Normally, `Cursor` maintains a flag to keep track of when that occurs, but Windows Terminal isn't maintaining that properly in `Terminal::WriteBuffer`.
The _correct_ approach would be to fix `WriteBuffer` then leverage that flag for validation in `UiaTextRange`. However, messing with `WriteBuffer` is a little too risky for our comfort right now. So we'll do the second half of that by checking if the cursor position is valid. Since the cursor is really only expected to be out of bounds when it's in that delayed state, we get the same result (just maybe a tad slower than simply checking a flag).
Closes#8730
Filed #12440 to track changes in `Terminal::_WriteBuffer` for delayed EOL wrap.
## Validation Steps Performed
While using magnifier, input/delete wrapped text in input buffer.
With the recent change to allow text boxes to be bigger, the `Browse` button that some of them have was getting cut off when the window was too narrow. This change puts the `Browse` button below the text box instead of next to it to prevent this issue.
## PR Checklist
* [x] Closes#12335
Segoe Fluent isn't available on Windows 10, and doesn't stealthily ship with WinUI. So if we manually set the font family to `"Segoe Fluent Icons"`, then that will just display boxes in Win10.
This instead uses the resource `"{ThemeResource SymbolThemeFontFamily}"` which will gracefully fall back on Win10.
See:
* https://github.com/microsoft/microsoft-ui-xaml/issues/3745, which inspired this solution.
Guess what! The backgound image icons were also manually specifying this font, so they had to get updated too. I couldn't find any other `Segoe Fluent` references in the code.
* [x] Closes#12350
* [x] Checked Windows 11 locally
* [x] Checked Win10 (screenshots incoming from other machine)
This commit fixes an issue, where we failed to emit a DECTCEM sequence to hide
the cursor if it was hidden before XtermEngine's first frame was finalized.
Even in such cases we need to emit a DECTCEM sequence
in order to ensure we're in a consistent state.
## Validation Steps Performed
* Added test✅
* Run #12401's repro steps around 30 times✅Closes#12401
The focus box around the color schemes combo box was getting cut off, this change adds a small margin to the stackpanel to allow space for the focus box
## PR Checklist
* [x] Closes#12328
I have no idea how this is even possible to hit. If this is able to be null, then we failed to load the settings in such a catastrophic way that nothing should work. However, OP's Terminal seemed to have already loaded the settings. By all accounts, doesn't make sense.
Regardless, the code here would crash if this ever is null, so we may as well catch it.
* [x] Closes#12360
* [ ] No way to verify this since it isn't even reproable on OPs machine, but it does have a lot of hits for that failure bucket (!!!)
The previous code had two bugs for:
* paths with more than 1 whitespace
The code joins the argv array by replacing null-word terminators with
whitespace. Unfortunately it always referred to the separator between
`argv[0]` and `argv[1]` for this instead of continuing to join
those between 1 and 2, etc.
* paths sharing a common prefix with another directory
`SearchPathW` returns paths that aren't necessarily paths to files.
A call to `GetFileAttributesW` was added, ensuring we only resolve file paths.
## PR Checklist
* [x] Closes#12345
* [x] I work here
* [ ] Tests added/passed
## Validation Steps Performed
* Paths with more than 1 whitespace resolve correctly ✅
* Paths with neighboring directories sharing a common prefix resolve correctly ✅
* Tests added ✅
## Summary of the Pull Request
After 'must', the verb is used without 'to'. Correct: "must" or "have to".
## PR Checklist
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
## Validation Steps Performed
Not required, only comment has been changed.
## Summary of the Pull Request
We no longer do anything when the rightmost breadcrumb is invoked
## PR Checklist
* [x] Closes#12325
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here
## Validation Steps Performed
Tested manually, cannot repro #12325 anymore
The `x-generate` statement seems to have fallen apart somewhere and is no longer generating the valid list of languages for display. This hardcodes the list into the manifest to restore it, which is a valid option per the documentation.
We also hardcode the limited subset of languages into the Settings application because the main application supports fewer languages than we have been translated into for the shell extensions for Windows Explorer and Start Menu integration.
## PR Checklist
* [x] Closes#12351
* [x] I work here.
* [x] Manual tests below
## Validation Steps Performed
- [x] Clean built locally with `msbuild.exe openconsole.sln /p:Configuration=Release /p:Platform=x64 /p:WindowsTerminalBranding=Release /t:Terminal\CascadiaPackage /m /bl:log4.binlog` and checked that the `appxmanifest.xml` that popped out the other side contained the same languages that it used to contain.
- [x] Built in the release pipeline
- [x] Installed release and preview branded packages. Changed my machine language to Polish (pl-PL) which is not one of the fully localized languages, but is one of the limited ones. Checked the start menu and right-click menus and saw Polish text for Terminal and Terminal Preview. Checked the Settings page in our app and saw only the limited 14 language list for the application itself.
## Summary of the Pull Request
Reducing the `MinWidth` of a toggle switch means it no longer needs a negative margin to align it correctly
## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here
## Validation Steps Performed
Setting a different language no longer causes the toggle switch to fall out of the expander
We're investigating an issue where the build succeeded but something still got lost somewhere. If we had the binlogs, maybe we could diff and track it down faster.
## Summary of the Pull Request
This PR refactors the `ConGetSet` API, eliminating some of the bloat produced by the `DoSrvPrivateXXXX` functions, simplifying the method naming to more closely match the `ITerminalApi` interface, and making better use of exceptions for error conditions in place of boolean return values.
## References
This is another small step towards merging the `AdaptDispatch` and `TerminalDispatch` classes (#3849).
## PR Checklist
* [x] Closes#12193
* [x] Closes#12194
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number where discussion took place: #3849
## Detailed Description of the Pull Request / Additional comments
There are two main parts to this. The first step was to get rid of all the `DoSrvPrivateXXX` functions, and move their implementation directly into the `ConhostInternalGetSet` class. For the most part this was just copying and pasting the code, but I also fixed a couple of bugs where we were using the wrong output buffer (the global buffer rather than the one associated with the output handle), and got rid of some unnecessary calls to `GetActiveBuffer`.
The second part was to make better use of exceptions for error conditions. Instead of catching the exceptions at the `ConGetSet` level, we now allow them to fall through all the way to the `StateMachine`. This greatly simplifies the `AdaptDispatch` implementation since it no longer needs to check a boolean return value on every `ConGetSet` call. This also enables the getter methods to return properties directly instead of having to use a reference parameter.
## Validation Steps Performed
A number of the unit tests had to be updated to match the new API. Sometimes this just required changes to method names, but in other cases error conditions that were previously detected with boolean returns now needed to be caught as exceptions.
There were also a few direct calls to `DoSrvPrivateXXX` functions that now needed to be invoked through other means: either by generating an equivalent escape sequence, or calling a lower level API serving the same purpose.
And in the adapter tests, the mock `ConGetSet` implementation required significant refactoring to match the new interface, mostly to account for the changes in error handling.
We have to do this so that the store sees us as one thing ("Windows
Terminal") and the Start menu sees us as another ("Terminal").
The store will reject our package if the value we use for "DisplayName"
here doesn't match the store's "reserved names".
This value is *not used* by the start menu.
- The add new profile page now uses a dropdown rather than radio buttons
- Subheaders, breadcrumb bar, buttons etc are now all centralized when the window is maximized (so they all align with the expanders now)
- We no longer override the titlebar colors and instead use the xaml defaults (these still aren't great but at least we will get the fix automatically when it happens upstream)
- Breadcrumb bar no longer has a negative margin, so there's no weird overlap that happens when the window becomes small
- The number boxes for launch size and font size now use the `Inline` placement mode rather than compact, allowing modification to the number with fewer clicks
- Textboxes now have a greater max width so they can occupy more space in the expander if needed
## Summary of the Pull Request
When using a screen reader, the buttons on the "add a new profile" page were being read weirdly:
- "New empty profile" button read as "create new button button"
- "duplicate" button read as "duplicate button button"
It's generally standard to read out the text inside the button, so I did just that by reusing the existing localized resources. This also removes the redundant "button" that is said by the screen reader.
I also removed the unused `AutomationId` and unnecessary `Button.Content` tags.
#11156 can be closed upon validation by the accessibility team.
## Validation Steps Performed
✅ navigate to both buttons using Narrator; make sure it sounds right
## Summary of the Pull Request
Adds some polish around the navigators in the profile page (i.e. "appearance" and "advanced" button) by doing the following:
- use the localized resources for the pivot on the navigators
- simplify the navigators to be buttons instead of toggle buttons
Doing so has Narrator identify these as buttons rather than toggle buttons. So now Narrator won't say that the button is "off", which just makes more sense.
## Validation Steps Performed
✅ Narrator says "Advanced button" or "Appearance button" on the navigator
✅ The navigators look the same as before
Since we turned this feature on in windows, and it relies on _lying
about the contents of the registry_, Terminal needs to be in on the
joke.
This will need to be reverted and serviced if we choose not to ship like
this.
Fixes#12308
`IDWriteTextAnalyzer::GetGlyphs` is not enough to get a
`DWRITE_SHAPING_TEXT_PROPERTIES::canBreakShapingAfter`
value that works for combining diacritical marks.
This requires an additional call to `GetGlyphPlacements`.
This commit increases CPU usage for complex text by ~10%.
## PR Checklist
* [x] Closes#11925
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* ``echo "[e`u{0301}`u{0301}]"`` prints an "e" with 2 accents ✅
I added a condition to exclude some of the NuGet PGO stuff when there was no build mode, but appear to not have propagated any of it in the PGD merge job. This sets it to Optimize here so it'll go through.
## PR Checklist
* [x] Closes#12300
* [x] I work here.
* [x] It blends.
## Validation Steps Performed
* [x] Ran the PGO Instrument Phase
* [x] Ran the PGO Optimize Phase
Basically, this is the same as #12266, but for the `SearchBoxControl`. Trickily, the ControlCore is the one that knows if there were search results, but the TermControl has to be the one to announce it.
* [x] Will take care of #11973 once a11y team confirms
* [x] Tested manually with Narrator
* [x] Resolves a part of #6319, which I'm repurposing just to displaying the number of results in general.
* See also #3920
The pull request fixes the issue where "sizeof" parameter was use instead of "ARRAYSIZE".
## PR Checklist
* [x] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [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] 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
## Detailed Description of the Pull Request / Additional comments
This was a pretty straight forward issue, i just replace sizeof which gives the byte size with ARRAYSIZE which give the number of elements in the array.
## Summary of the Pull Request
This adds names to more of our focusable elements. This should be the rest of them that I missed in #11364
## References
* #9990: a11y megathread
* #11155: original version of this
## PR Checklist
* [x] Should take care of #11996 once confirmed
* [x] I work here
## Validation Steps Performed
Used Accessibility Insights to verify.
## Detailed Description of the Pull Request / Additional comments
There is one other weird bit. All the expanders that have content below the expander (not inline), show up as focusable, but don't have names. Even when I add names to them. I believe this is due to https://github.com/microsoft/microsoft-ui-xaml/issues/5820, which is fixed in https://github.com/microsoft/microsoft-ui-xaml/pull/6032, in https://github.com/microsoft/microsoft-ui-xaml/releases/tag/v2.8.0-prerelease.220118001. Unfortunately, we're on a 2.7 prerelease, so we don't have that fix yet. I may see how painful moving to that is, because we're gonna get another a11y ping as soon as 1.13 ships.
I pre-emptively added names to these guys in f7ba158dc, so that the new MUX should just fix this without any thinking on our part.
Introduced in #11416
We weren't using these macros for duplicating as well, so I forgot to duplicate a couple settings. This PR switches duplicating over to using the macros as well, which shou;d reduce future bugs.
Also adds notes to which properties are intentionally omitted from these macros.
* [x] closes#12265
* [x] Verified manually that #12120 still works as expected
Sorry for combining two fixes in one PR. I can separate if need be.
* [x] Closes#12276:
- `"bellSound": null` didn't work. This one was easier, and is atomically in bcc2ca04fc. Basically, we would deserialize that as an array with a single empty string in it, which we'd try to then play. I think it's more idomatic to have that deserialized as an empty array, which correctly falls back to playing the default sound.
* [x] Closes#12258:
- This one is the majority of the rest of the PR. If you leave the MediaPlayer open, then the media keys will _affect the Terminal_. More importantly, once the bell sounds, they'd replay the bell, which is insane. So the fix is to re-create the media player when we need it. We do this per-pane for simpler lifetime tracking. I'm not worried about the overhead of creating a mediaplayer here, since we're already throttling bells.
* Originally added in #11511
* [x] Tested manually
- Use [`no.mp4`](https://www.youtube.com/watch?v=x2w9TyCv2gk) for this since that's like, 17s long
- Checked that closing panes / the terminal while a bell was playing didn't crash
- Playing a bunch of bells at once works
- closing a pane stops the bell it's playing
- once the bell stops, the media keys went back to working for Spotify
* [x] I work here
## Summary of the Pull Request
Fix various things from the recent SUI changes
- The Appearance/Advanced toggle buttons now have a max width
- We don't need `Profiles.cpp` anymore
- The `Elevate` setting is now back in the SUI
- There is no longer an alignment difference between non-expander settings and expander settings
- Expander settings no longer require hitting `Tab` twice to get to them
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here
## Summary of the Pull Request
According to https://github.com/microsoft/microsoft-ui-xaml/issues/1971, `PaneFooter` does not set the `SizeOfSet` or `PositionInSet` properties. However, `FooterMenuItems` does and works for our scenario. So we just replaced `PaneFooter` with `FooterMenuItems`.
Will handle #11154 upon verification from the accessibility team.
## Validation Steps Performed
✅ Verified using Accessibility Insights
✅ "Open Json File" button can still be invoked and keyboard navigated to as expected
There were a number of methods in the `IStateMachineEngine` interface
which controlled how the `StateMachine` interpreted escape sequences.
But essentially what it came down to was a bunch of a properties that
were always true for the `InputStateMachineEngine`, and always false for
the `OutputStateMachine` engine. To simplify the implementation, and
make things a little more efficient, I've now replaced all of those
virtual calls with a single boolean field in the `StateMachine` that is
initialised in the constructor.
I started by adding an `isEngineForInput` parameter to the constructor
to indicate the the type of engine being passed in. But to keep things
simple for callers, and I also then added a constructor without that
parameter, which could derive the value automatically based on the type
of the engine pointer.
Then in the `StateMachine` implementation, anywhere we were previously
calling `ParseControlSequenceAfterSs3`, `FlushAtEndOfString`,
`DispatchControlCharsFromEscape`, or `DispatchIntermediatesFromEscape`,
we now just reference `_isEngineForInput`. But I've also copied across
some of the original comments from those methods, to make it clear at
the point of usage why we have a difference in behavior for input and
output.
To make sure the unit tests would catch any problems, I hardcoded the
`_isEngineForInput` field to `false`, and confirmed that it broke a
bunch of input engine tests. Then I hardcoded it to `true`, and
confirmed that it broke a bunch of state machine and output engine
tests. With the `_isEngineForInput` set correctly, everything passed.
I also manually tested the various output edge cases that would be
effected by this code - C0 controls within an escape sequence, time
delays in the middle of an escape sequence, `SCS` character set
selection which requires intermediates following an escape, and a G3
single shift select which depends on `SS3`.
Closes#12254
I didn't have the tray icon enabled before I suppose, so this never got hit? Anyhow, we need to change where we look for the AppName. Otherwise we crash on launch 😨
* [x] fixes `main`
* [x] I work here
* regressed in #12264
* [x] Tested by: actually running the Terminal with this, it launched
## Summary of the Pull Request
**Note: This PR targets #11720**
Replaces our old pivot-style settings UI with a breadcrumb bar style, as per the windows 11 style guidelines. This required splitting `Profiles.xaml` into 3 separate files, `Profiles_Base.xaml` for general settings, `Profiles_Appearance.xaml` for appearance settings, `Profiles_Advanced.xaml` for advanced settings
The header in the navigation view is now a [BreadcrumbBar](https://docs.microsoft.com/en-us/windows/apps/design/controls/breadcrumbbar), which can be used to navigate back to `Profiles_Base` after moving into the advanced or appearance page (see GIF below)
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here
## Validation Steps Performed

This commit fixes the following issues when ClearType rendering is enabled:
* Colored glyphs are now drawn using grayscale AA, similar to all current
browsers. This ensures proper gamma correctness during blending in our
shader, while generally making no discernable difference for legibility.
* Our ClearType shader only emits fully opaque colors, just like the official
ClearType implementation. Due to this we need to force grayscale AA if the
user specifies both ClearType and a background image, as the image would
otherwise not be visible.
## PR Checklist
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Grayscale AA when drawing emojis ✅
* Grayscale AA when using a background image ✅
## Summary of the Pull Request
Updates our SUI to follow the windows 11 style guidelines. Includes updating our setting containers to follow the 'expander' style.
## PR Checklist
* [x] Closes#10631
* [x] Closes#9978
* [x] Closes#9595
* [x] Closes#11231
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here
## Summary of the Pull Request
This fixes a bug where several settings would not show the reset button. The root cause of this issue is two fold:
1. Hooking up `CurrentXXX`
- `GETSET_BINDABLE_ENUM_SETTING` was hooked up to the **settings** model profile object instead of the **view** model profile object. Since the settings model has no `PropertyChanged` system, any changes were directly being applied to the setting, but not notifying the view model (and thus, the view, by extension) to update themselves.
- This fix required me to slightly modify the macro. Rather than using two parameters (object and function name), I used one parameter (path to getter/setter).
2. Responding to the `PropertyChanged` notifications
- Now that we're actually dispatching the `PropertyChanged` notifications, we need to actually respond to them. This behavior was defined in `Profiles::OnNavigatedTo()` in the `PropertyChanged()` handler. Funny enough, that code was still there, it just didn't do anything because it was trying to notify that `Profiles::CurrentXXX` changed. This is invalid because `CurrentXXX` got moved to `ProfileViewModel`.
- The fix here was pretty easy. Just move the property changed handler to `ProfileViewModel`'s `PropertyChanged` handler that is defined in the ctor.
## References
Bug introduced in #11877
## Validation Steps Performed
✅ Profile termination behavior
✅ Bell notification style
✅ Text antialiasing
✅ Scrollbar visibility
Turns out, this bug only repros in Controls version 2. I'm not sure why, but it didn't repro only on main. So this fix does nothing until #11720 merges.
This PR prevents us from setting properties on the paste warning dialog unless we actually need to paste. 5f9c551b7e proves that settings these properties is what would cause the bug in the first place.
I went a step further and cleaned this up a bit. This was always a little weird, having to get the `BracketedPasteEnabled` for the active control on the UI thread before we actually display the warning. In the post-#5000 future where going back to the control like this would be a x-proc hop, I figured I should just skip that entirely and plumb the `BracketedPaste` state out in the initial request.
* [x] Closes#12202
* [x] I work here
* [x] No tests, but there's not a great place for a test like this
* [x] Doesn't affect docs
See also: #12241 which would introduce #12202 on its own.
Just like the shift+click and the alt click shortcuts, now Ctrl+Click will launch a new window with that profile, elevated.
I also found that the GenerateName wasn't updated for the elevate arg, so added that. I considered adding the following to the defaults, but decided against it. It added 10 more entries to the command palette that were only separated by the `elevate: true` param, so that didn't feel valuable. Those are posted below for posterity.
* [x] closes https://github.com/microsoft/terminal/projects/5#card-50759221
* [x] Tested manually
Includes a semi-related dead code removal for the `elevated` param for `_OpenNewWindow`, which didn't end up being used, and wouldn't work as intended anyways.
This should be most of the surfaces that we really care about for displaying "Windows Terminal". There's a pile of other references in code, but I couldn't find any other resources that mention it.
I left a lot of the references to Windows Terminal throughout. Seemed like it was fine to keep calling it that in most places, just these localized strings that are going to be displayed in the Shell that should be changed.
Rough compare:

The strings were also moved to the Context Menu resources file, because that's localized into more languages.
@DHowett we may want to spin a full build to make sure this works and I didn't miss anything
* [x] Closes#12091
There are a couple places where we now bail immediately on startup, if we think the window is going to get created without any tabs. We do that to prevent a blank window from flashing on the screen when launching auto-elevate profiles. Unfortunately, those broke defterm in a particularly hard to debug way. In the defterm invocation, there actually aren't any tabs when the app completes initialization. We use the initialization to actually accept the defterm handoff. So what would happen is that the window would immediately close itself gracefully, never accepting the handoff.
In my defense, #8514, the original auto-elevated PR, predates defterm merging (906edf7) by a few months, so I totally forgot to test this when rolling it into the subsequent iterations of that PR.
* Related to:
* #7489
* #12137
* #12205
* [x] Closes#12267
* [x] I work here
* [ ] No tests on this code unfortunately
* [x] Tested manually
Includes a semi-related code fix to #10922 to make that quieter. That is perpetually noisy, and when trying to debug defterm, you've only got about 30s to do that before it bails, so the `sxe eh` breaks in there are quite annoying.
This commit extracts DirectWrite related shader code into dwrite.hlsl
and adds support for ClearType blending.
Additionally the following changes are piggybacked into this commit:
* Some incorrect code around fallback glyph sizing was removed as
this is already accomplished by `CreateTextLayout` internally
* Hot-reload failed to work with dwrite.hlsl as the `pFileName`
parameter was missing
* Legibility of the dotted underline was improved by increasing
the line gap from 1:1 to 3:1
Part of #9999.
## PR Checklist
* [x] I work here
* [x] Tests added/passed
## Validation Steps Performed
* Types are clear ✅
When we gave users the ability to configure how the `SGR 1` attribute
should be rendered, we described those options as "intense is bright"
and "intense is bold". Internally, though, we still referred to the `SGR 1`
attribute as bold. This PR renames all occurrences of "Bold" (when
referring to the `SGR 1` attribute) as "Intense", so the terminology is
more consistent now.
PR #10969 is where we decided on the wording to describe the `SGR 1`
attribute.
Specific changes include:
* `TextAttribute::IsBold` method renamed to `IsIntense`
* `TextAttribute::SetBold` method renamed to `SetIntense`
* `VtEngine::_SetBold` method renamed to `_SetIntense`
* `ExtendedAttributes::Bold` enum renamed to `Intense`
* `GraphicsOptions::BoldBright` enum renamed to `Intense`
* `GraphicsOptions::NotBoldOrFaint` enum renamed to `NotIntenseOrFaint`
* `SgrSaveRestoreStackOptions::Boldness` enum renamed to `Intense`
## Validation Steps Performed
I've checked that the code still compiles and the unit tests still run
successfully.
Closes#12252
## Summary of the Pull Request
Expands on #9582. If the command palette finds results, the screen reader says "Suggestions available".
Makes the scenario mentioned in #7907 work.
This is sufficient for various reasons:
1. According to the bug report, saying that suggestions are available is sufficient
> Screen reader should provide the results info on searching commands like 10 results found or suggestions available when there are any search results (Source: #7907)
2. This is common practice. Settings app and XAML Controls Gallery do this for their search box.
Also, the user should be able to know how many results were found by tabbing/selecting a result item. When this is done, the screen reader will use `SizeOfSet` and `PositionInSet` to announce how many results were found and which one we're currently on.
## Validation Steps Performed
Verified this behavior using Narrator.
Verified it matches the behavior of the Settings app and the XAML Controls Gallery.
This makes the scenario mentioned in #8480 work. It's maybe not as holistic a solution as we'd like, but it definitely works.
Tested both with Narrator, and using the TabView scroll handles to get tab focus into the tab row manually
* [x] Closing the _active_ tab with <kbd>Ctrl+Shift+w</kbd> works (not the `TabViewItem` that has focus, but that's how Edgium works so that seems fine)
* [x] Opening a tab with <kbd>Ctrl+Shift+t</kbd> works
* [x] Opening the cmdpal with <kbd>Ctrl+Shift+p</kbd> works
* [x] Will take care of #8480 once we get the a11y team to validate
* [x] I work here
#### Notes:
None of
```xaml
PreviewKeyDown="_KeyDownHandler"
KeyDown="_KeyDownHandler"
KeyUp="_KeyDownHandler"
```
On the TerminalPage directly seem to fire when the focus is in the `TabViewItem` or the New Tab flyout. But they fire just fine when focus is in the `TermControl`. Interesting, because you'd think that the `TermControl` would have already handled the key...
## Summary of the Pull Request
Makes `Model::DefaultTerminal` an `IStringable`, which presents it as a string, when possible. This enables text search for defterm's setting. This also enables screen readers to identify the combo box items by their text content (app name, author, and version) as opposed to being treated as an item containing more text. As a part of that, I cleaned up the UIA tree to treat the item's name as "\<name\>, \<author\>, \<version\>". This is consistent with how the Settings App presents installed apps in Apps > Installed apps.
#11251 will be resolved upon verification by the accessibility team.
## Validation Steps Performed
Verified using Narrator and Accessibility Insights.
The PGO helpers NuGet had the Y2K22 bug. This receives and integrates the updated package in our project to restore NuGet functionality.
## PR Checklist
* [x] Closes#12261
* [x] I work here
* [x] If it builds it sits.
## Validation Steps Performed
* [x] Build new PGO instrument data with this pipeline update: https://dev.azure.com/microsoft/Dart/_build/results?buildId=44304850&view=results
More fallout from the settings refactor. Probably because testing on a Windows
10 device is hard, because you actually need a physical machine to get acrylic
to behave correctly.
Basically, the code is simpler now, but we missed the windows 10 only edge case
where acrylic can get turned on, but we forget to enable the acrylic brush, so
it just stays off.
Refer to #11619 where this regressed, and #11643, #12229, because this is just a
hard problem apparently
* [x] Closes#11743. Technically OP is complaining about behavior that's
by-design, but it made me realize this regressed in 1.12.
* [ ] No tests on this part of the `TermControl` unfortunately.
* [x] Hauled out my old Win10 laptop to verify that opacity works right:
- [x] A fresh profile isn't created with any opacity
- [x] Mouse wheeling turns on acrylic
- [x] Using `opacity` only in the settings still stealthily enables acrylic
This will turn the feature on always from this point on. That means 1.13 Stble
would be the first Stable release to have this feature (unless we cherry-pick
this to 1.12 stable, which we may)
* [x] Closes#12220
* [x] I work here
Manifest validation won't accept migration/initialization of HKCU-based registry keys anymore. The enforcement scripts says that they should be defined in code instead. So here it is: defined in code insteead.
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 67c720b628de4acefbc381891b7e7d29d387038e
Related work items: MSFT-37867666
[Git2Git] Merged PR 6881093: BUILD FIX: Reintroduce BOM to conhost manifests
Related work items: MSFT-37882151
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev b6f388b08b0b431ffc5663fe27eef260688febd6
2022-01-25 20:14:48 +00:00
1097 changed files with 44778 additions and 27510 deletions
[allow/*.txt](allow/) | Add words to the dictionary | one word per line (only letters and `'`s allowed) | [allow](https://github.com/check-spelling/check-spelling/wiki/Configuration#allow)
[reject.txt](reject.txt) | Remove words from the dictionary (after allow) | grep pattern matching whole dictionary words | [reject](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-reject)
[patterns/*.txt](patterns/) | Patterns to ignore from checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
[candidate.patterns](candidate.patterns) | Patterns that might be worth adding to [patterns.txt](patterns.txt) | perl regular expression with optional comment block introductions (all matches will be suggested) | [candidates](https://github.com/check-spelling/check-spelling/wiki/Feature:-Suggest-patterns)
[line_forbidden.patterns](line_forbidden.patterns) | Patterns to flag in checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
[expect/*.txt](expect.txt) | Expected words that aren't in the dictionary | one word per line (sorted, alphabetically) | [expect](https://github.com/check-spelling/check-spelling/wiki/Configuration#expect)
[advice.md](advice.md) | Supplement for GitHub comment when unrecognized words are found | GitHub Markdown | [advice](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice)
Note: you can replace any of these files with a directory by the same name (minus the suffix)
and then include multiple files inside that directory (with that suffix) to merge multiple files together.
<!-- See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice --> <!-- markdownlint-disable MD033 MD041 -->
<details>
<summary>
:pencil2: Contributor please read this
@@ -6,7 +6,7 @@
By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.
:warning: The command is written for posix shells. You can copy the contents of each `perl` command excluding the outer `'` marks and dropping any `'"`/`"'` quotation mark pairs into a file and then run `perl file.pl` from the root of the repository to run the code. Alternatively, you can manually insert the items...
:warning: The command is written for posix shells. If it doesn't work for you, you can manually _add_ (one word per line) / _remove_ items to `expect.txt` and the `excludes.txt` files.
If the listed items are:
@@ -20,31 +20,29 @@ See the `README.md` in each directory for more information.
:microscope: You can test your commits **without***appending* to a PR by creating a new branch with that extra change and pushing it to your fork. The [check-spelling](https://github.com/marketplace/actions/check-spelling) action will run in response to your **push** -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. :wink:
<details><summary>:clamp: If you see a bunch of garbage</summary>
If it relates to a ...
<details><summary>well-formed pattern</summary>
<details><summary>If the flagged items are :exploding_head: false positives</summary>
See if there's a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it.
If items relate to a ...
* binary file (or some other file you wouldn't want to check at all).
If not, try writing one and adding it to a `patterns/{file}.txt`.
Please add a file path to the `excludes.txt` file matching the containing file.
Patterns are Perl 5 Regular Expressions - you can [test](
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines.
Note that patterns can't match multiline strings.
</details>
<details><summary>binary-ish string</summary>
Please add a file path to the `excludes.txt` file instead of just accepting the garbage.
File paths are Perl 5 Regular Expressions - you can [test](
File paths are Perl 5 Regular Expressions - you can [test](
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files.
`^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md](
`^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md](
../tree/HEAD/README.md) (on whichever branch you're using).
</details>
* well-formed pattern.
If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it,
try adding it to the `patterns.txt` file.
Patterns are Perl 5 Regular Expressions - you can [test](
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines.
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
> * You may need to install the [VC++ v14 Desktop Framework Package](https://docs.microsoft.com/troubleshoot/cpp/c-runtime-packages-desktop-bridge#how-to-install-and-update-desktop-framework-packages).
> This should only be necessary on older builds of Windows 10 and only if you get an error about missing framework packages.
> * Terminal will not auto-update when new builds are released so you will need
> to regularly install the latest Terminal release to receive all the latest
> fixes and improvements!
@@ -111,10 +113,10 @@ repository.
---
## Windows Terminal 2.0 Roadmap
## Windows Terminal Roadmap
The plan for delivering Windows Terminal 2.0 [is described
here](/doc/terminal-v2-roadmap.md) and will be updated as the project proceeds.
The plan for the Windows Terminal [is described here](/doc/roadmap-2022.md) and
will be updated as the project proceeds.
## Project Build Status
@@ -233,7 +235,7 @@ Cause: You're launching the incorrect solution in Visual Studio.
Solution: Make sure you're building & deploying the `CascadiaPackage` project in
Visual Studio.
> ⚠ Note: `OpenConsole.exe` is just a locally-built `conhost.exe`, the classic
> **Note**: `OpenConsole.exe` is just a locally-built `conhost.exe`, the classic
> Windows Console that hosts Windows' command-line infrastructure. OpenConsole
> is used by Windows Terminal to connect to and communicate with command-line
> applications (via
@@ -264,7 +266,7 @@ help avoid any wasted or duplicate effort.
The easiest way to communicate with the team is via GitHub issues.
Please file new issues, feature requests and suggestions, but **DO search for
similar open/closed pre-existing issues before creating a new issue.**
similar open/closed preexisting issues before creating a new issue.**
If you would like to ask a question that you feel doesn't warrant an issue
(yet), please reach out to us via Twitter:
@@ -272,11 +274,8 @@ If you would like to ask a question that you feel doesn't warrant an issue
@@ -302,6 +301,7 @@ If you would like to ask a question that you feel doesn't warrant an issue
* Universal Windows Platform Development
* **The following Individual Components**
* C++ (v142) Universal Windows Platform Tools
* You must install the [.NET Framework Targeting Pack](https://docs.microsoft.com/dotnet/framework/install/guide-for-developers#to-install-the-net-framework-developer-pack-or-targeting-pack) to build test projects
<!-- Mandatory. Minor version number of the PGO database which should match the version of the product. This can be hardcoded or obtained from other sources in build system. -->
<!-- Mandatory, defaults to 0. Patch version number of the PGO database which should match the version of the product. This can be hardcoded or obtained from other sources in build system. -->
<!-- Optional, defaults to empty. Prerelease version number of the PGO database which should match the version of the product. This can be hardcoded or obtained from other sources in build system. -->
<!-- This file is read by XES, which we use in our Release builds. -->
<PropertyGroup Label="Version">
<!--
The Windows 11 build is going to have the same package name, so it *must* have a different version.
The easiest way for us to do this is to add 1 to the revision field.
In short, for a given Terminal build 1.11, we will emit two different versions (assume this is build
4 on day 23 of the year):
- 1.11.234.0 for Windows 10
- 1.11.235.0 for Windows 11
This presents a potential for conflicts if we want to ship two builds produced back to back on the
same day... which is terribly unlikely.
-->
<VersionBuildRevision Condition="'$(TerminalTargetWindowsVersion)'=='Win11' and '$(VersionBuildRevision)'!=''">$([MSBuild]::Add($(VersionBuildRevision), 1))</VersionBuildRevision>
@@ -163,7 +163,7 @@ Given that we're using Xaml islands to host a modern UI and stitching a DirectX
Now, the obvious followup question is _"why can't you have one elevated connection in a tab next to a non-elevated connection?"_ This is where @sba923 should pick up reading (:smile:). I'm probably going to cover some things that you (@robomac) know already.
[2] When you have two windows on the same desktop in the same window station, they can communicate with eachother. I can use `SendKeys` easily through `WScript.Shell` to send keyboard input to any window that the shell can see.
[2] When you have two windows on the same desktop in the same window station, they can communicate with eachother. I can use `SendKeys` easily through `WScript.Shell` to send keyboard input to any window that the shell can see.
Running a process elevated _severs_ that connection. The shell can't see the elevated window. No other program at the same integrity level as the shell can see the elevated window. Even if it has its window handle, it can't really interact with it. This is also why you can't drag/drop from explorer into notepad if notepad is running elevated. Only another elevated process can interact with another elevated window.
Most Nuget package references in this project are centralized in a single configuration so that there is a single canonical version for everything. This canonical version is restored before builds by the build pipeline, environment initialization scripts, or Visual Studio (as appropriate).
The canonical version numbers are defined in dep/nuget/packages.config. That defines what will be downloaded by nuget.exe. Most Nuget packages also have a .props and/or .targets file that must be imported by every project that consumes it. Those import statements are consolidated in:
- src/common.nugetversions.props
- src/common.nugetversions.targets
When a globally managed version changes all three of those files must be changed in unison.
Certain Nuget package references in this project, like `Microsoft.UI.Xaml`, must be updated outside of the Visual Studio NuGet package manager. This can be done using the snippet below.
> Note that to run this snippet, you need to use WSL as the command uses `sed`.
To update the version of a given package, use the following snippet
@@ -101,7 +110,7 @@ This takes quite some time, and only generates an `msix`. It does not install th
```powershell
# If you haven't already:
Import-Moduletools\OpenConsole.psm1;
Import-Module.\tools\OpenConsole.psm1;
Set-MsBuildDevEnvironment;
# The Set-MsBuildDevEnvironment call is needed for finding the path to
(yes, the cmd version is just calling powershell to do the powershell version. Too lazy to convert the rest by hand, I'm already copying from `.vscode\tasks.json`)
Building the package from VS generates the loose layout to begin with, and then registers the loose manifest, skipping the msix stop. It's a lot faster than the commandline inner loop here, unfortunately.
### 2022 Update
The following command can be used to build the terminal package, and then deploy it.
The `bx` will build just the Terminal package, critically, populating the `CascadiaPackage.build.appxrecipe` file. Once that's been built, then the `DeployAppRecipe.exe` command can be used to deploy a loose layout in the same way that Visual Studio does.
Notably, this method of building the Terminal package can't leverage the FastUpToDate check in Visual Studio, so the builds end up being considerably slower for the whole package, as cppwinrt does a lot of work before confirming that it's up to date and doing nothing.
"description":"Sets the file location of the sound played when the application emits a BEL character. If the path is invalid no sound will be played. This property also accepts an array of sounds and the terminal will pick one at random.",
"oneOf":[
{
"type":[
"string",
"null"
]
},
{
"type":"array",
"items":{
"type":"string"
}
}
]
},
"AppearanceConfig":{
"properties":{
"colorScheme":{
@@ -189,8 +207,14 @@
"type":"string"
},
"adjustIndistinguishableColors":{
"description":"When set to true, we will (when necessary) adjust the foreground color to make it more visible, based on the background color.",
"type":"boolean"
"default":"never",
"description":"Setting to adjust the foreground color to make it more visible, based on the background color. When set to \"indexed\", we will only adjust the colors if they came from the color scheme. Other possible values are \"never\" and \"always\".",
"enum":[
"never",
"indexed",
"always"
],
"type":"string"
},
"experimental.retroTerminalEffect":{
"description":"When set to true, enable retro terminal effects when unfocused. This is an experimental feature, and its continued existence is not guaranteed.",
@@ -300,6 +324,7 @@
"moveFocus",
"movePane",
"swapPane",
"markMode",
"moveTab",
"multipleActions",
"newTab",
@@ -331,8 +356,11 @@
"switchToTab",
"tabSearch",
"toggleAlwaysOnTop",
"toggleBlockSelection",
"toggleFocusMode",
"selectAll",
"setFocusMode",
"switchSelectionEndpoint",
"toggleFullscreen",
"setFullScreen",
"setMaximized",
@@ -344,6 +372,10 @@
"quit",
"adjustOpacity",
"restoreLastClosed",
"addMark",
"scrollToMark",
"clearMark",
"clearAllMarks",
"unbound"
],
"type":"string"
@@ -363,6 +395,15 @@
],
"type":"string"
},
"ScrollToMarkDirection":{
"enum":[
"previous",
"next",
"first",
"last"
],
"type":"string"
},
"ResizeDirection":{
"enum":[
"left",
@@ -485,7 +526,7 @@
"type":"boolean",
"default":false,
"description":"This will override the profile's `elevate` setting."
},
}
},
"type":"object"
},
@@ -712,6 +753,30 @@
"direction"
]
},
"ScrollToMarkAction":{
"description":"Arguments corresponding to a Scroll to Mark Action",
"allOf":[
{
"$ref":"#/$defs/ShortcutAction"
},
{
"properties":{
"action":{
"type":"string",
"const":"scrollToMark"
},
"direction":{
"$ref":"#/$defs/ScrollToMarkDirection",
"default":"previous",
"description":"The direction to scroll to a mark."
}
}
}
],
"required":[
"direction"
]
},
"SendInputAction":{
"description":"Arguments corresponding to a Send Input Action",
"allOf":[
@@ -819,6 +884,27 @@
}
]
},
"AddMarkAction":{
"description":"Arguments corresponding to an Add Mark Action",
"allOf":[
{
"$ref":"#/$defs/ShortcutAction"
},
{
"properties":{
"action":{
"type":"string",
"const":"addMark"
},
"color":{
"$ref":"#/$defs/Color",
"default":null,
"description":"If provided, will set the mark's color to the given value."
}
}
}
]
},
"SetColorSchemeAction":{
"description":"Arguments corresponding to a Set Color Scheme Action",
"allOf":[
@@ -861,7 +947,7 @@
}
}
}
],
]
},
"SetFullScreenAction":{
"description":"Arguments for a setFullScreen action",
@@ -881,7 +967,7 @@
}
}
}
],
]
},
"SetMaximizedAction":{
"description":"Arguments for a setMaximized action",
@@ -901,7 +987,7 @@
}
}
}
],
]
},
"WtAction":{
"description":"Arguments corresponding to a wt Action",
@@ -1633,7 +1719,7 @@
"$ref":"#/$defs/CopyFormat"
},
"trimBlockSelection":{
"default":false,
"default":true,
"description":"When set to true, trailing white-spaces will be removed from text in rectangular (block) selection while copied to your clipboard. When set to false, the white-spaces will be preserved.",
"type":"boolean"
},
@@ -1689,6 +1775,11 @@
"description":"Force the terminal to use the legacy input encoding. Certain keys in some applications may stop working when enabling this setting.",
"type":"boolean"
},
"experimental.useBackgroundImageForWindow":{
"default":false,
"description":"When set to true, the background image for the currently focused profile is expanded to encompass the entire window, beneath other panes.",
"type":"boolean"
},
"initialCols":{
"default":120,
"description":"The number of columns displayed in the window upon first load. If \"launchMode\" is set to \"maximized\" (or \"maximizedFocus\"), this property is ignored.",
@@ -1709,7 +1800,7 @@
},
"startOnUserLogin":{
"default":false,
"description":"When set to true, this enables the launch of Windows Terminal at startup. Setting this to false will disable the startup task entry. If the Windows Terminal startup task entry is disabled either by org policy or by user action this setting will have no effect.",
"description":"When set to true, this enables the launch of Terminal at startup. Setting this to false will disable the startup task entry. If the Terminal startup task entry is disabled either by org policy or by user action this setting will have no effect.",
"type":"boolean"
},
"firstWindowPreference":{
@@ -1761,7 +1852,7 @@
},
"useAcrylicInTabRow":{
"default":false,
"description":"When set to true, the tab row will have an acrylic background with 50% opacity.",
"description":"When set to true, the tab row will have an acrylic material background with 50% opacity.",
"type":"boolean"
},
"actions":{
@@ -1873,6 +1964,20 @@
"useAnyExisting"
],
"type":"string"
},
"newTabPosition":{
"default":"afterLastTab",
"description":"Position of newly created tabs. Possible values are \"afterLastTab\" and \"afterCurrentTab\".",
"enum":[
"afterLastTab",
"afterCurrentTab"
],
"type":"string"
},
"autoHideWindow":{
"default":false,
"description":"If enabled, Terminal window will be hidden as soon as it loses focus.",
"type":"boolean"
}
},
"required":[
@@ -1986,15 +2091,20 @@
"description":"Controls what happens when the application emits a BEL character. When set to \"all\", the Terminal will play a sound, flash the taskbar icon (if the terminal window is not in focus) and flash the window. An array of specific behaviors can also be used. Supported array values include `audible`, `window` and `taskbar`. When set to \"none\", nothing will happen.",
"$ref":"#/$defs/BellStyle"
},
"bellSound":{
"description":"Sets the sound played when the application emits a BEL. When set to an array, the terminal will pick one of those sounds at random.",
"$ref":"#/$defs/BellSound"
},
"closeOnExit":{
"default":"graceful",
"description":"Sets how the profile reacts to termination or failure to launch. Possible values:\n -\"graceful\" (close when exit is typed or the process exits normally)\n -\"always\" (always close)\n -\"never\" (never close).\ntrue and false are accepted as synonyms for \"graceful\" and \"never\" respectively.",
"default":"automatic",
"description":"Sets how the profile reacts to termination or failure to launch. Possible values:\n -\"graceful\" (close when exit is typed or the process exits normally)\n -\"always\" (always close)\n -\"automatic\" (behave as \"graceful\" only for processes launched by terminal, behave as \"always\" otherwise)\n -\"never\" (never close).\ntrue and false are accepted as synonyms for \"graceful\" and \"never\" respectively.",
"oneOf":[
{
"enum":[
"never",
"graceful",
"always"
"always",
"automatic"
],
"type":"string"
},
@@ -2051,14 +2161,33 @@
"default":false,
"description":"When true, this profile should always open in an elevated context. If the window isn't running as an Administrator, then a new elevated window will be created."
},
"experimental.autoMarkPrompts":{
"default":false,
"description":"When set to true, prompts will automatically be marked.",
"type":"boolean"
},
"experimental.connection.passthroughMode":{
"description":"When set to true, directs the PTY for this connection to use pass-through mode instead of the original Conhost PTY simulation engine. This is an experimental feature, and its continued existence is not guaranteed.",
"type":"boolean"
},
"experimental.retroTerminalEffect":{
"description":"When set to true, enable retro terminal effects. This is an experimental feature, and its continued existence is not guaranteed.",
"type":"boolean"
},
"experimental.showMarksOnScrollbar":{
"default":false,
"description":"When set to true, marks added to the buffer via the addMark action will appear on the scrollbar.",
"type":"boolean"
},
"experimental.pixelShaderPath":{
"description":"Use to set a path to a pixel shader to use with the Terminal. Overrides `experimental.retroTerminalEffect`. This is an experimental feature, and its continued existence is not guaranteed.",
"type":"string"
},
"experimental.useAtlasEngine":{
"description":"Enable using the experimental new rendering engine for this profile. This is an experimental feature, and its continued existence is not guaranteed.",
"type":"boolean",
"default":false
},
"fontFace":{
"default":"Cascadia Mono",
"description":"[deprecated] Define 'face' within the 'font' object instead.",
@@ -2153,8 +2282,14 @@
]
},
"adjustIndistinguishableColors":{
"description":"When set to true, we will (when necessary) adjust the foreground color to make it more visible, based on the background color.",
"type":"boolean"
"default":"never",
"description":"Setting to adjust the foreground color to make it more visible, based on the background color. When set to \"indexed\", we will only adjust the colors if they came from the color scheme. Other possible values are \"never\" and \"always\".",
"enum":[
"never",
"indexed",
"always"
],
"type":"string"
},
"scrollbarState":{
"default":"visible",
@@ -2219,7 +2354,7 @@
},
"useAcrylic":{
"default":false,
"description":"When set to true, the window will have an acrylic background. When set to false, the window will have a plain, untextured background.",
"description":"When set to true, the window will have an acrylic material background. When set to false, the window will have a plain, untextured background.",
| 2020-06-18 | [1.1] in Windows Terminal Preview | [Windows Terminal Preview 1.1 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-1-release/) |
| 2020-07-31 | [1.2] in Windows Terminal Preview<br>[1.1] in Windows Terminal | [Windows Terminal Preview 1.2 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-2-release/) |
| 2020-08-31 | [1.3] in Windows Terminal Preview<br>[1.2] in Windows Terminal | [Windows Terminal Preview 1.3 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-3-release/) |
| 2020-09-30 | [1.4] in Windows Terminal Preview<br>[1.3] in Windows Terminal | [Windows Terminal Preview 1.4 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-4-release/) |
| 2020-11-30 | [1.5] in Windows Terminal Preview<br>[1.4] in Windows Terminal | [Windows Terminal Preview 1.5 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-5-release/) |
| 2021-01-31 | [1.6] in Windows Terminal Preview<br>[1.5] in Windows Terminal | [Windows Terminal Preview 1.6 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-6-release/) |
| 2021-03-01 | [1.7] in Windows Terminal Preview<br>[1.6] in Windows Terminal | [Windows Terminal Preview 1.7 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-7-release/) |
| 2021-04-14 | [1.8] in Windows Terminal Preview<br>[1.7] in Windows Terminal | [Windows Terminal Preview 1.8 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-8-release/) |
| 2021-05-31 | [1.9] in Windows Terminal Preview<br>[1.8] in Windows Terminal | [Windows Terminal Preview 1.9 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-9-release/) |
| 2021-07-14 | [1.10] in Windows Terminal Preview<br>[1.9] in Windows Terminal | [Windows Terminal Preview 1.10 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-10-release/) |
| 2021-08-31 | [1.11] in Windows Terminal Preview<br>[1.10] in Windows Terminal | [Windows Terminal Preview 1.11 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-11-release/) |
| 2021-10-20 | [1.12] in Windows Terminal Preview<br>[1.11] in Windows Terminal | [Windows Terminal Preview 1.12 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-12-release/) |
| | [1.13] in Windows Terminal Preview<br>[1.12] in Windows Terminal | |
| | [1.14] in Windows Terminal Preview<br>[1.13] in Windows Terminal | |
| 2020-07-31 | [1.2] in Windows Terminal Preview<br>[1.1] in Windows Terminal | [Windows Terminal Preview 1.2 Release] |
| 2020-08-31 | [1.3] in Windows Terminal Preview<br>[1.2] in Windows Terminal | [Windows Terminal Preview 1.3 Release] |
| 2020-09-30 | [1.4] in Windows Terminal Preview<br>[1.3] in Windows Terminal | [Windows Terminal Preview 1.4 Release] |
| 2020-11-30 | [1.5] in Windows Terminal Preview<br>[1.4] in Windows Terminal | [Windows Terminal Preview 1.5 Release] |
| 2021-01-31 | [1.6] in Windows Terminal Preview<br>[1.5] in Windows Terminal | [Windows Terminal Preview 1.6 Release] |
| 2021-03-01 | [1.7] in Windows Terminal Preview<br>[1.6] in Windows Terminal | [Windows Terminal Preview 1.7 Release] |
| 2021-04-14 | [1.8] in Windows Terminal Preview<br>[1.7] in Windows Terminal | [Windows Terminal Preview 1.8 Release] |
| 2021-05-31 | [1.9] in Windows Terminal Preview<br>[1.8] in Windows Terminal | [Windows Terminal Preview 1.9 Release] |
| 2021-07-14 | [1.10] in Windows Terminal Preview<br>[1.9] in Windows Terminal | [Windows Terminal Preview 1.10 Release] |
| 2021-08-31 | [1.11] in Windows Terminal Preview<br>[1.10] in Windows Terminal | [Windows Terminal Preview 1.11 Release] |
| 2021-10-20 | [1.12] in Windows Terminal Preview<br>[1.11] in Windows Terminal | [Windows Terminal Preview 1.12 Release] |
| 2022-02-03 | [1.13] in Windows Terminal Preview<br>[1.12] in Windows Terminal | [Windows Terminal Preview 1.13 Release] |
| 2022-05-24 | [1.14] in Windows Terminal Preview<br>[1.13] in Windows Terminal | [Windows Terminal Preview 1.14 Release] |
| | [1.15] in Windows Terminal Preview<br>[1.14] in Windows Terminal | |
| | [1.16] in Windows Terminal Preview<br>[1.15] in Windows Terminal | |
| | [1.17] in Windows Terminal Preview<br>[1.16] in Windows Terminal | |
### Release outline
Below is a VERY vague outline of the remaining calendar year that was drafted late May 2022. This was drafted for internal planning purposes, as a guide. It is not meant to represent official dates. More often than not, releases are synced to official features landing, rather than arbitrary dates. Drift from this initial draft is entirely expected.
```mermaid
gantt
title Proposed Terminal Releases 1.14-1.18
dateFormat YYYY-MM-DD
axisFormat %d %b
section Terminal 1.14
Lock down & bake :done, 2022-05-06, 2w
Release 1.14 :milestone, 2022-05-24
section Terminal 1.15
Features :done, a1, 2022-05-06, 4w
Bugfix :active, a2, after a1 , 1w
Lock down & bake :after a2 , 1w
Release 1.15 :milestone, 2022-06-21, 0
1.15 becomes Stable :milestone, after b3, 0
section Terminal 1.16
Features :b1, after a2, 4w
Bugfix :b2, after b1 , 2w
Lock down & bake :b3, after b2 , 2w
Release 1.16 :milestone, after b3, 0
1.16 becomes Stable :milestone, after c3, 0
section Terminal 1.17
Features :c1, after b2, 4w
Bugfix :c2, after c1 , 2w
Lock down & bake :c3, after c2 , 2w
Release 1.17 :milestone, after c3, 0
1.17 becomes Stable :milestone, after d3, 0
section Terminal 1.18
Features :d1, after c2, 4w
Bugfix :d2, after d1 , 2w
Lock down & bake :d3, after d2 , 2w
Release 1.18 :milestone, after d3, 0
```
## Issue Triage & Prioritization
Incoming issues/asks/etc. are triaged several times a week, labeled appropriately, and assigned to a milestone in priority order:
@@ -62,7 +102,9 @@ Incoming issues/asks/etc. are triaged several times a week, labeled appropriatel
# Show Hide operations on GetConsoleWindow via PTY
## Abstract
To maintain compatibility with command-line tools, utilities, and tests that desire to
manipulate the final presentation window of their output through retrieving the raw
console window handle and performing `user32` operations against it like [ShowWindow](https://docs.microsoft.com//windows/win32/api/winuser/nf-winuser-showwindow),
we will create a compatibility layer that captures this intent and translates it into
the nearest equivalent in the cross-platform virtual terminal language and implement the
understanding of these sequences in our own Windows Terminal.
## Inspiration
When attempting to enable the Windows Terminal as the default terminal application on Windows
(to supersede the execution of command-line utilities inside the classic console host window),
we discovered that there were a bunch of automated tests, tools, and utilities that relied on
showing and hiding the console window using the `::GetConsoleWindow()` API in conjunction with
`::ShowWindow()`.
When we initially invented the ConPTY, we worked to ensure that we built to the common
denominator that would work cross-platform in all scenarios, avoiding situations that were
dependent on Windows-isms like `user32k` including the full knowledge of how windowing occurs
specific to the Windows platform.
We also understood that on Windows, the [**CreateProcess**](https://docs.microsoft.com/windows/win32/procthread/process-creation-flags) API provides ample flags specifically
for command-line applications to command the need for (or lack thereof) a window on startup
such as `CREATE_NEW_CONSOLE`, `CREATE_NO_WINDOW`, and `DETACHED_PROCESS`. The understanding
was that people who didn't need or want a window, or otherwise needed to manipulate the
console session, would use those flags on process creation to dictate the session. Additionally,
the `::CreateProcess` call will accept information in `STARTUPINFO` or `STARTUPINFOEX` that
can dictate the placement, size, and visibility of a window... including some fields specific
to console sessions. We had accepted those as ways applications would specify their intent.
Those assumptions have proven incorrect. Because it was too easy to just `::CreateProcess` in
the default manner and then get access to the session after-the-fact and manipulate it with
APIs like `::GetConsoleWindow()`, tooling and tests organically grew to make use of this process.
Instead of requesting up front that they didn't need a window or the overhead of a console session,
they would create one anyway by default and then manipulate it afterward to hide it, move it off-
screen, or otherwise push it around. Overall, this is terrible for their performance and overall
reliability because they've obscured their intent by not asking for it upfront and impacted their
performance by having the entire subsystem spin up interactive work when they intend to not use it.
But Windows is the place for compatibility, so we must react and compensate for the existing
non-ideal situation.
We will implement a mechanism to compensate for these that attempts to capture the intent of the
requests from the calling applications against the ConPTY and translates them into the "universal"
Virtual Terminal language to the best of its ability to make the same effects as prior to the
change to the new PTY + Terminal platform.
## Solution Design
Overall, there are three processes involved in this situation:
1. The client command-line application utility, tool, or test that will manipulate the window.
1. The console host (`conhost.exe` or `openconsole.exe`) operating in PTY mode.
1. The terminal (`windowsterminal.exe` when it's Windows Terminal, but could be a third party).
The following diagram shows the components and how they will interact.
1. The command-line tool calls `::GetConsoleWindow()` on the PTY host
2. The PTY host returns the raw `HWND` to the *Hidden Fake PTY Window* in its control
3. The command-line tool calls `::ShowWindow()` on the `user32.dll` API surface to manipulate that window.
4.`user32.dll` sends a message to the window message queue on the *Fake PTY Window*
5. The PTY host retrieves the message from the queue and translates it to a virtual terminal message
6. The Windows Terminal connection layer receives the virtual terminal message and decodes it into a window operation.
7. The true displayed *Windows Terminal Window* is told to change its status to show or hide.
8. The changed Show/Hide status is returned to the back-end on completion.
9. The Windows Terminal connection layer returns that information to the PTY host so it can remain in-the-know.
10. The PTY updates its *Fake PTY Window* status to match the real one so it continues to receive appropriate messages from `user32`.
This can be conceptually understood in a few phases:
- The client application grabs a handle and attempts to send a command via a back-channel through user32.
- User32 decides what message to send based on the window state of the handle.
- The message is translated by the PTY and propagated to the true visible window.
- The visible window state is returned back to the hidden/fake window to remain in synchronization so the next call to user32 can make the correct decision.
The communication between the PTY and the hosting terminal application occurs with a virtual terminal sequence.
Fortunately, *xterm* had already invented and implemented one for this behavior called **XTWINOPS** which means
we should be able to utilize that one and not worry about inventing our own Microsoft-specific thing. This ensures
that there is some precedence for what we're doing, guarantees a major third party terminal can support the same
sequence, and induces a high probability of other terminals already using it given *xterm* is the defacto standard
for terminal emulation.
Information about **XTWINOPS** can be found at [Xterm control sequences](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html). Search for *XTWINOPS*.
The sequence is **CSI***Ps*; *Ps*; *Ps***t**. It starts with the common "control sequence initiator" of `ESC [` (`0x1B 0x5B`).
Then between 1 and 3 numerical parameters are given, separated by semicolons (`0x3B`).
And finally, the sequence is terminated with `t` (`0x74`).
Specifically, the two parameter commands of `1` for *De-iconify window* and `2` for *Iconify window* appear relevant to our interests.
In `user32` parlance, "iconify" traditionally corresponds to minimize/restore state and is a good proxy for overall visibility of the window.
The theory then is to detect when the assorted calls to `::ShowWindow()` against the *Fake PTY Window* are asking for a command that
maps to either "iconify" or "deiconify" and translate them into the corresponding message over the VT channel to the attached terminal.
To detect this, we need to use some heuristics inside the [window procedure](https://docs.microsoft.com/windows/win32/winmsg/window-procedures) for the window owned by the PTY.
Unfortunately, calls to `::ShowWindow()` on research with the team that owns `user32` do not go straight into the window message queue. Instead, they're dispatched straight into `win32k` to be analyzed and then trigger an array of follow on window messages into the queue depending on the `HWND`'s current state. Most specifically, they vary based on the `WS_VISIBLE` state of the `HWND`. (See [Window Styles](https://docs.microsoft.com/windows/win32/winmsg/window-styles) for details on the `WS_VISIBLE` flag.)
I evaluated a handful of messages with the help of the IXP Essentials team to see which ones would telegraph the changes from `::ShowWindow()` into our window procedure:
- [WM_QUERYOPEN](https://docs.microsoft.com/windows/win32/winmsg/wm-queryopen) - This one allows us to accept/reject a minimize/restore call. Not really useful for finding out current state
- [WM_SYSCOMMAND](https://docs.microsoft.com/windows/win32/menurc/wm-syscommand) - This one is what is called when the minimize, maximize/restore, and exit buttons are called in the window toolbar. But apparently it is not generated for these requests coming from outside the window itself through the `user32` APIs.
- [WM_SHOWWINDOW](https://docs.microsoft.com/windows/win32/winmsg/wm-showwindow) - This one provides some insight in certain transitions, specifically around force hiding and showing. When the `lParam` is `0`, we're supposed to know that someone explicitly called `::ShowWindow()` to show or hide with the `wParam` being a `BOOL` where `TRUE` is "show" and `FALSE` is "hide". We can translate that into *de-iconify* and *iconify* respectively.
- [WM_WINDOWPOSCHANGING](https://docs.microsoft.com/windows/win32/winmsg/wm-windowposchanging) - This one I evaluated extensively as it looked to provide us insight into how the window was about to change before it did so and offered us the opportunity to veto some of those changes (for instance, if we wanted to remain invisible while propagating a "show" message). I'll detail more about this one in a sub-heading below.
- [WM_SIZE](https://docs.microsoft.com/windows/win32/winmsg/wm-size) - This one has a `wParam` that specifically sends `SIZE_MINIMIZED` (`1`) and `SIZE_RESTORED` (`0`) that should translate into *iconify* and *de-iconify respectively.
#### WM_WINDOWPOSCHANGING data
In investigating `WM_WINDOWPOSCHANGING`, I built a table of some of the states I observed while receiving messages from an external caller that was using `::ShowWindow()`:
- integer - The value of the Show Window constant `SW_*` (see [ShowWindow](https://docs.microsoft.com/windows/win32/api/winuser/nf-winuser-showwindow))
- constant - The name of the Show Window constant
- flags - The `lParam` field is a pointer to a [**WINDOWPOS**](https://docs.microsoft.com/windows/win32/api/winuser/ns-winuser-windowpos) structure during this message. This the `UINT flags` field of that structure.
- Should Hide? - Whether or not I believe that the window should hide if this constant is seen. (Conversely, should show on the opposite.)
- minimizing - This is the `BOOL` response from a call to [**IsIconic()**](https://docs.microsoft.com/windows/win32/api/winuser/nf-winuser-isiconic) during this message.
- maximizing - This is the `BOOL` response from a call to [**IsZoomed()**](https://docs.microsoft.com/windows/win32/api/winuser/nf-winuser-iszoomed) during this message.
- showing - This is whether `SWP_SHOWWINDOW` is set on the `WINDOWPOS.flags` field during this message.
- hiding - This is whether `SWP_HIDEWINDOW` is set on the `WINDOWPOS.flags` field during this message.
- activating - This is the inverse of whether `SWP_NOACTIVATE` is set on the `WINDOWPOS.flags` field during this message.
- Remaining headings are `flags` values expanded to `X` is set and blank is unset. See [**SetWindowPos()**](https://docs.microsoft.com/windows/win32/api/winuser/nf-winuser-setwindowpos) for the definitions of all the flags.
From this data collection, I noticed a few things:
- The data in this table was unstable. The fields varied depending on the order in which I called the various constants against `ShowWindow()`. This is just one particular capture.
- Some of the states, I wouldn't see any message data at all (`SW_HIDE` and `SW_FORCEMINIMIZE`).
- There didn't seem to be a definitive way to use this data to reliably decide when to show or hide the window. I didn't have a reliable way of pulling this together with my *Should Hide?* column.
On further investigation, it became apparent that the values received were sometimes not coming through or varying because the `WS_VISIBLE` state of the `HWND` affected how `win32k` decided to dispatch messages and what values they contained. This is where I determined that steps #8-10 in the diagram above were going to be necessary: to report the state of the real window back to the *fake window* so it could report status to `user32` and `win32k` and receive state-appropriate messages.
For reporting back #8-10, I initially was going to use the `XTWINOPS` call with parameter `11`. The PTY could ask the attached terminal for its state and expect to hear back an answer of either `1` or `2` in the same format message depending on the state. However, on further consideration, I realized that the real window could change at a moments notice without prompting from the PTY, so I instead wrote the PTY to always listen for this and had the Windows Terminal send this back down unprompted.
#### Refined WM_SHOWWINDOW and WM_SIZE data
Upon setting up the synchronization for #8-10, I then tried again to build the table using just the two window messages that were giving me reliable data: `WM_SHOWWINDOW` and `WM_SIZE`:
|integer|constant|Should Hide?|`WM_SHOWWINDOW` OR `WM_SIZE` reported hide?|
|---|---|---|---|
|0|`SW_HIDE`|YES|YES|
|1|`SW_NORMAL`|NO|NO|
|2|`SW_SHOWMINIMIZED`|YES|YES|
|3|`SW_SHOWMAXIMIZED`|NO|NO|
|4|`SW_SHOWNOACTIVATE`|NO|NO|
|5|`SW_SHOW`|NO|NO|
|6|`SW_MINIMIZE`|YES|YES|
|7|`SW_SHOWMINNOACTIVE`|YES|YES|
|8|`SW_SHOWNA`|NO|NO|
|9|`SW_RESTORE`|NO|NO|
|10|`SW_SHOWDEFAULT`|NO|NO|
|11|`SW_FORCEMINIMIZE`|YES|YES|
Since this now matched up perfectly with what I was suspecting should happen *and* it was easier to implement than picking apart the `WM_WINDOWPOSCHANGING` message, it is what I believe the design should be.
Finally, with the *fake window* changing state to and from `WS_VISIBLE`... it was appearing on the screen and showing up in the taskbar and alt-tab. To resolve this, I utilized [**DWMWA_CLOAK**](https://docs.microsoft.com//windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute) which makes the window completely invisible even when in a normally `WS_VISIBLE` state. I then added the [**WS_EX_TOOLWINDOW**](https://docs.microsoft.com/windows/win32/winmsg/extended-window-styles) extended window style to hide it from alt-tab and taskbar.
With this setup, the PTY now has a completely invisible window with a synchronized `WS_VISIBLE` state with the real terminal window, a bidirectional signal channel to adjust the state between the terminal and PTY, and the ability to catch `user32` calls being made against the *fake window* that the PTY stands up for the client command-line application.
## UI/UX Design
The visible change in behavior is that a call to `::ShowWindow()` against the `::GetConsoleWindow()`
handle that is returned by the ConPTY will be propagated to the attached Terminal. As such, a
user will see the entire window be shown or hidden if one of the underlying attached
command-line applications requests a show or hide.
At the initial moment, the fact that the Terminal contains tabbed and/or paned sessions and
therefore multiple command-line clients on "different sessions" are attached to the same window
is partially ignored. If one attached client calls "show", the entire window will be shown with
all tabs. If another calls "hide", the entire window will be hidden including the other tab
that just requested a show. In the opposite direction, when the window is shown, all attached
PTYs for all tabs/panes will be alerted that they're now shown at once.
## Capabilities
### Accessibility
Users of assistive devices will have the same experience that they did with the legacy Windows
Console after this change. If a command-line application decides to show or hide the window
through the API without their consent, they will receive notification of the showing/hiding
window through our UIA framework.
Prior to this change, the window would have always remained visible and there would be no
action.
Overall, the experience will be consistent between what is happening on-screen and what is
presented through the UIA framework to assistive tools.
For third party terminals, it will be up to them to decide what their reaction and experience is.
### Security
We will maintain the security and integrity of the Terminal application chosen for presentation
by not revealing its true window handle information to the client process through the existing
`::GetConsoleWindow()` API. Through our design for default terminal applications, the final
presentation terminal could be Windows Terminal or it could be any third-party terminal that
meets the same specifications for communication. Giving raw access to its `HWND` to a client
application could disrupt its security.
By maintaining a level of separation with this feature by generating a "fake window" in the
ConPTY layer and only forwarding events, the attached terminal (whether ours or a 3rd party)
maintains the final level of control on whether or not it processes the message. This is
improved security over the legacy console host where the tool had full backdoor style access
to all `user32` based window APIs.
### Reliability
This test doesn't improve overall reliability in the system because utilities that are relying
on the behavior that this compatibility shim will restore are already introducing additional
layers of complexity and additional processes into their operation than were strictly necessary
simply by not stating their desires upfront at creation time.
In some capacity, you could argue it increases reliability of the existing tests that were
using this complex behavior in that they didn't work before and they will work now, but
the entire process is fragile. We're just restoring the fragile process instead of having
it not work at all.
### Compatibility
This change restores compatibility with existing applications that were relying on the behavior
we had excluded from our initial designs.
### Performance, Power, and Efficiency
The performance of tooling that is leveraging this process to create a console and then hide
or manipulate the session after the fact will be significantly worse when we enable the
default Windows Terminal than it was with the old Windows Console. This is because the
Terminal is significantly heavier weight (with its modern technologies like WinUI) and
will take more time to start and more committed memory. Additionally, more processes
will be in use because there will be the `conhost.exe` doing the ConPTY translation
and then the `windowsterminal.exe` doing the presentation.
However, this particular feature doesn't do anything to make that better or worse.
The appropriate solution for any tooling, test, or scenario that has a need for
performance and efficiency is to use the flags to `::CreateProcess` in the first place
to specify that they did not need a console window session at all, or to direct its
placement and visibility as a part of the creation call. We are working with
Microsoft's test automation tooling (TAEF) as well as the Windows performance
fundamentals (FUN) team to ensure that the test automation supports creating sessions
without a console window and that our internal performance test suite uses those
specifications on creation so we have accurate performance testing of the operating
system.
## Potential Issues
### Multiple clients sharing the same window host
With the initial design, multiple clients sharing the same window host will effectively
share the window state. Two different tabs or panes with two different client applications
could fight over the show/hide state of the window. In the initial revision, this is
ignored because this feature is being driven by a narrow failure scenario in the test gates.
In the reported scenario, a singular application is default-launched into a singular tab
in a terminal window and then the application expects to be able to hide it after the creation.
In the future, we may have to implement a conflict resolution or a graphical variance to
compensate for multiple tabs.
### Other verbs against the console window handle
This scenario initially focuses on just the `::ShowWindow()` call against the window handle
from `::GetConsoleWindow()`. Other functions from `user32` against the `HWND` will not
necessarily be captured and forwarded to the attached terminal application. And even more
specifically, we're focusing only on the Show and Hide state. Other state modifications that
are subtle related to z-ordering, activation, maximizing, snapping, and so on are not considered.
## Future considerations
### Multiple clients
If the multiple clients problem becomes more widespread, we may need to change the graphical
behavior of the Windows Terminal window to only hide certain tabs or panes when a command
comes in instead of hiding the entire window (unless of course there is only one tab/pane).
We may also need to adjust that once consensus is reached among tabs/panes that it can then
and only then propagate up to the entire window.
We will decide on this after we receive feedback that it is a necessary scenario. Otherwise,
we will hold for now.
### Other verbs
If it turns out that we discover tests/scenarios that need maximizing, activation, or other
properties of the `::ShowWindow()` call to be propagated to maintain compatibility, we will
be able to carry those through on the same channel and command. Most of them have an existing
equivalent in `XTWINOPS`. Those that do not, we would want to probably avoid as they will not
be implemented in any other terminal. We would extend the protocol as an absolute last resort
and only after receiving feedback from the greater worldwide terminal community.
### Z-ordering
The channel we're establishing here to communicate information about the window and its
placement may be useful for the z-ordering issues we have in #2988. In those scenarios,
a console client application is attempting to launch and position a window on top of the
terminal, wherever it is. Further synchronizing the state of the new fake-window in the
ConPTY with the real window on the terminal side may enable those tools to function as
they expect.
This is another circumstance we didn't expect: having command-line applications create windows
with a need for complex layout and ordering. These sorts of behaviors cannot be translated
to a universal language and will not be available off the singular machine, so encouraged
alternative methods like command-line based UI. However, for single-box scenarios, this
behavior is engrained in some Windows tooling due to its ease of use.
@@ -60,7 +60,7 @@ Users will be able to add a new setting to their font objects (added in [#10433]
There is one point to note here about clashing. For example, if a user has the old "weight" setting defined _as well as_ a "wght" axis defined, we will only use the "wght" axis value. We prioritize that value for a few reasons:
1. It is the more recent addition to our settings model. Thus, it is likely that a user that has defined both values probably just forgot to remove the old value.
2. It is the more precise value, it is a specific float value whereas the the old "weight" setting is an enum (that eventually gets mapped to a float value).
2. It is the more precise value, it is a specific float value whereas the old "weight" setting is an enum (that eventually gets mapped to a float value).
## Capabilities
@@ -74,7 +74,7 @@ Should not affect security.
### Reliability
Aside from additional parsing required for the settings file (which inherently offers more locations for parsing to fail), we need to be careful about badly formed/non-existant feature tags or axes specified in the user-defined dictionaries. We must make sure to ignore such declarations (perhaps alongside emitting a warning to the user) and only apply those that are correctly formed and exist.
Aside from additional parsing required for the settings file (which inherently offers more locations for parsing to fail), we need to be careful about badly formed/nonexistent feature tags or axes specified in the user-defined dictionaries. We must make sure to ignore such declarations (perhaps alongside emitting a warning to the user) and only apply those that are correctly formed and exist.
The idea is for Windows Terminal to change automatically its color schemes according to what theme is selected, including the case where `system` theme is selected.
## Inspiration
I work remotely as a developer, so I have to spend a lot of hours in front of my PC screen. In my setup, right behind my desk I have a window, which is the only source of natural sunlight in my room.
Normally I like dark modes in all the programs and apps I use, but when there's too much sunlight, it becomes annoying, and sometimes even painful, to work in dark mode. So, I have all the programs and apps I use (at least, those that can) set to switch their color themes to what the system has.
The company I work for sent me a Macbook Pro, and my personal phone is an Android, both with automatic dark mode at sunset and light mode at sunrise, and in those devices it's been working relatively well. In Windows, as it is known, there's no such feature, so I manually change between dark and light mode when it's needed, and most of the programs and apps I use go along with this change. Windows Terminal, is not one of them.
The theme changes just as expected, but in an app like this, this change only affects the top of the window, leaving almost all of the screen at the mercy of what the color scheme is, and it doesn't depend on the theme, which defeats any attempt to make a good use of the `system` theme feature.
## Solution Design
Could be implemented in the form of:
```json
"colorScheme":{
"light":"BlulocoLight",
"dark":"BlulocoDark"
}
```
or:
```json
"colorSchemeLight":"BlulocoLight",
"colorSchemeDark":"BlulocoDark"
```
## UI/UX Design
In a first version it could look like the terminal in Visual Studio Code, and an improvement could be to have light mode specific color schemes, just like those already present in Windows terminal. A good idea could be to get an inspiration in Dark++ and Light++ VSCode color themes.
A user could benefit from a more healthy light level contrast between the screen their looking at and the environment they are, reducing the risk of headache or developing/intensifying eye problems, and any other related eye conditions. Plus, it adds to a more consistent experience between different programs and apps, and the system itself.
## Capabilities
### Accessibility
This feature improves accessibility more than any other capability, because the key is to be able to read and see anything better when the environment, both the external to the device, and the device's system itself, is in a certain mode (dark/light).
### Security
The proposed solution is based in the current way one sets Windows Terminal settings, so it isn't expected to add any security issues.
### Reliability
Adding this feature would make Windows Terminal more reliable when it's expected that it changes it's visual theme/color scheme along with the whole system.
### Compatibility
The solution is not expected to break anything.
### Performance, Power, and Efficiency
It might increase the energy spent in the cases where people who were used to use the terminal in regular dark color schemes start using more light color schemes, but that is the case for any other program that shows lighter colors and I don't think the increment would be as high as to be even considered a downside.
## Potential Issues
Some users might not like the change in color schemes or be too used to the terminal being dark, but this may be avoided making the current schemes a default and adding this solution as an alternative setting.
## Future considerations
This solution might bring more attention to the color schemes setting, even more when considering light mode specific color schemes
## Resources
Inspired by what's been said in the issue comments. Credits to them.
Since the beginning, Windows has offered a single choice in default terminal hosting behavior. Specifically, the default terminal is defined as the one that the operating system will start on your behalf when a command-line application is started without a terminal attached. This specification intends to detail how we will offer customers the ultimate in choice among first and third party replacements for their default terminal experience.
## Inspiration
We've had a lot of success in the past several years on our terminal team journey. We updated the old console host user interface with long-desired features. We updated the console environment to bring Windows closer to Linux and Mac by implementing the client (receiving) end of Virtual Terminal sequences to unlock WSL, Docker, and other cross-platform command-line application compatibility. We then created the ConPTY to expose the server end of the console environment to first and third party applications to enable the hosting of any of those command-line clients within their own user interfaces by implementing the server (sending) end of Virtual Terminal sequences. And then we built Windows Terminal as our flagship implementation of the development environment on this model.
Through all of this, the entrypoint for alternatives to the console host UX continued to be "Start your alternative terminal implementation first, then start the command-line application inside." For those familiar with Linux and Mac or for those using the broad ecosystem of alternative Windows Terminals like ConEmu, Cmder, Console2, and the like... that was natural. But Windows did it differently a long time ago allowing the starting of a command-line application directly from the shell or kernel without a terminal specified. On noticing the missing terminal, the system would just-in-time start and attach the one terminal it could count on as always present, `conhost.exe`.
And so the inspiration of this is simple: We want to allow our customers to choose whichever terminal they want as the just-in-time terminal attached to an application without one present/specified on launch. This final move completes our journey to allow the ultimate in choice AND decouple the terminal experience from the operating system release schedule.
## Solution Design
There are three components to the proposed design:
1.**Inbox console**: This is the `conhost.exe` that is resident inside every Windows installation.
1.**Updated console**: This is the `openconsole.exe` that we ship with the Windows Terminal to provide a more up-to-date console server experience.
1.**Terminal UX**: This is `WindowsTerminal.exe`, the new Terminal user interface that runs on VT sequences.
And there are a few scenarios here to consider:
1. Replacement console API server and replacement terminal UX.
1. This is the Windows Terminal scenario today. `OpenConsole.exe` is packed in the package to be the console API server and ConPTY environment for `WindowsTerminal.exe`.
1. Replacement console API server and legacy terminal UX.
1. We don't explicitly distribute this today, but it's technically possible to just run `OpenConsole.exe` to accomplish this.
1. Inbox console API server and replacement terminal UX.
1. The WSL environment does this when doing Windows interop and I believe VS Code does this too when told to use the ConPTY environment. (And since VS Code does it, anything using node-pty also does it, covering some 3rd party terminals as well).
1. Inbox console API server and inbox terminal UX.
1. This is what we have today in `conhost.exe` running as the default application.
The goal is to offer the ultimate in choice here where any of the components can be replaced as necessary for a 1st or 3rd party scenario.
### Overview
#### Inbox console
The inbox console will be updated to support delegation of the incoming console client application connection to another console API server if one is registered and available.
We leave the inbox console in-place and always available on the operating system for these reasons:
1. A last chance fall-back should any of the delegation operations fail
1. An ongoing host for applications that aren't going to need a window at all
1. Continued support of our legacy `conhostv1.dll` environment, if chosen
The general operation is as follows:
- A command-line client application is started (from the start menu, run box, or any other `CreateProcess` or `ShellExecute` route) without an existing console server attached
- The inbox console is launched from `C:\windows\system32\conhost.exe` as always by the initialization routines inside `kernelbase.dll`.
- The inbox console accepts the incoming initial connection and looks for the `ShowWindow` information on the connection packet, as received from the kernel's process creation routines based on the parameters given to the `CreateProcess` call. (See [CREATE_NO_WINDOW](https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags) flag for details.)
- If the session is about to create a window, check for registration of a delegated/updated console and hand-off to it if it exists.
- Otherwise, start normally.
This workflow affords us several benefits:
- The only inbox component we have to change is `conhost.exe`, the one we already regularly update from open source on a regular basis. There is no change to the `kernelbase.dll` console initialization routines, `conclnt.lib` communication protocol, nor the `condrv.sys` driver.
- We should be able to make this change quickly, relatively easily, and the code delta should be relatively small
- This makes it easy to squeeze in early in the development of the solution and get it into the Windows OS product as soon as possible for self-hosting, validation, and potentially shipping in the OS before the remainder of the solution has shaken out
- This also makes it potentially possible to backport this portion of the code change to popular in-market versions of Windows 10. For instance, WSL2 has just backported to 1903 and 1909. The less churn and risk, the easier it is to sell a backport.
*Potential future:*
- ~~If no updated console exists, potentially check for registration of a terminal UX that is willing to use the inbox ConPTY bits, start it, and transition to being a PTY instead.~~
- **CUT FROM v1**: To simplify the story for end-users, we're offering this as a package deal in the first revision. Explaining the difference between consoles and terminals to end users is very difficult.
The registration would operate as follows:
- A registry key in `HKCU\Console\%%Startup` (format `REG_SZ`, name `DelegationConsole`) would specify ~~the path to ~~the replacement console that would be used to service the remainder of the connection process.
- Alternatively or additionally, this same `REG_SZ` could list a COM server ID that could be looked up in the classes root and invoked. **V1 NOTE:** This was what was done.
- Packaged applications and classic applications can easily register a COM server
- WinRT libraries should be able to be easily registered as the COM server as well (given WinRT is COM underneath)
- WinRT cannot be exposed outside of the package context itself, so the `conhost.exe` that is in the OS and is naturally outside the package cannot find it.
- **V1 NOTE:** The subkey `%%Startup` was chosen to separate these keys (this one and the `DelegationTerminal` one below) in case we needed to ACL them or protect them in some way. We want a per-user choice of which Terminal/Console are used, but we might need to take action to prevent these keys from being slammed at some point in the future. Why `%%`? The subkeys are traditionally used to resolve paths to client binaries that have their own console preferences set. The `%%` should never be resolvable as it won't lead to a valid path or expanded path variable.
The delegation process would operate as follows:
- A method contract is established between the existing inbox console and any updated console (an interface).
-`HANDLE server`: This is the server side handle to the console driver, used with `DeviceIoControl` to receive/send messages with the client command-line application
-`HANDLE driverInputEvent`: The input event is created and assigned to the driver immediately on first connection, before any messages are read from the driver, to ensure that it can track a blocking state should first message be an input request that we do not yet have data to fill. As such, the inbox console will have created this and assigned it to the driver before pulling off the connection packet and determining that it wants to delegate. Therefore, we will transfer ownership of this event to the updated console.
- ~~`const PortableArguments* const args`: This contains the startup argument information that was passed in when the process was started including the original command line and the in/out handles.~~
- ~~The `ConsoleArguments` structure could technically change between versions, so we will make a version agnostic portable structure that just carries the communication from the old one to the new one.~~
- **CUT FROM V1**: The only arguments coming in from a default light-up are the server handle. Pretty much all the other arguments are related to the operation of the PTY. Since this feature is about "default application" launches where no arguments are specified, this was cut from the initial revision.
-`const PortableConnectMessage* const msg`:
- The `CONSOLE_API_MSG` structure contains both the actual packet data from the driver as well as some overhead/administration data related to the packet state, ordering, completion, errors, and buffers. It's a broad scope structure for every type of message we process and it can change over time as we improve the way the `conserver.lib` handles packets.
- This represents a version agnostic variant for ONLY the connect message that can pass along the initial connect information structure, the packet sequencing information, and other relevant payload only to that one message type. It will purposefully discard references to things like a specific set of API servicing routines because the point of handing off is to get updated routines, if necessary.
- **V1 NOTE:** This was named `CONSOLE_PORTABLE_ATTACH_MSG`
-`HANDLE signalPipe`: During authoring, it was identified that <kbd>Ctrl+C</kbd> and other similar signals need to make it back to the original `conhost.exe` application as the Operating System grants it special privilege over the originally attached client application. This privilege cannot be transferred to the delegated console. So this channel remains for the delegated one to send its signals back through the original one for commanding the underlying client. (This also implies the original `conhost.exe` inbox cannot close and must remain a part of the process tree for the life of the session to maintain this control.)
-`HANDLE inboxProcess`: Since we have to keep the inbox `conhost.exe` running for signal/ownership reasons, we also need to track its lifetime. If it disappears for whatever reason, we need to tear down the entire chain as part of our operation has been compromised.
-`HANDLE* process`: On the contrary to `inboxProcess`, we need to give our process handle back so it can also be tracked. After the inbox console delegates, it remains in a very limited capacity. If the delegation one disappears, the session will no longer function and needs to be torn down (and the client closed).
- *Return* `HRESULT`: This is one of the older style methods in the initialization. We moved them from mostly `NTSTATUS` to mostly `HRESULT` a while ago to take advantage of `wil`. This one will continue to follow the pattern and not move to exceptions. A return of `S_OK` will symbolize that the handoff worked and the inbox console can clean itself up and stop handling the session.
- When the connection packet is parsed for visibility information (see `srvinit.cpp`), we will attempt to resolve the registered handoff and call it.
- ~~In the initial revision here, I have this as a `LoadLibrary`/`GetProcAddress` to the above exported contract method from the updated console. This maintains the server session in the same process space and avoids:~~
1.~~The issue of passing the server, event, and other handles into another process space. We're not entirely sure if the console driver will happily accept these things moving to a different process. It probably should, but unconfirmed.~~
1.~~Some command-line client applications rely on spelunking the process tree to figure out who is their servicing application. Maintaining the delegated/updated console inside the same process space maintains some level of continuity for these sorts of applications.~~
- **Alternative:** We may make this just be a COM server/client contract. ~~An in-proc COM server should operate in much the same fashion here (loading the DLL into the process and running particular method) while being significantly more formal and customizable (version revisions, moving to out-of-proc, not really needing to know the binary path because the catalog knows).~~
- **V1 NOTE:** We landed on an out-of-proc COM server/client here. This maintains the isolation of the newly running code from the old code. Since we're maintaining the original `conhost.exe` for signaling purposes, we're no longer worried about the spelunking the process tree and not having the relationship for clients to find.
- **Not considering:** ~~WinRT. `conhost.exe` has no WinRT. Adding WinRT to it would significantly increase the complexity of compilation in the inbox and out of box code base. It would also significantly increase the compilation time, binary size, library link list, etc... unless we use just the ABI to access it. But I don't see an advantage to that over just using classic COM at that point. This is only one handoff method and a rather simplistic one at that. Every benefit WinRT provides is outweighed by the extra effort that would be required over just a classic COM server in this case.~~
- After delegation is complete, the inbox console will have to clean up any threads, handles, and state related to the session. We do a fairly good job with this normally, but some portions of the `conhost.exe` codebase are reliant on the process exiting for final cleanup. There may be a bit of extra effort to do some explicit cleanup here.
- **V1 NOTE:** The inbox one cleans up everything it can and sits in a state waiting for the child/delegated process handle to exit. It also maintains a thread listening for the signals to come through in case it needs to send a command to the client application using the privilege granted to it by the driver.
#### Updated console
The updated replacement console will have the same console API server capabilities as the inbox console, but will be a later, updated, or customized-to-the-scenario version of the API server generally revolving around improving ConPTY support for a Terminal application.
On receiving the handoff from the method signature listed above, the updated console will:
- Establish its own set of IO threading, device communication infrastructure, and API messaging routines while storing the handles given
- ~~Re-parse the command line arguments, if necessary, and store them for guiding the remainder of launch~~
- Dispatch the attach message as if it were received normally
- Continue execution from there
There will then either be a registration for a Terminal UX to take over the session by using ConPTY, ~~or the updated console will choose to launch its potentially updated version of the `conhost` UX~~.
For registration, we repeat the dance above with another key:
- A registry key in `HKCU\Console\%%Startup` (format `REG_SZ`, name `DelegationTerminal`).
The delegation repeats the same dance as above as well:
- A contract (interface) is established between the updated console and the terminal
-`HANDLE in`: The handle to read client application output from the ConPTY and display on the Terminal
-`HANDLE out`: The handle to write user input from the Terminal to the ConPTY
-`HANDLE signal`: The signal handle for the ConPTY for out-of-band communication between PTY server and Terminal application
- ~~`COORD size`: The initial window size from the starting application, as it can be a preference in the connection structure. (A resize message may get sent back downward almost immediately from the Terminal as its dimensions could be different.)~~ **V1 NOTE:** This proved unnecessary as the resize operations sorted themselves out naturally.
-`HANDLE ref`: This is a "client reference handle" to the console driver and session. We hold onto a copy of this in the Terminal so the session will stay alive until we let go. (The other console hosts in the chain also hold one of these, as should the client.)
-`HANDLE server`: This is a process handle to the PTY we're attached to. We monitor this to know when the PTY is still alive from the Terminal side.
-`HANDLE client`: This is a process handle to the underlying client application. The terminal tracks this for exit handling.
- **Alternative:** This should likely just be a COM server/client contract as well. This would be consistent with the above and wouldn't require argument parsing or wink/nudge understanding of standard handle passing. It also conveys the same COM flexibility as described in the inbox console section. **V1 NOTE:** We used this alternative. We used COM, not a well-known exported function from the prototype.
- The contract is called and on success, responsibility of the UX is given over to the Terminal. The console sits in PTY mode.
- On failure, the console launches interactive.
#### Terminal UX
The terminal will be its own complete presentation and input solution on top of a ConPTY connection, separating the concerns between API servicing and the user experience.
Today the Terminal knows how to start and then launches a ConPTY under it. The Terminal will need to be updated to accept a preexisting ConPTY connection on launch (or when the multi-process model arrives, as an inbound connection), and connect that to a new tab/pane instead of using the `winconpty.lib` libraries to make its own.
For now, I'm considering only the fresh-start scenario.
- The Terminal will have to detect the inbound connection through ~~its argument parsing (or through~~ a new entrypoint in the COM alternative ~~)~~ and store the PTY in/out/signal handles for that connection in the startup arguments information
- When the control is instantiated on a new tab, that initial creation where normally the "default profile" is launched will instead have to place the PTY in/out/signal handles already received into the `ConPtyConnection` object and use that as if it was already created.
- The Terminal can then let things run normally and the connection will come through and be hosted inside the session.
There are several issues/concerns:
- Which profile/settings get loaded? We don't really know anything about the client that is coming in already-established. That makes it difficult to know what user preferences to apply to the inbound tab. We could:
- Use only the defaults for the incoming connection. Do not apply any profile-specific settings.
- Use the profile information from the default profile to some degree. This could cause some weird scenarios/mismatches if that profile has a particular icon or a color scheme that makes it recognizable to the user.
- Create some sort of "inbound profile" profile that is used for incoming connections
- Add a heuristic that attempts to match the name/path of the connecting client binary to a profile that exists and use those settings, falling back if one is not found.
- **Proposal:** Do the first one immediately for bootstrapping, then investigate the others as a revision going forward.
- The handles that are coming in are "raw" and "unpacked", not in the nice opaque `HPCON` structure that is usually provided to the `ConPtyConnection` object by the `winconpty.lib`.
- Add methods to `winconpty.lib` that allow for the packing of incoming raw handles into the `HPCON` structure so the rest of the lifetime can be treated the same
- Put the entrypoint for the COM server (or delegate the entrypoint for an argument) directly into this library so it can pack them up right away and hand of a ready-made `HPCON`.
## UI/UX Design
The user experience for this feature overall should be:
1. The user launches a command-line client application through the Start Menu, Win+X menu, the Windows Explorer, the Run Dialog box (WinKey+R), or through another existing Windows application.
1. Using the established settings, the console system transparently starts, delegates itself to the updated console, switches itself into ConPTY mode, and a copy of Windows Terminal launches with the first tab open to host the command-line client application.
- **NOTE:** I'm not precluding 3rd party registrations of either the delegation updated console nor the delegation terminal. It is our intention to allow either or both of these pieces to be replaced to the user's desires. The example is for brevity of our golden path and motivation for this scenario.
1. The user is able to interact with the command-line client application as they would with the original console host.
- The user receives the additional benefit that short-running executions of a command-line application may not "blink in and disappear" as they do today when a user runs something like `ipconfig` from the run dialog. The Terminal's default states tend to leave the tab open and say that the client has exited. This would allow a Run Dialog `ipconfig` user an improved experience over the default console host state of disappearing quickly.
1. If any portion of the delegation fails, we will progressively degrade back to a `conhost` style Win32+GDI UX and nothing will be different from before.
The settings experience includes:
- Configuration of the delegation operations:
- Locations:
- With the registry
- This is what's going to be available first and will remain available. We will progress to some or all of the below after.
- We will need to potentially add specifications to this to both the default profile (for new installations of Windows) or to upgrade/migration profiles (for users coming from previous editions of Windows) to enable the delegation process, especially if we put a copy of Windows Terminal directly into the box.
- **V1 NOTE:** we didn't add additional migration logic here as `HKCU\Console*` and subkeys were already in the migration logic, so adding another should just carry along.
- Inside Windows Terminal
- Inside the new Settings UI, we will likely need a page that configures the delegation keys in `HKCU\Console\%%Startup`~~or a link out to the Windows Settings panel, should we manage to get the settings configurable there~~.
- Inside the console property sheet
- Same as for Terminal but with `comctl` controls over XAML +/- a link to the Windows Settings panel
- Inside the Settings panel for Windows (probably on the developer settings page)
- The ultimate location for this is likely a panel directly inside Windows. This is the hardest one to accomplish because of the timelines of the Windows product. We may not get this in an initial revision, but it should likely be our ultimate goal. **V1 NOTE:** We did it!
- Operation:
- Specify paths/server IDs - This is the initial revision
- Offer a list of registered servers or discovered manifests from the app catalog - This is the ideal scenario where we search the installed app catalog +/- the COM catalog and offer a list of apps that conform to the contract in a drop-down.
- The final process was to use [App Extensions](https://docs.microsoft.com/windows/uwp/launch-resume/how-to-create-an-extension) inside the Terminal APPX package to declare the COM GUIDs that were available for the `DelegationConsole` and `DelegationTerminal` fields respectively. A configuration class `DelegationConfig` was added to `propslib.lib` that enables the lookup of these from the application state catalog and presents a list of them to choose from. It also manages reading and writing the registry keys.
- **V1 NOTE:** Our configuration options currently allow pairings of replacement consoles and terminals to be adjusted in lock-step from the UI. That's not to say further combinations are not possible or even necessarily inhibited by the code. We just went for minimal confusion in our first round.
- Configuration of the legacy console state:
- ~~Since we could end up in an experience where the default launch experience gets you directly into Windows Terminal, we believe that the Terminal will likely need an additional setting or settings in the new Settings UI that will allow the toggling of some of the `HKCU\Console` values to do things like set/remove the legacy console state.~~ **V1 NOTE:** Cut as low priority. Switch back to console and configure it that way or use the existing property sheet or tamper with registry keys.
- We have left the per-launch debugging and advanced access hole of calling something like `conhost.exe cmd.exe` which will use the inbox conhost to launch `cmd.exe` even if there is a default specified.
Concerns:
- State separation policy for Windows. I believe `HKCU\Console` is already specified as a part of the "user state" that should be mutable and carried forward on OS Swap, especially as we have been improving the OS swap experience.
- Ability for installers/elevated scripts to stomp the Delegation keys
- This was a long time problem for default app registrations and was limited in our OS. Are we about to run down the same path?
- What is the alternative here? To use a protocol handler? To store this configuration state data with other protected state in a registry area that is mutable, but only ACL'd to the `SYSTEM` user like some other things in the Settings control panel?
- **V1 NOTE:** We set ourselves up for some future ACL thing with the subkey, but we otherwise haven't enforced anything at this time.
## Capabilities
### Accessibility
Accessibility applications are the most likely to resort to a method of spelunking the process tree or window handles to attempt to find content to read out. Presuming they have hardcoded rules for console-type applications, these algorithms could be surprised by the substitution of another terminal environment.
The major players here that I am considering are NVDA, JAWS, and Narrator. As far as I am aware, all of these applications attempt to drive their interactivity through UI Automation where possible. And we have worked with all of these applications in the past in improving their support for both `conhost.exe` and the Windows Terminal product. I have relatively high confidence that we will be able to work with them again to help update these assistive products to understand the new UI delegation, if necessary.
### Security
Let's hit the elephant in the room. "You plan on pulling a completely different binary inside the `conhost.exe` process and just... delegating all activity to it?" Yes.
(**V1 NOTE:** Well, it's out of proc now. But it is at the same privilege level as the original one thanks to the mechanics of COM.)
As far as I'm concerned, the `conhost.exe` that is started to host the command-line client application is running at the same integrity level as the client binary that is partially started and waiting for its server to be ready. This is the long-standing existing protection that we have from the Windows operating system. Anything running in the same integrity level is already expected to be able to tamper with anything else at the same integrity level. The delegated binary that we would be loading into our process space will also be at the same integrity level. Nothing really stops a malicious actor from launching that binary in any other way in the same integrity level as a part of the command-line client application's startup.
The mitigation here, if necessary, would be to use `WinVerifyTrust` to validate the certification path of the `OpenConsole.exe` binary to ensure that only one that is signed by Microsoft can be the substitute server host for the application. This doesn't stop third parties from redistributing our `OpenConsole.exe` off of GitHub if necessary with their products, but it would stop someone from introducing any random binary that met the signature interface of the delegation methods into `conhost.exe`. The only value I see this providing is stopping someone from being "tricked" into delegating their `conhost.exe` to another binary through the configuration methods we provide. It doesn't really stop someone (or an attacker) from taking ownership of the `conhost.exe` in System32 and replacing it directly. So this point might be moot. (It is expected that replacement of the System32 one is already protected, to some degree, by being owned by the SYSTEM account and requiring some measure of authority to replace.)
### Reliability
The change on its own may honestly improve reliability of the hosting system. The existing just-in-time startup of the console host application only had a single chance at initializing a user experience before it would give up and return that the command-line application could not be started.
However, there are now several phases in the startup process that will have the opportunity to make multiple attempts at multiple versions or applications to find a suitable host for the starting application before giving up.
One layer of this is where the `conhost.exe` baked into the operating system will be on the lookout for an `OpenConsole.exe` that will replace its server activities. The delegation binary loses a bit of reliability, theoretically, by the fact that loading another process during launch could have versioning/resolution/path/dependency issues, but it simultaneously offers us the opportunity for improved reliability by being able to service that binary quickly outside the Windows OS release cycle. Fixes can arrive in days instead of months to years.
Another layer of this is where either `conhost.exe` or the delegated `OpenConsole.exe` server will search for a terminal user experience host, like `WindowsTerminal.exe` or another registered first or third party host, and split the responsibility of hosting the session with that binary. Again, there's a theoretical reliability loss with the additional process launch/load, but there's much to be gained by reducing the scope of what each binary must accomplish. Removing the need to handle user interaction from `conhost.exe` or `OpenConsole.exe` and delegating those activities means there is less surface area running and less chance for a UX interaction to interfere with API call servicing and vice versa. And again, having the delegation to external components means that they can be fixed on a timeline of days instead of months or years as when baked into the operating system.
### Compatibility
One particular scenario that this could break is an application that makes use of spelunking the process tree when a command-line application starts to identify the hosting terminal application window by HWND to inject input, extract output, or otherwise hook and bind to hosting services. As the default application UI that will launch may not have the `conhost.exe` name (for spelunking via searching processes) and the HWND located may either be the ConPTY fake HWND or an HWND belonging to a completely different UI, these applications might not work.
Two considerations here:
1. At a minimum, we must offer an opt-out of the delegation to another terminal for the default application.
1. We may also want to offer a process-name, policy, manifest, or other per client application opt-out mechanism.
**V1 NOTE:** There is no per-client specific way of doing this. The toggle is per-user and can be adjusted in 3 different places.
### Performance, Power, and Efficiency
I expect to take some degree of performance, power, and efficiency hit by implementing this replacement default app scenario just by it's nature. We will be loading multiple processes, performing tests and branches during startup, and we will likely need to load COM/WinRT and packaging data that was not loaded prior to resolve the final state of default application load. I would expect this to accrue to some failures in the performance and power gates inside the Windows product. Additionally, the efficiency of running pretty much everything through the ConPTY is lower than just rendering it directly to `conhost.exe`'s embedded GDI-powered UI itself thanks to the multiple levels of translation and parsing that occur in this scenario.
The mitigations to these losses are as follows:
1. We will delay load any of the interface load and packaging data lookup libraries to only be pulled into process space should we determine that the application is non-interactive.
1. That should save us some of the commit and power costs for the sorts of non-interactive scripts and applications that typically run early in OS startup (and leverage `conhost.exe` as their host environment).
1. We will still likely get hit with the on-disk commit cost for the additional export libraries linked as well as additional code. That would be a by-design change.
1. We plan to begin Profile Guided Optimization across our `OpenConsole.exe` and `WindowsTerminal.exe` binaries. This should allow us to optimize the startup paths for this scenario and bias the `OpenConsole.exe` binary that we redistribute to focus its efforts and efficiency on the ConPTY role specifically, ignoring all of the interactive Win32/GDI portions that aren't typically used.
1. We may need to add a PGO scenario inside Windows to tune the optimization of `conhost.exe` especially if we're going to go full on Windows Terminal in the box default application. The existing PGO that occurs in the optimization branches is running on several `conhost.exe` interactive scenarios, none of which will be relevant here. We would probably want to update it to focus on the default app delegation routine AND on the non-interactive scenario for hosted applications (where delegation will not occur but Win32/GDI will still not be involved).
## Potential Issues
### Passing Handles with COM
COM doesn't inherently expose a way for us to pass handles directly between processes with the existing contracts. We know this is possible because Windows does it all the time, but it doesn't appear to be public. We believe the mission forward is to expose this functionality to the public as if it's good enough for us internally and it is a requirement to build complex functionality like this... then it should be good enough for the public.
**V1 NOTE:** We gained approval to open this up and documented it. [`system_handle` attribute](https://docs.microsoft.com/windows/win32/midl/system-handle). It didn't require any code changes because the public IDL compiler already recognized the existence of this attribute and did the correct thing. It just wasn't documented for use.
## Future considerations
* We additionally would like to leave the door open to distributing updated `OpenConsole.exe`s in their own app package as a dependency that others could rely on.
* This was one of the original management requests when we were opening the source of the console product as well as the Terminal back in spring of 2019. For the sake of ongoing servicing and maintainability, it was requested that we reach a point where our dependencies could be serviced potentially independently of the product as a whole static unit. We didn't achieve that goal initially, but this design would enable us to do something like this.
* One negative to this scenario is that dependency resolution and the installation of dependent packages through APPX is currently lacking in several ways. It's difficult/impossible to do in environments where the store or the internet is unavailable. And it's a problem often enough that the Windows Terminal package embeds the VC runtimes inside itself instead of relying on the dependency resolution of the app platform.
## Resources
- [Windows Terminal Process Model 2.0 spec](https://github.com/microsoft/terminal/pull/7240)
- [Windows Terminal 2.0 Process Model Improvements](https://github.com/microsoft/terminal/issues/5000)
This spec describes a new set of key bindings that allows the user to create and update a selection without the use of a mouse or stylus.
## Inspiration
ConHost allows the user to modify a selection using the keyboard. Holding `Shift` allows the user to move the second selection endpoint in accordance with the arrow keys. The selection endpoint updates by one cell per key event, allowing the user to refine the selected region.
### Creating a selection
Mark Mode is a ConHost feature that allows the user to create a selection using only the keyboard. In CMD, pressing <kbd>ctrl+m</kbd> enters mark mode. The current cursor position becomes a selection endpoint. The user can use the arrow keys to move that endpoint. While the user then holds <kbd>shift</kbd>, the selection endpoint ('start') is anchored to it's current position, and the arrow keys move the other selection endpoint ('end').
Additionally, pressing <kbd>shift+arrow</kbd> also initiates a selection, but it anchors the first selection endpoint to the cursor position.
Other terminal emulators have different approaches to this feature. iTerm2, for example, has Copy Mode (documentation [linked here](https://iterm2.com/documentation-copymode.html)). Here, <kbd>cmd+shift+c</kbd> makes the current cursor position become a selection endpoint. The arrow keys can be used to move that endpoint. However, unlike Mark Mode, a key binding <kbd>c+space</kbd> is used to change the start/stop selecting. The first time it's pressed, the 'start' endpoint is anchored. The second time it's pressed, the 'end' endpoint is set. After this, you can still move a cursor, but the selection persists until a new selection is created (either by pressing the key binding again, or using the mouse).
Though tmux is not a terminal emulator, it does also have Copy Mode that behaves fairly similarly to that of iTerm2's.
## Solution Design
The fundamental solution design for keyboard selection is that the responsibilities between the Terminal Control and Terminal Core must be very distinct. The Terminal Control is responsible for handling user interaction and directing the Terminal Core to update the selection. The Terminal Core will need to update the selection according to the direction of the Terminal Control. Terminal Core maintains the state of the selection.
Relatively recently, TerminalControl was split into `TerminalControl`, `ControlInteractivity`, and `ControlCore`. Changes made to `ControlInteractivity`, `ControlCore`, and below propagate functionality to all consumers, meaning that the WPF terminal would benefit from these changes with no additional work required.
### Fundamental Terminal Control Changes
`ControlCore::TrySendKeyEvent()` is responsible for handling the key events after key bindings are dealt with in `TermControl`. At the time of writing this spec, there are 2 cases handled in this order:
- Clear the selection (except in a few key scenarios)
- Send Key Event
The first branch will be updated to _modify_ the selection instead of usually _clearing_ it. This will happen by converting the key event into parameters to forward to `TerminalCore`, which then updates the selection appropriately.
#### Abandoned Idea: Make keyboard selection a collection of standard keybindings
One idea is to introduce an `updateSelection` action that conditionally works if a selection is active (similar to the `copy` action). For these key bindings, if there is no selection, the key events are forwarded to the application.
Thanks to Keybinding Args, there would only be 1 new command:
| Action | Keybinding Args | Description |
|--|--|--|
| `updateSelection` | | If a selection exists, moves the last selection endpoint. |
| | `Enum direction { up, down, left, right }` | The direction the selection will be moved in. |
| | `Enum mode { char, word, view, buffer }` | The context for which to move the selection endpoint to. (defaults to `char`) |
By default, the following keybindings will be set:
These are in accordance with ConHost's keyboard selection model.
This idea was abandoned due to several reasons:
1. Keyboard selection should be a standard way to interact with a terminal across all consumers (i.e. WPF control, etc.)
2. There isn't really another set of key bindings that makes sense for this. We already hardcoded <kbd>ESC</kbd> as a way to clear the selection. This is just an extension of that.
3. Adding 12 conditionally effective key bindings takes the spot of 12 potential non-conditional key bindings. It would be nice if a different key binding could be set when the selection is not active, but that makes the settings design much more complicated.
4. 12 new items in the command palette is also pretty excessive.
5. If proven wrong when this is in WT Preview, we can revisit this and make them customizable then. It's better to add the ability to customize it later than take it away.
#### Abandoned Idea: Make keyboard selection a simulation of mouse selection
It may seem that some effort can be saved by making the keyboard selection act as a simulation of mouse selection. There is a union of mouse and keyboard activity that can be represented in a single set of selection motion interfaces that are commanded by the TermControl's Mouse/Keyboard handler and adapted into appropriate motions in the Terminal Core.
However, the mouse handler operates by translating a pixel coordinate on the screen to a text buffer coordinate. This would have to be rewritten and the approach was deemed unworthy.
### Fundamental Terminal Core Changes
The Terminal Core will need to expose a `UpdateSelection()` function that is called by the keybinding handler. The following parameters will need to be passed in:
-`enum SelectionDirection`: the direction that the selection endpoint will attempt to move to. Possible values include `Up`, `Down`, `Left`, and `Right`.
-`enum SelectionExpansion`: the selection expansion mode that the selection endpoint will adhere to. Possible values include `Char`, `Word`, `View`, `Buffer`.
#### Moving by Cell
For `SelectionExpansion = Char`, the selection endpoint will be updated according to the buffer's output pattern. For **horizontal movements**, the selection endpoint will attempt to move left or right. If a viewport boundary is hit, the endpoint will wrap appropriately (i.e.: hitting the left boundary moves it to the last cell of the line above it).
For **vertical movements**, the selection endpoint will attempt to move up or down. If a **viewport boundary** is hit and there is a scroll buffer, the endpoint will move and scroll accordingly by a line.
If a **buffer boundary** is hit, the endpoint will not move. In this case, however, the event will still be considered handled.
**NOTE**: An important thing to handle properly in all cases is wide glyphs. The user should not be allowed to select a portion of a wide glyph; it should be all or none of it. When calling `_ExpandWideGlyphSelection` functions, the result must be saved to the endpoint.
#### Moving by Word
For `SelectionExpansion = Word`, the selection endpoint will also be updated according to the buffer's output pattern, as above. However, the selection will be updated in accordance with "chunk selection" (performing a double-click and dragging the mouse to expand the selection). For **horizontal movements**, the selection endpoint will be updated according to the `_ExpandDoubleClickSelection` functions. The result must be saved to the endpoint. As before, if a boundary is hit, the endpoint will wrap appropriately. See [Future Considerations](#FutureConsiderations) for how this will interact with line wrapping.
For **vertical movements**, the movement is a little more complicated than before. The selection will still respond to buffer and viewport boundaries as before. If the user is trying to move up, the selection endpoint will attempt to move up by one line, then selection will be expanded leftwards. Alternatively, if the user is trying to move down, the selection endpoint will attempt to move down by one line, then the selection will be expanded rightwards.
#### Moving by Viewport
For `SelectionExpansion = View`, the selection endpoint will be updated according to the viewport's height. Horizontal movements will be updated according to the viewport's width, thus resulting in the endpoint being moved to the left/right boundary of the viewport.
#### Moving by Buffer
For `SelectionExpansion = Buffer`, the selection endpoint will be moved to the beginning or end of all the text within the buffer. If moving up or left, set the position to 0,0 (the origin of the buffer). If moving down or right, set the position to the last character in the buffer.
**NOTE**: In all cases, horizontal movements attempting to move past the left/right viewport boundaries result in a wrap. Vertical movements attempting to move past the top/bottom viewport boundaries will scroll such that the selection is at the edge of the screen. Vertical movements attempting to move past the top/bottom buffer boundaries will be clamped to be within buffer boundaries.
**NOTE**: If `copyOnSelect` is enabled, we need to make sure we **DO NOT** update the clipboard on every change in selection. The user must explicitly choose to copy the selected text from the buffer.
### Mark Mode
Mark Mode is a mode where the user can create and modify a selection using only the keyboard.
When no selection is present, the user may use the `markMode` action to enter mark mode. Upon doing so, a selection will be created at the current cursor position.
When in mark mode, the user may...
- press <kbd>ESC</kbd> to clear the selection and exit mark mode
- invoke the `markMode` action to exit mark mode
- invoke the `copy` action (this includes right-clicking the terminal) to copy the selected text, clear the selection, and exit mark mode
- move the cursor in the following ways:
- arrow keys --> move by character
- ctrl + left/right --> move by word
- ctrl + home/end --> move to the beginning/end of the buffer
- home/end --> move to the beginning/end of the line respectively
- pgup/pgdn --> move up/down by viewport respectively
- expand the selection in the following ways:
- shift + arrow keys --> move the "end" endpoint by character
- ctrl + shift + left/right --> move the "end" endpoint by word
- ctrl + shift + home/end --> move the "end" endpoint to the beginning/end of the buffer
- shift + home/end --> move the "end" endpoint to the beginning/end of the line respectively
- shift + pgup/pgdn --> move the "end" endpoint up/down by viewport respectively
As with mouse selections, keybindings are still respected and pressing a key that is not bound to a keybinding (or mentioned above) will clear the selection and exit mark mode.
#### Corner cases
- In mark mode, if a selection was created via the keyboard, moving the cursor moves at the "end" endpoint. This is consistent with conhost.
- If a user creates a selection using the mouse, then enters mark mode, mark mode inherits the existing selection as if it was made using the keyboard.
- If `copyOnSelect` is enabled, the selection is copied when the selection operation is "complete". Thus, the selection is copied when the `copy` keybinding is used or the selection is copied using the mouse.
- If `copyOnSelect` is enabled, `ESC` is interpreted as "cancelling" the selection, so nothing is copied. Keys that generate input are also interpreted as "cancelling" the selection. Only the `copy` keybinding or copying using the mouse is considered "completing" the selection operation, and copying the content to the clipboard.
**NOTE** - Related to #3884:
If the user has chosen to have selections persist after a copy operation, the selection created by Copy Mode is treated no differently than one created with the mouse. The selection will persist after a copy operation. However, if the user exits Copy Mode in any of the other situations, the selection is cleared.
#### Block Selection
A user can normally create a block selection by holding <kbd>alt</kbd> then creating a selection.
If the user is in Mark Mode, and desires to make a block selection, they can use the `toggleBlockSelection()` action. `toggleBlockSelection()` takes an existing selection, and transforms it into a block selection (or vice-versa).
All selections created in Mark Mode will have block selection disabled by default.
#### Rendering during Copy Mode
Since we are just moving the selection endpoints, rendering the selection rects should operate normally. We need to ensure that we still scroll when we move a selection point past the top/bottom of the viewport.
In ConHost, output would be paused when a selection was present. Windows Terminal does not pause the output when a selection is present, however, it does not scroll to the new output.
#### Interaction with Mouse Selection
If a selection exists, the user is basically already in Copy Mode. The user should be modifying the "end" endpoint of the selection when using the `updateSelection()` bindings. The existing selection should not be cleared (contrary to prior behavior). However, the half-y-beam will not be drawn. Once the user presses the `copyMode` or `moveSelectionPoint` keybinding, the half-y-beam is drawn on the targeted endpoint (which will then be "start").
During Copy Mode, if the user attempts to create a selection using the mouse, any existing selections are cleared and the mouse creates a selection normally. However, contrary to prior behavior, the user will still be in Copy Mode. The target endpoint being modified in Copy Mode, however, will be the "end" endpoint of the selection, instead of the cursor (as explained earlier in the flowchart).
#### Abandoned Idea: Copy Mode
Copy Mode is a more complex version of Mark Mode that is intended to provide a built-in way to switch the active selection endpoint. This idea was abandoned because we would then run into a user education issue. Rather than reinventing the wheel, selection should feel natural like that of a text editor, and any diversion from that model should be introduced separately (i.e. keybindings). Doing so ensures that users can "hit the ground running" when trying to make a selection, but won't be hindered by new functionality that is available.
Copy Mode is a mode where the user can create and modify a selection using only the keyboard. The following flowchart covers how the new `copymode()` action works:
**NOTE**: `copyMode()` refers to the action, whereas `updateSelection()` refers to the underlying function that is being called in the code.
If a selection is not active, a "start" and "end" selection point is created at the cursor position. `updateSelection()` calls then move "start" and "end" together as one position.
Invoking `copyMode()` again, will then anchor "start" (meaning that it will be kept in place). Subsequent `updateSelection()` calls move the "end" selection point.
Invoking `copyMode()` essentially cycles between which selection point is targeted.
## UI/UX Design
### Key Bindings
| Action | Keybinding Args | Description |
|--|--|--|
| `selectAll` | none | Select the entire text buffer. |
| `markMode` | none | Toggle mark mode. If no selection exists, create a selection at the cursor position. Otherwise, use the existing selection as one in mark mode. |
| `toggleBlockSelection` | none | Transform the existing selection between a block selection and a line selection. |
| `switchSelectionEndpoint` | none | If a selection is present, switch which selection endpoint is targeted when in mark mode or another keyboard selection mode (i.e. modified a mouse selection using the keyboard). |
By default, the following key binding will be set:
```JS
{"command":"selectAll","keys":"ctrl+shift+a"},
// Copy Mode
{"command":"copyMode","keys":"ctrl+shift+m"},
{"command":"toggleBlockSelection"},
{"command":"switchSelectionEndpoint"},
```
### Selection Markers
A y-beam will be used to identify which selection endpoint is currently being moved when in mark mode. The y-beam will match the cursor color and the font size so that it essentially fills a cell in the buffer.
When we're moving the cursor (this happens when mark mode is entered from no existing selection), a full y-beam will be displayed at the cursor position.

When <kbd>shift</kbd> is held, we're expanding the selection. In this case, the y-beam will be split, and the relevant half will be rendered on the active endpoint functioning as a selection marker.
If the selection is up against the end (or beginning) of the line, the selection marker can't be rendered normally because there is no space to render it off the side of the terminal. Instead, the selection marker will be horizontally flipped. Alternatively, it can be rendered on the next available cell (i.e. end of line translates to the beginning of the next line), but that would cause issues when the selection is positioned at the beginning or end of the buffer, thus the idea was abandoned.
If the active endpoint crosses the inactive endpoint, the selection marker will be flipped. In a sense, the flag will always point away from the selection.
The y-beam doesn't make as much sense for block selections, so instead an L-shaped marker will be placed hugging the corner of the active selection endpoint.
**NOTE:** Both half y-beams could have been presented as shown in the image below. This idea was omitted because then there is no indication for which half y-beam is currently focused.
When mark mode is enabled, the cursor will stop blinking.
## Capabilities
### Accessibility
Using the keyboard is generally a more accessible experience than using the mouse. Being able to modify a selection by using the keyboard is a good first step towards making selecting text more accessible.
We will be expected to send "selection changed" events via UIA every time the cursor moves or selection updates (both are considered the same event).
### Security
N/A
### Reliability
With regards to the Terminal Core, the newly introduced code should rely on already existing and tested code. Thus no crash-related bugs are expected.
With regards to Terminal Control and the settings model, crash-related bugs are not expected. However, ensuring that the selection is updated and cleared in general use-case scenarios must be ensured.
### Compatibility
N/A
### Performance, Power, and Efficiency
N/A
## Potential Issues
### Grapheme Clusters
When grapheme cluster support is inevitably added to the Text Buffer, moving by "cell" is expected to move by "character" or "cluster". This is similar to how wide glyphs are handled today. Either all of it is selected, or none of it.
### Circling the buffer
As usual, if the buffer is circling, the selection should be updated to follow the content (and "scroll up" appropriately).
In the event that one endpoint "scrolls" off the buffer, we must clamp "start" to the buffer origin. Conversely, in the event that both endpoints "scroll" off the buffer, the selection must be considered cleared.
## Future considerations
### Word Selection Wrap
At the time of writing this spec, expanding or moving by word is interrupted by the beginning or end of the line, regardless of the wrap flag being set. In the future, selection and the accessibility models will respect the wrap flag on the text buffer.
This spec describes a new set of non-configurable keybindings that allows the user to update a selection without the use of a mouse or stylus.
## Inspiration
ConHost allows the user to modify a selection using the keyboard. Holding `Shift` allows the user to move the second selection endpoint in accordance with the arrow keys. The selection endpoint updates by one cell per key event, allowing the user to refine the selected region.
Mark mode allows the user to create a selection using only the keyboard, then edit it as mentioned above.
## Solution Design
The fundamental solution design for keyboard selection is that the responsibilities between the Terminal Control and Terminal Core must be very distinct. The Terminal Control is responsible for handling user interaction and directing the Terminal Core to update the selection. The Terminal Core will need to update the selection according to the preferences of the Terminal Control.
Relatively recently, TerminalControl was split into `TerminalControl`, `ControlInteractivity`, and `ControlCore`. Changes made to `ControlInteractivity`, `ControlCore`, and below propagate functionality to all consumers, meaning that the WPF terminal would benefit from these changes with no additional work required.
### Fundamental Terminal Control Changes
`ControlCore::TrySendKeyEvent()` is responsible for handling the key events after key bindings are dealt with in `TermControl`. At the time of writing this spec, there are 2 cases handled in this order:
- Clear the selection (except in a few key scenarios)
- Send Key Event
The first branch will be updated to _modify_ the selection instead of usually _clearing_ it. This will happen by converting the key event into parameters to forward to `TerminalCore`, which then updates the selection appropriately.
#### Idea: Make keyboard selection a collection of standard keybindings
One idea is to introduce an `updateSelection` action that conditionally works if a selection is active (similar to the `copy` action). For these key bindings, if there is no selection, the key events are forwarded to the application.
Thanks to Keybinding Args, there would only be 1 new command:
| Action | Keybinding Args | Description |
|--|--|--|
| `updateSelection` | | If a selection exists, moves the last selection endpoint. |
| | `Enum direction { up, down, left, right }` | The direction the selection will be moved in. |
| | `Enum mode { char, word, view, buffer }` | The context for which to move the selection endpoint to. (defaults to `char`) |
By default, the following keybindings will be set:
These are in accordance with ConHost's keyboard selection model.
This idea was abandoned due to several reasons:
1. Keyboard selection should be a standard way to interact with a terminal across all consumers (i.e. WPF control, etc.)
2. There isn't really another set of key bindings that makes sense for this. We already hardcoded <kbd>ESC</kbd> as a way to clear the selection. This is just an extension of that.
3. Adding 12 conditionally effective key bindings takes the spot of 12 potential non-conditional key bindings. It would be nice if a different key binding could be set when the selection is not active, but that makes the settings design much more complicated.
4. 12 new items in the command palette is also pretty excessive.
5. If proven wrong when this is in WT Preview, we can revisit this and make them customizable then. It's better to add the ability to customize it later than take it away.
#### Idea: Make keyboard selection a simulation of mouse selection
It may seem that some effort can be saved by making the keyboard selection act as a simulation of mouse selection. There is a union of mouse and keyboard activity that can be represented in a single set of selection motion interfaces that are commanded by the TermControl's Mouse/Keyboard handler and adapted into appropriate motions in the Terminal Core.
However, the mouse handler operates by translating a pixel coordinate on the screen to a text buffer coordinate. This would have to be rewritten and the approach was deemed unworthy.
### Fundamental Terminal Core Changes
The Terminal Core will need to expose a `UpdateSelection()` function that is called by the keybinding handler. The following parameters will need to be passed in:
-`enum SelectionDirection`: the direction that the selection endpoint will attempt to move to. Possible values include `Up`, `Down`, `Left`, and `Right`.
-`enum SelectionExpansion`: the selection expansion mode that the selection endpoint will adhere to. Possible values include `Char`, `Word`, `View`, `Buffer`.
#### Moving by Cell
For `SelectionExpansion = Char`, the selection endpoint will be updated according to the buffer's output pattern. For **horizontal movements**, the selection endpoint will attempt to move left or right. If a viewport boundary is hit, the endpoint will wrap appropriately (i.e.: hitting the left boundary moves it to the last cell of the line above it).
For **vertical movements**, the selection endpoint will attempt to move up or down. If a **viewport boundary** is hit and there is a scroll buffer, the endpoint will move and scroll accordingly by a line.
If a **buffer boundary** is hit, the endpoint will not move. In this case, however, the event will still be considered handled.
**NOTE**: An important thing to handle properly in all cases is wide glyphs. The user should not be allowed to select a portion of a wide glyph; it should be all or none of it. When calling `_ExpandWideGlyphSelection` functions, the result must be saved to the endpoint.
#### Moving by Word
For `SelectionExpansion = Word`, the selection endpoint will also be updated according to the buffer's output pattern, as above. However, the selection will be updated in accordance with "chunk selection" (performing a double-click and dragging the mouse to expand the selection). For **horizontal movements**, the selection endpoint will be updated according to the `_ExpandDoubleClickSelection` functions. The result must be saved to the endpoint. As before, if a boundary is hit, the endpoint will wrap appropriately. See [Future Considerations](#FutureConsiderations) for how this will interact with line wrapping.
For **vertical movements**, the movement is a little more complicated than before. The selection will still respond to buffer and viewport boundaries as before. If the user is trying to move up, the selection endpoint will attempt to move up by one line, then selection will be expanded leftwards. Alternatively, if the user is trying to move down, the selection endpoint will attempt to move down by one line, then the selection will be expanded rightwards.
#### Moving by Viewport
For `SelectionExpansion = View`, the selection endpoint will be updated according to the viewport's height. Horizontal movements will be updated according to the viewport's width, thus resulting in the endpoint being moved to the left/right boundary of the viewport.
#### Moving by Buffer
For `SelectionExpansion = Buffer`, the selection endpoint will be moved to the beginning or end of all the text within the buffer. If moving up or left, set the position to 0,0 (the origin of the buffer). If moving down or right, set the position to the last character in the buffer.
**NOTE**: In all cases, horizontal movements attempting to move past the left/right viewport boundaries result in a wrap. Vertical movements attempting to move past the top/bottom viewport boundaries will scroll such that the selection is at the edge of the screen. Vertical movements attempting to move past the top/bottom buffer boundaries will be clamped to be within buffer boundaries.
Every combination of the `SelectionDirection` and `SelectionExpansion` will map to a keybinding. These pairings are shown below in the UI/UX Design --> Keybindings section.
**NOTE**: If `copyOnSelect` is enabled, we need to make sure we **DO NOT** update the clipboard on every change in selection. The user must explicitly choose to copy the selected text from the buffer.
## UI/UX Design
### Key Bindings
There will only be 1 new command that needs to be added:
| Action | Keybinding Args | Description |
|--|--|--|
| `selectAll` | | Select the entire text buffer.
By default, the following key binding will be set:
```JS
{"command":"selectAll","keys":"ctrl+shift+a"},
```
## Capabilities
### Accessibility
Using the keyboard is generally a more accessible experience than using the mouse. Being able to modify a selection by using the keyboard is a good first step towards making selecting text more accessible.
### Security
N/A
### Reliability
With regards to the Terminal Core, the newly introduced code should rely on already existing and tested code. Thus no crash-related bugs are expected.
With regards to Terminal Control and the settings model, crash-related bugs are not expected. However, ensuring that the selection is updated and cleared in general use-case scenarios must be ensured.
### Compatibility
N/A
### Performance, Power, and Efficiency
## Potential Issues
### Grapheme Clusters
When grapheme cluster support is inevitably added to the Text Buffer, moving by "cell" is expected to move by "character" or "cluster". This is similar to how wide glyphs are handled today. Either all of it is selected, or none of it.
## Future considerations
### Word Selection Wrap
At the time of writing this spec, expanding or moving by word is interrupted by the beginning or end of the line, regardless of the wrap flag being set. In the future, selection and the accessibility models will respect the wrap flag on the text buffer.
## Mark Mode
This functionality will be expanded to create a feature similar to Mark Mode. This will allow a user to create a selection using only the keyboard.
@@ -17,7 +17,7 @@ This spec will outline how various terminal frontends will be able to interact w
Terminal component.
***Terminal Layer**: This is the shared core implementation of the terminal.
This is the Terminal Connection, Parser/Adapter, Buffer, and Renderer (but not
the UX-dependant RenderEngine).
the UX-dependent RenderEngine).
## User Stories
1. "Project Cascadia" should be able to have both global settings (such as
@@ -58,7 +58,7 @@ VS needs to be able to persist settings just as a simple set of global settings.
When the application needs to retrieve these settings, they need to use them as a tripartite structure: frontend-component-terminal settings.
Each frontend will have its own set of settings.
Each component implementation will also ned to have some settings that control it.
Each component implementation will also need to have some settings that control it.
The terminal also will have some settings specific to the terminal.
### Globals and Profiles
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.