Campbell has been the default color scheme for a long time now,
but it has quite some issues with hue and chroma.
This PR introduces a new scheme which was created using the Oklab
color space to find colors with maximal distance to each other
and well distributed and consistent hue and chroma.
Because of this, I've named the scheme after the creator of Oklab.
Closes#17818
(cherry picked from commit e60acbc12a)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgW-IC8
Service-Version: 1.21
This update fixes a hinting issue in Arabic glyphs.
See microsoft/cascadia-code#746 for more details.
(cherry picked from commit bf074f3e40)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgW99Sw
Service-Version: 1.21
Apparently, we were using the package containing the CRT _source code_
to determine the version of the tools.
Also apparently, VS does not guarantee that that package has the same
version as the tools package.
We should use the version of the tools package instead.
(cherry picked from commit 8e4da6e938)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgWyLAM
Service-Version: 1.21
Reroutes the `closeWindow` action to use the `CloseWindow()` method like
the window's X button does. This includes logic to display the
confirmation dialog.
Also removes `CloseRequested` as it was only used by this action
handler. We already have `CloseWindowRequested` so we're just using that
instead.
## Validation Steps Performed
✅ `closeWindow` action while multiple tabs opened brings up the
confirmation dialog
Closes#17613
(cherry picked from commit fb7b0e1218)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgWkUeM
Service-Version: 1.21
CodeQL is raising errors when building Visual Studio since they have a
dependency on Windows Terminal for our integrated terminal. The issue
raised by CodeQL refers to a non-constant string format, but in this
case the string comes from a resource file and should be considered
constant.
(cherry picked from commit 25392ea604)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgWYgYM
Service-Version: 1.21
Adds a description and keyword for the `SessionBecameInteractive` event
Follow-up from #17682
(cherry picked from commit 3772fc3fc5)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgWWlDk
Service-Version: 1.21
Oops, it didn't support more than 100 items!
(cherry picked from commit 3e6690290f)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgWLtrI
Service-Version: 1.21
This is in support of some identity changes we need to make.
(cherry picked from commit a3a4464667)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgWLo5U
Service-Version: 1.21
CodeQL is raising errors when building Visual Studio since we have a
dependency on Windows Terminal for our integrated terminal. The issue
raised is not applicable to this case and therefore requires a
suppression comment to ignore the raised error.
(cherry picked from commit 19460f98e0)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgVqzx8
Service-Version: 1.21
The current `FindWindowOfActiveTSF` implementation can
result in infinite recursion which we must guard again.
This change is not tested as I don't know how to trigger
the issue to begin with (a missing CoreInput thread).
(cherry picked from commit 924310481a)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgVIDM8
Service-Version: 1.21
When file/folder is dropped to the terminal, its path is translated and
quoted with a pair of single quotes if necessary.
However, the terminal control does not escape single quotes (allowed in
the Win32 subsystem) that need escapes when translated.
On the translation styles other than `"none"` (note: all other
translation styles are currently intended for the POSIX shell), it
causes incorrect path to be pasted when the path contains one or more
single quotes (see #18006 for an example).
With this commit, the terminal control escapes a single quote with a
valid escape sequence `'\''` (finish quote, print a single quote then
begin quote again) when the path translation is required.
* Changed escape sequence from `'"'"'` to much shorter `'\''`.
* Reflected comments by the reviewer.
* Overhaul after addition of multiple path translation styles (not just
WSL but Cygwin and MSYS).
* More clarification both in the code and in the commit message.
* Minor clarification both in the code and in the commit message.
* #18006
* #16214
* #18195
This is a follow-up of #16214 and #18195, fixing #18006.
Closes#18006
(cherry picked from commit ae90d52bb1)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgVEvdY
Service-Version: 1.21
The original intent with dynamic profiles was that they could be
uninstalled but that Terminal would remember your settings in case they
ever came back.
After we implemented dynamic profile _deletion_, however, we
accidentally made it so that saving your settings after a dynamic
profile disappeared scoured it from the planet _forever_ (since we
remembered that we generated it, but now it was no longer in the
settings file).
This pull request implements:
- Tracking for orphaned dynamic profiles
Closes#14061Closes#11510
Refs #13916
Refs #9997
Modified for 1.22. I am not including any of the UI affordances.
(cherry picked from commit 90866c7c93)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmQzgU1-p4
Service-Version: 1.22
(cherry picked from commit 2143ca1c92)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgU2frw
Service-Version: 1.21
In #18195, we introduced a real `pathTranslationStyle` setting.
I'm not backporting that whole thing.
(cherry picked from commit e476dd2b9c)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgU2fsY
Service-Version: 1.21
"HighContrast" is not a possible requested theme. So `_UpdateBackgroundForMica()` would force the settings UI to be light or dark. To fix this, we just check if we're in high contrast mode and, if so, we don't bother setting the requested theme.
(cherry picked from commit d04381ec05)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgUZ6MY
Service-Version: 1.21
Turns out that having the styles for the KeyChordText and ParsedCommandLineText be empty for high contrast mode caused the issue. Since we're already using theme resources for the colors, we automatically adjust properly to whatever the high contrast theme is (Thanks XAML!).
Bonus points:
- we didn't need the theme dictionaries anymore, so I just moved them to the ResourceDictionary directly
- ParsedCommandLineTextBlockStyle isn't used. So I removed it altogether.
Validated command palette with multiple high contrast themes. See PR thread for demo.
Closes#17914
(cherry picked from commit e83434ff7e)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgUZ6Mk
Service-Version: 1.21
This adds a basic policy check for DisabledProfileSources, so that
organizations can easily disable certain profiles like the Azure one.
Closes#17964
* Add a policy to disable Azure under HKCU. Disabled ✅
* Add a policy to disable nothing under HKLM. Enabled ✅
(...because it overrides the HKCU setting.)
(cherry picked from commit 3a06826915)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgT6i0Y
Service-Version: 1.21
The settings UI and settings model allow you to set the icon to "none"
to hide the icon (you can actually see this effect in the settings UI
when changing the value of the profile icon). However, during settings
validation, "none" is considered a file path, which is then failed to be
parsed, resulting in the icon being marked as invalid and immediately
clearing the value.
This PR fixes this issue by considering "none" to be an accepted value
during validation.
Related to #15843Closes#17943
## Validation Steps Performed
When an icon is set to "none", ...
✅ no more warning
✅ the icon is hidden
(cherry picked from commit 36f064cfc8)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTyV8A
Service-Version: 1.21
This adds a "defaultInputScope" setting, hooks it up to our TSF,
and exposes it as a setting in the UI under the startup page.
In order to stay close with the other language setting, I moved that
one from the appearance to the startup page as well.
20 out of the 26 files in this PR are boilerplate unfortunately.
Closes#17816
* Install and use the Chinese IME
* Launch WT
* Chinese input ✅
* Change setting to `alphanumericHalfWidth`
* Restart WT
* English input ✅
(cherry picked from commit fc606d2bae)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTTKAE
Service-Version: 1.21
`AutoSuggestBox` has a `SuggestionChosen` event and any reasonable
person would assume that this means one of the items was chosen.
But with WinUI it's raised whenever a suggestion is merely highlighted.
`QuerySubmitted` is the right event instead. Clearly that naming is
a lot better than `SuggestionChosen`, since the property to get the
chosen item is called `ChosenSuggestion`.
WinUI, like the unrelenting wilderness of a world indifferent to human
suffering, stands as a testament to the futility of human aspiration.
Closes#17916
## Validation Steps Performed
* Type "Casc"
* Move up/down with the arrow keys
* Neither the filtered list nor the text updates ✅
* Press Enter on an item
* Text updates ✅
(cherry picked from commit bcac9993cb)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTW9-g
Service-Version: 1.21
Adds a theme resource for the color of the reset button in the settings UI.
Closes#17902
(cherry picked from commit 0bd19e9cfc)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTTb0s
Service-Version: 1.21
## Summary of the Pull Request
When conhost receives input from a conpty connection, and that input
arrives in a block larger than our 4K buffer, we can end up with a VT
sequence that's split at the buffer boundary. Previously that could
result in the start of the sequence being dropped, and the remaining
characters being interpreted as individual key presses.
This PR attempts to fix the issue by caching the unprocessed characters
from the start of the sequence, and then combining them with the second
half of the sequence when it's later received.
## Validation Steps Performed
I've confirmed that pasting into vim now works correctly with the sample
data from issue #16655. I've also tested with a `DECCTR` report larger
than 4K which would previously have been corrupted, and which now works
as expected.
## PR Checklist
- [x] Closes#16655
(cherry picked from commit 131728b17d)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSCpCk
Service-Version: 1.21
* Don't reset the position entirely when changing the needle
* Don't change the scroll position when output arrives
* Don't interfere with the search when output arrives constantly
Closes#17301
## Validation Steps Performed
* In pwsh, run `10000..20000 | % { sleep 0.25; $_ }`
* You can search for e.g. `1004` and it'll find 10 results. ✅
* You can scroll up and down past it and it won't snap back
when new output arrives. ✅
* `while ($true) { Write-Host -NoNewline "`e[Ha"; sleep 0.0001; }`
* You can cycle between the hits effortlessly. ✅ (This tests that
the constantly reset `OutputIdle` event won't interfere.)
* On input change, the focused result is near the previous one. ✅
(cherry picked from commit d9131c6889)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgS3elk PVTI_lADOAF3p4s4AmhmszgTEciI
Service-Version: 1.21
Adds a scroll offset to avoid hiding the current search highlight with
the search box.
- Offset is based on the number of rows that the search box takes up.
(I am not totally sure I am calculating this right)
- This won't help when the current highlight is in the first couple
rows of the buffer.
Fixes: #4407
(cherry picked from commit 0bafab9a0f)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTTNTE
Service-Version: 1.21
Worked with @ekoschik on this one.
## Bug the first: the MSAL window `ixptools` spawns
> The auth prompt in pwsh.exe is disabling the terminal window while its
opened and re-enabling it when the window closes. BUT it is enabling
Terminal after dismissing itself, instead of before, which means
terminal is disabled when activated.
>
> Terminal wants focus on the ISLAND window (a grandchild; island is
parented to bridge, which is parented to terminal’s TLW). When it is
activated, it gets a `WM_SETFOCUS` (in response to DefWindowProc
`WM_ACTIVATE`). From `WM_SETFOCUS` it calls `SetFocus` on the bridge
window, and similarly the bridge calls `SetFocus` on the island.
>
> If the TLW is disabled, these `SetFocus` calls fail (see [this
check](#internal-link-redacted) in `SetFocus`). In the case above, this
leaves Terminal’s TLW as focus, and it doesn’t handle keyboard input.
Note that the window IS foreground/active, but because focus is not on
the island it doesn’t see the keyboard input. Another thing to note is
that clicking on the space to the right of the tabs does NOT revive
keyboard input, but clicking on the tabs or main area does.
> **I recommend having the TLW handle WM_ENABLE and call SetFocus on the
island window.**
And guess what, that works!
## Bug the second: When sublime text is the git `EDITOR`, it doesn't
toss focus back to the Terminal
> In this case, Sublime is calling SFW on the pseudo console window. I
don’t have its code, but it is presumably doing something like
SetForegroundWindow(GetConsoleWindow()). This queues an event to the
pseudo window, and when that event is processed the pseudo window
becomes the active and focus window on the queue (which is shared with
Terminal).
>
> The sublime window dismisses itself and does the above SFW call.
Dismissing immediately activates the Terminal TLW, which does the
triple-focus dance (TLW sets focus on itself, then bridge, then island).
This completes but is overwritten immediately when the pseudo window
activates itself. Note that the pseudo window is active at this point
(not the terminal window).
> **I recommend having the Pseudo console window handle WM_ACTIVATE by
calling SetFocus on the island window (and not passing the message to
DefWindowProc).**
And guess what, that works!
----
Closes#15956 (I did test this)
This might be related to #13388, we'll have folks try canary and check
(cherry picked from commit 17a55da0f9)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSwIkA
Service-Version: 1.21
This just adds a quick registry check for `EnableHexNumpad`.
Depends on #17774Closes#17762 (again)
## Validation Steps Performed
* Alt + NumpadAdd + 221E doesn't do anything ✅
* Set the `EnableHexNumpad` registry key
* Restart
* Alt + NumpadAdd + 221E inserts ∞ ✅
(cherry picked from commit b520da26d4)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTQsd8
Service-Version: 1.21
Swapped the `swprintf_s` with no failure checks against a
`str_printf_nothrow` with checks. I also deduplicated the
`CreateProcess` calls since they're mostly identical.
Closes#16860
(cherry picked from commit b3f41626b4)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgS25_o
Service-Version: 1.21
## Summary of the Pull Request
Fixes some issues with truncated text in the settings UI when 200% text
scaling is applied.
For #17897, a minimum height was applied instead of a plain "height".
This ensures that the desired height is applied in general, but under
200% text scaling, we are allowed to grow past that, thus preventing the
truncation of the text.
For #17898, flyouts have a scroll viewer inside them by default. We
actually don't want the scroll viewer because that means the text will
appear "truncated" when in reality, the user is expected to notice the
small scrollbar and scroll horizontally (why that's the default, I will
never know). This PR introduces a new style that can be applied to these
flyouts to cause text wrapping instead of horizontal scrolling. Looked
through the app for any instances where this happens.
For #12006, simply changing the column width from a static value to
"auto" fixes the issue. Frankly, we care more about the text appearing
as a whole (and as whole words). The name of the actions wrap properly
anyways.
Closes#17897Closes#17898Closes#12006
(cherry picked from commit a7e47b711a)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTEfj0
Service-Version: 1.21
The underlying issue is that the "Pane" is used both as a model and as
a UI element and so a pane loses its content as soon as it is closed,
but the tree only gets reordered after the animation has finished.
This PR is truly just a hotfix, because it doesn't solve this issue,
it only adds checks to the function that crashes.
Closes#17869Closes#17871
## Validation Steps Performed
* `Split pane` a few times
* Run the "Close all other panes" action
* Doesn't crash ✅
(cherry picked from commit bc6f3e2275)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTEJYE
Service-Version: 1.21
PackageES is deprecated by known scourge-on-earth OneBranch, and is now
the cause of some non-compliance.
I got permission from them to open-source it, so that's coming next.
For now, we can just depend on a package based on our code based on
theirs.
Tested and working for C++ (DLL, EXE), C#, NuGet and MSIX.
(cherry picked from commit 4aa1624cd2)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTD8ik
Service-Version: 1.21
Under ConPTY we don't load any user settings. `SetUpConsole` notes:
> If we are [ConPTY], we don't want to load any user settings,
> because that could result in some strange rendering results [...]
This enables deduplication by default, which I figured wouldn't cause
any regressions since it's a user-controllable setting anyway, while
it's clearly something the average user wants enabled, for the same
reason that PSReadLine has HistoryNoDuplicates enabled by default.
Closes#17797
## Validation Steps Performed
* Launch conhost, enter 2 commands, press F7, select the older one,
press Enter, press F7. 2 entries ✅
* Launch WT, enter 2 commands, press F7, select the older one,
press Enter, press F7. 2 entries ✅
(cherry picked from commit 5fdfd51209)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSN1FM
Service-Version: 1.21
On Windows 10 Emojis don't finish composition until the Emoji picker
panel is closed. Each emoji is thus its own composition range.
`firstRange` thus caused only the first emoji to finish composition.
The end result was that all remaining emojis would stay around
forever, with the user entirely unable to clear them.
## Validation Steps Performed
* Windows 10 VM
* Open Emoji picker (Win+.)
* Press and hold Enter on any Emoji
* Press Esc to finish the composition
* All of the Emoji can be backspaced / deleted
(cherry picked from commit 49e4eea60f)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSLR0g
Service-Version: 1.21
* Repurposes `_sendInputToConnection` to send output to the connection
no matter whether the terminal is read-only or not.
Now `SendInput` is the function responsible for the UI handling.
* Buffers responses in a VT string into a single string
before sending it as a response all at once.
This reduces the chances for the UI thread to insert cursor positions
and similar into the input pipe, because we're not constantly unlocking
the terminal lock anymore for every response. The only way now that
unrelated inputs are inserted into the input pipe is because the VT
requests (e.g. DA1, DSR, etc.) are broken up across >1 reads.
This also fixes VT responses in read-only panes.
Closes#17775
* Repeatedly run `echo ^[[c` in cmd.
DA1 responses don't stack & always stay the same ✅
* Run nvim in WSL. Doesn't deadlock when pasting 1MB. ✅
* Run the repro from #17775, which requests a ton of OSC 4
(color palette) responses. Jiggle the cursor on top of the window.
Responses never get split up. ✅
(cherry picked from commit b07589e7a8)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSK_Dw
Service-Version: 1.21
We were erroneously eating Alt followed by VK_ADD. This change makes
sure we cache key presses and releases that happen once a numpad
composition is active so that we can send them when you release Alt.
Right now, we only send them when you release Alt after composing Alt
and VK_ADD (entering hex mode) and only if you haven't inserted an
actual hex numpad code. This does mean that `Alt VK_ADD 0 0 H I` will
result in an input of "+hi". That... seems like a small price to pay for
Alt VK_ADD working again.
Closes#17762
(cherry picked from commit e006f75f6c)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSF50M
Service-Version: 1.21
This adds an indirection for `_KeyHandler` so that `OnDirectKeyEvent`
can call `_KeyHandler`. This allows us to consistently handle
Alt-key-up events. Then I added custom handling for Alt+ddd (OEM),
Alt+0ddd (ANSI), and Alt+'+'+xxxx (Unicode) sequences, due to the
absence of Alt-key events with xaml islands and our TSF control.
Closes#17327
## Validation Steps Performed
* Tested it according to https://conemu.github.io/en/AltNumpad.html
* Unbind Alt+Space
* Run `showkey -a`
* Alt+Space generates `^[ `
* F7 generates `^[[18~`
(cherry picked from commit 2fab9866b2)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSCpCg
Service-Version: 1.21
Thanks to a string of compiler bugs, we had to use an older container
image that shipped with VS 17.9.
Unfortunately, that container image is falling further and further out
of date. The build agents don't cache it any longer, so they spend 30-45
minutes of every build pulling it from the registry.
With the changes to ConPTY in #17510 removing the need for til::bitmap,
we no longer need to work around the compiler bugs it exposed.
Furthermore, 17.10.6+ has a much more robust and presumably "working"
compiler.
(cherry picked from commit 39108a7a1b)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSI7RU
Service-Version: 1.21
We have to run in an older OneBranch Windows container image due to
compiler bugs.
This change prevents us from having to wait for the container image to
download for build legs that _aren't_ using the compiler.
(cherry picked from commit bc20225b08)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSI7Rw
Service-Version: 1.21
When you close a window, it naturally loses focus.
We were trying to use members of the control to update its appearance on
focus loss after it got torn down.
Closes#17520
(cherry picked from commit eabebc4cb2)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSIM6I
Service-Version: 1.21
Some simple logic to report whenever an action has successfully occurred
(and what ShortcutAction was used).
Note, there will be some false positives here from startup. I noticed we
get a `newTab` on launch. This is probably a result of restoring the
window layout of the previous session since we're using ActionAndArgs
for that.
(cherry picked from commit 56cfb77c6d)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSCpCo
Service-Version: 1.21
Same justification as #17749.
We will revert this when either OneBranch Custom Pools become
fit-for-purpose or they upgrade to VS 17.11. Or the heat death of the
universe.
(cherry picked from commit 628e99f5d2)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSGCaA
Service-Version: 1.21
I don't know what has changed between #17450 and now, but that fix
doesn't seem necessary anymore. If you add this action:
```json
{
"keys": "ctrl+a",
"command":
{
"action": "splitPane",
"commandline": "cmd /c exit"
}
}
```
and repeatedly spam Ctrl-A it used to lead to crashes. That doesn't
happen anymore, because some other PR must've fixed that.
Reverting #17450 fixes the issue found in #17578: Because the content
pointer didn't get reset to null anymore it meant that the root
pane retained the pointer after a split. After closing the split off
pane, it would assign the remaining one back to the root, which would
cause the still existing content pointer to be closed. That pointer
is potentially the same as the remaining pane and so no close events
would get received anymore.
Closes#17578
## Validation Steps Performed
* Add the above action and spam it ✅
* Start with an empty window, split pane, type `exit` in the new pane
then type it in the original pane. It closes the window ✅
(cherry picked from commit 056af83994)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSGCfE
Service-Version: 1.21
Once all applications that have received a `WM_ENDSESSION` message
have returned from processing said message, windows will terminate
all processes. This forces us to process the message synchronously.
This meant that this issue was timing dependent. If Windows Terminal
was quick at persisting buffers and you had some other application that
was slow to shut down (e.g. Steam), you would never see this issue.
Closes#17179Closes#17250
## Validation Steps Performed
* Set up a lean Hyper-V VM for fast reboots
* `Set-VMComPort <vm> 1 \\.pipe\\<pipe>`
* Hook up WIL to write to COM1
* Add a ton of debug prints all over the place
* Read COM output with Putty for hours
* RTFM, and notice that the `WM_ENDSESSION` documentation states
"the session can end any time after all applications
have returned from processing this message"
* Be very very sad ✅
* Fix it
* Rebooting now shows on COM1 that persistence runs ✅
* Windows get restored after reboot ✅
(cherry picked from commit b439925acc)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSGCik
Service-Version: 1.21
* Adds a check whether the thread dispatcher is already null.
(See code comments.)
* Moves the `_settings` to only happen on the UI thread.
Anything else wouldn't be thread safe.
Closes#17620
## Validation Steps Performed
Not reproducible. 🚫
(cherry picked from commit e0dae59f38)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSGBis
Service-Version: 1.21
Fixes a regression from the actions MVVM change in #14292 - attempting
to overwrite a keybinding was displaying a warning but propagating the
change before the user acknowledged it.
The overwrite key binding warning in the SUI works like before
Closes#17754
(cherry picked from commit ce92b18507)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSF01Y
Service-Version: 1.21
In #16886, the key for the nested action got renamed from `Split
Pane...` to `Split pane`. This accidentally caused a collision because
now there's two actions with the same name! The settings model then
prefers the user's action over the one defined in defaults.json, thus
completely hiding the nested version.
I tried to balance the stylistic recommendations from #16846 (mainly
[this
comment](https://github.com/microsoft/terminal/issues/16846#issuecomment-2005007519)
since it gave some excellent examples) while trying to maintain muscle
memory as much as possible (with similar substring sequences). There was
also one case where we still used "the tab" so I removed the "the" for
consistency.
Side effect of #16886 which closed#16846Closes#17294Closes#17684
(cherry picked from commit 0a7c2585a2)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSFdXc
Service-Version: 1.21
## Summary of the Pull Request
Fixes the `RangeFromPoint` API such that we're now properly locking when
we attempt to retrieve the viewport data. This also corrects the
conversion from `UiaPoint` (screen position) to buffer coordinates
(buffer cell).
Closes#17579
## Detailed Description of the Pull Request / Additional comments
- `UiaTextRangeBase::Initialize(UiaPoint)`:
- reordered logic to clamp to client area first, then begin conversion
to buffer coordinates
- properly lock when retrieving the viewport data
- updated `_TranslatePointToScreen` and `_TranslatePointFromScreen` to
use `&` instead of `*`
- we weren't properly updating the parameter before
- `TermControlUiaTextRange::_TranslatePointFromScreen()`
- `includeOffsets` was basically copied over from
`_TranslatePointToScreen`. The math itself was straight up wrong since
we had to do it backwards.
## Validation Steps Performed
✅ Moved WT to top-left of monitor, then used inspect.exe to call
`RangeFromPoint` API when mouse cursor is on top-left buffer cell (also
meticulously stepped through the two functions ensuring everything was
correct).
(cherry picked from commit 7b39d24913)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSC930 PVTI_lADOAF3p4s4AmhmszgSCpCs
Service-Version: 1.21
We got some new icons for Developer Command Prompt and Developer
PowerShell from our friends over on Visual Studio!
This pull request includes them in the package, and fixes up the VS
dynamic profiles to reset any icons that matched the old paths.
This may be a minor breaking change for user settings, but we're making
the assumption that if they didn't change their VS profile icons from
the defaults, they probably want to follow us to the new defaults.
To prevent anything like this from happening again, we're going to stop
serializing icons for stub profiles.
I've also included a VS version of the PowerShell "black" icon which is
currently unused, but can be used in the future for PS7+-based VS Dev
Shell.
Closes#17627
(cherry picked from commit 06c07ab50d)
Service-Card-Id: 93531229
Service-Version: 1.21
The strided `memcpy` between buffers failed to account for situations
where the destination stride is smaller than the source stride.
The solution is to only copy as many bytes as are in each row.
## Validation Steps Performed
Even with AppVerifier the issue could not be reproduced.
Adding an `assert(srcStride <= mapped.RowPitch)`, however, did trap
the bug when WARP is used while BackendD3D is force-enabled.
(cherry picked from commit ae8c868a1c)
Service-Card-Id: 92972720
Service-Version: 1.21
We'd previously subtract one underline-height from the curly line
offset, even though we already had subtracted its complete height.
Additionally, the pixel shader received some fine tuning:
* Shrink the stroke width so that the anti-aliasing can be seen
all the way up to the horizontal edges of the bounding box.
* Add a phase shift to break apart the symmetry of the curve.
Closes#17482
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
(cherry picked from commit ad3797ace9)
Service-Card-Id: 92942049
Service-Version: 1.21
BackendD2D will now draw one extra cell on all sides when rendering the
background, filled with the expected background color, starting at (-1,
-1) to ensure that cell backgrounds do not bleed over the edges of the
viewport where the is swapchain but no content.
Fixes#17672
(cherry picked from commit 9007fc2894)
Service-Card-Id: 93494324
Service-Version: 1.21
This sends a telemetry event if a session is interacted with.
Specifically, key events are essential to have an interactive session in
Windows Terminal, so we're tracking sessions that have had a key down
event.
(cherry picked from commit ac865e6666)
Service-Card-Id: 93498660
Service-Version: 1.21
The "copy the remaining attributes" loop assumes that it has full
ownership over the rows that it copies. For that to be true,
we have to of course make sure that the current write-cursor
is at a fresh, new row in the first place.
## Validation Steps Performed
* In a new pwsh tab with 120 colums:
``Write-Host -NoNewline "`e[36m$('a'*120)`e[m"; sleep 10``
* Resize the window wider
* Color doesn't get lost
(cherry picked from commit 2f43886ab5)
Service-Card-Id: 93441137
Service-Version: 1.21
The initial contents of a texture are undefined. That's not good.
Now they are. That's good.
(cherry picked from commit 8c14a34263)
Service-Card-Id: 92788897
Service-Version: 1.21
This implements builtin glyphs for our Direct2D renderer, as well as
dashed and curly underlines. With this in place the only two features
it doesn't support are inverted cursors and VT soft fonts.
This allows us to remove the `_hack*` members introduced in a6a0e44.
The implementation of dashed underlines is trivial, while curly
underlines use quadratic bezier curves. Caching the curve as a sprite
is possible, however I feel like that can be done in the future.
Builtin glyphs on the other hand require a cache, because otherwise
filling the entire viewport with shaded glyphs would result in poor
performance. This is why it's built on top of `ID2D1SpriteBatch`.
Unfortunately the API causes an eager flush of other pending graphics
instructions, which is why there's still a decent perf hit.
Finally, as a little extra, this fixes the rounded powerline glyph
shapes being slightly cut off. The fix is to simply don't round the
position and radius of the ellipsis/semi-circle.
Closes#17224
## Validation Steps Performed
* RenderingTests.exe updated ✅
* All supported builtin glyphs look sorta right at different sizes ✅
(cherry picked from commit 3486111722)
Service-Card-Id: 92572076
Service-Version: 1.21
Sometimes subsequent WT windows open in the background behind other
applications. This PR tries to fix it.
Refs #15895
Refs #15479
Mysterious bug (and annoying). There are even some discussions about
happening to the first startup, not just subsequent ones. Sometimes the
window may show up without animation too. So I don't think this is the
final solution, but it did get solved on my computer, for now.
## Validation Steps Performed
0. Quit all WT windows if some.
1. Open File Explorer, click "Open in Terminal" in context menu.
2. Move the newly opened window and minimize it.
3. Back to step 1 and repeat several times.
4. All the windows should open in the foreground correctly (yet possibly
without animation).
---------
Co-authored-by: Mike Griese <migrie@microsoft.com>
(cherry picked from commit c52ba7dec6)
Service-Card-Id: 92715122
Service-Version: 1.21
#17358 introduced a bug where if you open/close panes very rapidly
Terminal will crash. This was because `_content` was being set to `null`
and then a `Close` event was being emitted, but several functions
attempt to access the pane's `_content` as part of the close routine.
For example, `TerminalTab` tries to update the `TaskbarProgress` every
time a pane is closed and as part of that update sequence it queries the
pane - which has `null` content now - for the taskbar progress,
resulting in a crash. This PR fixes that crash.
Refs #17358
(cherry picked from commit 5d46e317b2)
Service-Card-Id: 92776947
Service-Version: 1.21
Fixes:
- Snapping the current match to the current selection doesn't work.
- Fast closing and re-opening SearchBox would leave search highlights in
an inconsistent state. The highlights would be active even when SB is
not on the screen, and results are not updated as more text is added to
the buffer.
- Search highlights scroll marks are not cleared when the search box is
closed.
(cherry picked from commit 7c1e2298f8)
Service-Card-Id: 92736967
Service-Version: 1.21
This adds a check for whether MacType is injected and whether it's
a known bad version (pre-2023). In that case we avoid calling the
known faulty `ID2D1Device4` interface. We could avoid it in general to
fix the issue without a warning (it's only a very mild optimization),
but on the other hand, the bug that MacType has is a very serious one
and it's probably better overall to suggest users to update.
See: https://github.com/snowie2000/mactype/pull/938
## Validation Steps Performed
* MacType 2021.1-RC1 results in a warning and no crash ✅
* MacType 2023.5.31 results in no warning ✅
---------
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
(cherry picked from commit 9317d42045)
Service-Card-Id: 92687129
Service-Version: 1.21
I think I forgot to complete that section of the code...
The parentheses were missing and `beg` was repeated twice. The last
line in the comment above this explains what I intended it to be.
Closes#17365
## Validation Steps Performed
* In a new PowerShell tab
* Run ``"`e[999C`e[2D`e[42mfoo`e[m"``
* Newline until it scrolls
* Run it again
* Close and reopen
* The green "foo" is still green ✅
(cherry picked from commit 640424e03f)
Service-Card-Id: 92687334
Service-Version: 1.21
`utextAccess` apparently doesn't actually need to clamp the
`chunkOffset` to be in range of the current chunk. Also, I missed to
implement the part of the spec that says to leave the iterator on the
first/last chunk of the `UText` in case of an out-of-bounds index.
This PR fixes the issue by simply not returning early, doing a more
liberal clamp of the offset, and then checking whether it was in range.
As an aside, this also fixes a one-off bug when hovering URLs that
end on the very last cell of the viewport (or are cut off).
Closes#17343
## Validation Steps Performed
* Write an URL that wraps across the last 2 lines in the buffer
* Scroll 1 line up
* No assert ✅
* Hovering the URL shows the full, still visible parts of the URL ✅
(cherry picked from commit 261a3fec7a)
Service-Card-Id: 92678596
Service-Version: 1.21
#17333 introduced a regression: While it fixes a recursion *into*
`Pane::Close()` that doesn't fix the recursion outside of it.
In this case, `Close()` raises the `Closed` event which results
in another tab being closed because it's bound to `_RemoveTab`.
The recursion is now obvious, because I made the entire process
synchronous. Previously, it would (hopefully) just be scheduled
after the pane and its content are already gone.
The issue can be fixed by moving the recursion check from
`Pane::Close()` to `TerminalTab::Shutdown()` but I felt like
it would better to fix the issue a bit more thoroughly.
`IPaneContent` can raise a `CloseRequested` event to indicate it wants
to be closed. However, that also contained recursion, because the
content would call its own `Close()` to raise the event, which the
tab catches, calls `Close()` on the `Pane` which calls `Close()` on
the content which raises the event again and so on. That's what was
fixed in #17333 among others. We can do this better by not raising
the event from `IPaneContent::Close()`. Instead, that method will now
be exclusively called by `Pane`. The `CloseRequested` event will now
truly be just a request and nothing more. Furthermore, the ownership
of the event handling was moved from the `TerminalTab` to the `Pane`.
To make all of this a bit simpler and more robust, two new methods
were added to `Pane`: `_takePaneContent` and `_setPaneContent`.
These methods ensure that `Close()` is called on the content,
that the event handlers are always added and revoked
and that the ownership transfers cleanly between panes.
## Validation Steps Performed
* Open 3 tabs, close the middle one ✅
* Open 3 vertical panes, close the middle one ✅
* Drag tabs with multiple panes between windows ✅
(cherry picked from commit ce0f8d6db2)
Service-Card-Id: 92678790
Service-Version: 1.21
Calling Close() from within WalkPanes is not safe. Simply using
_FindPane is enough to fix this.
This PR also fixes another potential source of infinite recursion, and
fixes panes being passed by-value into the callbacks.
Closes#17305
## Validation Steps Performed
* Split panes vertically 3 times
* `exit` the middle, the bottom and final one, in that order
* Doesn't crash ✅
(cherry picked from commit baba406a07)
Service-Card-Id: 92643006
Service-Version: 1.21
This is fallout from #16937.
* Typing a command then backspacing the chars then asking for
suggestions would think the current commandline ended with spaces,
making filtering very hard.
* The currently typed command would _also_ appear in the command
history, which isn't useful.
I actually did TDD for this and wrote the test first, then confirmed
again running through the build script, I wasn't hitting any of the
earlier issues.
Closes#17241Closes#17243
(cherry picked from commit bf8a647788)
Service-Card-Id: 92638413
Service-Version: 1.21
A few minor changes to better guide people along new features in 1.21.
The font face box gets a sub-text that explains how to add multiple
fonts and the builtin glyph toggle now explains its dependence to D3D.
(cherry picked from commit 0d39c008cb)
Service-Card-Id: 92546504
Service-Version: 1.21
This centralized all our ESRP calls in one file, which will make it
easier in the future when we are invariable required to change how we
call it again.
(cherry picked from commit 5ce7fb7403)
Service-Card-Id: 92577955
Service-Version: 1.21
As it turns out, for handoff'd connections `Initialize` isn't called
and this meant the `_sessionId` was always null.
After this PR we still don't have a `_profileGuid` but that's probably
not a critical issue, since that's an inherent flaw with handoff.
It can only be solved in a robust manner if WT gets launched before the
console app is launched, but it's unlikely for that to ever happen.
## Validation Steps Performed
* Launch
* Register that version of WT as the default
* Close all tabs (Ctrl+Shift+W)
* `persistedWindowLayouts` is empty ✅
* Launch cmd/pwsh via handoff
* You get 1 window ✅
* Close the window (= press the X button)
* Launch
* You get 2 windows ✅
(cherry picked from commit 9054c81934)
Service-Card-Id: 92556178
Service-Version: 1.21
This clamps the font sizes between 1 and 100. Additionally, it fixes
a warning that I randomly noticed when reproducing the issue: D2D
complained that `EndDraw` must be called before releasing resources.
Finally, this fixes a crash when the terminal size is exactly (1,1)
cells, which happened because the initial (invalid) size was (1,1) too.
This doesn't fully fix all font-size related issues, but that's
currently difficult to achieve, as for instance the swap chain size
isn't actually based on the window size, nay, it's based on the cell
size multiplied by the cell count. So if the cell size is egregiously
large then we get a swap chain size that's larger than the display and
potentially larger than what the GPU supports which results in errors.
Closes#17227
(cherry picked from commit f62d2d5d2c)
Service-Card-Id: 92546470
Service-Version: 1.21
We need to lock the buffer when getting the viewport/cursor position.
This caused the UIA overlay to randomly fail to update.
## Validation Steps Performed
* Open a cmd tab and hold any key immediately
* Repeat until you're somewhat confident it's gone ✅
(cherry picked from commit e1b102a354)
Service-Card-Id: 92546408
Service-Version: 1.21
gotta go fast, and these animations are not fast
noted in #15845
(cherry picked from commit 46526bc00c)
Service-Card-Id: 92546875
Service-Version: 1.21
## Validation Steps Performed
- Opened multi-tab terminal window with Narrator. Narrator can read
characters from the tabs.
- Started a drag and drop (tear-off) of a tab, and it didn't crash. This
was repeated multiple times.
(cherry picked from commit 30ef1f461d)
Service-Card-Id: 92546869
Service-Version: 1.21
Fix Terminal crashing when experimental PowerShell menu completion is
very quickly invoked multiple times.
`Command::ParsePowerShellMenuComplete` can be called from multiple
threads, but it uses a `static` `Json::CharReader`, which cannot safely
parse data from multiple threads at the same time. Removing `static`
fixes the problem, since every function call gets its own `reader`.
Validation: Pressed Ctrl+Space quickly a few times with hardcoded huge
JSON as the completion payload. Also shown at the end of the second
video in #17220.
Closes#17220
(cherry picked from commit 44516ad7cf)
Service-Card-Id: 92524217
Service-Version: 1.21
This fixes 2 bugs:
* `PersistState` being called when the window is closed
(as opposed to closing the tab). The settings check was missing.
* Session cleanup running depending on whether the feature is
currently enabled as opposed to whether it was enabled on launch.
Closes#17206Closes#17207
## Validation Steps Performed
* Create a bunch of leftover buffer_*.txt files by running
the current Dev version off of main
* Build this branch, then open and close a window
* All buffer_*.txt are gone and state.json is cleaned up ✅
(cherry picked from commit dbac3a1fa3)
Service-Card-Id: 92515454
Service-Version: 1.21
This simply copies a bit more from `VtEngine::EndPaint`'s
`_noFlushOnEnd` handling which already seems to fix the linked issue.
Closes#17204
(cherry picked from commit 0b76c51ba1)
Service-Card-Id: 92516193
Service-Version: 1.21
We use `if (auto self = weakSelf.get())` in a lot of places.
That assigns the value to `self` and then checks if it's truthy.
Sometimes we need to add a "is (app) closing" check because XAML,
so we wrote something akin to `if (self = ...; !closing)`.
But that's wrong because the correct `if (foo)` is the same as
`if (void; foo)` and not `if (foo; void)` and that meant that
we didn't check for `self`'s truthiness anymore.
This issue became apparent now, because we added a new kind of
delayed callback invocation (which is a lot cheaper).
This made the lack of a `nullptr` check finally obvious.
(cherry picked from commit 6d0342f0bb)
Service-Card-Id: 92509288
Service-Version: 1.21
When the `DCS` passthrough code was first implemented, it relied on the
`ActionPassThroughString` method flushing the given string immediately.
However, that has since stopped being the case, so `DCS` operations end
up being delayed until the entire sequence has been parsed.
This PR fixes the issue by introducing a `flush` parameter to force an
immediate flush on the `ActionPassThroughString` method, as well as the
`XtermEngine::WriteTerminalW` method that it calls.
## Validation Steps Performed
I've confirmed that the test case in issue #17111 now updates the color
table as soon as each color entry is parsed, instead of delaying the
updates until the end of the sequence.
Closes#17111
(cherry picked from commit 9c16c5ca82)
Service-Card-Id: 92501226
Service-Version: 1.21
When the VT render engine starts a paint operation, it first checks to
see whether there is actually something to do, and if not it can end the
frame early. However, the result of that check was being ignored, which
could sometimes result in an unwanted `SGR` reset being written to the
conpty pipe.
This was particular concerning when passing through `DCS` sequences,
because an unexpected `SGR` in the middle of the `DCS` string would
cause it to abort early.
This PR addresses the problem by making sure the `VtEngine::StartPaint`
return value is appropriately handled in the `XtermEngine` class.
## Detailed Description of the Pull Request / Additional comments
To make this work, I also needed to correct the `_cursorMoved` flag,
because that is one of things that determines whether a paint is needed
or not, but it was being set in the `InvalidateCursor` method at the
start of ever frame, regardless of whether the cursor had actually
moved.
I also took this opportunity to get rid of the `_WillWriteSingleChar`
method and the `_quickReturn` flag, which have been mostly obsolete for
a long time now. The only place the flag was still used was to optimize
single char writes when line renditions are active. But that could more
easily be handled by testing the `_invalidMap` directly.
## Validation Steps Performed
I've confirmed that the test case in issue #17117 is no longer aborting
the `DCS` color table sequence early.
Closes#17117
(cherry picked from commit 432dfcc490)
Service-Card-Id: 92501130
Service-Version: 1.21
This fixes:
* `HRESULT`s not being shown as unsigned hex
* `D2DERR_RECREATE_TARGET` not being handled
* 4 calls not checking their `HRESULT` return
Out of the 4 only `CreateCompatibleRenderTarget` will throw in
practice, however it throws `D2DERR_RECREATE_TARGET` which is common.
Without this error handling, AtlasEngine may crash.
## Validation Steps Performed
* Set Graphics API to Direct2D
* Use `DXGIAdapterRemovalSupportTest.exe` to trigger
`D2DERR_RECREATE_TARGET`
* No error message is shown ✅
* If the `D2DERR_RECREATE_TARGET` handling is removed, the application
never crashes due to `cursorRenderTarget` being `nullptr` ✅
(cherry picked from commit b31059e53e)
Service-Card-Id: 92492429
Service-Version: 1.21
There were multiple bugs:
* GDI engine only paints whatever has been invalidated.
This means we need to not just invalidate the old cursor rect
but also the new one, or else movements may not be visible.
* The composition should be drawn at the cursor position even if
the cursor is invisible, but inside the renderer viewport.
* Conceptually, scrolling the viewport moves the relative cursor
position even if the cursor is invisible.
* An invisible cursor is not the same as one that's outside the
viewport. It's more like a cursor that's not turned on.
To resolve the first issue we simply need to call `InvalidateCursor`
again. To do so, it was abstracted into `_invalidateCurrentCursor()`.
The next 2 issues are resolved by un-`optional`-izing `CursorOptions`.
After all, even an invisible or an out-of-bounds cursor still has a
coordinate and it may still be scrolled into view.
Instead, it has the new `inViewport` property as a replacement.
This allows for instance the IME composition code in the renderer
to use the cursor coordinate while the cursor is invisible.
The last issue is fixed by simply changing the `.isOn` logic.
Closes#17150
## Validation Steps Performed
* In conhost with the GDI renderer:
`printf "\e[2 q"; sleep 2; printf "\e[A"; sleep 2; printf "\e[B"`
Cursor moves up after 2s and then down again after 2s. ✅
* Hide the cursor (`"\e[?25l"`) and use a CJK IME.
Words can still be written and deleted correctly. ✅
* Turning the cursor back on (`"\e[?25h"`) works ✅
* Scrolling shows/hides the cursor ✅
It may be more accurate to say: "Fix _known_ remaining buffer
serialization bugs", but I'll try to be positive about my code.
Initially, the buffer is initialized with the default attributes,
but once it begins to scroll, newly scrolled in rows are initialized
with the current attributes. This means we need to set the current
attributes to those of the upcoming row before the row comes up.
This is related to #17074.
## Validation Steps Performed
* Persist and restore a buffer 10 times
* All previous "Restore" status messages look correct ✅
* The escape sequences in the buffer file look correct ✅
Initially the PR restored the original v1 conhost code for
`MatchAndCopyAlias` which fixed the linked issue.
Afterwards, I've taken the liberty to rewrite the code to use modern
constructs again, primarily `string_view`. Additionally, the v1 code
first counted the number of arguments and then iterated through it
again to assemble them. This new code does both things at once.
Closes#15736
## Validation Steps Performed
The unit tests have been extended to cover multiple consecutive
spaces. All tests pass.
Noticed all these while prepping for Build:
* Promotes the stabilized features out of `experimental.`
* fixes a bug where a nested command with a `name` would match to a
`renameWindow` action, instead of a command.
* Adds the tab theme icon style
* fixes a bug where `ScrollToMarkAction` wasn't in the list of possible
args, so they would incorrectly get flagged as `moveTab`
* outright adds `experimental.rightClickContextMenu` which was missing
(?)
Something something code changes, fixes issue. Events need throwing,
some events don't need throwing, some events need throttling to
not overwhelm the flurble function within the gumbies component.
This is all boilerplate and it works now.
Closes#17171Closes#17172
## Validation Steps Performed
* Resetting the font axis/feature expander keeps
the add new button flyout sorted ✅
* Changing a font axis/feature value updates the preview ✅
* After changing the font, features/axes can still be edited ✅
You'll never believe this. Clicking on the dropdown button on a ComboBox
doesn't set `e.Tapped = true`. It bubbles up, and lands in our `Pane`'s
`Border`'s tapped handler. And in there, we yeet focus to the first
content. We end up stealing focus from the combobox, and then the
combobox doesn't actually open its dropdown.
So yea we can just fix that. Easy enough.
Closes#17062
---------
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
These feature tests continue to plague us. Seems like the most likely
outcome nowadays is that the test fails to attach immediately, so we
don't even get to the retry loop.
Easy enough. Let's move the AttachConsole into the loop too.
Re-add some machinery to special case settings tabs. When we're going to
persist a tab that only has a single settings pane in it, we'll now
promote that to the first-class "openSettings" action. This will allow
our other code in TerminalPage to route multiple settings tabs all to
the same tab.
This of course doesn't stop you from opening multiple settings tabs with
`{ "command": {"action": "newTab", "type": "settings"} }` actions. If we
did that, then that would prevent someone from having a settings pane in
the first pane, and a terminal to the right.
Closes#17070
This required me to push a bunch more parameters through the build
pipeline, but it gave me the opportunity to define them as variables
that can be set at queue time.
Due to #16821 everything about #16104 broke. This PR rights the wrongs
by rewriting all the `Font`-based code to not use `Font` at all.
Instead we split the font spec once into font families, do a lot of
complex logic to split font axes/features into used and unused ones
and construct all the UI elements. So. much. boilerplate. code.
Closes#16943
## Validation Steps Performed
There are more edge cases than I can list here... Some ideas:
* Edit the settings.json with invalid axis/feature keys ✅
* ...out of range values ✅
* Settings UI reloads when the settings.json changes ✅
* Adding axes/features works ✅
* Removing axes/features works ✅
* Resetting axes/features works ✅
* Axes/features apply in the renderer when saving ✅
I think this subtly regressed in #16611. Jump to
90b8bb7c2d (diff-f9112caf8cb75e7a48a7b84987724d754181227385fbfcc2cc09a879b1f97c12L171-L223)
`Terminal::SelectNewRegion` is the only thing that uses the return value
from `Terminal::_ScrollToPoints`. Before that PR, `_ScrollToPoints` was
just a part of `SelectNewRegion`, and it moved the start & end coords by
the `_VisibleStartIndex`, not the `_scrollOffset`.
Kinda weird there weren't any _other_ tests for `SelectNewRegion`?
I also caught a second bug while I was here - If you had a line with an
exact wrap, and tried to select that like with selectOutput, we'd
explode.
Closes#17131
This addresses a review comment left by tusharsnx in #17092 which I
forgot to fix before merging the PR. The fix itself is somewhat simple:
`Terminal::SetSearchHighlightFocused` triggers a scroll if the target
is outside of the current (scrolled) viewport and avoiding the call
unless necessary fixes it. To do it properly though, I've split up
`Search::ResetIfStale` into `IsStale` and `Reset`. Now we can properly
detect staleness in advance and branch out the search reset cleanly.
Additionally, I've taken the liberty to replace the `IVector` in
`SearchResultRows` with a direct `const std::vector&` into `Searcher`.
This removes a bunch of code and makes it faster to boot.
## Validation Steps Performed
* Print lots of text
* Search a common letter
* Scroll up
* Doesn't scroll back down ✅
* Hold enter to search more occurrences scrolls up as needed ✅
* `showMarksOnScrollbar` still works ✅
## Summary of the Pull Request
Fixed default selection background colors with light schemes. Default
color now matches the scheme and contrasts well
## References and Relevant Issues
none
## Detailed Description of the Pull Request / Additional comments
This is my first contribution ever :) Even though its simple, im happy
to help
## Validation Steps Performed
## PR Checklist
- [ ] Closes#8716
- [ ] 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 (if necessary)
These changes were automatically generated by clang-tidy.
```
clang-tidy --checks=modernize-avoid-bind --fix
```
I have not bothered with the test code.
---------
Co-authored-by: Mike Griese <migrie@microsoft.com>
This PR achieves two things:
* When encountering rows with newlines (`WasForceWrapped` = `false`)
we'll now copy the contents out of the row and append a `\n`.
To make `utext_clone` cheap, it adds a reference counted buffer.
* Text extraction in `Terminal::GetHyperlinkAtBufferPosition`
was fixed by using a higher level `TextBuffer::GetPlainText`
instead of iterating through each cell.
Closes#16676Closes#17065
## Validation Steps Performed
* In pwsh execute the following:
``"`e[999C`e[22Dhttps://example.com/foo`nbar"``
* Hovering over the URL only underlines `.../foo` and not `bar` ✅
* The tooltip ends in `.../foo` and not `.../fo` ✅
We will no longer serialize IDs that we generated for the user.
This change is being made so that we can release user action IDs at the
same time as the features that require them!
Validation: Generated IDs do not get written to the json, user-made IDs
still do
Closes#17109
## Summary of the Pull Request
When the conpty renderer determines that it needs to hide the cursor,
it does so by inserting a `DECTCEM` reset sequence at the start of the
output buffer, assuming that is the start of the frame. But when the
`_noFlushOnEnd` flag is set, you can have multiple frames pending in the
buffer, and the `DECTCEM` sequence will then end up in the wrong place.
This PR fixes the issue by saving the buffer size at the start of the
frame, and using that saved offset as the insert position for the
`DECTCEM` sequence.
## Validation Steps Performed
I have a game that was frequently affected by this issue (the cursor
would be visible when it was meant to be hidden). With this PR applied,
it now works perfectly.
## PR Checklist
- [x] Closes#15449
This shouldn't have ever worked...? This looks like it was a typo and
should have been `mark.end`.
Thanks @joadoumie for asking about the moving the cursor in the prompt,
that convo lead to me finding this.
This update adds support for:
- Unicode 16 Large Type Pieces (they are really cool, you *have* to see
them)
- Unicode 13 Sextants (U+1FB00 - U+1FB3B)
- Octants, sedecimants, eights, miscellanrous blocks, separated
quadrants and sextants, and diagonals
- Segmented digits (think LED numbers)
- Checkerboards
It also fixes the coordinate system used in all of the blocks,
half-blocks, quadrants and eights for consistency.
This update does **not** include the new "Nerd Fonts" variant of
Cascadia Code or Cascadia Mono.
With big thanks to @PhMajerus for contributing all of the new symbols
for legacy computing.
See microsoft/cascadia-code#723, microsoft/cascadia-code#708 and
microsoft/cascadia-code#727 for more details.
While I was fixing the initial position thing, I figured I'd fix this
too. We were mistakenly accounting for the size of the titlebar when we
should launch into focus mode (without one)
Closes#10730
This adds a system message which displays the time at which the
buffer snapshot was written to disk.
Additionally, this PR moves the snapshot loading into a background
thread, so that the UI thread is unblocked and that multiple
tabs/panes can load simultaneously.
Closes#17031Closes#17074
## Validation Steps Performed
Repeatedly closing and opening WT adds more and more messages.
Currently, the messages get somewhat corrupted due to a bug
in our line-wrap handling, or some similar part.
This is required for us to move off Entra ID Application identity.
(cherry picked from commit 2e7c3fa313)
This was approved in #16957, so I will merge with one signoff.
Updates the `api-version` to `2023-02-01-preview` when requesting for
CloudShell settings and shell
## Validation Steps Performed
Can still use Azure Cloud Shell through Windows Terminal
This PR extends `til::throttled_func` to also support debouncing:
* throttling: "At most 1 call every N seconds"
* debouncing: "Exactly 1 call after N seconds of inactivity"
Based on the latter the following series of changes were made:
* An `OutputIdle` event was added to `ControlCore` which is
raised once there hasn't been any incoming data in 100ms.
This also triggers an update of our regex patterns (URL detection).
* The event is then caught by `TermControl` which calls `Search()`.
* `Search()` in turn was modified to return its results by-value
as a struct, which avoids the need for a search-update event
and simplifies how we update the UI.
This architectural change, most importantly the removal of the
`TextLayoutUpdated` event, fixes a DoS bug in Windows Terminal:
As the event leads to UI thread activity, printing lots of text
continuously results in the UI thread becoming unresponsive.
On top of these, a number of improvements were made:
* `IRenderEngine::InvalidateHighlight` was changed to take the
`TextBuffer` by-reference which avoids the need to accumulate the
line renditions in a `std::vector` first. This improves Debug build
performance during reflow by what I guess must be roughly
a magnitude faster. This difference is very noticeable.
* When closing the search box, `ClearSearch()` is called to remove
the highlights. The search text is restored when it's reopened,
however the current search position isn't.
Closes#17073Closes#17089
## Validation Steps Performed
* UIA announcements:
* Pressing Ctrl+Shift+F the first time does not lead to one ✅
* Typing the first letter does ✅
* Closing doesn't ✅
* Reopening does (as it restores the letter) ✅
* Closing the search box dismisses the highlights ✅
* Resizing the window recalculates the highlights ✅
* Changing the terminal output while the box is open
recalculates the highlights ✅
Since floats are imprecise we need to constrain the time value into a
range that can be accurately represented. Assuming a monitor refresh
rate of 1000 Hz, we can still easily represent 1000 seconds accurately
(roughly 16 minutes). So to solve this, we'll simply treat the shader
time modulo 1000s. This may lead to some unexpected jank every 16min
but it keeps any ongoing animation smooth otherwise.
Because this holds onto the root element, `TerminalPage` gets "leaked"
on Windows 10 when a window is closed until another is opened.
## Validation Steps Performed
* Set a breakpoint in `Renderer::~Renderer`
* Open and close a window
* Breakpoint used to not get hit and now it does ✅
While `double` is probably generally preferable for UI code,
our application is essentially a complex wrapper wrapper around
DWrite, D2D and D3D, all of which use `float` exclusively.
Of course it also uses XAML, but that one uses `float` for roughly
1/3rd of its API functions, so I'm not sure what it prefers.
Additionally, it's mostly a coincidence that we use WinUI/XAML for
Windows Terminal whereas DWrite/D2D/D3D are effectively essential.
This is demonstrated by the fact that we have a `HwndTerminal`,
while there's no alternative to e.g. D3D on Windows.
The goal of this PR is that DIP based calculations never end up
mixing `float` and `double`. This PR also changes opacity-related
values to `float` because I felt like that fits the theme.
More TraceLogging = More better?
I made this change as I noticed that most calls are not being logged.
Even after this change some crucial information won't be logged
(for instance arrays of `INPUT_RECORD`), because I couldn't come up
with a clever way to do so, but I think this is better than nothing.
Next in the popular series of minor refactorings:
Out with the old, in with the new!
This PR removes all of the existing TSF code, both for conhost and
Windows Terminal. conhost's TSF implementation was awful:
It allocated an entire text buffer _per line_ of input.
Additionally, its implementation spanned a whopping 40 files and
almost 5000 lines of code. Windows Terminal's implementation was
absolutely fine in comparison, but it was user unfriendly due to
two reasons: Its usage of the `CoreTextServices` WinRT API indirectly
meant that it used a non-transitory TSF document, which is not the
right choice for a terminal. A `TF_SS_TRANSITORY` document (-context)
indicates to TSF that it cannot undo a previously completed composition
which is exactly what we need: Once composition has completed we send
the result to the shell and we cannot undo this later on.
The WinRT API does not allow us to use `TF_SS_TRANSITORY` and so it's
unsuitable for our application. Additionally, the implementation used
XAML to render the composition instead of being part of our text
renderer, which resulted in the text looking weird and hard to read.
The new implementation spans just 8 files and is ~1000 lines which
should make it significantly easier to maintain. The architecture is
not particularly great, but it's certainly better than what we had.
The implementation is almost entirely identical between both conhost
and Windows Terminal and thus they both also behave identical.
It fixes an uncountable number of subtle bugs in the conhost TSF
implementation, as it failed to check for status codes after calls.
It also adds several new features, like support for wavy underlines
(as used by the Japanese IME), dashed underlines (the default for
various languages now, like Vietnamese), colored underlines,
colored foreground/background controlled by the IME, and more!
I have tried to replicate the following issues and have a high
confidence that they're resolved now:
Closes#1304Closes#3730Closes#4052Closes#5007 (as it is not applicable anymore)
Closes#5110Closes#6186Closes#6192Closes#13805Closes#14349Closes#14407Closes#16180
For the following issues I'm not entirely sure if it'll fix it,
but I suspect it's somewhat likely:
#13681#16305#16817
Lastly, there's one remaining bug that I don't know how to resolve.
However, that issue also plagues conhost and Windows Terminal
right now, so it's at least not a regression:
* Press Win+. (emoji picker) and close it
* Move the window around
* Press Win+.
This will open the emoji picker at the old window location.
It also occurs when the cursor moves within the window.
While this is super annoying, I could not find a way to fix it.
## Validation Steps Performed
* See the above closed issues
* Use Vietnamese Telex and type "xin choaf"
Results in "xin chào" ✅
* Use the MS Japanese IME and press Alt+`
Toggles between the last 2 modes ✅
* Use the MS Japanese IME, type "kyouhaishaheiku", and press Space
* The text is converted, underlined and the first part is
doubly underlined ✅
* Left/Right moves between the 3 segments ✅
* Home/End moves between start/end ✅
* Esc puts a wavy line under the current segment ✅
* Use the Korean IME, type "gksgks"
This results in "한한" ✅
* Use the Korean IME, type "gks", and press Right Ctrl
Opens a popup which allows you to navigate with Arrow/Tab keys ✅
As laid out in #16816, adds an `ID` field to `Command`.
**This first PR only adds IDs for built-in commands in defaults, and
generates IDs for user-created commands that don't define an ID.** Also
note that for now we **will not** be allowing IDs for iterable/nested
commands.
The follow-up PR is where we will actually use the IDs by referring to
commands with them.
Refs #16816
## Validation Steps Performed
User-created commands in the settings file get rewritten with generated
IDs
### The changeset involves:
- Decoupling Selection and Search Highlighting code paths.
- We no longer invalidate search highlights when:
- Left-clicking on terminal
- A new selection is made
- Left-clicking on Search-box
- Dispatching Find Next/Prev Match Action. (The search highlight was
removed after pressing the first key of the Action's key combination)
- And, anything that doesn't change buffer content, shouldn't invalidate
the highlighted region (E.g. Cursor movement)
- Highlighting foreground color is *actually* applied to the highlighted
text.
- Double-clicking on SearchBox no longer starts a text selection in the
terminal.
- Selected text is properly populated in the Search Box (#16355)
Closes: #16355

## Some Implementation Details
### Detecting text layout changes in the Control layer
As Search Highlight regions need to be removed when new text is added,
or the existing text is re-arranged due to window resize or similar
events, a new event `TextLayoutUpdated` is added that notifies
`CoreControl` of any text layout changes. The event is used to
invalidate and remove all search highlight regions from the buffer
(because the regions might not be _fresh_ anymore.
The new event is raised when:
1. `AdaptDispatch` writes new text into the buffer.
2. MainBuffer is switched to AltBuffer or vice-versa.
3. The user resized the window.
4. Font size changed.
5. Zoom level changed.
(Intensionally,) It's not raised when:
1. Buffer is scrolled.
2. The text cursor is moved.
When `ControlCore` receives a `TextLayoutUpdated` event, it clears the
Search Highlights in the *render data*, and raises an
`UpdateSearchResults` event to notify `TermControl` to update the Search
UI (`SearchBoxControl`).
In the future, we can use `TextLayoutUpdated` event to start a new
search which would refresh the results automatically after a slight
delay (throttled). *VSCode already does this today*.
### How does AtlasEngine draw the highlighted regions?
We follow a similar idea as for drawing the Selection region. When new
regions are available, the old+new regions are marked invalidated.
Later, a call to `_drawHighlighted()` is made at the end of
`PaintBufferLine()` to override the highlighted regions' colors with
highlight colors. The highlighting colors replace the buffer colors
while search highlights are active.
Note that to paint search highlights, we currently invalidate the row
completely. This forces text shaping for the rows in the viewport that
have at least one highlighted region. This is done to keep the (already
lengthy) PR... simple. We could take advantage of the fact that only
colors have changed and not the characters (or glyphs). I'm expecting
that this could be improved like:
1. When search regions are added, we add the highlighting colors to the
color bitmaps without causing text shaping.
2. When search regions are removed, we re-fill the color bitmaps with
the original colors from the Buffer.
## Validation Steps:
- New text, window resize, font size changes, zooming, and pasting
content into the terminal removes search highlights.
- highlighting colors override the foreground and background color of
the text (in the rendered output).
- Blinking, faded, reverse video, Intense text is highlighted as
expected.
Closes: #17032
We were wrongly calling the Ctor of CommandPalette which led to the
creation of an uninitialized winrt command palette object, and then
OnCreateAutomationPeer() was called on that. This seems to be the cause
of #17032.
## Validation Steps Performed
- Open WT.
- Try to tear off a tab out of the tab headers view.
- WT doesn't crash.
Closes: #13961
This PR changes the window styling we use under the minimized state. We
now retain the active window styling so the content's height doesn't
change when switching between minimized and maximized states.
## Validation Steps Performed
- Open Terminal and go into Maximized mode.
- Click on the Minimize button.
- No `SizeChanged` event in `ControlCore`.
- Click on the WT icon in the taskbar to restore it.
- No `SizeChanged` event in `ControlCore`.
In the spirit of #15360 this implements the copy part.
The problem is that we have an issue accessing the clipboard while
other applications continue to work just fine. The major difference
between us and the others is that we use the WinRT clipboard APIs.
So, the idea is that we just use the Win32 APIs instead.
The feel-good side-effect is that this is (no joke) 200-1000x faster,
but I suspect no one will notice the -3ms difference down to <0.01ms.
The objective effect however is that it just works.
This may resolve#16982.
## Validation Steps Performed
* Cycle through Text/HTML/RTF-only in the Interaction settings
* Paste the contents into Word each time
* Text is plain and HTML/RTF are colored ✅
Performance of printing enwik8.txt at the following block sizes:
4KiB (printf): 53MB/s -> 58MB/s
128KiB (cat): 170MB/s -> 235MB/s
This commit is imperfect. Support for more than one rendering
engine was "hacked" into `Renderer` and is not quite correct.
As such, this commit cannot fix cursor invalidation correctly either,
and while some bugs are fixed (engines may see highly inconsistent
TextBuffer and Cursor states), it introduces others (an error in the
first engine may result in the second engine not executing).
Neither of those are good and the underlying issue remains to be fixed.
## Validation Steps Performed
* Seems ok? ✅
This gets rid off the implicit dependency on `IsGlyphFullWidth`
for the IRM and DECSWL/DECDWL/DECDHL implementations.
## Validation Steps Performed
In pwsh:
* ``"`e[31mab`e[m`b`e[4h`e[32m$('*'*10)`e[m`e[4l"``
prints a red "a", 10 green "*" and a red "b" ✅
* ``"`e[31mab`e[m`b`e[4h`e[32m$('*'*1000)`e[m`e[4l"``
prints a red "a" and a couple lines of green "*" ✅
* ``"`e[31mf$('o'*70)`e[m`e#6`e#5"``
the right half of the row is erased ✅
I changed the improper capitalization and misuse of ellipses mark (...)
in the context menu and various other places.
Fixes issues #16819 and #16846
## PR Checklist
- [ ] Closes#16846
- [x] Tests added/passed - NA
- [x] Documentation updated - NA
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [x] Schema updated (if necessary) - NA
## Summary of the Pull Request
Adding more profile GUID tests
## References and Relevant Issues
Closes#2119
## Detailed Description of the Pull Request / Additional comments
Currently, there are formats that simply break GUID parsing (the
commented out test cases). Should we catch that and treat it like a
"null" GUID or should we generate a new GUID for those profiles?
## Validation Steps Performed
## PR Checklist
- [x] Closes#2119
- [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 (if necessary)
* Switches the marks feature to being stable.
* Renames the settings, to remove "experimental."
Stacked on top of #16937, so that we actually finish reflow before
merging this.
Closes#15057
This is pretty much a huge refactoring of how marks are stored in the
buffer.
Gone is the list of `ScrollMark`s in the buffer that store regions of
text as points marking the ends. Those would be nigh impossible to
reflow nicely.
Instead, we're going to use `TextAttribute`s to store the kind of output
we've got - `Prompt`, `Command`, `Output`, or, the default, `None`.
Those already reflow nicely!
But we also need to store things like, the exit code for the command.
That's why we've now added `ScrollbarData` to `ROW`s. There's really
only going to be one prompt->output on a single row. So, we only need to
store one ScrollbarData per-row. When a command ends, we can just go
update the mark on the row that started that command.
But iterating over the whole buffer to find the next/previous
prompt/command/output region sounds complicated. So, to avoid everyone
needing to do some variant of that, we've added `MarkExtents` (which is
literally just the same mark structure as before). TextBuffer can figure
out where all the mark regions are, and hand that back to callers. This
allows ControlCore to be basically unchanged.
_But collecting up all the regions for all the marks sounds expensive!
We need to update the scrollbar frequently, we can't just collect those
up every time!_ No we can't! But we also don't need to. The scrollbar
doesn't need to know where all the marks start and end and if they have
commands and this and that - no. We only need to know the rows that have
marks on them. So, we've now also got `ScrollMark` to represent just a
mark on a scrollbar at a specific row on the buffer. We can get those
quickly.
* [x] I added a bunch of tests for this.
* [x] I played with it and it feels good, even after a reflow (finally)
* See:
* #11000
* #15057 (I'm not marking this as closed. The stacked PR will close
this, when I move marks to Stable)
This changes `NewTabArgs`, `SplitPaneArgs`, and `NewWindowArgs` to
accept a `INewContentArgs`, rather than just a `NewTerminalArgs`. This
allows a couple things:
* Users can open arbitrary types of panes with the existing `splitPane`,
`newWindow` actions, just by passing `"type": "scartchpad"` (for
example). This is a lot more flexible than re-defining different
`"openScratchpad"`, `"openTasksPane"`, etc, etc actions for every kind
of pane.
* This allows us to use the existing machinery of session restore to
also restore non-terminal panes.
The `type` property was added to `newTab`, `splitPane`, `newWindow`.
When omitted, we still just treat the json as a blob of NewTerminalArgs.
There's not actually any other kinds of `INewContentArgs` in this PR
(other than the placeholder `GenericContentArgs`). In
[`dev/migrie/fhl/md-pane`](https://github.com/microsoft/terminal/compare/dev/migrie/f/tasks-pane...dev/migrie/fhl/md-pane),
I have a type of pane that would LOVE to add some args here. So that's
forward-thinking.
There's really just two stealth types of pane for now: `settings`, and
`scratchpad`. Those I DON'T have as constants or anything in this PR.
They probably should be? Though, I suspect around the time of the tasks
& MD panes, I'll come up with whatever structure I actually want them to
take.
### future considerations here
* In the future, this should allow extensions to say "I know how to host
`foo` content", for 3p content.
* The `wt` CLI args were not yet updated to also accept `--type` yet.
There's no reason we couldn't easily do that.
* I considered adding `ICanHasCommandline` to allow arbitrary content to
generate a `wt` commandline-serializable string. Punted on that for now.
## other PRs
* #16170
* #16171
* #16172
* #16895
* #16914 <-- you are here
Closes#17014
As we discussed in length over at #7657.
This changes the default <kbd>alt+shift+-</kbd> and
<kbd>alt+shift+plus</kbd> keybindings to split panes by duplicating the
pane by default.
Closes#7657
This is a rather simple PR overall. It mostly touches either test
or tracing code. Only a few changes affect the actual runtime.
The goal of this changeset is to get rid of the `double` format tables
in the OpenConsole build by using `FMT_COMPILE` everywhere.
I forgot to `buffer.clear()` after a write. Whoops.
This includes 2 additional, smaller improvements that I just happened
to notice: The `GenRTF` code calls `to_string` despite using `fmt`.
As @lhecker noted in the #16172 review, `UpdateTerminalSettings` is
wacky. We can just pass the cache in at the start, then reset it and
reuse it in `UpdateSettings`. One fewer `try_as`!
... technically. We still won't let it actually _be_ a pane, but now it
acts like one. It's hosted in a `SettingsPaneContent`. There's no more
`SettingsTab`. It totally _can_ be in a pane (but don't?)
## Validation Steps Performed
* Still opens the settings
* Only opens a single settings tab, or re-activates the existing one
* Session restores!
* Updates the title of the tab appropriately
* I previously _did_ use the scratchpad action to open the settings in a
pane, and that worked.
## Related PRs
* #16170
* #16171
* #16172 <-- you are here
* #16895
Refs #997Closes#8452
Work is ongoing to remove individually-authenticated service accounts
from some pipelines. This moves us closer to that goal.
Tested in Nightly 2403.28002.
#16953 got me thinking: what if we just published an extension ourselves
that just packages up every color scheme in the ever-amazing
https://github.com/mbadolato/iTerm2-Color-Schemes?
Well, this isn't a package for that file.
But it is a script to generate a fragment with all of them, and blat it
into your `%LOCALAPPDATA%\Microsoft\Windows Terminal\Fragments`.
It's a notebook because I've been really fascinated with the Polyglot
Notebooks recently.
Closes#16782
### Validation Steps Performed
- Double-clicking on a Double-Width row selects the word (identified by
delimiters) under the cursor.
- Tripple-clicking on a Double-Width row selects the whole line under
the cursor.
- The same works for Double-Height rows also.
- The same works for Single-Width rows also.
This clamps the initial rows and columns settings in two areas:
- When reading the JSON file
- In the settings dialogue
For consistency, I've also added a minimum value to the NumberBoxes even
though the default Minimum is 1. The Maximum and Minimum are taken from
the JSON Schema file (Min 1, Max 999).
Closes#11957
---------
Co-authored-by: Dustin L. Howett <dustin@howett.net>
As noted in #16995.
Don't persist us if we weren't ever initialized. In that case, we
never got an initial size, never instantiated a buffer, and didn't
start the connection yet, so there's nothing for us to add here.
If we were supposed to be restored from a path, then we don't need to
do anything special here. We'll leave the original file untouched,
and the next time we actually are initialized, we'll just use that
file then.
Closes#16995
* Since `FindFontWithLocalizedName` is broken (intentionally and
temporarily until #16943 is fixed) we have to be extra be careful
not to return a nullptr `Font`.
* Portable builds may not have a broken font cache, but also not have
the given font (Cascadia Mono for instance) installed. This requires
us to load the nearby fonts even if there aren't any exceptions.
## Validation Steps Performed
* Open `src/cascadia/CascadiaResources.build.items`
and remove the `Condition` for .ttf files
* Deploy on a clean Windows 10 VM
* Cascadia Mono loads without issues ✅
* Open the `Settings > Defaults > Appearance`,
enter a non-existing font and hit Save
* Doesn't crash ✅
`til::small_vector` had a bug: Its internal backing buffer didn't
prevent default initialization! Wrapping it in an `union` fixed that.
`til::some` had the same issue, but thinking about it I realized we
don't need both classes to exist, so I removed `til::some` since
`til::small_vector` is more flexible.
Checking the assembly, I noticed that `til::small_vector` with the
`union` fix produced a more compact result. I also noticed that in
combination with function calls and inlining the bit-wise ANDs in
the point/size/rect boolean operators produced poor-ish results.
Since their impact on performance is negligible to begin with I
simplified that code slightly.
Finally, I noticed that the boolean operator for `til::point`
was incorrect since it checked for `>0` instead of `>=0`.
Luckily nothing seemed to have used that operator yet.
(= No inbox regression.)
This takes care of an edge case in regards to SGR 22: It turns off
both intense and faint attributes which means that we may need to
turn on one of the two if only one of them turned off.
Additionally, this removes the mapping for `BottomGridline` which
has no real VT equivalent anyway.
## Validation Steps Performed
* Turn session restore on
* In pwsh write:
```pwsh
"`e[1;2mboth`e[0;1mintense`e[m`n`e[1;2mboth`e[0;2mfaint`e[m"
```
* Close the app and open the `buffer_*.txt` file next to settings.json
* It contains... ✅
```
␛[1m␛[2mboth␛[22;1mintense␛[22m
␛[1m␛[2mboth␛[22;2mfaint␛[22m
```
This changeset allows Windows Terminal to dump its buffer contents as
UTF-16LE VT text onto disk and restore it later. This functionality is
enabled whenever `persistedWindowLayout` is being used.
Closes#961Closes#16741
## Validation Steps Performed
* Open multiple windows with multiple tabs and restart the app
Everything's restored ✅
* Reopen a tab with output from `RenderingTests.exe`
Everything's restored ✅
* Closing tabs and windows with Ctrl+W deletes their buffer dumps ✅
* Closing tabs doesn't create buffer dumps ✅
I've found that #16079 was never properly addressed (it still randomly
occurred after even after PR #16349), which later led to the issues
described in #16769 (nushell flickering due to too many flushes).
The crux of the fix is that this brings back the `_noFlushOnEnd` flag
that was removed in PR #15991. This is then combined with a change to
the cork API: An `uncork` on `VtEngine` now only flushes if `_Flush`
got called while it was corked in the first place.
`_noFlushOnEnd` prevents us from flushing in between two "unknown"
VT sequences (like soft fonts or FTCS) which prevents them from being
corrupted. The corking prevents the remaining cases of flushing too
often. Long-term, a proper fix would be to pass through VT unmodified.
Closes#16769
Basically, title.
It'd be a neat idea for portable installs of the Terminal to reference
files that are right there in the portable install.
This PR adds a `WT_SETTINGS_DIR` var to Terminal's own env block. This
allows us to resolve profiles relative to our own settings folder.
Closes#16295
This removes `VtApiRoutines` and the VT passthrough mode.
Why? While VT passthrough mode has a clear advantage (doesn't corrupt
VT sequences) it fails to address other pain points (performance,
out-of-sync issues after resize, etc.). Alternative options are
available which have less restrictions.
Why now? It's spring! Spring cleanup!
## Summary of the Pull Request
## References and Relevant Issues
Fixes "Align 'Run this profile as Administrator' Settings Description
with Microsoft Style Guidelines" #16946
## Detailed Description of the Pull Request / Additional comments
Expanded the contraction "it'll" to "it will" on line 993 of
`src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw`
## Validation Steps Performed
N/A
## PR Checklist
- [X] Closes#16946
- [ ] Tests added/passed
- No tests were added
- [ ] Documentation updated
- No documentation was updated
- [ ] Schema updated (if necessary)
- No schema was updated
This adds support for specifying more than one font family using a
syntax that is similar to CSS' `font-family` property.
The implementation is straight-forward and is effectively
just a wrapper around `IDWriteFontFallbackBuilder`.
Closes#2664
## PR Checklist
* Font fallback
* Write "「猫」"
* Use "Consolas" and remember the shape of the glyphs
* Use "Consolas, MS Gothic" and check that it changed ✅
* Settings UI autocompletion
* It completes ✅
* It filters ✅
* It recognizes commas and starts a new name ✅
* All invalid font names are listed in the warning message ✅
---------
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
This implements `SetForceFullRepaintRendering` and adds a new
`SetGraphicsAPI` function. The former toggles `Present1` on and off
and the latter allows users to explicitly request Direct2D/3D.
On top of these changes I did a minor cleanup of the interface,
because now that DxRenderer is gone we don't need all that anymore.
Closes#14254Closes#16747
## Validation Steps Performed
* Toggling Direct2D on/off changes colored ligature support ✅
* Toggling Present1 on/off can be observed in a debugger ✅
* Toggling WARP on/off changes GPU metrics ✅
---------
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
## Summary of the Pull Request
Builds upon #16170. This PR simply adds a singly type of non-terminal
pane - a "scratchpad pane". This is literally just a single text box, in
a pane. It's on the `{ "command": "experimental.openScratchpad" }`
action.
## References and Relevant Issues
See: #997
## Detailed Description of the Pull Request / Additional comments
I also put it behind velocity so it won't even go into preview while
this bakes.
This is really just here to demonstrate that this works, and is viable.
The next PR is much more interesting.
## Validation Steps Performed
Screenshot below.
## other PRs
* #16170
* #16171 <-- you are here
* #16172
Instead of `Pane` hosting a `TermControl` directly, it now hosts an
`IPaneContent`. This is an abstraction between the TermControl and the
pane itself, to allow for arbitrary implementations of `IPaneContent`,
with things that might not be terminals.
## References and Relevant Issues
* #997
* #1000
## Detailed Description of the Pull Request / Additional comments
This PR by itself doesn't do much. It's just a refactoring.
- It doesn't actually add any other types of pane content.
- It overall just tries to move code whenever possible, with as little
refactoring as possible. There are some patterns from before that don't
super scale well to other types of pane content (think: the `xyzChanged`
events on `IPaneContent`).
- There's a few remaining places where Pane is explicitly checking if
its content is a terminal. We probably shouldn't, but meh
There are two follow-up PRs to this PR:
* #16171
* #16172
In addition, there's more work to be done after these merge:
* TODO! issue number for "Replace `IPaneContent::xyzChanged` with
`PropertyChanged` events"
* TODO! issue number for "Re-write state restoration so panes don't
produce `NewTerminalArgs`"
## Validation Steps Performed
* It still launches
* It still works
* Broadcasting still works
* The weird restart connection thing from #16001 still works
## PR Checklist
- [x] Closes#997
## other PRs
* #16170 <-- you are here
* #16171
* #16172
Prevents errors generated due to unresolved headers in VSCode
## Validation Steps Performed
- Errors messages are removed.
- Headers are resolved properly.
When no soft fonts are set up but we're asked to draw a U+EF20, etc.,
character we'll currently read out-of-bounds, because we don't check
whether the soft fonts array is non-empty. This PR fixes the issue by
first getting a slice of the data and then checking if it's ok to use.
This changeset additionally fixes a couple constinit vs. constexpr
cases. I changed them to constinit at some point because I thought
that it's more constexpr than constexpr by guaranteeing initialization
at compile time. But nope, constinit is actually weaker in a way,
because while it does guarantee that, it doesn't actually make the
data constant. In other words, constinit is not `.rdata`.
As noted in #3337, we never actually added this menu to the settings.
Since we're planning on taking this out of "experimental" in 1.21, we
should have a visible setting for it too.
**Default Terminal**: Everyone who cares to know, knows. Everyone who
doesn't, has an annoying bar above all terminals
I had to introduce a workaround for the fact that unknown dismissed
message keys in `state.json` result in Terminal exploding on launch.
😁 That's tracked in #16874.
Closes#11930 (but not in the way you'd expect)
The `nLength` parameter of `ReadConsoleOutputCharacterW` indicates
the number of columns that should be read. For single-column (narrow)
surrogate pairs this previously clipped a trailing character of the
returned string. In the major Unicode support update in #13626
surrogate pairs truly got stored as atomic units for the first time.
This now meant that a 120 column read with such codepoints resulted
in 121 characters. Other parts of conhost still assume UCS2 however,
and so this results in the entire read failing.
This fixes the issue by turning surrogate pairs into U+FFFD
which makes it UCS2 compatible.
Closes#16892
## Validation Steps Performed
* Write U+F15C0 and read it back with `ReadConsoleOutputCharacterW`
* Read succeeds with a single U+FFFD ✅
This PR automagically finds and replaces all[^1] usages of our
TYPED_EVENT macro with `til::event`. Benefits include:
* less macro magic
* editors are more easily able to figure out the relationship between
`til::event<> Foo;`, `Foo.raise(...)`, and `bar.Foo({this,
&Bar::FooHandler})` (whereas before the relationship between
`_FooHandlers(...)` and `bar.Foo({...})`) couldn't be figured out by
vscode & sublime.
Other find & replace work that had to be done:
* I added the `til::typed_event<>` == `<IInspectable, IInspectable>`
thing from #16170, since that is goodness
* I actually fixed `til::property_changed_event`, so you can use that
for your property changed events. They're all the same anyways.
* events had to come before `WINRT_PROPERTY`s, since the latter macro
leaves us in a `private:` block
* `Pane::SetupChildCloseHandlers` I had to swap _back_, because the
script thought that was an event 🤦
* `ProfileViewModel::DeleteProfile` had to be renamed
`DeleteProfileRequested`, since there was already a `DeleteProfile`
method on it.
* WindowManager.cpp was directly wiring up it's `winrt::event`s to the
monarch & peasant. That doesn't work with `til::event`s and I'm kinda
surprised it ever did
<details>
<summary>The script in question</summary>
```py
import os
import re
def replace_in_file(file_path, file_name):
with open(file_path, 'r', encoding="utf8") as file:
content = file.read()
found_matches = False
# Define the pattern for matching
pattern = r' WINRT_CALLBACK\((\w+),\s*(.*?)\);'
event_matches = re.findall(pattern, content)
if event_matches:
found_matches = True
print(f'found events in {file_path}:')
for match in event_matches:
name = match[0]
args = match[1]
if name == "newConnection" and file_name == "ConptyConnection.cpp":
# This one is special
continue
old_declaration = 'WINRT_CALLBACK(' + name + ', ' + args + ');'
new_declaration = 'til::event<' + args + '> ' + name + ';' if name != "PropertyChanged" else 'til::property_changed_event PropertyChanged;'
print(f' {old_declaration} -> {new_declaration}')
content = content.replace(old_declaration, new_declaration)
typed_event_pattern = r' TYPED_EVENT\((\w+),\s*(.*?)\);'
typed_matches = re.findall(typed_event_pattern, content)
if typed_matches:
found_matches = True
print(f'found typed_events in {file_path}:')
for match in typed_matches:
name = match[0]
args = match[1]
if name == "newConnection" and file_name == "ConptyConnection.cpp":
# This one is special
continue
old_declaration = f'TYPED_EVENT({name}, {args});'
was_inspectable = (args == "winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable" ) or (args == "IInspectable, IInspectable" )
new_declaration = f'til::typed_event<{args}> {name};' if not was_inspectable else f"til::typed_event<> {name};"
print(f' {old_declaration} -> {new_declaration}')
content = content.replace(old_declaration, new_declaration)
handlers_pattern = r'_(\w+)Handlers\('
handler_matches = re.findall(handlers_pattern, content)
if handler_matches:
found_matches = True
print(f'found handlers in {file_path}:')
for match in handler_matches:
name = match
if name == "newConnection" and file_name == "ConptyConnection.cpp":
# This one is special
continue
old_declaration = f'_{name}Handlers('
new_declaration = f'{name}.raise('
print(f' {old_declaration} -> {new_declaration}')
content = content.replace(old_declaration, new_declaration)
if found_matches:
with open(file_path, 'w', encoding="utf8") as file:
file.write(content)
def find_and_replace(directory):
for root, dirs, files in os.walk(directory):
if 'Generated Files' in dirs:
dirs.remove('Generated Files') # Exclude the "Generated Files" directory
for file in files:
if file.endswith('.cpp') or file.endswith('.h') or file.endswith('.hpp'):
file_path = os.path.join(root, file)
try:
replace_in_file(file_path, file)
except Exception as e:
print(f"error reading {file_path}")
if file == "TermControl.cpp":
print(e)
# raise e
# Replace in files within a specific directory
directory_path = 'D:\\dev\\public\\terminal\\src'
find_and_replace(directory_path)
```
</details>
[^1]: there are other macros we use that were also using this macro,
those weren't replaced.
---------
Co-authored-by: Dustin Howett <duhowett@microsoft.com>
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
## Summary of the Pull Request
As outlined in #16816 , adding `OriginTag` to `Command` is one of the
prerequisites to implementing Action IDs. This PR does that.
## Validation Steps Performed
Actions/Commands still get parsed and work
## PR Checklist
- [ ] Closes #xxx
- [ ] 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 (if necessary)
## Summary of the Pull Request
update to the latest cli11 version
## References and Relevant Issues
none
## Detailed Description of the Pull Request / Additional comments
none
## Validation Steps Performed
## PR Checklist
- [ ] Closes #xxx
- [ ] 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 (if necessary)
---------
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
I thought the Converters.idl file had a really neat ordering,
and I felt like the .cpp implementation fell short of this.
This PR reorders the functions in the implementation to match the IDL.
It also gets rid of some unnecessary math (int vs. float, clamping)
and removes another use of `std::stringstream` (= bad STL class).
This commit adds some styles to SettingContainer that can be used to
display informational messages. They don't have reset buttons or content
and they can't be interacted with.
I did this because the InfoBars didn't scale properly when the window
was wide. Also they had an [X] button that hid the warning but didn't
persist that they had been hidden or anything.
* `[[nodiscard]]` and `[[maybe_unused]]` must come before `virtual` and
`static` qualifiers
* MSVC and Clang disagree on how `gsl::suppress` should look;
fortunately, GSL provides a macro to paper over the difference
* Clang throws "pessimizing move" warnings when you `std::move` a
temporary, as it makes copy elision impossible
* The fuzzing logic was using an unspecified template expansion
`CFuzzLogic<>` before the type had been declared
* LibraryResources was emitting most of the `.util` section with
read-write permissions and some of it with read-only
Refs #15952
This pull request introduces support for disabling full-color emoji (and
technically other COLR-related font features!)
Full-color emoji don't respond to SGR colors, intensity, faint or blink.
Some users also just prefer the line art ones.
Related to #15979
Refs #1790Closes#956
More prerequisite work for Action IDs - turns out if we add the action
IDs to the actions defined in `defaults.json` the string ends up being
too large and the compiler complains about it. Use a `.rc` file for
`defaults.json` instead and also for `enableColorSelection.json` +
`userDefaults.json`.
As mentioned in #11146, when the "Next/Prev" command is executed from
the command line with a string in the search bar, this is setting always
the first tab.
When using the command "Next/Previous Tab" from the command line, we are
creating another tab (as if we are using the keyboard shortcut), and
this triggers the `_filterTextChanged` that resets the index to the
first item in because the current mode that it has.
This could be cause because, It seems that it detects as if we are
deleting the entered letter or creating an empty string, causing the
execution of the mentioned method and resetting its index to 0.
To avoid this, we are making sure that when this action is triggerd and
we are in the `TabSwitchMode`, we should ignore the following execution
of the method.
## Validation Steps Performed
I tested out the following scenarios:
1. Performing the action with the keyboard shorcut
2. Perfoming the action with an empty string
3. Performing the action with a string in the search bar.
Also validated with the current tests.
Closes#11146
As we start to work on implementing Action IDs, the spec written a few
years ago needs some updates. This PR makes those updates for the
current implementation plan.
References #6899
Right now, the localization submission pipeline runs every night and
sends our localizable resources over to Touchdown. Later, release builds
pick up the localizations directly from Touchdown, move them into place,
and consume them.
This allowed us to avoid having localized content in the repository, but
it came with too many downsides:
- Users could not contribute additional localizations very easily
- We use the same release pipeline and Touchdown configuration for every
branch, so strings needed to either slightly match or _entirely match_
across an entire set of active release branches
- Building from day to day can pull in different strings, making the
product not reproduceable
- Calling TDBuild during release builds requires network access from the
build machine (so does restoring NuGet packages, but that's neither
here nor there)
- Local developers and users could not test out other languages
This pull request moves all localization processing into the nightly
build phase and introduces support for checking loc in and submitting a
pull request. The pull request will not be created anew if one already
exists which has not been merged.
Anything we needed to do on release is now done overnight. This includes
moving loc files into the right places and merging the Cascadia
resources with the Context Menu resources (so that we can work around a
relatively lower amount of translations being chosen for the app versus
the context menu; see #12491 for more info.)
There are some smaller downsides to this approach and its
implementation:
- The first commit is going to be huge
- Right now, it only manages a single branch and uses a force push; if a
PR is not reviewed timely, it will be force-pushed and you cannot see
the day-to-day changes in the strings. Hopefully there won't be any.
I've taken great care to ensure that repeated runs of this new pipeline
will not result in unnecessary whitespace changes. This required
changing how we merge ContextMenu.resw into CascadiaPackage to always
use the .NET XmlWriter with specific flags.
NOTE that this does not allow users to _contribute_ translation fixes
for the 10 languages which we are importing. We will still need to pull
changes out of those files and submit them as bugs to the localization
team separately, and hope they come back around in another nightly
build. However, there is no reason users cannot contribute
_non-Touchdown_ languages.
We don't need to use `stringstream` to generate a ten-character string,
and we for _sure_ don't need to use the locale-aware ctype functions
after we just wrote a comment saying "XOrg colors are always Latin-1"
| Size Diff | Object | Library |
| --------- | -------------- | -------- |
| -11.8 KB | colorTable.obj | ConTypes |
I realize I might be one of the few developers that care about custom
shader support in terminal but I thought it's worth proposing it and see
what you think.
This is to support custom shaders with custom textures.
I was thinking of exposing the background image to the shader but that
felt complicated after looking into it.
I have tested exploratively. I think the texture loader is possible to
unit test so that is a possible improvement.
The error reporting (as with other custom pixel shader code) is not very
good. That is also an area that I could improve upon.
I do think the risk of adding this is rather low as the new code is only
executed when experimental.pixelShaderImagePath is set.
### Details
Only added to the Atlas engine.
Instead I load the texture using WIC into a shader resource view. When
binding shader resources I test for presence of custom texture and bind
it to register t1.
The image loading code was found in [the D3D Texture documentation].
It's a mouthful but seems rather robust.
Tested setting: "experimental.pixelShaderImagePath"
1. Tested not specifying it.
2. Tested setting it.
3. Tested changing it (the changes are picked up)
4. Tested invalid path
5. Tested a custom shader that made use of the custom texture.
[the D3D Texture documentation]: https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-textures-how-to
Co-authored-by: Mike Griese <migrie@microsoft.com>
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
"ConptyConnection::CreateSettings()" was modified to include some extra
parameters related to the environment variable changes. This just
updates the call in Scratch.sln so that it builds and deploys properly.
When using the legacy console APIs, it's possible to write arbitrary
codepoints into the buffer. If any of those codepoints are in the C0 or
C1 range, and the buffer contents are forwarded over conpty, they can
end up mistakenly interpreted as controls by the connected terminal.
This PR fixes that issue by converting any C0 and C1 codepoints in the
buffer into printable glyphs before forwarding them over conpty. I've
used the C0 glyphs from the DOS 437 codepage and just a `?` for the C1
codepoints, since that's what you would typically have seen in the v1
console with a raster font.
Although this doesn't address the main problem in #16410, it should at
least fix the rendering issues they're seeing when running their app in
Windows Terminal.
I've confirmed that the test case in #4363 now looks the same in Windows
Terminal as it does in conhost, and I've tested the Windows version of
the terminal game [Gorched], and confirmed that it now works correctly
in Window Terminal.
[Gorched]: https://github.com/zladovan/gorchedCloses#4363Closes#6265
Welp, would you look at that? We never actually supported "canary"
feature settings. Canary's been defaulting to the "Dev" config since
inception.
There's a couple things that are supposed to only be on in Dev and not
Canary. They clearly haven't mattered, but better safe than sorry!
This PR adds support for the `OSC 21` sequence used on DEC terminals to
set the window title. It's just an alias of the `OSC 2` title sequence
used by XTerm.
This PR also corrects the handling of blank title sequences, which are
supposed to reset the title to its default value, but were previously
ignored.
## Detailed Description of the Pull Request / Additional comments
To handle the blank title parsing correctly, I had to make some changes
to the state machine. Previously it would not have dispatched an `OSC`
sequence unless it received a semicolon following the `OSC` number, but
when there's a blank string, that semicolon should not be required.
I also took this opportunity to simplify the `OSC` parsing in the state
machine, and eliminate the `_GetOscTitle` method which no longer served
any purpose.
## Validation Steps Performed
I've manually confirmed that the title sequences are now working as
expected, and added some state machine unit tests covering the blank
value handling for these sequences.
I also had to update one of the existing state machine tests to account
for the changes I made to allow the semicolon to be omitted.
Closes#16783Closes#16784
This pull request introduces the module Microsoft.Terminal.UI.dll, and
moves into it the following things:
- Any `IDirectKeyListener`
- All XAML converter helpers from around the project
- ... including `IconPathConverter` from TerminalSettingsModel
- ... but not `EmptyStringVisibilityConverter`, which has died
It also adds a XAML Markup Extension named `mtu:ResourceString`, which
will allow us to refer to string resources directly from XAML. It will
allow us to remove all of the places in the code where we manually set
resources on XAML controls.
---------
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
Make sure the delete button's `Tag` updates when the selected
axis/feature changes, so that the correct key value gets propagated when
the delete button is clicked.
Refs #16678#16104
## Validation Steps Performed
1. Add a new feature/axis
2. Change the key
3. Click the delete button
4. Delete button works
Aside from overall simplifying `CharToColumnMapper` this fixes 2 bugs:
* The backward search loop may have iterated 1 column too far,
because it didn't stop at `*current <= *target`, but rather at
`*(current - 1) <= *target`. This issue was only apparent when
surrogate pairs were being used in a row.
* When the target offset is that of a trailing surrogate pair
the forward search loop may have iterated 1 column too far.
It's somewhat unlikely for this to happen since this code is
only used through ICU, but you never know.
This is a continuation of PR #16775.
This is just a minor cleanup I did as a drive-by while working on
customized font fallback. The benefit of this change is that it's
a tiny bit less expensive, but also that it's a lot easier to read.
The split into "get index" and "get string by index" helps us to
more easily handle both, missing locales and locale fallback.
The code that ties everything together then ends up being just 7 lines.
## Summary of the Pull Request
Allow editing of font features and axes in the SUI to get the UI closer
towards JSON parity
The allowed font axes are obtained directly from the currently selected
font, and their display names are presented to the user in the user's
current locale (if it exists). Otherwise, we just display the axis tag
to the user.
## References and Relevant Issues
#10000
## Validation Steps Performed
- [x] Font Axes can be added/changed/removed from the Settings UI


## PR Checklist
- [ ] Closes #xxx
- [ ] 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 (if necessary)
This pull request removes the need for the SettingsModel tests to run in
a UAP harness and puts them into the standard CI rotation.
This required some changes to `Run-Tests.ps1` to ensure that the right
`te.exe` is selected for each test harness. It's a bit annoying, but for
things that depend on a `resources.pri`, that file must be in the same
directory as the EXE that is hosting the test. Not the DLL, mind you,
the EXE. In our case, that's `TE.ProcessHost.exe`
The bulk of the change is honestly namespace tidying.
Co-authored-by: Mike Griese <migrie@microsoft.com>
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
Shaded glyphs (U+2591..3, etc.) all have one problem in common:
The cell size may not be evenly divisible by the pixel/dot size in
the glyph. This either results in blurring, or in moiré-like patterns
at the edges of the cells with its neighbors, because they happen to
start with a pattern that overlaps with the end of the previous cell.
This PR solves the issue by moving the pixel/dot pattern generation
into the shader. That way the pixel/dot location can be made dependent
on the viewport-position of the actual underlying pixels, which avoids
repeating patterns between cells.
The PR contains some additional modifications, all of which either
extend or improve the existing debug facilities in AtlasEngine.
Suppressing whitespaces changes makes the diff way smaller.
`wstring_case_insensitive_compare` is not a great name for what it
does as it's incorrect to use for regular (human readable) strings.
This PR thus renames it to `env_key_sorter`.
`compare_string_ordinal` was renamed to `compare_ordinal_insensitive`
to make sure callers know that the comparison is insensitive
(this may otherwise be incorrect in certain contexts after all).
The return value was changed to match `memcmp` so that the API
is detached from its underlying implementation (= NLS).
`compare_linguistic_insensitive` and `contains_linguistic_insensitive`
were added to sort and filter human-readable strings respectively.
`prefix_split` was extended to allow for needles that are just a
single character. This significantly improves the generated assembly
and is also usually what someone would want to actually use.
I've left the string-as-needle variant in just in case.
This PR is prep-work for #2664
## Summary of the Pull Request
URL detection was broken again in #15858. When the regex matched, we
calculate the column(cell) by its offset, we use forward or backward
iteration of the column to find the correct column that displays the
glyphs of `_chars[offset]`.
abf5d9423a/src/buffer/out/Row.cpp (L95-L104)
However, when calculating the `currentOffset` we forget that MSB of
`_charOffsets[col]` could be `1`, or col is pointing to another glyph in
preceding column.
abf5d9423a/src/buffer/out/Row.hpp (L223-L226)
Up until now, we have treated inbox, fragment and user color schemes the
same: we load them all into one big map and when we save the settings
file we write them *all* out. It's been a big annoyance pretty much
forever.
In addition to cluttering the user's settings file, it prevents us from
making changes to the stock color schemes (like to change the cursor
color, or to adjust the colors in Tango Dark, or what have you) because
they're already copied in full in the user settings. It also means that
we need some special UI affordances for color schemes that you are
allowed to view but not to delete or rename.
We also have a funny hardcoded list of color scheme names and we use
that to determine whether they're "inbox" for UI purposes.
Because of all that, we are hesitant to add *more* color schemes to the
default set.
This pull request resolves all of those issues at once.
It:
- Adds an "origin" to color schemes indicating where they're from
(Inbox, Fragment, User, ...)
- Replaces the Edit UI with a much simpler version that pretty much only
has a "duplicate this color scheme to start editing it" button
- Deletes color schemes that we consider to be equivalent to inbox ones;
this allows us to finally disentangle the user's preferences from the
terminal's.
- Migrates all user settings that referred to schemes they may have
modified (even implicitly!) to their modified versions.
The equivalence check intentionally leaves out the cursor and selection
colors, so that we have the freedom to change them in the future.
The Origin is part of a new interface, `ISettingsModelObject`, which we
can use in the future for things like Themes and Actions.
I thought, "what if I could just have a script make all the releases,
tags and names and upload all the assets to the right place?"
So, here's that script.
Basically, title. If you null out the icon, we'll automatically try to
use the `commandline` as an icon (because we can now). We'll even be
smart about it - `cmd.exe /k echo wassup` will still just use the ico of
`cmd.exe`.
This doesn't work for `ubuntu.exe` (et. al), because that commandline is
technically a reparse point, that doesn't actually have an icon
associated with it.
Closes#705
`"none"` becomes our sentinel value for "no icon".
This will also use the same `NormalizeCommandLine` we use for
commandline matching for finding the full path to the exe.
Surprisingly easier than I thought this would be. ActionMap already
supports layering (from defaults.json), so this basically re-uses a lot
of that for fun and profit.
The trickiest bits:
* In `SettingsLoader::_parseFragment`, I'm constructing a fake, empty
JSON object, and taking _only_ the actions out from the fragment, and
stuffing them into this temp json. Then, I parse that as a globals
object, and set _that_ as the parent to the user settings file. That
results in _only_ the actions from the fragment being parsed before the
user's actions.
* In that same method, I'm also explicitly preventing the ActionMap (et
al.) from parsing `keys` from these actions. We don't want fragments to
be able to say "ctrl+f is clear buffer" or something like that. This
required a bit of annoying plumbing.
Closes#16063
Tests added.
Docs need to be updated.
This includes a fix for the hang on shutdown due to the folder change
reader.
WIL now validates format strings in `LOG...` macros (yay!) and so we
needed to fix some of our `LOG` macros.
Closes#16456
(cherry picked from commit ce30e7c89c)
Service-Card-Id: 91923199
Service-Version: 1.19
This changeset makes 3 improvements:
* Dotted lines now use a 2:1 ratio between gaps and dots (from 1:1).
This makes the dots a lot easier to spot at small font sizes.
* Dashed lines use a 1:2 ratio and a cells-size independent stride.
By being cell-size independent it works more consistently with a
wider variety of fonts with weird cell aspect ratios.
* Curly lines are now cell-size independent as well and have a
height that equals the double-underline size.
This ensures that the curve isn't cut off anymore and just like
with dashed lines, that it works under weird aspect ratios.
Closes#16712
## Validation Steps Performed
This was tested using RenderingTests using Cascadia Mono, Consolas,
Courier New, Lucida Console and MS Gothic.
(cherry picked from commit 9c8058c326)
Service-Card-Id: 91922825
Service-Version: 1.19
This adds support for drawing our own box drawing, block element,
and basic Powerline (U+E0Bx) glyphs in AtlasEngine.
This PR consists of 4 parts:
* AtlasEngine was refactored to simplify `_drawGlyph` because I've
wanted to do that for ~1 year now and never got a chance.
Well, now I'm doing it and you all will review it muahahaha.
The good news is that it removes a goto usage that even for my
standards was rather dangerous. Now it's gone and the risk with it.
* AtlasEngine was further refactored to properly parse out text that
we want to handle different from regular text. Previously, we only
did that for soft fonts, but now we want to do that for a lot more,
so a refactor was in order. The new code is still extremely
disgusting, because I now stuff `wchar_t`s into an array that's
intended for glyph indices, but that's the best way to make it fast
and not blow up the complexity of the code even further.
* Finally this adds a huge LUT for all the aforementioned glyphs.
The LUT has 4 "drawing instruction" entries per glyph which describe
the shape (rectangle, circle, lines, etc.) and the start/end coord.
With a lot of bit packing each entry is only 4 bytes large.
* Finally-finally a `builtinGlyphs` setting was added to the font
object and it defaults to `true`.
Closes#5897
## Validation Steps Performed
* RenderingTests with soft fonts ✅
* All the aforementioned glyphs ✅
* ...with color ✅
* `customGlyphs` setting can be toggled on and off ✅
`ConsoleBench` is capable of launching conhost instances and measuring
their performance characteristics. It writes these out as an HTML file
with violin graphs (using plotly.js) for easy comparison.
Currently, only a small number of tests have been added, but the code
is structured in such a way that more tests can be added easily.
This changeset makes 3 improvements:
* Dotted lines now use a 2:1 ratio between gaps and dots (from 1:1).
This makes the dots a lot easier to spot at small font sizes.
* Dashed lines use a 1:2 ratio and a cells-size independent stride.
By being cell-size independent it works more consistently with a
wider variety of fonts with weird cell aspect ratios.
* Curly lines are now cell-size independent as well and have a
height that equals the double-underline size.
This ensures that the curve isn't cut off anymore and just like
with dashed lines, that it works under weird aspect ratios.
Closes#16712
## Validation Steps Performed
This was tested using RenderingTests using Cascadia Mono, Consolas,
Courier New, Lucida Console and MS Gothic.
With AtlasEngine being fairly stable at this point and being enabled
by default in the 1.19 branch, this changeset removes DxEngine.
## Validation Steps Performed
* WT builds and runs ✅
* WpfTestNetCore ✅
* Saving the config removes the `useAtlasEngine` key ✅
## Summary of the Pull Request
This PR adds support for the missing operations that are required in the
8-bit interface architecture extension.
`DECAUPSS` - Assign User-Preference Supplemental Set
`DECRQUPSS` - Request User-Preference Supplemental Set
`ACS` - Announce Code Structure for ANSI levels 1, 2, and 3
## Detailed Description of the Pull Request / Additional comments
For the UPSS assignment there's a new `wstring_view` in `TerminalOutput`
that tracks the current mapping table for the character set, and a new
`VTID` field tracking the ID so it can be queried. The ANSI conformance
just required a couple of calls to existing methods to designate the
appropriate character sets and GL/GR maps.
And now that we've implemented everything that's required, I've updated
our device attributes report (`DA1`) to indicate support for the 8-bit
interface architecture (feature 14).
This PR also addresses some issues with the way the 8-bit GR capability
is managed. Previously a soft reset (`DECSTR`) would return the code
page to its startup state, and the restore cursor operation (`DECRC`)
could have a similar effect. This was a problem for 8-bit apps that
weren't expecting that behavior.
I've now made it so those operations no longer have any effect on the
code page, and the same applies to the C1 parsing option (`DECAC1`). The
only way to restore the code page and C1 parsing to their startup state
now is with a hard reset (`RIS`).
## Validation Steps Performed
I've added unit tests covering the `DECAUPSS` and `DECRQUPSS` sequences,
and I've also manually tested their behavior in Vttest.
## PR Checklist
- [x] Closes#16546
- [x] Tests added/passed
There's an apparent miscompilation of `dynamic_bitset` on x86 with
MSVC 19.38, where the following code:
```cpp
dynamic_bitset<uint64_t> bits(80 * 24, 0);
bits.set(0, 3 * 80, true);
```
is expected to set the first 3.75 blocks to 1 which should produce
the following blocks:
```
0xffffffffffffffff
0xffffffffffffffff
0xffffffffffffffff
0x0000ffffffffffff
```
but it actually produces:
```
0xffffffffffffffff
0x00000000ffffffff
0xffffffffffffffff
0x0000ffffffffffff
```
The weird thing here is that this only happens if `til::bitmap`
uses a `dynamic_bitset<uint64_t>`. As soon as it uses `<uint32_t>`
any other instantiation of `<uint64_t>` is magically fixed.
Conclusion: Use `size_t` until we know what's going on.
Last known good CL version: 14.37.32822
Current broken CL version: 14.38.33130
## Validation Steps Performed
The following test completes successfully again:
```cpp
til::bitmap map{ { 80, 24 } };
map.translate({ 0, 3 }, true);
VERIFY_ARE_EQUAL(3u, map.runs().size());
```
(cherry picked from commit d3ec47a7fc)
Service-Card-Id: 91885583
Service-Version: 1.19
There's an apparent miscompilation of `dynamic_bitset` on x86 with
MSVC 19.38, where the following code:
```cpp
dynamic_bitset<uint64_t> bits(80 * 24, 0);
bits.set(0, 3 * 80, true);
```
is expected to set the first 3.75 blocks to 1 which should produce
the following blocks:
```
0xffffffffffffffff
0xffffffffffffffff
0xffffffffffffffff
0x0000ffffffffffff
```
but it actually produces:
```
0xffffffffffffffff
0x00000000ffffffff
0xffffffffffffffff
0x0000ffffffffffff
```
The weird thing here is that this only happens if `til::bitmap`
uses a `dynamic_bitset<uint64_t>`. As soon as it uses `<uint32_t>`
any other instantiation of `<uint64_t>` is magically fixed.
Conclusion: Use `size_t` until we know what's going on.
Last known good CL version: 14.37.32822
Current broken CL version: 14.38.33130
## Validation Steps Performed
The following test completes successfully again:
```cpp
til::bitmap map{ { 80, 24 } };
map.translate({ 0, 3 }, true);
VERIFY_ARE_EQUAL(3u, map.runs().size());
```
Write "<command that doesn't exist> foo" in cmd.exe, move yours cursor
past the <command> and press tab. The "foo" will still be there but
will be inaccessible. This commit fixes the issue. As far as I can
tell, this never worked in any conhost version ever.
Closes#16704
(cherry picked from commit 5e9f223a6c)
Service-Card-Id: 91851714
Service-Version: 1.19
Write "<command that doesn't exist> foo" in cmd.exe, move yours cursor
past the <command> and press tab. The "foo" will still be there but
will be inaccessible. This commit fixes the issue. As far as I can
tell, this never worked in any conhost version ever.
Closes#16704
Changes recently landed in `ge_release_we_adept_dev` that result in
conhost loading `Windows.Storage.dll` during startup, rather than
`shell32`. This causes a memory usage regression.
The only thing we need from `shell32` during startup is
`ExtractIconExW`. Fortunately, that function is relatively simple and
it relies only on things from `user32` (and one thing from `comctl32`).
Enclosed herein is an implementation of `ExtractIconExW` that is tuned
for conhost's specific use case and tidied up.
Related work items: MSFT-48947348
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/ge_release_we_adept_dev c54c102a362c3dbc7a64cc148b45b993b4154ead
## Summary of the Pull Request
Implements an `ActionsViewModel` for the `Actions` page in the SUI
## References
## 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
A few annoyances:
- Because of the shifts in the UI when switching between edit
mode/regular mode on the `KeyBindingViewModel`s, the page used to
manually handle moving focus accordingly so that focus does not get
lost. However, the page no longer owns the `KeyBindingViewModel`,
instead the `ActionsViewModel` owns them but the `ActionsViewModel`
cannot manually move focus around since it does not own the UI Element.
So, the `ActionsViewModel` emits an event for the page to catch that
tells the page to move focus (`FocusContainer`).
- Similarly, the page used to manually update the `ContainerBackground`
of the `KeyBindingViewModel` when the kbdVM enters `EditMode`. The
`ActionsViewModel` does not have access to the page's resources though
(to determine the correct background brush to use). So, the
`ActionsViewModel` emits another event for the page to catch
(`UpdateBackground`).
## Validation Steps Performed
Actions page still works as before
---------
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
Hi, I realized I had a bug in my pull request for search selections
where when the highlight is wrapped it causes the selection to select
back to start of the current line instead of wrapping to the next line.
PR where I introduced this bug: #16227
This is a specification for a way to customize console allocations.
The new manifest type `consoleAllocationPolicy` and the new
`AllocConsoleWithOptions` API were already added to the console
client library internally.
Closes#7335
DECKPAM originally tracked in #16506.
Support was added in #16511.
But turns out people didn't expect the Terminal to actually be like,
compliant: #16654
This closes#16654 while we think over in #16672 how we want to solve
this
This fixes two issues where the `Space` key wasn't being handled
correctly:
* Keyboards with an `AltGr`+`Space` mapping were not generating the
expected character.
* Pressing a dead key followed by `Space` is supposed to generate the
accent character associated with that key, but it wasn't doing so.
## References and Relevant Issues
These were both regressions from the keyboard refactor in PR #16511.
## Detailed Description of the Pull Request / Additional comments
The problem was that we were treating `VK_SPACE` as a "functional" key,
which means it gets hardcoded VT mappings which take precedence over
whatever is in the keyboard layout. This was deemed necessary to deal
with the fact that many keyboards incorrectly map `Ctrl`+`Space` as a
`SP` character, when it's expected to be `NUL`.
I've now dropped `VK_SPACE` from the functional mapping table and allow
it be handled by the default mapping algorithm for "graphic" keys.
However, I've also introduced a special case check for `Ctrl`+`Space`
(and other modifier variants), so we can bypass any incorrect keyboard
layouts for those combinations.
## Validation Steps Performed
I couldn't test with a French-BEPO keyboard layout directly, because the
MS Keyboard Layout Creator wouldn't accept a `Space` key mapping that
wasn't whitespace. However, if I remapped the `AltGr`+`Space` combo to
`LF`, I could confirm that we are now generating that correctly.
I've also tested the dead key `Space` combination on various keyboard
layouts and confirmed that that is now working correctly, and checked
that the `Ctrl`+`Space` combinations are still working too.
Closes#16641Closes#16642
This contains all the parts of #16598 that aren't specific to session
restore, but are required for the code in #16598:
* Adds new GUID<>String functions that remove the `{}` brackets.
* Adds `SessionId` to the `ITerminalConnection` interface.
* Flush the `ApplicationState` before we terminate the process.
* Not monitoring `state.json` for changes is important as it prevents
disturbing the session state while session persistence is ongoing.
That's because when `ApplicationState` flushes to disk, the FS
monitor will be triggered and reload the `ApplicationState` again.
TIL: You could Ctrl+V files into Windows Terminal and here I am,
always opening the context menu and selecting "Copy as path"... smh
This restores the support by adding a very rudimentary HDROP handler.
The flip side of the regression is that I learned about this and so
conhost also gets this now, because why not!
Closes#16627
* Single files can be pasted in WT and conhost ✅
(cherry picked from commit ef96e225da)
Service-Card-Id: 91727725
Service-Version: 1.19
TIL: You could Ctrl+V files into Windows Terminal and here I am,
always opening the context menu and selecting "Copy as path"... smh
This restores the support by adding a very rudimentary HDROP handler.
The flip side of the regression is that I learned about this and so
conhost also gets this now, because why not!
Closes#16627
## Validation Steps Performed
* Single files can be pasted in WT and conhost ✅
#16592 passes the return value of `GetEnvironmentStringsW` directly
to the `hstring` constructor even though the former returns a
double-null terminated string and the latter expects a regular one.
This PR fixes the issue by using a basic strlen() loop to compute
the length ourselves. It's still theoretically beneficial over
the previous code, but now it's rather bitter since the code isn't
particularly short anymore and so the biggest benefit is gone.
Closes#16623
## Validation Steps Performed
* Validated the `env` string in a debugger ✅
It's 1 character shorter than the old `til::env` string.
That's fine however, since any `HSTRING` is always null-terminated
anyways and so we get an extra null-terminator for free.
* `wt powershell` works ✅
(cherry picked from commit c669afe2a0)
Service-Card-Id: 91719862
Service-Version: 1.19
Due to things outside our control, sometimes the Package phase fails
when VPack publication is enabled. Because of this, symbols won't be
published. We still want these builds to be considered "golden" and we
are still shipping them, so we *must* publish symbols.
(cherry picked from commit bcca7aac1b)
Service-Card-Id: 91719595
Service-Version: 1.19
#16592 passes the return value of `GetEnvironmentStringsW` directly
to the `hstring` constructor even though the former returns a
double-null terminated string and the latter expects a regular one.
This PR fixes the issue by using a basic strlen() loop to compute
the length ourselves. It's still theoretically beneficial over
the previous code, but now it's rather bitter since the code isn't
particularly short anymore and so the biggest benefit is gone.
Closes#16623
## Validation Steps Performed
* Validated the `env` string in a debugger ✅
It's 1 character shorter than the old `til::env` string.
That's fine however, since any `HSTRING` is always null-terminated
anyways and so we get an extra null-terminator for free.
* `wt powershell` works ✅
This includes a fix for the hang on shutdown due to the folder change
reader.
WIL now validates format strings in `LOG...` macros (yay!) and so we
needed to fix some of our `LOG` macros.
Closes#16456
Due to things outside our control, sometimes the Package phase fails
when VPack publication is enabled. Because of this, symbols won't be
published. We still want these builds to be considered "golden" and we
are still shipping them, so we *must* publish symbols.
conhost has 2 bugs related to clipboard handling:
* Missing retry on `OpenClipboard`: When copying to the clipboard
explorer.exe is very eager to open the clipboard and peek into it.
I'm not sure why it happens, but I can see `CFSDropTarget` in the
call stack. It uses COM RPC and so this takes ~20ms every time.
That breaks conhost's clipboard randomly during `ConsoleBench`.
During non-benchmarks I expect this to break during RDP.
* Missing null-terminator check during paste: `CF_UNICODETEXT` is
documented to be a null-terminated string, which conhost v2
failed to handle as it relied entirely on `GlobalSize`.
Additionally, this changeset simplifies the `HGLOBAL` code slightly
by adding `_copyToClipboard` to abstract it away.
* `ConsoleBench` (#16453) doesn't fail randomly anymore ✅
(cherry picked from commit 86c30bd)
The primary reason for this refactoring was to simplify the management
of VT input sequences that vary depending on modes, adding support for
the missing application keypad sequences, and preparing the way for
future extensions like `S8C1T`.
However, it also includes fixes for a number of keyboard related bugs,
including a variety of missing or incorrect mappings for the `Ctrl` and
`Ctrl`+`Alt` key combinations,
## References and Relevant Issues
This PR also includes a fix for #10308, which was previously closed as a
duplicate of #10551. I don't think those bugs were related, though, and
although they're both supposed to be fixed in Windows 11, this PR fixes
the issue in Windows 10.
## Detailed Description of the Pull Request / Additional comments
The way the input now works, there's a single keyboard map that takes a
virtual key code combined with `Ctrl`, `Alt`, and `Shift` modifier bits
as the lookup key, and the expected VT input sequence as the value. This
map is initially constructed at startup, and then regenerated whenever a
keyboard mode is changed.
This map takes care of the cursor keys, editing keys, function keys, and
keys like `BkSp` and `Return` which can be affected by mode changes. The
remaining "graphic" key combinations are determined manually at the time
of input.
The order of precedence looks like this:
1. If the virtual key is `0` or `VK_PACKET`, it's considered to be a
synthesized keyboard event, and the `UnicodeChar` value is used
exactly as given.
2. If it's a numeric keypad key, and `Alt` is pressed (but not `Ctrl`),
then it's assumedly part of an Alt-Numpad composition, so the key
press is ignored (the generated character will be transmitted when
the `Alt` is released).
3. If the virtual key combined with modifier bits is found in the key
map described above, then the matched escape sequence will be used
used as the output.
4. If a `UnicodeChar` value has been provided, that will be used as the
output, but possibly with additional Ctrl and Alt modifiers applied:
a. If it's an `AltGr` key, and we've got either two `Ctrl` keys
pressed or a left `Ctrl` key that is distinctly separate from a
right `Alt` key, then we will try and convert the character into
a C0 control code.
b. If an `Alt` key is pressed (or in the case of an `AltGr` value,
both `Alt` keys are pressed), then we will convert it into an
Alt-key sequence by prefixing the character with an `ESC`.
5. If we don't have a `UnicodeChar`, we'll use the `ToUnicodeEx` API to
check whether the current keyboard state reflects a dead key, and if
so, return nothing.
6. Otherwise we'll make another `ToUnicodeEx` call but with any `Ctrl`
and `Alt` modifiers removed from the state to determine the base key
value. Once we have that, we can apply the modifiers ourself.
a. If the `Ctrl` key is pressed, we'll try and convert the base value
into a C0 control code. But if we can't do that, we'll try again
with the virtual key code (if it's alphanumeric) as a fallback.
b. If the `Alt` key is pressed, we'll convert the base value (or
control code value) into an Alt-key sequence by prefixing it with
an `ESC`.
For step 4-a, we determine whether the left `Ctrl` key is distinctly
separate from the right `Alt` key by recording the time that those keys
are pressed, and checking for a time gap greater than 50ms. This is
necessary to distinguish between the user pressing `Ctrl`+`AltGr`, or
just pressing `AltGr` alone, which triggers a fake `Ctrl` key press at
the same time.
## Validation Steps Performed
I created a test script to automate key presses in the terminal window
for every relevant key, along with every Ctrl/Alt/Shift modifier, and
every relevant mode combination. I then compared the generated input
sequences with XTerm and a DEC VT240 terminal. The idea wasn't to match
either of them exactly, but to make sure the places where we differed
were intentional and reasonable.
This mostly dealt with the US keyboard layout. Comparing international
layouts wasn't really feasible because DEC, Linux, and Windows keyboard
assignments tend to be quite different. However, I've manually tested a
number of different layouts, and tried to make sure that they were all
working in a reasonable manner.
In terms of unit testing, I haven't done much more than patching the
ones that already existed to get them to pass. They're honestly not
great tests, because they aren't generating events in the form that
you'd expect for a genuine key press, and that can significantly affect
the results, but I can't think of an easy way to improve them.
## PR Checklist
- [x] Closes#16506
- [x] Closes#16508
- [x] Closes#16509
- [x] Closes#16510
- [x] Closes#3483
- [x] Closes#11194
- [x] Closes#11700
- [x] Closes#12555
- [x] Closes#13319
- [x] Closes#15367
- [x] Closes#16173
- [x] Tests added/passed
conhost has 2 bugs related to clipboard handling:
* Missing retry on `OpenClipboard`: When copying to the clipboard
explorer.exe is very eager to open the clipboard and peek into it.
I'm not sure why it happens, but I can see `CFSDropTarget` in the
call stack. It uses COM RPC and so this takes ~20ms every time.
That breaks conhost's clipboard randomly during `ConsoleBench`.
During non-benchmarks I expect this to break during RDP.
* Missing null-terminator check during paste: `CF_UNICODETEXT` is
documented to be a null-terminated string, which conhost v2
failed to handle as it relied entirely on `GlobalSize`.
Additionally, this changeset simplifies the `HGLOBAL` code slightly
by adding `_copyToClipboard` to abstract it away.
## Validation Steps Performed
* `ConsoleBench` (#16453) doesn't fail randomly anymore ✅
#15541 changed `AdaptDispatch::_FillRect` which caused it to not affect
the `ROW::_wrapForced` flag anymore. This change in behavior was not
noticeable as `TextBuffer::GetLastNonSpaceCharacter` had a bug where
rows of only whitespace text would always be treated as empty.
This would then affect `AdaptDispatch::_EraseAll` to accidentally
correctly guess the last row with text despite the `_FillRect` change.
#15701 then fixed `GetLastNonSpaceCharacter` indirectly by fixing
`ROW::MeasureRight` which now made the previous change apparent.
`_EraseAll` would now guess the last row of text incorrectly,
because it would find the rows that `_FillRect` cleared but still
had `_wrapForced` set to `true`.
This PR fixes the issue by replacing the `_FillRect` usage to clear
rows with direct calls to `ROW::Reset()`. In the future this could be
extended by also `MEM_DECOMMIT`ing the now unused underlying memory.
Closes#16603
## Validation Steps Performed
* Enter WSL and resize the window to <40 columns
* Execute
```sh
cd /bin
ls -la
printf "\e[3J"
ls -la
printf "\e[3J"
printf "\e[2J"
```
* Only one viewport-height-many lines of whitespace exist between the
current prompt line and the previous scrollback contents ✅
(cherry picked from commit 5f71cf3e94)
Service-Card-Id: 91707937
Service-Version: 1.19
`EnableScrollbar()` and especially `SetScrollInfo()` are prohibitively
expensive functions nowadays. This improves throughput of good old
`type` in cmd.exe by ~10x, by briefly releasing the console lock.
## Validation Steps Performed
* `type`ing a file in `cmd` is as fast while the window is scrolling
as it is while it isn't scrolling ✅
* Scrollbar pops in and out when scroll-forward is disabled ✅
(cherry picked from commit 71a6f26e6e)
Service-Card-Id: 91152166
Service-Version: 1.19
#15541 changed `AdaptDispatch::_FillRect` which caused it to not affect
the `ROW::_wrapForced` flag anymore. This change in behavior was not
noticeable as `TextBuffer::GetLastNonSpaceCharacter` had a bug where
rows of only whitespace text would always be treated as empty.
This would then affect `AdaptDispatch::_EraseAll` to accidentally
correctly guess the last row with text despite the `_FillRect` change.
#15701 then fixed `GetLastNonSpaceCharacter` indirectly by fixing
`ROW::MeasureRight` which now made the previous change apparent.
`_EraseAll` would now guess the last row of text incorrectly,
because it would find the rows that `_FillRect` cleared but still
had `_wrapForced` set to `true`.
This PR fixes the issue by replacing the `_FillRect` usage to clear
rows with direct calls to `ROW::Reset()`. In the future this could be
extended by also `MEM_DECOMMIT`ing the now unused underlying memory.
Closes#16603
## Validation Steps Performed
* Enter WSL and resize the window to <40 columns
* Execute
```sh
cd /bin
ls -la
printf "\e[3J"
ls -la
printf "\e[3J"
printf "\e[2J"
```
* Only one viewport-height-many lines of whitespace exist between the
current prompt line and the previous scrollback contents ✅
This changeset ensures that the message queue of frozen windows is
always being serviced. This should ensure that it won't fill up and
lead to deadlocks, freezes, or similar. I've tried _a lot_ of different
approaches before settling on this one. Introducing a custom `WM_APP`
message has the benefit of being the least intrusive to the existing
code base.
The approach that I would have favored the most would be to never
destroy the `AppHost` instance in the first place, as I imagined that
this would be more robust in general and resolve other (rare) bugs.
However, I found that this requires rewriting some substantial parts
of the code base around `AppHost` and it could be something that may
be of interest in the future.
Closes#16332
Depends on #16587 and #16575
(cherry picked from commit 5d2fa4782f)
Service-Card-Id: 91642479
Service-Version: 1.19
If you're already in the "output" state, then an app requesting an
"output" mark probably shouldn't end the current mark and start a new
one. It should just keep on keepin' on.
The decision to end the previous one was arbitrary in the first place,
so let's arbitrarily change it back.
Especially noticable if you hit <kbd>Enter</kbd> during a command,
because the auto-mark prompt work will do a CommandEnd, so long-running
commands will get broken into multiple marks 🥲
(cherry picked from commit 0144cdd7bc)
Service-Card-Id: 91707294
Service-Version: 1.19
`TextBuffer::GenHTML` and `TextBuffer::GenRTF` now read directly from
the TextBuffer.
- Since we're reading from the buffer, we can now read _all_ the
attributes saved in the buffer. Formatted copy now copies most (if not
all) font/color attributes in the requested format (RTF/HTML).
- Use `TextBuffer::CopyRequest` to pass all copy-related options into
text generation functions as one unit.
- Helper function `TextBuffer::CopyRequest::FromConfig()` generates a
copy request based on Selection mode and user configuration.
- Both formatted text generation functions now use `std::string` and
`fmt::format_to` to generate the required strings. Previously, we were
using `std::ostringstream` which is not recommended due to its potential
overhead.
- Reading attributes from `ROW`'s attribute RLE simplified the logic as
we don't have to track attribute change between the text.
- On the caller side, we do not have to rebuild the plain text string
from the vector of strings anymore. `TextBuffer::GetPlainText()` returns
the entire text as one `std::string`.
- Removed `TextBuffer::TextAndColors`.
- Removed `TextBuffer::GetText()`. `TextBuffer::GetPlainText()` took its
place.
This PR also fixes two bugs in the formatted copy:
- We were applying line breaks after each selected row, even though the
row could have been a Wrapped row. This caused the wrapped rows to break
when they shouldn't.
- We mishandled Unicode text (\uN) within the RTF copy. Every next
character that uses a surrogate pair or high codepoint was missing in
the copied text when pasted to MSWord. The command `\uc4` should have
been `\uc1`, which is used to tell how many fallback characters are used
for each Unicode codepoint (\u). We always use one `?` character as the
fallback.
Closes#16191
**References and Relevant Issues**
- #16270
**Validation Steps Performed**
- Casual copy-pasting from Terminal or OpenConsole to word editors works
as before.
- Verified HTML copy by copying the generated HTML string and running it
through an HTML viewer.
[Sample](https://codepen.io/tusharvickey/pen/wvNXbVN)
- Verified RTF copy by copy-pasting the generated RTF string into
MSWord.
- SingleLine mode works (<kbd>Shift</kbd>+ copy)
- BlockSelection mode works (<kbd>Alt</kbd> selection)
This changeset ensures that the message queue of frozen windows is
always being serviced. This should ensure that it won't fill up and
lead to deadlocks, freezes, or similar. I've tried _a lot_ of different
approaches before settling on this one. Introducing a custom `WM_APP`
message has the benefit of being the least intrusive to the existing
code base.
The approach that I would have favored the most would be to never
destroy the `AppHost` instance in the first place, as I imagined that
this would be more robust in general and resolve other (rare) bugs.
However, I found that this requires rewriting some substantial parts
of the code base around `AppHost` and it could be something that may
be of interest in the future.
Closes#16332
Depends on #16587 and #16575
17cc109 and e9de646 both made the same mistake: When cleaning up our
telemetry code they also removed the calls to `TraceLoggingRegister`
which also broke regular tracing. Windows Defender in particular uses
the "CookedRead" event to monitor for malicious shell commands.
This doesn't fix it the "right way", because destructors of statics
aren't executed when DLLs are unloaded. But I felt like that this is
fine because we have way more statics than that in conhost land,
all of which have the same kind of issue.
(cherry picked from commit a65d5f321f)
Service-Card-Id: 91337330
Service-Version: 1.19
After exiting the main loop in this function the invariant
`nFont <= NumberOfFonts` still holds true. Additionally,
preceding this removed code is this (paraphrased):
```cpp
if (nFont < NumberOfFonts) {
RtlMoveMemory(...);
}
```
It ensures that the given slot `nFont` is always unoccupied by moving
it and all following items upwards if needed. As such, the call to
`DeleteObject` is always incorrect, as the slot is always "empty",
but may contain a copy of the previous occupant due to the `memmove`.
This regressed in 154ac2b.
Closes#16297
## Validation Steps Performed
* All fonts have a unique look in the preview panel ✅
(cherry picked from commit 35240f263e)
Service-Card-Id: 91120871
Service-Version: 1.19
Closes MSFT:46744208
BODGY: If the emperor is being dtor'd, it's because we've gone past the
end of main, and released the ref in main. Then we might run into an
edge case where main releases it's ref to the emperor, but one of the
window threads might be in the process of exiting, and still holding a
strong ref to the emperor. In that case, we can actually end up with
the _window thread_ being the last reference, and calling App::Close
on that thread will crash us with a E_WRONG_THREAD.
This fixes the issue by calling `TerminateProcess` explicitly.
How validated: The ES team manually ran the test pass this was
crashing in a hundred times to make sure this actually fixed it.
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
(cherry picked from commit 0d47c862c2)
Service-Card-Id: 91642489
Service-Version: 1.19
This simplifies the function in two ways:
* Passing `nCmdShow` from `wWinMain` alleviates the need to interpret
the return value of `GetStartupInfoW`.
* `til::env::from_current_environment()` calls `GetEnvironmentStringsW`
to get the environment variables, while `to_string()` turns it back.
Calling the latter directly alleviates the need for this round-trip.
(cherry picked from commit a39ac598cd)
Service-Card-Id: 91643115
Service-Version: 1.19
Closes MSFT:46744208
BODGY: If the emperor is being dtor'd, it's because we've gone past the
end of main, and released the ref in main. Then we might run into an
edge case where main releases it's ref to the emperor, but one of the
window threads might be in the process of exiting, and still holding a
strong ref to the emperor. In that case, we can actually end up with
the _window thread_ being the last reference, and calling App::Close
on that thread will crash us with a E_WRONG_THREAD.
This fixes the issue by calling `TerminateProcess` explicitly.
How validated: The ES team manually ran the test pass this was
crashing in a hundred times to make sure this actually fixed it.
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
This simplifies the function in two ways:
* Passing `nCmdShow` from `wWinMain` alleviates the need to interpret
the return value of `GetStartupInfoW`.
* `til::env::from_current_environment()` calls `GetEnvironmentStringsW`
to get the environment variables, while `to_string()` turns it back.
Calling the latter directly alleviates the need for this round-trip.
In WindowsTerminal, there was a leak of a BSTR with every call to
ITextRangeProvider::GetText, and a failure to call VariantClear in
ITextRange::GetAttributeValue when the value stored in the variant is
VT_BSTR. These were fixed by switching to wil::unique_bstr and
wil::unique_variant.
(cherry picked from commit da99d892f4)
Service-Card-Id: 91631736
Service-Version: 1.19
## Summary of the Pull Request
This PR adds support for the `DECST8C` escape sequence, which resets the
tab stops to every 8 columns.
## Detailed Description of the Pull Request / Additional comments
This is actually a private parameter variant of the ANSI `CTC` sequence
(Cursor Tabulation Control), which accepts a selective parameter which
specifies the type of tab operation to be performed. But the DEC variant
only defines a single parameter value (5), which resets all tab stops.
It also considers an omitted parameter to be the equivalent of 5, so we
support that too.
## Validation Steps Performed
I've extended the existing tab stop tests in `ScreenBufferTests` with
some basic coverage of this sequence.
I've also manually verified that the `DECTABSR` script in #14984 now
passes the `DECST8C` portion of the test.
## PR Checklist
- [x] Closes#16533
- [x] Tests added/passed
(cherry picked from commit f5898886be)
Service-Card-Id: 91631721
Service-Version: 1.19
This reverts commit abab8705fe.
It went badly, as you might imagine.
(cherry picked from commit fe65d9ac8f)
Service-Card-Id: 91620326
Service-Version: 1.19
## Summary of the Pull Request
This PR adds support for more Device Status Report (`DSR`) queries,
specifically:
* Printer Status (`DSR ?15`)
* User Defined Keys (`DSR ?25`)
* Keyboard Status (`DSR ?26`)
* Locator Status (`DSR ?55`)
* Locator Identity (`DSR ?56`)
* Data Integrity (`DSR ?75`)
* Multiple Session Status (`DSR ?85`)
## Detailed Description of the Pull Request / Additional comments
For most of these, we just need to return a `DSR` sequence indicating
that the functionality isn't supported.
* `DSR ?13` indicates that a printer isn't connected.
* `DSR ?23` indicates the UDK extension isn't supported.
* `DSR ?53` indicates that a locator device isn't connected
* `DSR ?57;0` indicates the locator type is unknown or not connected.
* `DSR ?83` indicates that multiple sessions aren't supported.
For the keyboard, we report `DSR ?27;0;0;5`, indicating a PC keyboard
(the `5` parameter), a "ready" status (the second `0` parameter), and an
unknown language (the first `0` parameter). In the long term, there may
be some value in identifying the actual keyboard language, but for now
this should be good enough.
The data integrity report was originally used to detect communication
errors between the terminal and host, but that's not really applicable
for modern terminals, so we always just report `DSR ?70`, indicating
that there are no errors.
## Validation Steps Performed
I've added some more adapter tests and output engine tests covering the
new reports.
## PR Checklist
- [x] Closes#16518
- [x] Tests added/passed
(cherry picked from commit 6c192d15be)
Service-Card-Id: 91631713
Service-Version: 1.19
At the time of writing, closing the last tab of a window inexplicably
doesn't lead to the destruction of the remaining TermControl instance.
On top of that, on Win10 we don't destroy window threads due to bugs in
DesktopWindowXamlSource. In other words, we leak TermControl instances.
Additionally, the XAML timer class is "self-referential".
Releasing all references to an instance will not stop the timer.
Only calling Stop() explicitly will achieve that.
The result is that the message loop of a frozen window thread has so
far received 1-2 messages per second due to the blink timer not being
stopped. This may have filled the message queue and lead to bugs as
described in #16332 where keyboard input stopped working.
(cherry picked from commit 521a300c17)
Service-Card-Id: 91642474
Service-Version: 1.19
In the Settings UI's Color Scheme page (where you edit the color scheme itself), update the color chip buttons to include the RGB value in the tooltip and screen reader announcements.
Closes#15985Closes#15983
## Validation Steps Performed
Tooltip and screen reader announcement is updated on launch and when a new value is selected.
(cherry picked from commit 057183b651)
Service-Card-Id: 91642735
Service-Version: 1.19
Fix overlapping disclaimer text in Profiles' Defaults section
In #16261, when we removed ScrollViewer from the subpages in the
settings UI, the main Grid child element order was not preserved and as
a result, the disclaimer text overlapped with the main content on the
page.
To fix that we now apply (the lost) `Grid.Row` property on the parent
StackPanel of the main content.
### Validation Steps Performed
- Disclaimer text does not overlap.
### PR Checklist
- [x] Tests added/passed
In WindowsTerminal, there was a leak of a BSTR with every call to
ITextRangeProvider::GetText, and a failure to call VariantClear in
ITextRange::GetAttributeValue when the value stored in the variant is
VT_BSTR. These were fixed by switching to wil::unique_bstr and
wil::unique_variant.
## Summary of the Pull Request
This PR adds support for the `DECST8C` escape sequence, which resets the
tab stops to every 8 columns.
## Detailed Description of the Pull Request / Additional comments
This is actually a private parameter variant of the ANSI `CTC` sequence
(Cursor Tabulation Control), which accepts a selective parameter which
specifies the type of tab operation to be performed. But the DEC variant
only defines a single parameter value (5), which resets all tab stops.
It also considers an omitted parameter to be the equivalent of 5, so we
support that too.
## Validation Steps Performed
I've extended the existing tab stop tests in `ScreenBufferTests` with
some basic coverage of this sequence.
I've also manually verified that the `DECTABSR` script in #14984 now
passes the `DECST8C` portion of the test.
## PR Checklist
- [x] Closes#16533
- [x] Tests added/passed
## Summary of the Pull Request
This PR adds support for more Device Status Report (`DSR`) queries,
specifically:
* Printer Status (`DSR ?15`)
* User Defined Keys (`DSR ?25`)
* Keyboard Status (`DSR ?26`)
* Locator Status (`DSR ?55`)
* Locator Identity (`DSR ?56`)
* Data Integrity (`DSR ?75`)
* Multiple Session Status (`DSR ?85`)
## Detailed Description of the Pull Request / Additional comments
For most of these, we just need to return a `DSR` sequence indicating
that the functionality isn't supported.
* `DSR ?13` indicates that a printer isn't connected.
* `DSR ?23` indicates the UDK extension isn't supported.
* `DSR ?53` indicates that a locator device isn't connected
* `DSR ?57;0` indicates the locator type is unknown or not connected.
* `DSR ?83` indicates that multiple sessions aren't supported.
For the keyboard, we report `DSR ?27;0;0;5`, indicating a PC keyboard
(the `5` parameter), a "ready" status (the second `0` parameter), and an
unknown language (the first `0` parameter). In the long term, there may
be some value in identifying the actual keyboard language, but for now
this should be good enough.
The data integrity report was originally used to detect communication
errors between the terminal and host, but that's not really applicable
for modern terminals, so we always just report `DSR ?70`, indicating
that there are no errors.
## Validation Steps Performed
I've added some more adapter tests and output engine tests covering the
new reports.
## PR Checklist
- [x] Closes#16518
- [x] Tests added/passed
Avoid generating extra formatted copies when action's `copyFormatting`
is not present and globally set `copyFormatting` is used.
Previously, when the action's `copyFormatting` wasn't set we deferred
the decision of which formats needed to be copied to the
`TerminalPage::CopyToClipboard` handler. This meant we needed to copy
the text in all the available formats and pass it to the handler to copy
the required formats after querying the global `copyFormatting`.
To avoid making extra copies, we'll store the global `copyFormatting` in
TerminalSettings and pass it down to `TermControl`. If
`ControlCore::CopySelectionToClipboard()` doesn't receive action
specific `copyFormatting`, it will fall back to the global one _before
generating the texts_.
## Validation Steps Performed
- no `copyFormatting` set for the copy action: Copies formats according
to the global `copyFormatting`.
- `copyFormatting` is set for the copy action: Copies formats according
to the action's `copyFormatting`.
At the time of writing, closing the last tab of a window inexplicably
doesn't lead to the destruction of the remaining TermControl instance.
On top of that, on Win10 we don't destroy window threads due to bugs in
DesktopWindowXamlSource. In other words, we leak TermControl instances.
Additionally, the XAML timer class is "self-referential".
Releasing all references to an instance will not stop the timer.
Only calling Stop() explicitly will achieve that.
The result is that the message loop of a frozen window thread has so
far received 1-2 messages per second due to the blink timer not being
stopped. This may have filled the message queue and lead to bugs as
described in #16332 where keyboard input stopped working.
Up to now we've using `U+2E2E` (reverse question mark) to represent the
`SUB` control glyph. This PR changes the glyph to `U+2426` (substitute
form two), which is also rendered as a reverse question mark, but is
more semantically correct.
The original `SUB` control rendering was implemented in PR #15075.
I've manually confirmed that `printf "\x1A"` is now shown as a reverse
question mark in OpenConsole when using the Cascadia Code font. That
would not previously have worked, because `U+2E2E` is not supported by
Cascadia Code.
Closes#16558
(cherry picked from commit 92f9ff948b)
Service-Card-Id: 91559316
Service-Version: 1.19
This pull request started out very differently. I was going to move all
the EDP code from the internal `conint` project into the public, because
EDP is [fully documented]!
Well, it doesn't have any headers in the SDK.
Or import libraries.
And it's got a deprecation notice:
> [!NOTE]
> Starting in July 2022, Microsoft is deprecating Windows Information
> Protection (WIP) and the APIs that support WIP. Microsoft will
continue
> to support WIP on supported versions of Windows. New versions of
Windows
> won't include new capabilities for WIP, and it won't be supported in
> future versions of Windows.
So I'm blasting it out the airlock instead.
[fully documented]:
https://learn.microsoft.com/en-us/windows/win32/devnotes/windows-information-protection-api
(cherry picked from commit c4c06dadad)
Service-Card-Id: 91327265
Service-Version: 1.19
2024-01-22 16:50:24 -06:00
1018 changed files with 127559 additions and 38150 deletions
* Handles the command prompt line as you see in CMD.exe (known as the processed input line… most other shells handle this themselves with raw input and don’t use ours. This is a legacy of bad architectural design, putting stuff in conhost not in CMD)
*`cmdline.cpp`
* Handles shunting IME data back and forth to the TSF library and to and from the various buffers
*`Conimeinfo.cpp`
*`Convarea.cpp`
* Contains the global state for the entire console application
*`consoleInformation.cpp`
* Stuff related to the low-level server communication over our protocol with the driver
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.
### Are you seeing `DEP0700: Registration of the app failed`?
Once in a blue moon, I get a `DEP0700: Registration of the app failed.
[0x80073CF6] error 0x80070020: Windows cannot register the package because of an
internal error or low memory.` when trying to deploy in VS. For us, that can
happen if the `OpenConsoleProxy.dll` gets locked up, in use by some other
terminal package.
Doing the equivalent command in powershell can give us more info:
"description":"Sets the DWrite font features for the given font. For example, { \"ss01\": 1, \"liga\":0 } will enable ss01 and disable ligatures.",
"type":"object",
"patternProperties":{
"^(([A-Za-z0-9]){4})$":{
"^[\\x20-\\x7E]{4}$":{
"type":"integer"
}
},
@@ -359,7 +360,7 @@
"description":"Sets the DWrite font axes for the given font. For example, { \"wght\": 200 } will set the font weight to 200.",
"type":"object",
"patternProperties":{
"^([A-Za-z]{4})$":{
"^[\\x20-\\x7E]{4}$":{
"type":"number"
}
},
@@ -618,6 +619,11 @@
"type":"boolean",
"default":false,
"description":"This will override the profile's `elevate` setting."
},
"reloadEnvironmentVariables":{
"type":"boolean",
"default":true,
"description":"When set to true, a new environment block will be generated when creating a new session. Otherwise, the session will inherit the variables the Terminal was started with."
}
},
"type":"object"
@@ -1501,8 +1507,10 @@
"const":"multipleActions"
},
"actions":{
"$ref":"#/$defs/ShortcutAction",
"type":"array",
"items":{
"$ref":"#/$defs/ShortcutAction"
},
"minItems":1,
"description":"A list of other actions."
}
@@ -1891,6 +1899,14 @@
],
"type":"string"
},
"IconStyle":{
"enum":[
"default",
"hidden",
"monochrome"
],
"type":"string"
},
"ThemeColor":{
"description":"A special kind of color for use in themes. Can be an #rrggbb color, #rrggbbaa color, or a special value. 'accent' is evaluated as the user's selected Accent color in the OS, and 'terminalBackground' will be evaluated as the background color of the active terminal pane.",
"oneOf":[
@@ -1928,6 +1944,10 @@
"showCloseButton":{
"description":"Controls the visibility of the close button on the tab",
"$ref":"#/$defs/ShowCloseButton"
},
"iconStyle":{
"description":"Controls the appearance of a tab's icon",
"$ref":"#/$defs/IconStyle"
}
}
},
@@ -2065,6 +2085,9 @@
{
"$ref":"#/$defs/SwitchToTabAction"
},
{
"$ref":"#/$defs/ScrollToMarkAction"
},
{
"$ref":"#/$defs/MoveFocusAction"
},
@@ -2200,6 +2223,10 @@
}
}
},
"id":{
"description":"The ID of this command. If one isn't provided, we will generate one internally.",
"type":"string"
},
"iterateOn":{
"type":"string",
"description":"Used to create iterable commands based on other objects in your settings. Possible values:\n- \"profiles\" \n- \"schemes\"",
@@ -2211,7 +2238,15 @@
"commands":{
"description":"List of commands to execute",
"items":{
"$ref":"#/$defs/Keybinding/properties/command"
"type":"object",
"properties":{
"command":{
"$ref":"#/$defs/Keybinding/properties/command"
},
"name":{
"$ref":"#/$defs/Keybinding/properties/name"
}
}
},
"minItems":1,
"type":"array"
@@ -2332,12 +2367,20 @@
},
"type":"array"
},
"experimental.rendering.forceFullRepaint":{
"description":"When set to true, we will redraw the entire screen each frame. When set to false, we will render only the updates to the screen between frames.",
"rendering.graphicsAPI":{
"description":"Direct3D 11 provides a more performant and feature-rich experience, whereas Direct2D is more stable. The default option \"Automatic\" will pick the API that best fits your graphics hardware. If you experience significant issues, consider using Direct2D.",
"type":"string",
"enum":[
"direct2d",
"direct3d11"
]
},
"rendering.disablePartialInvalidation":{
"description":"By default, the text renderer uses a FLIP_SEQUENTIAL Swap Chain and declares dirty rectangles via the Present1 API. When this setting is enabled, a FLIP_DISCARD Swap Chain will be used instead, and no dirty rectangles will be declared. Whether one or the other is better depends on your hardware and various other factors.",
"type":"boolean"
},
"experimental.rendering.software":{
"description":"When set to true, we will use the software renderer (a.k.a. WARP) instead of the hardware one.",
"rendering.software":{
"description":"When enabled, the terminal will use a software rasterizer (WARP). This setting should be left disabled under almost all circumstances.",
"type":"boolean"
},
"experimental.input.forceVT":{
@@ -2764,13 +2807,14 @@
"type":"string"
}
},
"experimental.autoMarkPrompts":{
"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.",
"experimental.autoMarkPrompts":{
"deprecated":true,
"description":"This has been replaced by autoMarkPrompts in 1.21",
"type":"boolean"
},
"experimental.retroTerminalEffect":{
@@ -2778,19 +2822,29 @@
"type":"boolean"
},
"experimental.showMarksOnScrollbar":{
"deprecated":true,
"description":"This has been replaced by showMarksOnScrollbar in 1.21",
"type":"boolean"
},
"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.rightClickContextMenu":{
"default":false,
"description":"When set to true, right-clicking on the terminal will show a context menu. When set to false, right-click will copy",
"type":"boolean"
},
"experimental.repositionCursorWithMouse":{
"default":false,
"description":"When set to true, you can move the text cursor by clicking with the mouse on the current commandline. This is an experimental feature - there are lots of edge cases where this will not work as expected.",
"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"
},
"useAtlasEngine":{
"description":"Windows Terminal 1.16 and later ship with a new, performant text renderer. Set this to false to revert back to the old text renderer.",
"type":"boolean",
"default":true
},
"fontFace":{
"default":"Cascadia Mono",
"description":"[deprecated] Define 'face' within the 'font' object instead.",
@@ -23,7 +23,7 @@ contexts without needing to replicate an entire json blob.
This spec was largely inspired by the following diagram from @DHowett:


The goal is to introduce an `id` parameter by which actions could be uniquely
referred to. If we'd ever like to use an action outside the list of `actions`, we
@@ -36,38 +36,54 @@ Discussion with the team lead to the understanding that the name `actions` would
be even better, as a way of making the meaning of the "list of actions" more
obvious.
When we're parsing `actions`, we'll make three passes:
*The first pass will scan the list for objects with an `id` property. We'll
We will then restructure `defaults.json`, and also users' settings files (via `fixUpUserSettings`), in the following manner:
*Instead of each `command` json block containing both the `action` (along with additional arguments) and the `keys`, these will now be split up -
* There will now be one json block for just the `command`/`action`, which will also contain the `id`. These json blocks will be in their own list called `actions`.
* There will be another json block for the `keys`, which will refer to the action to be invoked by `id`. These json blocks will be in their own list called `keybindings`.
For example, let's take a look at the `split pane right` action in `defaults.json` as we currently have it:
Here is how we will parse settings file and construct the relevant settings model objects:
* We will first scan the `actions` list. We'll
attempt to parse those entries into `ActionAndArgs` which we'll store in the
global `id->ActionAndArgs` map. If any entry doesn't have an`id` set, we'll
skip it in this phase. If an entry doesn't have a `command` set, we'll ignore
it in this pass.
* The second pass will scan for _keybindings_. Any entries with `keys` set will
create a `KeyChord->ActionAndArgs` entry in the keybindings map. If the entry
has an `id` set, then we'll simply re-use the action we've already parsed for
the `id`, from the action map. If there isn't an `id`, then we'll parse the
action manually at this time. Entries without a `keys` set will be ignored in
this pass.
* The final pass will be to generate _commands_. Similar to the keybindings
pass, we'll attempt to lookup actions for entries with an `id` set. If there
isn't an `id`, then we'll parse the action manually at this time. We'll then
get the name for the entry, either from the `name` property if it's set, or
the action's `GenerateName` method.
global `id->ActionAndArgs` map. All actions defined in `defaults.json` must have an `id` specified, and all actions provided by fragments must also have `id`s. Any actions from the defaults or fragments that do not provide `id`s will be ignored. As for user-specified commands, if no`id` is set, we will auto-generate one for that command based on the action and any additional arguments. For example, the `split pane right` command above might result in an autogenerated id `User.SplitPaneRight`.
* Note: this step is also where we will generate _commands_. We will use the name provided in the entry if it's set or the action's `GenerateName` method.
* Next we will scan the `keybindings` list. These entries will
create a `KeyChord->ActionAndArgs` entry in the keybindings map. Since these objects should all contain an `id`, we will simply use the `id->ActionAndArgs` map we created in the previous step. Any object with `keys` set but no `id` will be ignored.
For a visual representation, let's assume the user has the following in their
For this case, having an `id` on the top level could potentially make sense when it comes to using that `id` in a menu, but not in the case of using that `id` for a keybinding. For the initial implementation, we will not support an `id` for these types of actions, which leaves us open to revisiting this in the future.
### Layering
When layering `actions`, if a later settings file contains an action with the
same `id`, it will replace the current value. In this way, users can redefine
@@ -87,6 +103,9 @@ As we add additional menus to the Terminal, like the customization for the new
tab dropdown, or the tab context menu, or the `TermControl` context menu, they
could all refer to these actions by `id`, rather than duplicating the same json.
As for fragments, all actions in fragments _must_ have an `id`. If a fragment provides an action without an `id`, or provides an `id` that clashes with one of the actions in `defaults.json`, that action will be ignored.
> 👉 NOTE: This will mean that actions will now need an `OriginTag`, similar to profiles and color schemes
| `ALLOC_CONSOLE_MODE_DEFAULT` | Allocate a console session if (and how) one was requested by the parent process. |
| `ALLOC_CONSOLE_MODE_NEW_WINDOW` | Allocate a console session with a window, even if this process was created with `CREATE_NO_CONSOLE` or `DETACHED_PROCESS`. |
| `ALLOC_CONSOLE_MODE_NO_WINDOW` | Allocate a console session _without_ a window, even if this process was created with `CREATE_NEW_WINDOW` or `DETACHED_PROCESS` |
###### Notes
Applications seeking backwards compatibility are encouraged to delay-load `AllocConsoleWithOptions` or check for its presence in
the `api-ms-win-core-console-l1` APISet.
## Inspiration
Fusion manifest entries are used to make application-scoped decisions like this all the time, like `longPathAware` and
`heapType`.
CUI applications that can spawn a UI (or GUI applications that can print to a console) are commonplace on other
platforms because there is no subsystem differentiation.
## UI/UX Design
There is no UI for this feature.
## Capabilities
### Accessibility
This should have no impact on accessibility.
### Security
One reviewer brought up the potential for a malicious actor to spawn an endless stream of headless daemon processes.
This proposal in no way changes the facilities available to malicious people for causing harm: they could have simply
used `IMAGE_SUBSYSTEM_WINDOWS_GUI` and not presented a UI--an option that has been available to them for 35 years.
### Reliability
This should have no impact on reliability.
### Compatibility
An existing application opting into **detached** may constitute a breaking change, but the scope of the breakage is
restricted to that application and is expected to be managed by the application.
All behavioral changes are opt-in.
> **EXAMPLE**: If Python updates python.exe to specify an allocation policy of **detached**, graphical python applications
> will become double-click runnable from the graphical shell without spawning a console window. _However_, console-based
> python applications will no longer spawn a console window when double-clicked from the graphical shell.
>
> In addition, if python.exe specifies **detached**, Console APIs will fail until a console is allocated.
Python could work around this by calling [`AllocConsole`] or [new API `AllocConsoleWithOptions`](#allocconsolewithoptions)
if it can be detected that console I/O is required.
#### Downlevel
On downlevel versions of Windows that do not understand (or expect) this manifest field, applications will allocate
consoles as specified by their image subsystem (described in the [abstract](#abstract) above).
### Performance, Power, and Efficiency
This should have no impact on performance, power or efficiency.
## Potential Issues
### Shell Hang
I am **not** proposing a change in how shells determine whether to wait for an application before returning to a prompt.
This means that a console subsystem application that intends to primarily present a UI but occasionally print text to a
console (therefore choosing the **detached** allocation policy) will cause the shell to "hang" and wait for it to
exit.
The decision to pause/wait is made entirely in the calling shell, and the console subsystem cannot influence that
decision.
Because the vast majority of shells on Windows "hang" by calling `WaitFor...Object` with a HANDLE to the spawned
process, an application that wants to be a "hybrid" CUI/GUI application will be forced to spawn a separate process to
detach from the shell and then terminate its main process.
This is very similar to the forking model seen in many POSIX-compliant operating systems.
### Launching interactively from Explorer, Task Scheduler, etc.
Applications like PowerShell may wish to retain automatic console allocation, and **detached** would be unsuitable for
them. If PowerShell specifies the `detached` console allocation policy, launching `pwsh.exe` from File Explorer it will
no longer spawn a console. This would almost certainly break PowerShell for all users.
Such applications can use `AllocConsole()` early in their startup.
At the same time, PowerShell wants `-WindowStyle Hidden` to suppress the console _before it's created_.
Applications in this category can use `AllocConsoleWithOptions()` to specify additional information about the new console window.
PowerShell, and any other shell that wishes to maintain interactive launch from the graphical shell, can start in
**detached** mode and then allocate a console as necessary. Therefore:
* PowerShell will set `<consoleAllocationPolicy>detached</consoleAllocationPolicy>`
* On startup, it will process its commandline arguments.
* If `-WindowStyle Hidden` is **not** present (the default case), it can:
* `AllocConsole()` or `AllocConsoleWithOptions(NULL)`
* Either of these APIs will present a console window (or not) based on the flags passed through `STARTUPINFO` during
[`CreateProcess`].
* If `-WindowStyle Hidden` is present, it can:
* `AllocConsoleWithOptions(&alloc)` where `alloc.mode` specifies `ALLOC_CONSOLE_MODE_HIDDEN`
## Future considerations
We're introducing a new manifest field today -- what if we want to introduce more? Should we have a `consoleSettings`
manifest block?
Are there other allocation policies we need to consider?
## Resources
### Rejected Solutions
- A new PE subsystem, `IMAGE_SUBSYSTEM_WINDOWS_HYBRID`
- it would behave like **inheritOnly**
- relies on shells to update and check for this
- checking a subsystem doesn't work right with app execution aliases[^3]
- This is not a new problem, but it digs the hole a little deeper.
- requires standardization outside of Microsoft because the PE format is a dependency of the UEFI specification[^4]
- requires coordination between tooling teams both within and without Microsoft (regarding any tool that operates on
or produces PE files)
- An exported symbol that shells can check for to determine whether to wait for the attached process to exit
- relies on shells to update and check for this
- cracking an executable to look for symbols is probably the last thing shells want to do
- we could provide an API to determine whether to wait or return?
- fragile, somewhat silly, exporting symbols from EXEs is annoying and uncommon
An earlier version of this specification offered the **always** allocation policy, with the following behaviors:
> **STRUCK FROM SPECIFICATION**
>
> * A GUI subsystem application would always get a console window.
> * A command-line shell would not wait for it to exit before returning a prompt.
It was cut because a GUI application that wants a console window can simply attach to an existing console session or
allocate a new one. We found no compelling use case that would require the forced allocation of a console session
outside of the application's code.
An earlier version of this specification offered the **inheritOnly** allocation policy, instead of the finer-grained
**hidden** and **detached** policies. We deemed it insufficient for PowerShell's use case because any application
launched by an **inheritOnly** PowerShell would immediately force the uncontrolled allocation of a console window.
> **STRUCK FROM SPECIFICATION**
>
> The move to **hidden** allows PowerShell to offer a fully-fledged console connection that can be itself inherited by a
> downstream application.
#### Additional allocation policies
An earlier revision of this specification suggested two allocation policies:
> **STRUCK FROM SPECIFICATION**
>
> **hidden** is intended to be used by console applications that want finer-grained control over the visibility of their
> console windows, but that still need a console host to service console APIs. This includes most scripting language
> interpreters.
>
> **detached** is intended to be used by primarily graphical applications that would like to operate against a console _if
> one is present_ but do not mind its absence. This includes any graphical tool with a `--help` or `/?` argument.
The `hidden` policy was rejected due to an incompatibility with modern console hosting, as `hidden` would require an
application to interact with the console window via `GetConsoleWindow()` and explicitly show it.
> **STRUCK FROM SPECIFICATION**
>
> ##### ShowWindow and ConPTY
>
> The pseudoconsole creates a hidden window to service `GetConsoleWindow()`, and it can be trivially shown using
> `ShowWindow`. If we recommend that applications `ShowWindow` on startup, we will need to guard the pseudoconsole's
> pseudo-window from being shown.
[^1]: [Powershell -WindowStyle Hidden still shows a window briefly]
[^2]: [StackOverflow: pythonw.exe or python.exe?]
[^3]: [PowerShell: Windows Store applications incorrectly assumed to be console applications]
[^4]: [UEFI spec 2.6 appendix Q.1]
[Powershell -WindowStyle Hidden still shows a window briefly]: https://github.com/PowerShell/PowerShell/issues/3028
[PowerShell: Windows Store applications incorrectly assumed to be console applications]: https://github.com/PowerShell/PowerShell/issues/9970
[StackOverflow: pythonw.exe or python.exe?]: https://stackoverflow.com/questions/9705982/pythonw-exe-or-python-exe
<string id="DisabledProfileSourcesText">Profiles will not be generated from any sources listed here. Source names can be arbitrary strings. Potential candidates can be found as the "source" property on profile definitions in Windows Terminal's settings.json file.
Common sources are:
- Windows.Terminal.Azure
- Windows.Terminal.PowershellCore
- Windows.Terminal.Wsl
For instance, setting this policy to Windows.Terminal.Wsl will disable the builtin WSL integration of Windows Terminal.
Note: Existing profiles will disappear from Windows Terminal after adding their source to this policy.</string>
</stringTable>
<presentationTable>
<presentation id="DisabledProfileSources">
<multiTextBox refId="DisabledProfileSources">List of disabled sources (one per line)</multiTextBox>
// We must not just ensure that `buffer` has at least `capacity`, but also that its reference count is <= 1, because otherwise we would resize a shared buffer.
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.