## Summary of the Pull Request
Updates the NullableColorPicker to use a flyout instead of a content
dialog. Frankly, it should've been this way from the start.
#19561 is an issue regarding the rectangle on the right side of the
picker. The complaint being that it should be something more useful than
a preview, an idea being that it could be a lightness gradient.
Unfortunately, the WinUI color picker doesn't let you do that. It's just
a plain preview.
That said, there's a lot of customizations that can be added still to
increase value here. To name a few:
- IsColorSliderVisible --> a color slider to adjust the lightness of the
color (as desired in #19561)
- IsHexInputVisible --> an input field to see and adjust the hex value
directly
- IsColorChannelTextInputVisible --> several input fields to adjust
individual RGB channels or switch over to HSV
However, the content dialog doesn't allow for text input due to a WinUI
bug and it's too small to display all of those controls.
Instead, I just discarded the content dialog altogether and opted into a
flyout. This makes it a more consistent experience with the other color
pickers (i.e. tab color, edit color scheme page). This also adds space
for all of the functionality mentioned above (those properties are
enabled by default).
## Validation Steps Performed
✅ selecting a color still works
Closes#19561
## Summary of the Pull Request
Fixes a bug where search would not scroll to results just below the
viewport.
This was caused by code intended to scroll the search result in such a
way that it isn't covered by the search box. The scroll offset is
calculated in `TermControl::_calculateSearchScrollOffset()` then handed
down in the `SearchRequest` when conducting a search. This would get to
`Terminal::ScrollToSearchHighlight()` where the offset is applied to the
search result's position so that we would scroll to the adjusted
position.
The adjustment was overly aggressive in that it would apply it to both
"start" and "end". In reality, we don't need to apply it to "end"
because it wouldn't be covered by the search box (we only scroll to end
if it's past the end of the current view anyways).
The fix applies the adjustment only to "start" and only does so if it's
actually in the first few rows that would be covered by the search box.
That unveiled another bug where `Terminal::_ScrollToPoints()` would also
be too aggressive about scrolling the "end" into view. In some testing,
it would generally end up scrolling to the end of the buffer. To fix
this cascading bug, I just had `_ScrollToPoints()` just call
`Terminal::_ScrollToPoint()` (singular, not plural) which is
consistently used throughout the Terminal code for selection (so it's
battle tested).
`_ScrollToPoints()` was kept since it's still used for accessibility
when selecting a new region to keep the new selection in view. It's also
just a nice wrapper that ensures a range is visible (or at least as much
as it could be).
## References and Relevant Issues
Scroll offset was added in #17516
## Validation Steps Performed
✅ search results that would be covered by the search box are still
adjusted
✅ search results that are past the end of the view become visible
✅ UIA still selects properly and brings the selection into view
## PR Checklist
Duncan reported this bug internally, but there doesn't seem to be one on
the repo.
Previously, launching an unelevated session after an elevated one would
delete the latter's persisted buffers, and vice versa of course. Also,
elevated buffers didn't have an ACL forbidding access to unelevated
users. That's also fixed now.
Closes#19526
## Validation Steps Performed
* Unelevated/elevated WT doesn't erase each other's buffers ✅
* Old buffers named `buffer_` are renamed to `elevated_` if needed ✅
## Summary of the Pull Request
Replaces the `ComboBox` used for built-in profile icons with an
`AutoSuggestBox` to allow for searching.
## References and Relevant Issues
Practically plagiarizes #16821
## Validation Steps Performed
✅ It completes
✅ It filters
## PR Checklist
Closes#19457
## Summary of the Pull Request
This PR fixes a bug where programmatic scrolling would get stuck. The
fix makes the "snap-on-input" feature conditional, activating it only
for modern applications that use Virtual Terminal (VT) processing. This
restores correct scrolling behavior for legacy applications without
removing the feature for new ones.
## References and Relevant Issues
Fixes#19390: OpenConsole: Cursor visibility prevents programmatic
scrolling
## Detailed Description of the Pull Request / Additional comments
The "snap-on-input" feature introduced in a previous PR caused an
unintended side effect for older console programs that use the
SetConsoleWindowInfo API to manage their own viewport. When such a
program tried to scroll using a key press, the snap feature would
immediately pull the view back to the cursor's position, causing the
screen to flicker and get stuck.
This fix makes the snap-on-input feature smarter by checking the
application's mode first.
## Validation Steps Performed
Compiled the minimal C++ reproduction case from issue #19390.
Ran the test executable inside the newly built OpenConsole.exe.
Confirmed that scrolling with the Up/Down arrow keys now works
correctly, even with a visible cursor. The view no longer flickers or
gets stuck when the cursor moves outside the viewport.
Closes#19390
## Summary of the Pull Request
Searching in terminal highlights all search results. However, those
results are considered separate from a selection. In the past, the
highlighted result would be selected, resulting in it being the initial
position for mark mode. Now that it's separate, mark mode doesn't start
there.
To fix this, there's 2 changes here:
1. When we exit the search, we now select the focused search result.
This becomes the initial position for mark mode.
2. When we're in the middle of a search and mark mode becomes enabled,
the focused search result becomes the initial position for mark mode.
With this change, mark mode's initial position is determined in this
order:
1. the position of an active selection
2. the position of the focused search result (if one is available)
3. the top-left position of the viewport (if there is a scrollback) (see
#19549)
4. the current cursor position
## Validation Steps Performed
Entering mark mode in scenario X results in a starting position of Y:
✅ selected text during a search --> selected text
- NOTE: this seems to only occur if you start a search, then manually
click on the terminal to bring focus there, but keep the search results
active
✅ performed a search and results are available -->focused search result
✅ performed a search and no results are available
- scrolled up --> top-left of viewport
- no scrollback --> cursor position
✅ performed a search, got results, then closed search --> focused search
result
Closes#19358
## Summary of the Pull Request
Updates mark mode so that it starts at the viewport's origin (top-left)
if we're not scrolled to the bottom. This is based on the discussion in
#19488.
## Validation Steps Performed
✅ scrolled at bottom --> mark mode starts at cursor
✅ scrolled up --> mark mode starts at cursor
Closes#19488
This PR moves the cursor blinker and VT blink rendition timer into
`Renderer`. To do so, this PR introduces a generic timer system with
which you can schedule arbitrary timer jobs. Thanks to this, this PR
removes a crapton of code, particularly throughout conhost.
## Validation Steps Performed
* Focus/unfocus starts/stops blinking ✅
* OS-wide blink settings apply on focus ✅
We used to run the cloud shell connector in an intermediate process
because our VT implementation lived mostly in conhost. James fixed that
up over the intervening years, and since #17510 landed Terminal is
exposed to 100% of application-originated VT. That means we no longer
need this workaround, its build steps, or anything else about it.
Closes#4661
I looked as far back as I was able to find, and we've used the OutputCP
since at least Windows NT 3.51.
I think it has _never_ been correct.
At issue today is the GB18030-2022 test string, which contains the
following problematic characters:
* `ˊ` `U+02CA` Modifier Letter Acute Accent
* `ˋ` `U+02CB` Modifier Letter Grave Accent
* `˙` `U+02D9` Dot Above
* `–` `U+2013` En Dash
They cannot be pasted into PowerShell 5.1 (PSReadline).
It turns out that when we try to synthesize an input event (Alt down,
numpad press, Alt up **with wchar**) we are using their output codepage
65001. These characters, of course, do not have a single byte encoding
in that codepage... and so we do not generate the numpad portion of the
synthesized event, only the alt down and up parts!
This is totally fine. **However**, there is also a .NET Framework bug
(which was only fixed after they released .NET Core, and rebranded, and
the community stepped in, ...) finally fixed in .NET 9 which used to
result in some Alt KeyUp events being dropped from the queue entirely.
https://github.com/dotnet/runtime/issues/102425
Using the input codepage ensures the right events get synthesized. It
works around the .NET bug.
Technically, padding in those numpad input events is _also more
correct_.
It also scares me, because it has been this way since NT 3.51 or
earlier.
## Summary of the Pull Request
Updates the "firstWindowPreference" global setting to take 3 values:
"defaultProfile", "persistedLayout", and "persistedLayoutAndContent".
The legacy "persistedWindowLayout" is being interpreted as
"persistedLayoutAndContent".
The tricky part here is that we need to maintain support for the legacy
value as persisting the layout and content, even though the value's name
suggests that it should just support the layout and no content. To get
around this, I added "persistedLayout" and "persistedLayoutAndContent".
The enum map is manually constructed for `FirstWindowPreference` to
exclude the deprecated value. This prevents the legacy value from
leaking into the settings UI.
Functionally, the change to serialize the contents is simple.
`WindowEmperor::_persistState()`'s second parameter is used to serialize
the buffer. Rather than having it set to `true`, we set it to
`GlobalSettings().FirstWindowPreference() ==
FirstWindowPreference::PersistedLayoutAndContent`.
## Validation Steps Performed
✅ "persistedWindowLayout" is changed to "persistedLayoutAndContent"
Closes#18757
Whoops. Closes#18652
<DHowett> I chatted with Leonard to figure out why I kept
misunderstanding this PR. The key is that **this function should not
always return an existing window.** It's supposed to find an existing
window on the current virtual desktop, not literally any window
anywhere.
Render SGR1 as bold in 256 and true colors, where "bold is intense" is
not applicable.
Implemented by creating 2 extra fonts: bold for 1 and bold italic for 1
+ 3.
No non-trivial changes, just extensions.
LOGFONT also supports Underline and StrikeOut, but they seem to be
already covered by other means, so no combinatorial explosion of fonts
expected.
Refs #18919
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
## Summary of the Pull Request
Update the WinGet CNF package search to match that of the updated
PowerShell WinGet CNF module. Now, we'll only search for matching
commands instead of by name and moniker.
## References and Relevant Issues
https://github.com/microsoft/winget-command-not-found/pull/29
## Validation Steps Performed
✅ In CMD, type "vim" and vim packages are suggested
## Summary of the Pull Request
Turns out that the `"TabViewItemHeaderBackground"` resource should be
set to the _selected_ color instead of the _deselected_ color.
In 1.22, (pre-#18109) we actually didn't set this resource. But we do
actually need it for high contrast mode! (verified)
## Validation Steps Performed
✅ High contrast mode looks right
✅ "Snazzy" theme from bug report looks right
## PR Checklist
Closes#19343
Apparently, `GetModuleFileNameW` returns exactly the path (or prefix, in
case of a DLL) passed to `CreateProcess` casing and all. Since we were
using it to generate the uniquing hash for Portable and Unpackaged
instances, this meant that `C:\Terminal\wt` and `C:\TeRmInAl\wt` were
considered different instances. Whoops.
Using `QueryFullProcessImageNameW` instead results in canonicalization.
Maybe the kernel does it. I don't know. What I do know is that it works
more correctly.
(`Query...` goes through the kernel, while `GetModule...` goes through
the loader. Interesting!)
Closes#19253
## Summary of the Pull Request
When we introduced action IDs, we separated "commands" from
"keybindings", and introduced fixup logic to rewrite the legacy-style
command blocks into the new version. However we don't do any ID logic
for nested and iterable commands, so make sure we don't inform the
loader for fixups in those cases.
## Validation Steps Performed
We no longer repeatedly attempt to fixup the settings file when we see a
`"keys"` entry in a nested/iterable command block
## PR Checklist
- [x] Closes#18736
## Summary of the Pull Request
Fixes a couple of minor issues in the settings schema which can result
in erroneous settings validation failures.
## References and Relevant Issues
None
## Detailed Description of the Pull Request / Additional comments
- `answerbackMessage`
Permit `null` type (corresponds to the default value).
- `compatibility.input.forceVT`
Add missing setting (previously was `experimental.input.forceVT`).
- `rendering.graphicsAPI`
Add missing `automatic` enumeration value.
- Mark several settings as deprecated using the same format and direct
the user to the updated settings to use.
## Validation Steps Performed
Tested updated schema against configuration with above settings present.
## PR Checklist
- [X] Schema updated (if necessary)
---------
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
If the progress state hasn't been set for more than 200ms, we shouldn't
even bother flickering the old state.
This prevents applications from making the tab (and the taskbar icon)
flicker.
We were reviewing #19394 and decided that the _original_ behavior before
Leonard's throttling fix was somewhat unfortunate as well. An
application that sets an indeterminate state for 10ms and then clears it
shouldn't be able to make any part of the application flicker, fast _or_
slow.
Removing the leading fire time from the throttled function ensures that
it will only fire once every 200ms, and only with the state most
recently set. It will not debounce (so setting the progress every 150ms
will not prevent it from updating.)
Closes#19394
The previous fix in #19296 moved the _destruction_ of AppHost into the
tail end after we manipulate the `_windows` vector; however, it kept the
part which calls into XAML (`Close`) before the `erase`. I suspect that
we still had some reentrancy issues, where we cached an iterator before
the list was modified by another window close event.
That is:
```mermaid
sequenceDiagram
Emperor->>Emperor: Close Window
Emperor->>+AppHost: Close (a)
AppHost->>XAML: Close
XAML-->>Emperor: pump loop
Emperor->>Emperor: Close Window
Emperor->>+AppHost: Close (b)
AppHost->>XAML: Close
XAML-->>Emperor: pump loop
AppHost->>-Emperor: Closed
Emperor->>Emperor: erase(b)
AppHost->>-Emperor: Closed
Emperor->>Emperor: erase(a)
```
Moving the `Close()` to after the `erase` ensures that there are no
cached iterators that survive beyond XAML pumping the message loop.
Fixes 8d41ace3
## Summary of the Pull Request
Adds the tab color profile setting to the settings UI. It's positioned
next to the tab title at the root of the profile page.
The new component uses a nullable color picker control to allow the user
to pick a color. The null color is represented as "Use theme color".
The tricky part is evaluating the `ThemeColor` for `null` (aka "use
theme color"). Since the value is dependent on the active theme, it can
be any of the following values:
- theme.tab.background...
- explicit color
- accent color
- terminal background color
- (if no theme.tab.background is defined) theme.window.applicationTheme
- light --> #F9F9F9
- dark --> #282828
- default --> one of the above two values depending on the application
theme
The above light/dark values were acquired by using the color picker on
the tab when in light/dark theme.
## Validation Steps Performed
✅ accessible value is read out
✅ explicit tab color set
- tab color is null, so we fall back to...
- ✅ theme.tab.background: explicit color, accent color, terminal
background color
- ✅ theme.window.applicationTheme (and no theme.tab.background defined):
light, dark, default (aka not defined)
- ✅ updates when theme is changed locally and via JSON
## PR Checklist
Closes part of #18318
This will allow us to publish vpacks without making the build fail
waiting for us to *merge* those vpacks into Windows. It also gives us
better control over when and where the vpack update gets merged.
Goal: Remove `CursorBlinker`.
Problem: Spooky action at a distance via `Cursor::HasMoved`.
Solution: Moved all the a11y event raising into `_stream.cpp` and pray
for the best.
Goal: Prevent node.js from tanking conhost performance via MSAA (WHY).
Problem: `ServiceLocator`.
Solution: Unserviced the locator. Debounced event raising. Performance
increased by >10x.
Problem 2: Lots of files changed.
This PR is a prerequisite for #19330
## Validation Steps Performed
Ran NVDA with and without UIA enabled and with different delays. ✅
Some of the other settings fixups require there to be a valid
NewTabMenu, rather than just a temporary object. Since the resolving all
the menu entries after loading already forces the user to have a
`newTabMenu`, let's just codify it as a real fixup.
I've moved the SSH folder fixup after the settings fixup because it
relies on there being a NTM.
I decided not to make this fixup write back to the user's settings.
There are a couple reasons for this, all of which are flimsy.
- There are a number of tests that test fixup behavior, especially those
around actions, which would need to be updated for this new mandatory
key. I did not think it proper to add `newTabMenu` to ten unrelated
tests that only contain actions (for example.)
- We actually don't currently have mandatory keys. But this one was
always being added anyway, in a later phase...
- It's consistent with the existing behavior.
Closes#19356
This adds support for horizontal mouse wheel events (`WM_MOUSEHWHEEL`).
With this change, applications running in the terminal can now receive
and respond to horizontal scroll inputs from the mouse/trackpad.
Closes#19245Closes#10329