Commit Graph

3926 Commits

Author SHA1 Message Date
Carlos Zamora
115ec2cbb9 Fix rounding error for word selection (#20084)
## Summary of the Pull Request
Dustin reported this bug to me. Thankfully it was an easy fix.

## References and Relevant Issues
Bug from implementing #5099

## Validation Steps Performed
Double-click ____ of right-most cell of a word selects the current word
 right-half
 left-half
2026-04-29 17:01:43 -05:00
Carlos Zamora
3362651659 Tab menu: show "restart" + maintain items' enable state (#19972)
## Summary of the Pull Request
Changes how/when we display the "restart connection" item in the tab's
context menu. Now, we always display it, but it's disabled if we're not
in a terminal tab.

Applies similar enable/disable logic to the rest of the menu items.
Previous to this, they just wouldn't do anything (which is fair, they
didn't make any sense).

## Validation Steps Performed
Check tab's menu in following scenarios:
 terminal pane
 settings tab
 snippets pane

Closes #18891
2026-04-29 18:54:43 +00:00
Carlos Zamora
c72600dd4f Add more settings model unit tests (#20117)
## Summary of the Pull Request
Adds tests to `UnitTests_SettingsModel` to improve coverage. Tests
include:
- `SettingInheritanceFallback`: Settings inherit from user defaults;
unset settings fall back to built-in defaults
- `ClearSettingRestoresInheritance`: `ClearXxx()` removes the value at
the current layer, causing fallback to the parent
- `HasSettingAtSpecificLayer`: `HasXxx() `distinguishes explicitly set
values from inherited ones
- `ModifyProfileSettingAndRoundtrip`: Change a profile setting via
setter and `ToJson()` reflects it
- `ModifyGlobalSettingAndRoundtrip`: Change global settings via setter
and `ToJson()` reflects them
- `ModifyColorSchemeAndRoundtrip`: Change a color scheme property and
the serialized JSON reflects it
- `FixupUserSettingsDetectsChanges`: A clean roundtrip produces
idempotent FixupUserSettings() (returns false)
- `FixupCommandlinePatching`: 4 sub-cases: CMD/PowerShell short names
get patched to full paths, no-op when already clean, custom profiles are
untouched

This also updates `TestCloneInheritanceTree` to verify that `HasXxx()`
and settters that modify the clone don't modify the original.

This is being done in preparation for auto-save to help ensure we don't
have any regressions.

## Validation Steps Performed
 Tests pass
 Manually reviewed the new tests, they make sense and do add value
(though some are less valuable than others, admittedly)
 Sent Copilot on a quest to ensure we're not adding redundant tests. It
did catch a few and remove them fwiw.
2026-04-29 10:16:30 -07:00
Windows Console Service Bot
eeb9f7a805 Localization Updates - minor wording changes after spell check - 04/24/2026 03:05:26 (#20140)
Co-authored-by: Console Service Bot <consvc@microsoft.com>
2026-04-28 03:41:39 +00:00
Josh Soref
c62bb193d3 Refresh check-spelling metadata for v0.0.26 (#20141)
This is a refresh of spell-check-this, more or less as of
e089393b4e.

## References and Relevant Issues

A number of changes take advantage of features from
http://github.com/check-spelling/check-spelling/releases/v0.0.26

1.
[`load-config-from`](https://docs.check-spelling.dev/Configuration#load-config-from)
will allow future PRs to switch cleanly w/o the mess that this PR has --
once this merges, the `config.json` file will be used for the three
dictionary configuration elements instead of the ones in the workflow.
2. `contents: read` is no longer needed by the comment jobs as the data
is provided by the main job

Contains fixes for the following specific issues:
`without`, `with`, `with the`, `with the window`, `will be`,
`whether or not`, `where the`, `using`, `uppercase or lowercase`,
`unit testing`, `to`, `to which...`, `to which`,
`to which the view refers`, `to which the pane was moved`,
`to run a command/switch to a tab/...`,
`to retrieve the user selected command`, `time,`, `the...that the`,
`the session's initial directory`, `that`, `that will ask`, `that the`,
`that opened the first flyout`, `same as terminal,`, `results,`,
`queue,`, `please`, `pane,`, `out-of-date`, `our`, `one`, `on-screen`,
`often`, `off-screen`, `of a`, `little-endian`, `left over`,
`includes, at a minimum,`, `know of`, `its`,
`if, after the calculation,`, `if`, `if we have an`, `if dragging`,
`if commands`, `guard,`, `given process information in a list`,
`from which`, `from creating`, `for which...`, `for the axis`,
`for initializing the buffer`, `containing the cursor`, `console-wait`,
`change`, `bytes`, `be`, `baseline,`, `aumid`, `at`, `ask me *again*`,
`an`, `also need to`, `again`, `add`, `add event`, `about spelunking`,
(rewrite `Appearances::_UpdateWithNewViewModel` comment), `'a'`, and ` (`

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2026-04-24 22:50:42 +00:00
jason
7a83c0f167 Fix Korean IME overlay hiding characters to the right of cursor (#20041)
This commit fixes a regression in v1.24, where composing Korean text
in-between existing characters causes text to the right to be hidden.
This is problematic for the Korean IME, because it commonly inserts
the composed syllable between existing characters.

The fix compresses (removes/absorbs) available whitespace to the right
of the composition to make space for any existing text. This means
that a composition now virtually acts in insert mode.

Closes #20040
Refs #19738
Refs #20039

## Validation Steps Performed

1. Korean IME: compose `ㄷ` between `가` and `나` → display shows `가ㄷ나`,
`나` visible.
2. TUI box (vim prompt with padding): compose inside padded text box →
border preserved in place.
3. Composition at end of line (no chars to right): unaffected.
4. English and other IME input: not affected (no active composition
row).

Co-authored-by: jason <drvoss@users.noreply.github.com>
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2026-04-16 19:12:19 -05:00
Carlos Zamora
b2666fb346 Fix local tests (#20120)
## Summary of the Pull Request
Fixes TabTests.cpp. Changes include:
- add `"closeOnExit": "never"` to some tests to avoid the race condition
discussed in #14623. It keeps the tabs/panes around so that we can
actually test them.
- removes the `assert(false)` in `TermControl::MinimumSize()`. I've been
hitting this assert in dev builds _every time_ I split a pane. I think
it isn't adding value, but if we want to investigate it further, we can.
- update MRU tests to not use the command palette (aka tab switcher) UI.
The UI requires you to hold a modifier key down to keep it displayed.
That isn't something we can simulate. Instead we just use the relevant
APIs to simulate switching tabs. This is ok because the `MRU` list is
still updated, so we're still able to validate that we're updating it
properly.
- Add `Tab[idx]` and `MRU[idx]` notation to MRU tests to make them
easier to follow

## Validation Steps Performed
 local tests pass

Closes #19610
Closes #14623
2026-04-15 22:24:13 +00:00
Carlos Zamora
8f4fdf9751 Normalize commandline in media resource tests (#20118)
## Summary of the Pull Request
Some of the Media Resource tests were failing on my machine. Turns out
that it's because my machine uses `C:\WINDOWS` instead of `C:\Windows`.

This PR fixes those tests by calling `Profile::NormalizeCommandline()`
on a few impacted strings. This also makes them loaded after enabling
filesystem redirection in `TEST_CLASS_SETUP` so that we resolve to the
correct path expected by x86.

Admittedly, I'm not the biggest fan of using that to fix the tests, but
it's better than the alternative which is a case-insensitive string
comparison. Also, the tests are testing fallback behavior, so this
doesn't really impact that. It just makes the tests more consistently
reliable.

This also removes the unused `pingCommandline` variable.

## Validation Steps Performed
 Tests pass
2026-04-15 19:13:41 +00:00
Windows Console Service Bot
33a80191c1 Localization Updates - URL dialog and PathTranslation - 04/11/2026 (#20096)
Co-authored-by: Console Service Bot <consvc@microsoft.com>
2026-04-15 14:09:19 -05:00
Dustin L. Howett
84ae7adec6 OS PR 14890400: fix defects caught with strict compiler switches (#20100)
Related work items: MSFT-53015560

Co-authored-by: Sudhakar Prabhu <sprabhu@microsoft.com>
2026-04-10 11:41:03 -07:00
Dustin L. Howett
a6ebdd3d4a render: check the thread exit condition after every long operation (#20097)
We have received an internal report that teardown on OneCore is still
hanging. It looks like there's a chance that `TriggerTeardown` is called
during `PaintFrame`, which may result in `_threadShouldKeepRunning`
getting set to `false` (TriggerTeardown) and `_redraw` being set to
`false` as well (PaintFrame). The thread will wait forever on `_redraw`
to be signalled, which it never will, because `TriggerTeardown` is
waiting for the thread to exit.

That is:

```
Render Thread      | ConIoSrv Thread
------------------------------------
Check _enabled     |
Wait on _redraw    |
Check _keepRunning | TriggerTeardown
Paint              |   _keepRunning = false
                   |   _redraw = true
    _redraw = false|   Signal _enabled
Paint Completes    |   Wait on thread
Check _enabled     |
Wait on _redraw    |
**DEADLOCK**       | **DEADLOCK**
                   v
```

This may not be an ideal fix, but at least it checks
`_threadShouldKeepRunning` after every "long" operation (waiting and
painting) now.
2026-04-09 16:34:09 -05:00
Dustin L. Howett
031998bfc3 Track the cursor dirty flag in the correct buffer (#20095)
Failure to do so will result in every console API requiring a cursor
update stalling for 500ms because we sent the update to the wrong
buffer.

Closes #20092
2026-04-08 22:08:28 +00:00
Dustin L. Howett
41e08a68bd Path translation setting: use 🡒 instead of -> (#20088)
It looks better, as decided by committee.
2026-04-07 16:38:51 -05:00
Dustin L. Howett
81170aff78 Display a warning dialog for unsafe URLs (#20065)
We are getting a sufficient number of LLM-generated security reports
telling us that Ctrl+click and a tooltip are insufficient protection
from users clicking on links to dangerous things.

This commit displays a warning that prevents users from blindly clicking
on dangerous things.

Dangerous things include:
- any non-http and non-https and non-file URLs
- any file URLs that point to something understandable as a "program"
(so, something which resides in `PATHEXT`.)

In doing this, I learned that `til::ends_with_insensitive_ascii` was
broken.

I also learned that ContentDialogs summoned by any event handler out of
TermControl::Pointer* would lose focus immediately. It turns out that in
the absolute earliest days of Terminal, when we first created the
UserControl that became TermControl, we added our Tapped event handler.

It unconditionally focused the control.

Since `Tapped` is a higher-level event handler than `PointerPressed`, it
was firing after the gesture that opened the content dialog and stealing
focus back.

I'm fairly certain we don't need it.

Refs #7562
2026-04-07 11:23:15 -05:00
Windows Console Service Bot
c90ace8326 Localization Updates - drag drop delimiter - 04/07/2026 03:05:15 (#20042)
Co-authored-by: Console Service Bot <consvc@microsoft.com>
2026-04-07 09:59:50 -05:00
Dustin L. Howett
c334f91f80 Move PointerId, focus and in-bounds handling down into Interactivity (#20017)
These do not notionally belong to TermControl; as we prepare to move
automatic scrolling down into the Interactivity layer (for
WpfTerminalControl to depend on,) we're going to need to track these in
Interactivity too.

This also converts the arguments from the winrt-specific
Foundation::Point to Core::Point, and simplifies some of the signatures
to no longer pass things we do not need to pass.

Right now, this should result in no functional change.

Some of the tests are sensitive to the fact that we never loaded
`SPI_GETWHEELSCROLLLINES`
and instead defaulted to `1`. They've been hammered back into shape.
2026-03-31 16:38:32 -07:00
jason
14f4271954 Fix Korean IME arrow key inserting character at wrong position (#20039)
Fix a regression introduced in v1.24 where pressing an arrow key during
Korean IME composition caused the committed character to be inserted at
the wrong cursor position.

Before #19738, the Korean IME activated through IMM32 (excluded from TSF
by `TF_TMAE_UIELEMENTENABLEDONLY`) and was not affected by
`TermControl::_KeyHandler` forwarding keys to the PTY during
composition. After #19738, the Korean IME activates through TSF, making
a missing composition guard in `_KeyHandler` visible as a bug.

The sequence of events that causes the bug:

1. User presses Left arrow during active Korean IME composition (e.g.
composing `가`).
2. `_KeyHandler` calls `_TrySendKeyEvent(VK_LEFT)` which enqueues
`\x1b[D` to the PTY input queue. The cursor moves.
3. TSF processes the key. The Korean IME sees the arrow and ends the
composition.
4. `OnEndComposition` schedules `_doCompositionUpdate` with
`TF_ES_ASYNC`.
5. The async session fires, reads finalized text `가`, calls
`HandleOutput("가")`.
6. PTY processes `[\x1b[D, "가"]`: cursor moves left first, then `가` is
inserted at the wrong (already-moved) position.

The fix adds a guard before `_TrySendKeyEvent`, which mirrors the
existing behavior in conhost (windowio.cpp). When TSF has an active
composition, key events are not converted into input. The Korean IME
re-injects navigation and confirmation keys after the composition ends,
at which point `HasActiveComposition()` returns false and they are
forwarded normally.

**Historical note:** This guard was not needed before PR #17067 (v1.22)
because the old implementation used WinRT `CoreTextServices` via XAML
(`TSFInputControl.xaml`). The XAML framework intercepted composition key
events before `_KeyHandler`. The new custom Win32 TSF context in #17067
no longer does this. The bug was latent from v1.22 but only became
visible for Korean in v1.24 when #19738 removed
`TF_TMAE_UIELEMENTENABLEDONLY`.

## Validation Steps Performed

1. Open Windows Terminal with Korean IME (Dubeolsik layout).
2. Type `rk` to begin composing `가` (composition active, syllable not
yet committed).
3. Press the Left arrow key.
4. Before fix: `가` is inserted one cell to the left of the intended
position.
5. After fix: `가` is inserted at the correct position, then cursor moves
left.

Also verified:
- Normal Korean text input (typing without arrow keys) still works
correctly.
- Arrow key navigation when no composition is active still works
correctly.
- English and other IME input is not affected.

Closes #20038
Refs #19738
2026-03-31 22:37:15 +00:00
Carlos Zamora
3104c8feb2 Fix selection markers appearing on scroll (#20045)
## Summary of the Pull Request
Updates the scroll handler to check the selection mode before updating
the markers.

Introduced in #19974 

## Validation Steps Performed
`ls` --> create selection --> scroll away and back
 keyboard selection: markers are present both times
 mouse selection: markers are missing both times
2026-03-31 22:29:34 +00:00
Dustin L. Howett
01f8a4031d conpty: remove accidental bool; use BOOL instead (#20035)
Closes #19102
2026-03-31 18:58:10 +02:00
Dustin L. Howett
2870a702f4 Reinstate the (apparently) load-bearing empty bracketed paste (#20037)
Some applications have come to rely on an "empty" bracketed paste packet
to indicate that the clipboard was _requested,_ but not sent. Some
agentic CLI tools use this to guess whether the clipboard contained e.g.
an image or otherwise unserializable data.

Apparently, gnome-terminal and VS Code do this; others as well (I tested
xterm, konsole, gnome-terminal and I can't remember which ones did and
which ones did not.)

Refs #19517
2026-03-30 19:00:52 -05:00
Carlos Zamora
ec939aabda Update 'restart connection' action to reset internal state (#19971)
## Summary of the Pull Request
I was becoming frustrated with getting in a state where a CLI app (i.e.
Copilot CLI) enters some VT state (like mouse mode) then doesn't unset
it when it accidentally exits. I normally use "Restart connection" to
keep the buffer and connect again. Problem is, "restart connection"
didn't actually reset the internal state! So I would type and get a
bunch of lingering VT escape sequences. This bug is tracked over in
#18425 in a more generic way.

This fixes that bug by doing the following:
- update `ITermDispatch::HardReset()` -->`HardReset(bool erase)`
   - `erase=true` does what `HardReset()` already did
- `erase=false` skips over clearing the screen and resetting the cursor
position
- expose `HardReset(false)` as `HardResetWithoutErase()` by piping it up
through `Terminal` --> `ControlCore` --> `TermControl`
-  update the restart connection handler
- `TerminalPage::_restartPaneConnection()` now calls
`HardResetWithoutErase()` before setting the new connection
- this is also the same route for the "Enter to restart connection"
scenario (text displayed when connection ends)

Relevant notes from PR discussion:
- `PSEUDOCONSOLE_INHERIT_CURSOR` is passed into the new connection via
`_restartPaneConnection()` --> `_duplicateConnectionForRestart()` -->
`_CreateConnectionFromSettings(profile,
*controlSettings.DefaultSettings(), true)`

## Validation Steps Performed
- Used this to enter mouse tracking mode: `Write-Host -NoNewline
"`e[?1003h`e[?1006h"`
- mouse selection doesn't work as usual (expected)
- invoke "restart connection" action
- mouse selection works as usual

Closes #18425
2026-03-30 18:25:12 -05:00
gcrtnst
be5dcf8e7a Fix MSB4019 error in ConPTY nupkg (#20029)
This commit fixes the following error that occurs when attempting to use the
`Microsoft.Windows.Console.ConPTY` nupkg in a Visual C++ project:

    MSB4019: The imported project "C:\Microsoft.Windows.Console.ConPTY.props" was not found.

Based on the list of reserved and well-known properties, the property
`MSBuildThisProjectDirectory` does not appear to exist.  This PR
replaces it with the correct property, `MSBuildThisFileDirectory`.
2026-03-30 21:54:39 +00:00
Leonard Hecker
4ce79d7289 Implement OSC 7 for setting the CWD (#20019)
This adds support for OSC 7 which is the same as OSC 9;9 but using
file URIs. As per the previous discussion in #8214, the problem is
that WSL shells emit URIs that can't work because the hostname in
the URI translates to an UNC path with an non-existing hostname.
In my opinion this doesn't deter the fact though that OSC 7 works
just fine for a native Windows application.

In the future we should consider trying to detect WSL file URIs
and translating it to the `--cd` argument for `wsl.exe`.

All of the heavy lifting for parsing the URI is done by 
`PathCreateFromUrlW`. It just had to be plugged into the OSC 9;9 code.

Closes #3158

## Validation Steps Performed
* Launch fish-shell in WSL
* Duplicate tab works 
* (And because it doesn't work without using
  `IsValidDirectory` I know that OSC 7 works )
2026-03-30 18:10:26 +00:00
Vallabh Mahajan
69e4590bc5 Add setting for customizable delimiter for file drag-and-drop (#19799)
## Summary of the Pull Request
This PR introduces a new profile setting, `dragDropDelimiter`, which
allows users to configure the string separator used when dragging and
dropping multiple files into the terminal. The default behavior remains
a single space (`" "`) for backward compatibility.

## References and Relevant Issues
* Closes #19565

## Detailed Description of the Pull Request / Additional comments
**Implementation Details:**
* **Settings:** Added `DragDropDelimiter` to `MTSMSettings.h` and
`Profile.idl`.
* **Control:** Wired the setting through `ControlProperties.h` so the
terminal logic can see it.
* **Logic:** Updated `TermControl::OnDrop` to use the new delimiter when
joining paths.
* **UI:** Added the text box in the Advanced Settings page and updated
the ViewModel.

## Validation Steps Performed
* **Manual Verification:**
    * Verified default behavior (space separator) works as before.
* Configured `dragDropDelimiter` to `", "`, `";"`, and custom strings in
`settings.json` and from settings UI.
    * Confirmed dropped files are joined correctly.
* **Build:** Validated that the solution builds cleanly.

## Notes for Reviewers
1. **Delimiter Length:** Currently, there is no limit on the maximum
length of the delimiter string. Let me know if this should be changed.
3.  **Localization:** I changed only `Resources/en-US` file.
4. **ViewModel:** In `ProfileViewModel.cpp`, I added the `else if` block
for the new setting, but left it empty because no other UI logic
currently depends on it.

## PR Checklist
- [x] Closes #19565
- [ ] Documentation updated
- [x] Schema updated (if necessary)
2026-03-30 10:38:01 -07:00
Ethan Balakumar
a1a43a4ff5 Terminal receives focus on drag n drop (#20003)
### Summary
Updates terminal to gain foreground focus when a user drags and drops a
file into the terminal.

### Changes
Updates the `DragDropHandler` to call `SetForegroundWindow`.

### Validation
* Built and deployed locally
* Manually verified terminal gains focus when dragging and dropping

Closes #19934
2026-03-27 21:48:01 +00:00
Sagar
3ab2acc2ad Fix Settings tab color mismatch with Settings page background (#19999)
## Summary
The Settings tab color (`SettingsUiTabBrush`) was out of sync with the
Settings page background (`SettingsPageBackground`), causing a visible
mismatch - the tab appeared black while the page was dark gray.

## Changes
Aligned `SettingsUiTabBrush` in `App.xaml` to match
`SettingsPageBackground` from `MainPage.xaml`:

## Validation
- Built and deployed locally as Windows Terminal Dev
- Verified Settings tab and page backgrounds match in Dark and Light
themes
- No impact on other tab colors or theming

Closes #19873
Co-authored-by: Sagar Bhure <sagarbhure@microsoft.com>
2026-03-27 21:42:50 +00:00
Carlos Zamora
eea035cb8e Set AppUserModelID for unpackaged (#20018)
## Summary of the Pull Request
Does what it says on the tin. Sets the AUMID to
`WindowsTerminal.<hash>` with a slightly different prefix
based on the branding. The hash is based on the full process image name.

Extracted from #20013
2026-03-27 18:52:32 +00:00
Leonard Hecker
da0446a7d1 Send a CPR request on every unknown sequence (#20009)
This PR is 90% wiring up OOP interfaces.

Closes #19926

## Validation Steps Performed
* Run `github.com/xtermjs/vtc`
* Observed `UnknownSequence` calls under a debugger
2026-03-24 23:00:13 +00:00
Theodore Tsirpanis
e0400150d0 Use vs-pwsh icons if applicable. (#19990)
## Summary of the Pull Request
This PR updates `VsDevShellGenerator` to use the `vs-pwsh` icon in
generated profiles, if modern PowerShell has been detected.

## References and Relevant Issues
The icons were added in #17706, but are not used anywhere.

## Detailed Description of the Pull Request / Additional comments
* Updated `VsDevShellGenerator::GetProfileCommandLine` to accept a
`bool& isPwsh` parameter, which is set to whether the generated profile
command line is using modern PowerShell. This value gets passed to
`VsDevShellGenerator::GetProfileIconPath`'s new parameter, which
determines whether to return the icon for `powershell` or `pwsh`.
2026-03-24 18:46:16 +00:00
Carlos Zamora
c562dad15d Fix search dropdown theming (#19987)
## Summary of the Pull Request
Popups are in their own separate tree, so we had to find it and set the
theme ourselves.

## Validation Steps Performed
Prereq: Windows theme = light + terminal theme = dark
 settings search dropdown is dark theme

Closes #19927
2026-03-23 11:05:02 -07:00
Leonard Hecker
0f5d883c59 Make disabling the Kitty Keyboard Protocol possible (#19995)
Avoid translating W32IM sequences to KKP.

Closes #19977

## Validation Steps Performed
* Use French Bepo keyboard layout
* Disable KKP
* Use fish shell
* `AltGr+Y` produces `{` 
2026-03-19 21:42:15 +01:00
Sagar
ad7b34e55f Fix copyOnSelect right-click overwriting clipboard with stale selection (#19943)
## Summary of the Pull Request
Fix `copyOnSelect` right-click paste overwriting the clipboard with a
stale selection instead of pasting the current clipboard contents.

## Detailed Description of the Pull Request / Additional comments
When `copyOnSelect` is enabled, the selected text is already copied to
the clipboard on left mouse button release in `PointerReleased`. The
selection is intentionally left visible as a visual reference (the
`_selectionNeedsToBeCopied` flag is set to `false` to track that the
copy already happened).

However, the right-click handler in `PointerPressed` unconditionally
called `CopySelectionToClipboard()` before pasting, ignoring both the
`copyOnSelect` setting and the `_selectionNeedsToBeCopied` flag. This
caused any still-visible selection to be re-copied to the clipboard,
overwriting whatever the user may have copied from another application
(or another terminal tab) in the meantime.

This change splits the right-click behavior based on the `copyOnSelect`
setting:
- **`copyOnSelect: true`** — Skip the redundant copy, clear the
selection, and paste directly. The text was already copied on mouse-up.
- **`copyOnSelect: false`** — Preserve existing behavior: copy the
selection (if any), clear it, and paste only if there was no selection
to copy.

## Validation Steps Performed
1. Set `"copyOnSelect": true` in `settings.json`.
2. Selected text in a terminal pane - verified it was copied to
clipboard on mouse-up.
3. Switched to Notepad, copied different text ("NEW TEXT").
4. Switched back to Terminal (selection still visible), right-clicked —
verified "NEW TEXT" was pasted, not the old selection.
5. Verified right-click with no active selection still pastes clipboard
contents.
6. Verified right-click immediately after selecting (no app switch)
pastes the just-selected text.
7. Set `"copyOnSelect": false` — verified right-click still copies
selection first, then pastes only when no selection exists (original
behavior unchanged).
8. Verified tab-switching with an active selection does not cause stale
clipboard overwrites on right-click.

## PR Checklist
Closes #14465 (dupe of #19942)

---------

Co-authored-by: Sagar Bhure <sagarbhure@microsoft.com>
2026-03-19 11:29:01 -07:00
Leonard Hecker
ddf514e99e Fix a deadlock during cooked reads (#19994)
Closes #19922

## Validation Steps Performed
* The repro now works as expected 
  (`CreatePseudoConsole({1,20})` + `WriteFile("キ")`)
2026-03-19 17:31:04 +00:00
Dustin L. Howett
d4425a397c conhost: atlas: prevent D3DCompile/hot shader reload in CHK builds (#19924)
Whoops. `chk` builds are failing because Atlas tries to do hot shader
reload in `DEBUG` builds.

That works in our public repo, but here there is not usually going to be
access to the source code.

Reviewed-by: Leonard Hecker <lhecker@microsoft.com>
2026-03-18 17:34:33 -07:00
Dustin L. Howett
0e19570468 Only run the render thread for headed console apps (#19986)
This saves us all of the cost of preparing the renderer when we're not
going to use it.

Related to #19984
2026-03-18 17:53:05 -05:00
Dustin L. Howett
f8b4e19e51 avoid committing rows just to figure out rendition, blink and cursor (#19984)
We have been looking at a set of conhost crashes due to low-memory
conditions. I've observed that they all happen during the first pass of
rendering, before there's even an engine set up, when we try to estimate
whether there are any blink attributes. I also found that we'll commit
the buffer to check the cursor's double-width status and whether it's on
a double-width-rendition line.

Uncommitted rows _never_ contain a blinker, are never double-width and
never contain DBCS.

We can't necessarily avoid committing an empty buffer _forever,_ but
this at least moves the first commit until after the renderer truly
starts.

This prevents us from committing an empty buffer for headless console
apps (!)
2026-03-18 17:52:59 -05:00
Carlos Zamora
2e33056fd8 Improve UX for selection during VTMM (#19973)
Selection in VT mouse mode has been feeling a little weird. I've made a
few changes in this space to improve the overall experience when in vt
mouse mode:
- don't round selection positions: this means that you now highlight the
cell you're on if you're going right, and the adjacent cell if you're
going left
- fix drag-left excluding the current cell
- #9608: shift+click now clears any existing selection instead of
extending it. This feels more intuitive since Shift already works as the
override modifier

Somewhat related to #18106 

## Validation
 alt selections feel consistent
 selecting in VTMM feels accurate (selects the cell we started on)
 creating new selections (aka clearing old selection) in VTMM feels
intuitive (forwards and backwards)

Closes #9608
2026-03-17 16:46:36 -05:00
Carlos Zamora
14ee19fc27 Fix selection markers disappearing after scrolling out of view (#19974)
## Summary of the Pull Request
Pretty straightforward

## Validation Steps Performed
 Selection markers are present after scrolling them out of view and
scrolling back

Closes #17135
2026-03-16 17:21:39 -05:00
Dustin L. Howett
987fce20a1 OS-15022958: conhost: onboard our RI-TPs for other internal Windows editions (#19975)
This required the following changes:
- Delayloading ICU in all of our tests, and skipping tests where it
could not be loaded
- Adding a new test group which skips the PolicyTests, which cannot be
run on some editions which have no app platform.

In addition, instead of onboarding new failing test passes, this pull
request finally repairs the broken ConPTY tests (which diverged from the
OSS implementation and had to be re-en-verged)

Closes MSFT-61409507
Reflected from OS PR !15022958
2026-03-14 11:33:04 -05:00
Carlos Zamora
040c730a44 Simplify word expansion functions (#19882)
## Summary of the Pull Request
Simplifies the word expansion functions in TextBuffer by removing the
following functions:
- `GetWordStart2()`
- `GetWordEnd2()`
- `MoveToNextWord()`
- `MoveToPreviousWord()`
-  `_GetWordStartForAccessibility()`
-  `_GetWordStartForSelection()`
- `_GetWordEndForAccessibility()`
- `_GetWordEndForSelection()`

In favor of a simple:
- `GetWordStart()`
- `GetWordEnd()`
- _GetDelimiterClassRunStart()`
- `_GetDelimiterClassRunEnd()`

Tests were used to help ensure a regression doesn't occur. That said,
there were a few modifications there too:
- Removed `MoveByWord` test
- It directly called `MoveToNextWord()` and `MoveToPreviousWord()`,
which no longer exist. These were helper functions for
`UiaTextRangeBase`, and any special logic has been moved into
`_moveEndpointByUnitWord` using the unified
`GetWordStart()`/`GetWordEnd()` APIs.
- The tested behavior is still covered by `MoveToPreviousWord`,
`MovementAtExclusiveEnd`, and the generated word movement tests.
- updated `GetWordBoundaries` tests
- Inclusive --> exclusive end positions for `GetWordEnd()`: The old
`_GetWordEndForSelection()` returned inclusive end positions, whereas
the new `GetWordEnd()` returns exclusive end positions. This is what
`GetWordEnd2()` already used, so every old expected value shifted +1 in
the x direction (or to {RightExclusive, y} at row boundaries) to account
for that.
- `ControlChar` wrap-crossing behavior: The old
`_GetWordStartForSelection()` had a special check at the left boundary
that prevented whitespace runs from crossing wrapped row boundaries. The
new `_GetDelimiterClassRunStart()` doesn't have this special case (it
treats ControlChar the same as other delimiter classes when the row was
wrap-forced). This changed one test case: `GetWordStart({1, 4})` in
selection mode went from `{0, 4}` to `{6, 3}` (the whitespace run now
crosses the wrap boundary to row 3). This matches the behavior
TerminalSelection was already getting from `GetWordStart2()`.

## Validation Steps Performed
Tests passed:
 Conhost.Interactivity.Win32.Unit.Tests.dll
 UnitTests_TerminalCore\Terminal.Core.Unit.Tests.dll

Word navigation feels good for...
 Narrator
 NVDA
 Mouse selection
 Mark mode

Closes #4423
2026-03-13 21:18:04 +00:00
Dustin L. Howett
6d7fac999a Suppress the invalid media error in Stable (#19969)
It's creating a lot of noise for folks, and it is not particularly
_helpful_ since it does not specify a location or even name which
resource failed to load or parse.

On stable, let's just silently ignore them.

Refs #19964
2026-03-12 17:07:18 -05:00
Dustin L. Howett
e6ea8ace6d conhost: Unlock the console while tearing down during coniosrv focus evt (#19967)
With the rendering thread changes in #18632 and #19330, we strengthened
a requirement that render shutdown be done outside of the console lock.
This works on all platforms except OneCore, where ConIoSrv manages the
focus of multiple console windows and we need to explicitly order the
handling of tearing down and relinquishing device resources.

The old code (before #18632) used to wait for a whole second before
giving up.

Instead, let's just unlock the console to let the final frame drain out.

I created a synthetic repro: start two cmd sessions with a lot of
rendering load (`cmdd start cmd /c dir /s c:\`), and then run `cmdd date
/t` in a tight loop while tabbing between the console windows.

Before this fix, it hangs within a couple tens of date invocations. With
this fix, it does not hang at all.

Fixes MSFT-61354695
2026-03-12 12:30:45 -05:00
Leonard Hecker
36fb444d3e Improve TSF failure handling (#19965)
An internal AI correctly flagged that we aren't calling
`UnadviseSink()` in case a later `Initialize()` call fails.
We can easily fix this by calling `Uninitialize()`.
2026-03-11 21:31:04 +01:00
Artem Lytkin
e2d51636cd control: focus terminal on click-drag while search is open (#19931)
## Summary
- Fix inability to copy terminal text via Ctrl+C when the search dialog
is open
- Root cause: click-and-drag doesn't call `Focus()` because `_focused`
is already `true` (set by the search box's bubbling GotFocus)
- Fix: also focus the terminal when the search box contains keyboard
focus

## Detailed Description of the Pull Request / Additional comments
When the search dialog is open and the user click-drags in the terminal
to select text, `_PointerPressedHandler` skips
`Focus(FocusState::Pointer)` because `_focused` is `true`. The
`_focused` flag is `true` because the `SearchBoxControl` is a child of
`TermControl` in the XAML visual tree, so `TermControl`'s
`_GotFocusHandler` fires (via bubbling `GotFocus`) when the search box's
`TextBox` gains focus, setting `_focused = true`.

The fix adds a `ContainsFocus()` check so that focus is explicitly moved
to the terminal when the search box has keyboard focus. This makes
click-drag behavior consistent with tap behavior (`_TappedHandler`
already focuses unconditionally) and uses the same `ContainsFocus()`
pattern already established at lines 1569 and 2366 in the same file.

## Validation Steps Performed
- Verified click-drag + Ctrl+C copies selected text when search dialog
is open
- Verified simple click (tap) in terminal while search is open still
works
- Verified clicking in the search box retains focus in the search box
- Verified typing in search box still works when it has focus
- Verified Escape still closes the search box
- Verified Ctrl+C with no selection while search is open doesn't break
- Code formatted with clang-format

## PR Checklist
 Closes #19908
2026-03-11 18:03:21 +00:00
Dustin L. Howett
80e4b3c947 Only honor Ctrl+Z during ReadFile if the console is in PROCESSED mode (#19940)
This restores the behavior of ReadFile to that of Windows 7.

Closes #4958
2026-03-11 11:52:33 -05:00
Carlos Zamora
e2110e716c Fix memory leaks with UIA (#19950)
## Summary of the Pull Request
This includes the memory leak fixes that @lhecker and I investigated as
a part of #19710.

The `ITextRangeProvider`s (namely `UiaTextRange`s) weren't being
destroyed after they were done being used by the screen reader.

## Validation Steps Performed
In my own testing, I set a breakpoint on the destructor for
`UiaTextRangeBase`. Prior to this change, that destructor would mainly
be called when the terminal control was closed, which would result in us
leaking these objects. With this change, I've confirmed that these text
ranges are being destroyed immediately after they are done being used
(without needing to close the terminal control).

## PR Checklist
Closes #19710
2026-03-11 02:08:32 +01:00
Leonard Hecker
30b1456ffe Make TSF initialization fully fallible (#19958)
Apparently, on some (internal) variants of Windows `TF_CategoryMgr`
can exist while `TF_DisplayAttributeMgr` is absent. This is likely
a variant configuration error, but we shouldn't crash anyway.

Closes MSFT-61309810
2026-03-10 21:31:54 +01:00
Leonard Hecker
5bd9e9fd89 Always use the cls shim for cmd/pwsh (#19957)
This improves performance and avoids a memory spike on `cls`.

## Validation Steps Performed
* `cls` clears 
* RSS doesn't spike 
2026-03-10 21:31:44 +01:00
sagarbhure-dev
8cad67020f Fix GenerateSettingsIndex using element name instead of x:Name (#19945)
Use GetAttribute('x:Name') instead of .Name in GenerateSettingsIndex.ps1
to avoid PowerShell's XML integration returning the element tag name
(e.g. 'local:SettingContainer') when x:Name is absent.

Also add missing x:Name attributes to:
- Compatibility.xaml: AmbiguousWidth SettingContainer
- NewTabMenu.xaml: AddRemainingProfiles and CurrentFolderIcon containers

## Summary of the Pull Request
Fix GenerateSettingsIndex.ps1 emitting "local:SettingContainer" as the
element name in the generated index when a SettingContainer has no
x:Name attribute.

## References and Relevant Issues
Per DHowett's comment - the root cause is PowerShell's XML integration:
$element.Name returns the XML element tag name (e.g.
local:SettingContainer) when no x:Name attribute exists.

## Detailed Description of the Pull Request / Additional comments
Two changes:

- GenerateSettingsIndex.ps1: Replace $settingContainer.Name with
$settingContainer.GetAttribute("x:Name"), which correctly returns an
empty string when the attribute is absent instead of the element tag
name.

- Add missing x:Name attributes to three SettingContainer elements:
    - Compatibility.xaml: AmbiguousWidth (Globals_AmbiguousWidth)
- NewTabMenu.xaml: AddRemainingProfiles
(NewTabMenu_AddRemainingProfiles)
    - NewTabMenu.xaml: CurrentFolderIcon (NewTabMenu_CurrentFolderIcon)
- This fixes four incorrect IndexEntry lines in the generated output
that previously contained L"local:SettingContainer" as the element name.

## Validation Steps Performed
Ran GenerateSettingsIndex.ps1 before and after - confirmed the four
incorrect entries with L"local:SettingContainer" are now generated with
the correct x:Name values (or empty string where appropriate).

## PR Checklist
Closes #19929

Co-authored-by: Sagar Bhure <sagarbhure@microsoft.com>
2026-03-10 17:03:15 +00:00
Windows Console Service Bot
59c7e3b73c Localization Updates - main - 03/02/2026 (#19914)
Co-authored-by: Console Service Bot <consvc@microsoft.com>
2026-03-02 12:14:43 -06:00