Throwing an exception all the way out of COOKED_READ_DATA::Read is
deleterious for the health of the application. We fail to unbind the
waiter and may leave a dangling pointer around for some applications
(and for some NPC security researchers to think provides an EoP, but
does not.)
This also moves us away from std::stoi in the history pop-up path
entirely.
- Fixed#20772 by fully committing to lazy DA1 capabilities path via
`VtIo::SetDeviceAttributes`. It accidentally only did so with enabled
cursor inheritance before.
- Fixed#20773 by fixing the source/destination rectangle alignment
in the non-DECCRA path of `ScrollConsoleScreenBuffer`.
Also closes MSFT-64450466.
As a drive-by:
- Fixed the DECCRA path not restoring cursor attributes in conhost.
- Reduced memory use in the non-DECCRA path.
- Added a `IL/DL` sequence fast-pass for `ScrollConsoleScreenBuffer`.
- Fixed a broken bounds checks in `Read/WriteConsoleOutputWImplHelper`.
- Fixed the TraceLogging definition for `SMALL_RECT`.
Consumers have no need to know about these, and can instead deal with a
new opaque `IContentHandle`. Exposing them offered too much latitude to
do the "wrong thing" with TermControl's constituent types. Even _if_ we
were doing something cross-process, the upper layer doesn't need to use
our implementation details.
In doing this, I've also removed the unused Content::Attached event.
Our window message intercepts Alt key-up (and F7 key-down) to handle
them before XAML messes them up. These events get forwarded through
IDirectKeyListener, but the ENHANCED_KEY bit from `lParam` was being
lost.
Verified manually.
Closes#18120
This reverts a large part of #10051 and moves us back to using the
native `implementation`-namespace types from TermControl to talk to
ControlInteractivity and ControlCore.
I started down this rabbit hole because I was trying to get rid of
InteractivityAutomationPeer, and I learned that we introduced it as a
go-between for the process-split TermControl/Interactivity.
InteractviityAutomationPeer is not required, and removing it lets us get
rid of some other mild annoyances:
- We don't need to _push_ the bounds of the control down into
Interactivity any longer
- Likewise for padding
Bounds and padding can simply be read directly from the control.
I also undid the move from HANDLE to uint64_t which was only required
for projecting HANDLEs.
The only thing we risked losing out on was automatic event revokers, but
this pull request adds `winrt::auto_revoke` support directly to
`til::event`. It is suitably terrifying. It is certainly UB.
For experimental settings, display a bright yellow badge next to it. So,
as part of this, removed "experimental" from the descriptions since the
badge is indicating that already.
Closes#20687
`_kittyFlags` represents the current buffer flags. When you enable the
ASB, we reset `_kittyFlags` to 0. When you disable the ASB, we restore
the flags from the `_kittyMainStack`. Boom, broken. We never pushed
anything into the `_kittyMainStack` in the first place.
The gets rid of `_kittyFlags`. To make it neat, I also replaced
the heap vector with a static array + length.
Closes#20763
It didn't have one before, so screen readers were just reading out
"button". This commit fixes that, screen readers now read out "delete
shortcut button"
Closes#20601
This reverts commit 1507c46524.
The root cause of the PGO failure is documented in #20749. Also, the PR
#20560 didn't actually _fix_ them. :P
Note that this DOES NOT FIX the PGO build.
OpenCWD now no-ops unless the terminal working directory is an existing
directory, then opens that folder. It no longer passes the raw OSC
string to `explorer.exe` as parameters.
Refs #12859 (the original action asked to do nothing when no CWD is set)
OpenCWD was introduced in #18013.
`ControlCore::OpenCWD` is the command-palette action `Terminal.OpenCWD`.
It used:
```cpp
ShellExecute(nullptr, nullptr, L"explorer", workingDirectory.c_str(), nullptr, SW_SHOW);
```
The working-directory string comes from OSC 7 (`file:` URI, then
`PathCreateFromUrlW`) or OSC 9;9. Both only require
`til::is_legal_path`, which allows `:` and `/`. So a remote host can set
CWD to `https://example.com`, `shell:...`, or `/select,...`. Invoking
Open CWD then ran Explorer with that text as `lpParameters`.
Duplicate-tab and related paths already call `Utils::IsValidDirectory`
before trusting this string (`TerminalPage.cpp`,
`TerminalPaneContent.cpp`). Open CWD now does the same, then
`ShellExecute`s the directory path as `lpFile` so Explorer switches
cannot be supplied as parameters.
If the CWD is empty or not a directory, the action does nothing.
This pull request builds on the render timer infrastructure in #19330
and the pointer ID work in #20017 to move automatic scrolling down into
the Interactivity layer.
Leonard tells me that this is an acceptable use of the render timer
infrastructure because it directly results in a new frame or new content
being rendered (therefore, it does not spin the renderer for no reason.)
Much of the code is the same. I recommend reviewing with:
```
git diff --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space (git merge-base origin/main origin/dev/duhowett/wpf-1-autoscroll-to-interactivity) origin/dev/duhowett/wpf-1-autoscroll-to-interactivity
```
Hilarious repro: `printf "\e]0;A\a\e]52;c;Qg==\a"`
This issue is exactly what happens when you Ctrl+X in a clean file in
msedit and it freezes Windows Terminal. It's because it puts a "•" in
the title and copies the text.
It triggers a title and clipboard change in the same frame which causes
the UI and VT thread to deadlock trying to get the console lock.
* D3D uses deferred execution where render commands are collected as
descriptors in a ring buffer before they're sent off to the GPU.
When you don't call `Flush()` (or `Present()` which implies `Flush()`)
it'll fill up 100s of MB of memory rapidly.
This PR solves it in two ways:
* Call `Flush()` whenever we can't call `Present()`
* Make calling `Flush()` unnecessary by checking if we need to render
anything in the first place.
* This immediately results in an issue: Not rendering means the frame
latency waitable object yields immediately (because we can't wait on
it twice). The solution is to wait 16ms before trying again.
* If the display is off, DWM will not deque frames. `Present1()` will
indicate this (`DXGI_STATUS_OCCLUDED`) but it's not a failure so we
don't handle it. Because of this we'll fill the queue to its maximum
(64 frames). Once the display is on again, DWM will deque at V-Sync
rate, but since we render as fast as the frame latency waitable
object, also signaled at V-Sync rate, we'll push frames at the same
rate they're dequeued, causing a 64-frame latency (~1.1s at 60Hz).
`SetMaximumFrameLatency(1)` doesn't change this.
The solution is that we don't limit waiting on the frame latency
waitable object to just 100ms, but `INFINITE`.
* Since that fix causes the renderer to wait potentially forever,
a mechanism to cancel waits on shutdown is necessary.
This also uncovered a flaw in the current design, wherein it blocks
the UI thread for up to 100ms every time you close or move a tab
on a low frame rate (or no active) display.
Closes#20226Closes#20342Closes#20716
## Validation Steps Performed
* Continuously render, scroll up -> no GPU use ✅
When ControlCore is set up to target an HWND, there will not be a swap
chain handle.
When there's not going to be a swap chain handle or a listener who cares
about it, don't bother with the event registration (save memory on a
useless object) and don't bother sending the event.
Supersedes #20712
This is in advance of the UWP/WPF unification work, where we need to
provide a dispatcher from the WPF side. It should be a no-op today, but
we could also move _loading_ the dispatcher up to TermControl (XAML).
This prevents retry builds from failing because `logs-x64-Release` (or
whatever) already exists.
`build-platform-config` is not published if the prior steps fail, and
furthermore its name is a contract with the later stages, so I've left
it alone.
## Summary of the Pull Request
Updates the individual profile pages to include:
- icons + settings expanders/cards
- `SettingsResetButton`: a new "reset value" button
- a new "unfocused appearance" subpage with its own preview (similar to
default appearance)
## Detailed Description of the Pull Request / Additional comments
- `IInheritableViewModel`: interface exposing `HasSetting()`,
`ClearSetting()`, and `SettingOverrideSource()`
- To help ensure that these are updated properly, a static assert was
added that checks the number of profile settings. This is intended to be
a tripwire to ensure future changes also update the reset buttons.
- `Profiles_UnfocusedAppearance.h/cpp/idl/xaml`: the new unfocused
appearance page
- added helper functions `FormatAccessibleName()` and
`ColorToHexString()` to deduplicate code that creates accessible names
for SettingsExpanders across the entire SUI
## Validation Steps Performed
- [X] settings search + deep link navigation
- [X] "reset value" button
- [X] accessibility pass with Narrator
## PR Checklist
Related to #17000
---------
Co-authored-by: Dustin L. Howett <dustin@howett.net>
Okay, so, every SettingsCard inherits from ButtonBase. ButtonBase has
its own local KeyDown/KeyUp handler, which can prevent the event from
being bubbled at all.
Moving our key handling to our local KeyDown/KeyUp handler allows us to
decide when to involve ButtonBase's handler, rather than allowing it to
delegate to us.
Incidentally, this is probably why the implementer had to use the
PreviewKeyXxx events; it was the only other way to get a "say" before
the button handled it itself.
Closes#20657 (superseded)
## Summary of the Pull Request
Adds expander groups throughout the entire settings UI (except Profiles
pages) to group similar settings together. These expanders got an icon
to help make them easier to find and navigate.
There are also a few other changes that were folded into this PR:
- "Appearance" page was renamed to "Personalization"
- Move settings from "Rendering" page to "Compatibility"
Those were done as a part of this PR for a holistic restructuring. Given
that spacing has changed, the content also needs to be reviewed so that
it looks right with this new structure (i.e. long help text should be
reconsidered to be shorter).
## Validation Steps Performed
Scenarios:
- ensure all settings are in expanders
- [x] Startup
- [x] Interaction
- [x] Personalization
- [x] Compatibility
- [x] settings search still works and deep links
## PR Checklist
Related to #17000
Raise the visible terminal minimum from 1×1 cells to 2×2 cells so a pane
or window can no longer reach a 1-column viewport (keyboard, mouse,
`split-pane`, `wt --size`, `initialCols`/`initialRows`, or VT resize).
This mitigates an issue where we hang when we display a 2-cell char
in one cell.
Refs:
- j4james: 2×2 is the VT theoretical minimum (`DECSTBM` height ≥ 2,
`DECSLRM` width ≥ 2).
Verification:
- Confirmed the hang on unpatched Dev (`WindowsTerminalDev`) and Store
1.24.11911 with `echo 音楽🎵测试` in view, then shrink the left pane to the
stop.
Closes#19996
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>