Compare commits

...

18 Commits

Author SHA1 Message Date
Mike Griese
076ca02a12 Don't ever allow ~ as a startingDirectory (#12437)
Basically, some WSL distros ship fragments that replace the `commandline` with the executable for their distro (`ubuntu.exe`, etc.). We didn't expect that when we changed the `startingDirectory` for them all to `~`.

Unfortunately, `~` is really never a valid path for a process on windows, so those distros would now fail with

```
[error 2147942667 (0x8007010b) when launching `ubuntu1804.exe']
Could not access starting directory "~"
```

If we find that we were unable to mangle `~` into the user's WSL `commandline`, then we will re-evaluate that `startingDirectory` as `%USERPROFILE%`, which is at least something sensible, if albeit not what they wanted.

* regressed in #12315
* [x] Closes #12353
* [x] Tested with a (`ubuntu1804.exe`, `~`) profile - launched successfully, where 1.13 in market fails.
* [x] added tests

(cherry picked from commit 1870feeca3)
2022-02-08 18:52:50 -06:00
Mike Griese
37b59c180c Fix defterm + elevate by default (#12442)
We absolutely cannot allow a defterm connection to
auto-elevate. Defterm doesn't work for elevated senarios in the
first place. If we try accepting the connection, the spawning an
elevated version of the Terminal with that profile... that's a
recipe for disaster. We won't ever open up a tab in this window.

* [x] Closes #12370
* [x] Tested manually, since there's not a great way to add defterm tests

(cherry picked from commit 303f9d7cbd)
2022-02-08 18:52:50 -06:00
James Holderness
f740cf09b6 Allow exceptions from ITerminalApi and TerminalDispatch (#12432)
This PR updates the `ITerminalApi` and `TerminalDispatch` classes to
allow exceptions to be thrown in case of errors instead of using boolean
return values.

## References

This brings the Terminal code into alignment with the `AdaptDispatch`
and `ConGetSet` changes made in PR #12247.

And while this isn't exactly a fix for #12378, it does at least stop the
app from crashing now.

## Detailed Description of the Pull Request / Additional comments

All the `TerminalDispatch` methods have had their `noexcept` specifiers
dropped, and any `try`/`catch` wrapping removed, so exceptions will now
fall through to the `StateMachine` class where they should be safely
caught and logged.

The same goes for the `ITerminalApi` interface and its implementation in
the `Terminal` class. And many of the methods in this interface have
also had their `bool` return values changed to `void`, since there is
usually not a need for error return values now.

## Validation Steps Performed

I've manually tested the `OSC 9;9` sequence described in #12378 and
confirmed that it no longer crashes.

(cherry picked from commit 9c11e025bb)
2022-02-08 18:52:49 -06:00
Carlos Zamora
7f660c2786 Validate cursor position in UIA UTR ctor (#12436)
This adds some validation in the `UiaTextRange` ctor for the cursor position.

#8730 was caused by creating a `UiaTextRange` at the cursor position when it was in a delayed state (meaning it's purposefully hanging off of the right edge of the buffer). Normally, `Cursor` maintains a flag to keep track of when that occurs, but Windows Terminal isn't maintaining that properly in `Terminal::WriteBuffer`.

The _correct_ approach would be to fix `WriteBuffer` then leverage that flag for validation in `UiaTextRange`. However, messing with `WriteBuffer` is a little too risky for our comfort right now. So we'll do the second half of that by checking if the cursor position is valid. Since the cursor is really only expected to be out of bounds when it's in that delayed state, we get the same result (just maybe a tad slower than simply checking a flag).

Closes #8730

Filed #12440 to track changes in `Terminal::_WriteBuffer` for delayed EOL wrap.

## Validation Steps Performed
While using magnifier, input/delete wrapped text in input buffer.

(cherry picked from commit 5dcf5262b4)
2022-02-08 18:52:49 -06:00
Dustin L. Howett
287030377f Publish the symbols from our MSIX bundle to the public server (#12441)
Closes #12203

(cherry picked from commit 59ef21a124)
2022-02-08 18:52:49 -06:00
Mike Griese
a94989c89d Properly fall back to Segoe MDL2 for our icons on Win10 (#12438)
Segoe Fluent isn't available on Windows 10, and doesn't stealthily ship with WinUI. So if we manually set the font family to `"Segoe Fluent Icons"`, then that will just display boxes in Win10.

This instead uses the resource `"{ThemeResource SymbolThemeFontFamily}"` which will gracefully fall back on Win10.

See:
* https://github.com/microsoft/microsoft-ui-xaml/issues/3745, which inspired this solution.

Guess what! The backgound image icons were also manually specifying this font, so they had to get updated too. I couldn't find any other `Segoe Fluent` references in the code.

* [x] Closes #12350
* [x] Checked Windows 11 locally
* [x] Checked Win10 (screenshots incoming from other machine)

(cherry picked from commit 27a1b9de13)
2022-02-08 18:52:49 -06:00
Leonard Hecker
4c62adf17b XtermEngine: Explicitly emit cursor state on the first frame (#12434)
This commit fixes an issue, where we failed to emit a DECTCEM sequence to hide
the cursor if it was hidden before XtermEngine's first frame was finalized.
Even in such cases we need to emit a DECTCEM sequence
in order to ensure we're in a consistent state.

## Validation Steps Performed
* Added test
* Run #12401's repro steps around 30 times

Closes #12401

(cherry picked from commit dbb70778d4)
2022-02-08 18:52:49 -06:00
PankajBhojwani
8243087dcc Fix focus box around color schemes combo box (#12439)
The focus box around the color schemes combo box was getting cut off, this change adds a small margin to the stackpanel to allow space for the focus box

## PR Checklist
* [x] Closes #12328

(cherry picked from commit f5f0712ae3)
2022-02-08 18:52:48 -06:00
Mike Griese
25d4e72d77 Fix a potential crash when setting up the jumplist (#12430)
I have no idea how this is even possible to hit. If this is able to be null, then we failed to load the settings in such a catastrophic way that nothing should work. However, OP's Terminal seemed to have already loaded the settings. By all accounts, doesn't make sense.

Regardless, the code here would crash if this ever is null, so we may as well catch it.

* [x] Closes #12360
* [ ] No way to verify this since it isn't even reproable on OPs machine, but it does have a lot of hits for that failure bucket (!!!)

(cherry picked from commit d0daab6252)
2022-02-08 18:52:48 -06:00
Leonard Hecker
4cc8481fc7 Fix profile matching for paths containing unquoted whitespace (#12348)
The previous code had two bugs for:
* paths with more than 1 whitespace
  The code joins the argv array by replacing null-word terminators with
  whitespace. Unfortunately it always referred to the separator between
  `argv[0]` and `argv[1]` for this instead of continuing to join
  those between 1 and 2, etc.
* paths sharing a common prefix with another directory
  `SearchPathW` returns paths that aren't necessarily paths to files.
  A call to `GetFileAttributesW` was added, ensuring we only resolve file paths.

## PR Checklist
* [x] Closes #12345
* [x] I work here
* [ ] Tests added/passed

## Validation Steps Performed
* Paths with more than 1 whitespace resolve correctly 
* Paths with neighboring directories sharing a common prefix resolve correctly 
* Tests added 

(cherry picked from commit 3171a8957b)
2022-02-08 18:52:48 -06:00
PankajBhojwani
4d058c638a Fix invoking the rightmost breadcrumb bringing you back to Profiles_Base (#12376)
## Summary of the Pull Request
We no longer do anything when the rightmost breadcrumb is invoked

## PR Checklist
* [x] Closes #12325
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here

## Validation Steps Performed
Tested manually, cannot repro #12325 anymore

(cherry picked from commit 527b9cdf78)
2022-02-08 18:52:48 -06:00
PankajBhojwani
34aa297be2 Fix disclaimer text not centralizing when maximized (#12374)
## Summary of the Pull Request
Fix the disclaimer text boxes in `Rendering` and `Defaults`not centralizing along with the expanders when the window is maximized

## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here

## Validation Steps Performed
<img width="1128" alt="defaults" src="https://user-images.githubusercontent.com/26824113/152584084-a999cb29-73bc-4970-889a-f95ea64c1b4c.png">
<img width="1128" alt="rendering" src="https://user-images.githubusercontent.com/26824113/152584099-a54519da-7bca-4ebe-b487-b68ac5cf1a37.png">

(cherry picked from commit 260435860e)
2022-02-08 18:52:48 -06:00
Michael Niksa
db25a217ac Hardcode the language list for the package manifest and settings dropdown (#12375)
The `x-generate` statement seems to have fallen apart somewhere and is no longer generating the valid list of languages for display. This hardcodes the list into the manifest to restore it, which is a valid option per the documentation.

We also hardcode the limited subset of languages into the Settings application because the main application supports fewer languages than we have been translated into for the shell extensions for Windows Explorer and Start Menu integration.

## PR Checklist
* [x] Closes #12351
* [x] I work here.
* [x] Manual tests below

## Validation Steps Performed
- [x] Clean built locally with `msbuild.exe openconsole.sln /p:Configuration=Release /p:Platform=x64 /p:WindowsTerminalBranding=Release /t:Terminal\CascadiaPackage /m /bl:log4.binlog` and checked that the `appxmanifest.xml` that popped out the other side contained the same languages that it used to contain.
- [x] Built in the release pipeline
- [x] Installed release and preview branded packages. Changed my machine language to Polish (pl-PL) which is not one of the fully localized languages, but is one of the limited ones. Checked the start menu and right-click menus and saw Polish text for Terminal and Terminal Preview. Checked the Settings page in our app and saw only the limited 14 language list for the application itself.

(cherry picked from commit 7734cd7d80)
2022-02-08 18:52:47 -06:00
PankajBhojwani
3adf80d919 Fix toggle switches needing a negative margin (#12381)
## Summary of the Pull Request
Reducing the `MinWidth` of a toggle switch means it no longer needs a negative margin to align it correctly

## PR Checklist
* [ ] Closes #xxx
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [x] I work here

## Validation Steps Performed
Setting a different language no longer causes the toggle switch to fall out of the expander

(cherry picked from commit 64efa6745d)
2022-02-08 18:52:47 -06:00
Dustin L. Howett
93b5c3843e appx: Use a different resource for the Properties DisplayName (#12337)
We have to do this so that the store sees us as one thing ("Windows
Terminal") and the Start menu sees us as another ("Terminal").

The store will reject our package if the value we use for "DisplayName"
here doesn't match the store's "reserved names".

This value is *not used* by the start menu.

(cherry picked from commit e064c15675)
2022-02-02 21:00:06 -06:00
PankajBhojwani
1aab365ee1 Fix more SUI and Rejuvenated UI issues (#12326)
- The add new profile page now uses a dropdown rather than radio buttons
- Subheaders, breadcrumb bar, buttons etc are now all centralized when the window is maximized (so they all align with the expanders now)
- We no longer override the titlebar colors and instead use the xaml defaults (these still aren't great but at least we will get the fix automatically when it happens upstream)
- Breadcrumb bar no longer has a negative margin, so there's no weird overlap that happens when the window becomes small
- The number boxes for launch size and font size now use the `Inline` placement mode rather than compact, allowing modification to the number with fewer clicks
- Textboxes now have a greater max width so they can occupy more space in the expander if needed

(cherry picked from commit 0a545b7b94)
2022-02-02 15:44:44 -06:00
Carlos Zamora
8557748a06 Update accessible names for 'add profile' page buttons (#12324)
## Summary of the Pull Request
When using a screen reader, the buttons on the "add a new profile" page were being read weirdly:
- "New empty profile" button read as "create new button button"
- "duplicate" button read as "duplicate button button"

It's generally standard to read out the text inside the button, so I did just that by reusing the existing localized resources. This also removes the redundant "button" that is said by the screen reader.

I also removed the unused `AutomationId` and unnecessary `Button.Content` tags.

#11156 can be closed upon validation by the accessibility team.

## Validation Steps Performed
 navigate to both buttons using Narrator; make sure it sounds right

(cherry picked from commit 24c5f7bba4)
2022-02-02 15:00:33 -06:00
Dustin Howett
6ccbd62f04 PGO: train 1.13 separately
(cherry picked from commit 989a9303c39d924653472b3e4ee640411e969455)
2022-02-02 13:03:41 -06:00
41 changed files with 1116 additions and 869 deletions

View File

@@ -10,16 +10,16 @@ bitfields
BUILDBRANCH
BUILDMSG
BUILDNUMBER
BYPOSITION
BYCOMMAND
BYPOSITION
charconv
CLASSNOTAVAILABLE
cmdletbinding
COLORPROPERTY
colspan
COMDLG
comparand
commandlinetoargv
comparand
cstdint
CXICON
CYICON
@@ -52,8 +52,8 @@ hotkeys
href
hrgn
HTCLOSE
HWINSTA
hwinsta
HWINSTA
IActivation
IApp
IAppearance
@@ -76,8 +76,8 @@ IObject
iosfwd
IPackage
IPeasant
isspace
ISetup
isspace
IStorage
istream
IStringable
@@ -94,14 +94,14 @@ lround
Lsa
lsass
LSHIFT
memicmp
MENUCOMMAND
MENUDATA
MENUINFO
MENUITEMINFOW
memicmp
mptt
MOUSELEAVE
mov
mptt
msappx
MULTIPLEUSE
NCHITTEST
@@ -125,6 +125,7 @@ oaidl
ocidl
ODR
offsetof
ofstream
onefuzz
osver
OSVERSIONINFOEXW
@@ -176,6 +177,7 @@ THEMECHANGED
tlg
TME
tmp
tmpdir
tolower
toupper
TRACKMOUSEEVENT
@@ -188,7 +190,6 @@ UOI
UPDATEINIFILE
userenv
USEROBJECTFLAGS
WSF
wcsstr
wcstoui
winmain
@@ -196,6 +197,7 @@ winsta
winstamin
wmemcmp
wpc
WSF
wsregex
wwinmain
xchg

View File

@@ -471,6 +471,7 @@ cygwin
CYHSCROLL
CYMIN
CYPADDEDBORDER
CYRL
CYSIZE
CYSIZEFRAME
CYSMICON
@@ -1238,12 +1239,14 @@ KLF
KLMNO
KLMNOPQRST
KLMNOPQRSTQQQQQ
KOK
KPRIORITY
KVM
langid
LANGUAGELIST
lasterror
lastexitcode
LATN
LAYOUTRTL
LBN
LBound
@@ -1460,6 +1463,7 @@ msctls
msdata
msdn
msft
MSDL
MSGCMDLINEF
MSGF
MSGFILTER
@@ -1792,6 +1796,9 @@ placeholders
platforming
playsound
plist
PLOC
PLOCA
PLOCM
PLOGICAL
plugin
PMv
@@ -1925,6 +1932,7 @@ qsort
queryable
QUESTIONMARK
quickedit
QUZ
QWER
qzmp
RAII
@@ -2437,6 +2445,7 @@ TREX
triaged
triaging
TRIANGLESTRIP
Tribool
TRIMZEROHEADINGS
truetype
trx

View File

@@ -9,7 +9,7 @@
<PropertyGroup>
<!-- Optional, defaults to main. Name of the branch which will be used for calculating branch point. -->
<PGOBranch>main</PGOBranch>
<PGOBranch>release-1.13</PGOBranch>
<!-- Mandatory. Name of the NuGet package which will contain PGO databases for consumption by build system. -->
<PGOPackageName>Microsoft.Internal.Windows.Terminal.PGODatabase</PGOPackageName>

View File

@@ -287,14 +287,17 @@ jobs:
inputs:
disableOutputRedirect: true
- task: DownloadBuildArtifacts@0
displayName: Download Artifacts (*.appx, *.msix)
displayName: Download Artifacts (*.appx, *.msix, *.appxsym)
inputs:
downloadType: specific
itemPattern: >-
**/*.msix
**/*.appx
**/*.appxsym
extractTars: false
- task: PowerShell@2
displayName: Create WindowsTerminal*.msixbundle
inputs:
@@ -334,6 +337,43 @@ jobs:
"ToolVersion": "1.0"
}
]
# It seems easier to do this -- download every appxsym -- then enumerate all the PDBs in the build directory for the
# public symbol push. Otherwise, we would have to list all of the PDB files one by one.
- pwsh: |-
mkdir $(Build.SourcesDirectory)/appxsym-temp
Get-ChildItem "$(System.ArtifactsDirectory)" -Filter *.appxsym -Recurse | % {
$src = $_.FullName
$dest = Join-Path "$(Build.SourcesDirectory)/appxsym-temp/" $_.Name
mkdir $dest
Write-Host "Extracting $src to $dest..."
tar -x -v -f $src -C $dest
}
displayName: Extract symbols for public consumption
# Publish the app symbols to the public MSDL symbol server
# accessible via https://msdl.microsoft.com/download/symbols
- task: PublishSymbols@2
displayName: 'Publish app symbols to MSDL'
inputs:
symbolsFolder: '$(Build.SourcesDirectory)/appxsym-temp'
searchPattern: '**/*.pdb'
SymbolsMaximumWaitTime: 30
SymbolServerType: 'TeamServices'
SymbolsProduct: 'Windows Terminal Application Binaries'
SymbolsVersion: '$(XES_APPXMANIFESTVERSION)'
# The ADO task does not support indexing of GitHub sources.
indexSources: false
detailedLog: true
# There is a bug which causes this task to fail if LIB includes an inaccessible path (even though it does not depend on it).
# To work around this issue, we just force LIB to be any dir that we know exists.
# Copied from https://github.com/microsoft/icu/blob/f869c214adc87415dfe751d81f42f1bca55dcf5f/build/azure-nuget.yml#L564-L583
env:
LIB: $(Build.SourcesDirectory)
ArtifactServices_Symbol_AccountName: microsoftpublicsymbols
ArtifactServices_Symbol_PAT: $(ADO_microsoftpublicsymbols_PAT)
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: appxbundle-signed'
inputs:

View File

@@ -20,7 +20,7 @@
Version="0.0.1.0" />
<Properties>
<DisplayName>ms-resource:TerminalApp/ContextMenu/AppNameDev</DisplayName>
<DisplayName>ms-resource:TerminalApp/ContextMenu/AppStoreNameDev</DisplayName>
<PublisherDisplayName>A Lone Developer</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
</Properties>
@@ -30,7 +30,7 @@
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
<Resource Language="EN-US" />
</Resources>
<Applications>

View File

@@ -21,7 +21,7 @@
Version="0.5.0.0" />
<Properties>
<DisplayName>ms-resource:TerminalApp/ContextMenu/AppNamePre</DisplayName>
<DisplayName>ms-resource:TerminalApp/ContextMenu/AppStoreNamePre</DisplayName>
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
</Properties>
@@ -31,7 +31,95 @@
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
<Resource Language="EN-US" />
<Resource Language="EN-GB" />
<Resource Language="AF-ZA" />
<Resource Language="AM-ET" />
<Resource Language="AR-SA" />
<Resource Language="AS-IN" />
<Resource Language="AZ-LATN-AZ" />
<Resource Language="BG-BG" />
<Resource Language="BN-IN" />
<Resource Language="BS-LATN-BA" />
<Resource Language="CA-ES" />
<Resource Language="CA-ES-VALENCIA" />
<Resource Language="CS-CZ" />
<Resource Language="CY-GB" />
<Resource Language="DA-DK" />
<Resource Language="DE-DE" />
<Resource Language="EL-GR" />
<Resource Language="ES-ES" />
<Resource Language="ES-MX" />
<Resource Language="ET-EE" />
<Resource Language="EU-ES" />
<Resource Language="FA-IR" />
<Resource Language="FI-FI" />
<Resource Language="FIL-PH" />
<Resource Language="FR-CA" />
<Resource Language="FR-FR" />
<Resource Language="GA-IE" />
<Resource Language="GD-GB" />
<Resource Language="GL-ES" />
<Resource Language="GU-IN" />
<Resource Language="HE-IL" />
<Resource Language="HI-IN" />
<Resource Language="HR-HR" />
<Resource Language="HU-HU" />
<Resource Language="HY-AM" />
<Resource Language="ID-ID" />
<Resource Language="IS-IS" />
<Resource Language="IT-IT" />
<Resource Language="JA-JP" />
<Resource Language="KA-GE" />
<Resource Language="KK-KZ" />
<Resource Language="KM-KH" />
<Resource Language="KN-IN" />
<Resource Language="KO-KR" />
<Resource Language="KOK-IN" />
<Resource Language="LB-LU" />
<Resource Language="LO-LA" />
<Resource Language="LT-LT" />
<Resource Language="LV-LV" />
<Resource Language="MI-NZ" />
<Resource Language="MK-MK" />
<Resource Language="ML-IN" />
<Resource Language="MR-IN" />
<Resource Language="MS-MY" />
<Resource Language="MT-MT" />
<Resource Language="NB-NO" />
<Resource Language="NE-NP" />
<Resource Language="NL-NL" />
<Resource Language="NN-NO" />
<Resource Language="OR-IN" />
<Resource Language="PA-IN" />
<Resource Language="PL-PL" />
<Resource Language="PT-BR" />
<Resource Language="PT-PT" />
<Resource Language="QPS-PLOC" />
<Resource Language="QPS-PLOCA" />
<Resource Language="QPS-PLOCM" />
<Resource Language="QUZ-PE" />
<Resource Language="RO-RO" />
<Resource Language="RU-RU" />
<Resource Language="SK-SK" />
<Resource Language="SL-SI" />
<Resource Language="SQ-AL" />
<Resource Language="SR-CYRL-BA" />
<Resource Language="SR-CYRL-RS" />
<Resource Language="SR-LATN-RS" />
<Resource Language="SV-SE" />
<Resource Language="TA-IN" />
<Resource Language="TE-IN" />
<Resource Language="TH-TH" />
<Resource Language="TR-TR" />
<Resource Language="TT-RU" />
<Resource Language="UG-CN" />
<Resource Language="UK-UA" />
<Resource Language="UR-PK" />
<Resource Language="UZ-LATN-UZ" />
<Resource Language="VI-VN" />
<Resource Language="ZH-CN" />
<Resource Language="ZH-TW" />
</Resources>
<Applications>

View File

@@ -21,7 +21,7 @@
Version="1.0.0.0" />
<Properties>
<DisplayName>ms-resource:TerminalApp/ContextMenu/AppName</DisplayName>
<DisplayName>ms-resource:TerminalApp/ContextMenu/AppStoreName</DisplayName>
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
</Properties>
@@ -31,7 +31,95 @@
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
<Resource Language="EN-US" />
<Resource Language="EN-GB" />
<Resource Language="AF-ZA" />
<Resource Language="AM-ET" />
<Resource Language="AR-SA" />
<Resource Language="AS-IN" />
<Resource Language="AZ-LATN-AZ" />
<Resource Language="BG-BG" />
<Resource Language="BN-IN" />
<Resource Language="BS-LATN-BA" />
<Resource Language="CA-ES" />
<Resource Language="CA-ES-VALENCIA" />
<Resource Language="CS-CZ" />
<Resource Language="CY-GB" />
<Resource Language="DA-DK" />
<Resource Language="DE-DE" />
<Resource Language="EL-GR" />
<Resource Language="ES-ES" />
<Resource Language="ES-MX" />
<Resource Language="ET-EE" />
<Resource Language="EU-ES" />
<Resource Language="FA-IR" />
<Resource Language="FI-FI" />
<Resource Language="FIL-PH" />
<Resource Language="FR-CA" />
<Resource Language="FR-FR" />
<Resource Language="GA-IE" />
<Resource Language="GD-GB" />
<Resource Language="GL-ES" />
<Resource Language="GU-IN" />
<Resource Language="HE-IL" />
<Resource Language="HI-IN" />
<Resource Language="HR-HR" />
<Resource Language="HU-HU" />
<Resource Language="HY-AM" />
<Resource Language="ID-ID" />
<Resource Language="IS-IS" />
<Resource Language="IT-IT" />
<Resource Language="JA-JP" />
<Resource Language="KA-GE" />
<Resource Language="KK-KZ" />
<Resource Language="KM-KH" />
<Resource Language="KN-IN" />
<Resource Language="KO-KR" />
<Resource Language="KOK-IN" />
<Resource Language="LB-LU" />
<Resource Language="LO-LA" />
<Resource Language="LT-LT" />
<Resource Language="LV-LV" />
<Resource Language="MI-NZ" />
<Resource Language="MK-MK" />
<Resource Language="ML-IN" />
<Resource Language="MR-IN" />
<Resource Language="MS-MY" />
<Resource Language="MT-MT" />
<Resource Language="NB-NO" />
<Resource Language="NE-NP" />
<Resource Language="NL-NL" />
<Resource Language="NN-NO" />
<Resource Language="OR-IN" />
<Resource Language="PA-IN" />
<Resource Language="PL-PL" />
<Resource Language="PT-BR" />
<Resource Language="PT-PT" />
<Resource Language="QPS-PLOC" />
<Resource Language="QPS-PLOCA" />
<Resource Language="QPS-PLOCM" />
<Resource Language="QUZ-PE" />
<Resource Language="RO-RO" />
<Resource Language="RU-RU" />
<Resource Language="SK-SK" />
<Resource Language="SL-SI" />
<Resource Language="SQ-AL" />
<Resource Language="SR-CYRL-BA" />
<Resource Language="SR-CYRL-RS" />
<Resource Language="SR-LATN-RS" />
<Resource Language="SV-SE" />
<Resource Language="TA-IN" />
<Resource Language="TE-IN" />
<Resource Language="TH-TH" />
<Resource Language="TR-TR" />
<Resource Language="TT-RU" />
<Resource Language="UG-CN" />
<Resource Language="UK-UA" />
<Resource Language="UR-PK" />
<Resource Language="UZ-LATN-UZ" />
<Resource Language="VI-VN" />
<Resource Language="ZH-CN" />
<Resource Language="ZH-TW" />
</Resources>
<Applications>

View File

@@ -38,6 +38,7 @@ namespace SettingsModelLocalTests
TEST_METHOD(TryCreateWinRTType);
TEST_METHOD(TestTerminalArgsForBinding);
TEST_METHOD(CommandLineToArgvW);
TEST_METHOD(NormalizeCommandLine);
TEST_METHOD(GetProfileForArgsWithCommandline);
TEST_METHOD(MakeSettingsForProfile);
TEST_METHOD(MakeSettingsForDefaultProfileThatDoesntExist);
@@ -120,6 +121,59 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(0, memcmp(beg, expectedArgv.data(), expectedArgv.size()));
}
// This unit test covers GH#12345.
// * paths with more than 1 whitespace
// * paths sharing a common prefix with another directory
void TerminalSettingsTests::NormalizeCommandLine()
{
using namespace std::string_literals;
static constexpr auto touch = [](const auto& path) {
std::ofstream file{ path };
};
std::wstring guid;
{
GUID g{};
THROW_IF_FAILED(CoCreateGuid(&g));
guid = fmt::format(
L"{:08x}-{:04x}-{:04x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
g.Data1,
g.Data2,
g.Data3,
g.Data4[0],
g.Data4[1],
g.Data4[2],
g.Data4[3],
g.Data4[4],
g.Data4[5],
g.Data4[6],
g.Data4[7]);
}
const auto tmpdir = std::filesystem::temp_directory_path();
const auto dir1 = tmpdir / guid;
const auto dir2 = tmpdir / (guid + L" two");
const auto file1 = dir1 / L"file 1.exe";
const auto file2 = dir2 / L"file 2.exe";
const auto cleanup = wil::scope_exit([&]() {
std::error_code ec;
remove_all(dir1, ec);
remove_all(dir2, ec);
});
create_directory(dir1);
create_directory(dir2);
touch(file1);
touch(file2);
const auto commandLine = file2.native() + LR"( -foo "bar1 bar2" -baz)"s;
const auto expected = file2.native() + L"\0-foo\0bar1 bar2\0-baz"s;
const auto actual = implementation::CascadiaSettings::NormalizeCommandLine(commandLine.c_str());
VERIFY_ARE_EQUAL(expected, actual);
}
void TerminalSettingsTests::GetProfileForArgsWithCommandline()
{
// I'm exclusively using cmd.exe as I know exactly where it resides at.

View File

@@ -54,20 +54,20 @@
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<!-- Define resources for Dark mode here -->
<SolidColorBrush x:Key="TabViewBackground"
Color="#FF333333" />
<StaticResource x:Key="TabViewBackground"
ResourceKey="ApplicationPageBackgroundThemeBrush" />
<SolidColorBrush x:Key="UnfocusedBorderBrush"
Color="#FF333333" />
<StaticResource x:Key="UnfocusedBorderBrush"
ResourceKey="ApplicationPageBackgroundThemeBrush" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<!-- Define resources for Light mode here -->
<SolidColorBrush x:Key="TabViewBackground"
Color="#FFCCCCCC" />
<StaticResource x:Key="TabViewBackground"
ResourceKey="ApplicationPageBackgroundThemeBrush" />
<SolidColorBrush x:Key="UnfocusedBorderBrush"
Color="#FFCCCCCC" />
<StaticResource x:Key="UnfocusedBorderBrush"
ResourceKey="ApplicationPageBackgroundThemeBrush" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

View File

@@ -62,6 +62,19 @@ static std::wstring _normalizeIconPath(std::wstring_view path)
// - <none>
winrt::fire_and_forget Jumplist::UpdateJumplist(const CascadiaSettings& settings) noexcept
{
if (!settings)
{
// By all accounts, this shouldn't be null. Seemingly however (GH
// #12360), it sometimes is. So just check this case here and log a
// message.
TraceLoggingWrite(g_hTerminalAppProvider,
"Jumplist_UpdateJumplist_NullSettings",
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
co_return;
}
// make sure to capture the settings _before_ the co_await
const auto strongSettings = settings;

View File

@@ -127,6 +127,16 @@
<data name="AppNamePre" xml:space="preserve">
<value>Terminal Preview</value>
</data>
<data name="AppStoreName" xml:space="preserve">
<value>Windows Terminal</value>
</data>
<data name="AppStoreNameDev" xml:space="preserve">
<value>Windows Terminal Dev</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="AppStoreNamePre" xml:space="preserve">
<value>Windows Terminal Preview</value>
</data>
<data name="AppShortName" xml:space="preserve">
<value>Terminal</value>
</data>

View File

@@ -3095,9 +3095,12 @@ namespace winrt::TerminalApp::implementation
{
NewTerminalArgs newTerminalArgs;
newTerminalArgs.Commandline(connection.Commandline());
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
const auto settings{ TerminalSettings::CreateWithProfile(_settings, profile, *_bindings) };
// GH #12370: We absolutely cannot allow a defterm connection to
// auto-elevate. Defterm doesn't work for elevated scenarios in the
// first place. If we try accepting the connection, the spawning an
// elevated version of the Terminal with that profile... that's a
// recipe for disaster. We won't ever open up a tab in this window.
newTerminalArgs.Elevate(false);
_CreateNewTabFromPane(_MakePane(newTerminalArgs, false, connection));
// Request a summon of this window to the foreground

View File

@@ -19,54 +19,54 @@ namespace Microsoft::Terminal::Core
ITerminalApi& operator=(const ITerminalApi&) = default;
ITerminalApi& operator=(ITerminalApi&&) = default;
virtual bool PrintString(std::wstring_view string) noexcept = 0;
virtual bool ExecuteChar(wchar_t wch) noexcept = 0;
virtual void PrintString(std::wstring_view string) = 0;
virtual void ExecuteChar(wchar_t wch) = 0;
virtual TextAttribute GetTextAttributes() const noexcept = 0;
virtual void SetTextAttributes(const TextAttribute& attrs) noexcept = 0;
virtual TextAttribute GetTextAttributes() const = 0;
virtual void SetTextAttributes(const TextAttribute& attrs) = 0;
virtual Microsoft::Console::Types::Viewport GetBufferSize() noexcept = 0;
virtual bool SetCursorPosition(short x, short y) noexcept = 0;
virtual COORD GetCursorPosition() noexcept = 0;
virtual bool SetCursorVisibility(const bool visible) noexcept = 0;
virtual bool CursorLineFeed(const bool withReturn) noexcept = 0;
virtual bool EnableCursorBlinking(const bool enable) noexcept = 0;
virtual Microsoft::Console::Types::Viewport GetBufferSize() = 0;
virtual void SetCursorPosition(short x, short y) = 0;
virtual COORD GetCursorPosition() = 0;
virtual void SetCursorVisibility(const bool visible) = 0;
virtual void CursorLineFeed(const bool withReturn) = 0;
virtual void EnableCursorBlinking(const bool enable) = 0;
virtual bool DeleteCharacter(const size_t count) noexcept = 0;
virtual bool InsertCharacter(const size_t count) noexcept = 0;
virtual bool EraseCharacters(const size_t numChars) noexcept = 0;
virtual bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept = 0;
virtual bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept = 0;
virtual void DeleteCharacter(const size_t count) = 0;
virtual void InsertCharacter(const size_t count) = 0;
virtual void EraseCharacters(const size_t numChars) = 0;
virtual bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) = 0;
virtual bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) = 0;
virtual bool WarningBell() noexcept = 0;
virtual bool SetWindowTitle(std::wstring_view title) noexcept = 0;
virtual void WarningBell() = 0;
virtual void SetWindowTitle(std::wstring_view title) = 0;
virtual COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept = 0;
virtual bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept = 0;
virtual void SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex) noexcept = 0;
virtual COLORREF GetColorTableEntry(const size_t tableIndex) const = 0;
virtual void SetColorTableEntry(const size_t tableIndex, const COLORREF color) = 0;
virtual void SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex) = 0;
virtual bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept = 0;
virtual void SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) = 0;
virtual bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept = 0;
virtual bool SetRenderMode(const ::Microsoft::Console::Render::RenderSettings::Mode mode, const bool enabled) noexcept = 0;
virtual void SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) = 0;
virtual void SetRenderMode(const ::Microsoft::Console::Render::RenderSettings::Mode mode, const bool enabled) = 0;
virtual bool EnableXtermBracketedPasteMode(const bool enabled) noexcept = 0;
virtual void EnableXtermBracketedPasteMode(const bool enabled) = 0;
virtual bool IsXtermBracketedPasteModeEnabled() const = 0;
virtual bool IsVtInputEnabled() const = 0;
virtual bool CopyToClipboard(std::wstring_view content) noexcept = 0;
virtual void CopyToClipboard(std::wstring_view content) = 0;
virtual bool AddHyperlink(std::wstring_view uri, std::wstring_view params) noexcept = 0;
virtual bool EndHyperlink() noexcept = 0;
virtual void AddHyperlink(std::wstring_view uri, std::wstring_view params) = 0;
virtual void EndHyperlink() = 0;
virtual bool SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) noexcept = 0;
virtual void SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) = 0;
virtual bool SetWorkingDirectory(std::wstring_view uri) noexcept = 0;
virtual std::wstring_view GetWorkingDirectory() noexcept = 0;
virtual void SetWorkingDirectory(std::wstring_view uri) = 0;
virtual std::wstring_view GetWorkingDirectory() = 0;
virtual bool PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) noexcept = 0;
virtual bool PopGraphicsRendition() noexcept = 0;
virtual void PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) = 0;
virtual void PopGraphicsRendition() = 0;
protected:
ITerminalApi() = default;

View File

@@ -95,47 +95,47 @@ public:
#pragma region ITerminalApi
// These methods are defined in TerminalApi.cpp
bool PrintString(std::wstring_view stringView) noexcept override;
bool ExecuteChar(wchar_t wch) noexcept override;
TextAttribute GetTextAttributes() const noexcept override;
void SetTextAttributes(const TextAttribute& attrs) noexcept override;
Microsoft::Console::Types::Viewport GetBufferSize() noexcept override;
bool SetCursorPosition(short x, short y) noexcept override;
COORD GetCursorPosition() noexcept override;
bool SetCursorVisibility(const bool visible) noexcept override;
bool EnableCursorBlinking(const bool enable) noexcept override;
bool CursorLineFeed(const bool withReturn) noexcept override;
bool DeleteCharacter(const size_t count) noexcept override;
bool InsertCharacter(const size_t count) noexcept override;
bool EraseCharacters(const size_t numChars) noexcept override;
bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
bool WarningBell() noexcept override;
bool SetWindowTitle(std::wstring_view title) noexcept override;
COLORREF GetColorTableEntry(const size_t tableIndex) const noexcept override;
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override;
void SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex) noexcept override;
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept override;
void PrintString(std::wstring_view stringView) override;
void ExecuteChar(wchar_t wch) override;
TextAttribute GetTextAttributes() const override;
void SetTextAttributes(const TextAttribute& attrs) override;
Microsoft::Console::Types::Viewport GetBufferSize() override;
void SetCursorPosition(short x, short y) override;
COORD GetCursorPosition() override;
void SetCursorVisibility(const bool visible) override;
void EnableCursorBlinking(const bool enable) override;
void CursorLineFeed(const bool withReturn) override;
void DeleteCharacter(const size_t count) override;
void InsertCharacter(const size_t count) override;
void EraseCharacters(const size_t numChars) override;
bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) override;
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) override;
void WarningBell() override;
void SetWindowTitle(std::wstring_view title) override;
COLORREF GetColorTableEntry(const size_t tableIndex) const override;
void SetColorTableEntry(const size_t tableIndex, const COLORREF color) override;
void SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex) override;
void SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) override;
bool SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) noexcept override;
bool SetRenderMode(const ::Microsoft::Console::Render::RenderSettings::Mode mode, const bool enabled) noexcept override;
void SetInputMode(const ::Microsoft::Console::VirtualTerminal::TerminalInput::Mode mode, const bool enabled) override;
void SetRenderMode(const ::Microsoft::Console::Render::RenderSettings::Mode mode, const bool enabled) override;
bool EnableXtermBracketedPasteMode(const bool enabled) noexcept override;
bool IsXtermBracketedPasteModeEnabled() const noexcept override;
void EnableXtermBracketedPasteMode(const bool enabled) override;
bool IsXtermBracketedPasteModeEnabled() const override;
bool IsVtInputEnabled() const noexcept override;
bool IsVtInputEnabled() const override;
bool CopyToClipboard(std::wstring_view content) noexcept override;
void CopyToClipboard(std::wstring_view content) override;
bool AddHyperlink(std::wstring_view uri, std::wstring_view params) noexcept override;
bool EndHyperlink() noexcept override;
void AddHyperlink(std::wstring_view uri, std::wstring_view params) override;
void EndHyperlink() override;
bool SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) noexcept override;
bool SetWorkingDirectory(std::wstring_view uri) noexcept override;
std::wstring_view GetWorkingDirectory() noexcept override;
void SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) override;
void SetWorkingDirectory(std::wstring_view uri) override;
std::wstring_view GetWorkingDirectory() override;
bool PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) noexcept override;
bool PopGraphicsRendition() noexcept override;
void PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) override;
void PopGraphicsRendition() override;
#pragma endregion

View File

@@ -11,39 +11,32 @@ using namespace Microsoft::Console::Types;
using namespace Microsoft::Console::VirtualTerminal;
// Print puts the text in the buffer and moves the cursor
bool Terminal::PrintString(std::wstring_view stringView) noexcept
try
void Terminal::PrintString(std::wstring_view stringView)
{
_WriteBuffer(stringView);
return true;
}
CATCH_RETURN_FALSE()
bool Terminal::ExecuteChar(wchar_t wch) noexcept
try
void Terminal::ExecuteChar(wchar_t wch)
{
_WriteBuffer({ &wch, 1 });
return true;
}
CATCH_RETURN_FALSE()
TextAttribute Terminal::GetTextAttributes() const noexcept
TextAttribute Terminal::GetTextAttributes() const
{
return _buffer->GetCurrentAttributes();
}
void Terminal::SetTextAttributes(const TextAttribute& attrs) noexcept
void Terminal::SetTextAttributes(const TextAttribute& attrs)
{
_buffer->SetCurrentAttributes(attrs);
}
Viewport Terminal::GetBufferSize() noexcept
Viewport Terminal::GetBufferSize()
{
return _buffer->GetSize();
}
bool Terminal::SetCursorPosition(short x, short y) noexcept
try
void Terminal::SetCursorPosition(short x, short y)
{
const auto viewport = _GetMutableViewport();
const auto viewOrigin = viewport.Origin();
@@ -52,12 +45,9 @@ try
COORD newPos{ absoluteX, absoluteY };
viewport.Clamp(newPos);
_buffer->GetCursor().SetPosition(newPos);
return true;
}
CATCH_RETURN_FALSE()
COORD Terminal::GetCursorPosition() noexcept
COORD Terminal::GetCursorPosition()
{
const auto absoluteCursorPos = _buffer->GetCursor().GetPosition();
const auto viewport = _GetMutableViewport();
@@ -75,9 +65,8 @@ COORD Terminal::GetCursorPosition() noexcept
// Arguments:
// - withReturn, set to true if a carriage return should be performed as well.
// Return value:
// - true if succeeded, false otherwise
bool Terminal::CursorLineFeed(const bool withReturn) noexcept
try
// - <none>
void Terminal::CursorLineFeed(const bool withReturn)
{
auto cursorPos = _buffer->GetCursor().GetPosition();
@@ -91,10 +80,7 @@ try
cursorPos.X = 0;
}
_AdjustCursorPosition(cursorPos);
return true;
}
CATCH_RETURN_FALSE()
// Method Description:
// - deletes count characters starting from the cursor's current position
@@ -105,24 +91,17 @@ CATCH_RETURN_FALSE()
// Arguments:
// - count, the number of characters to delete
// Return value:
// - true if succeeded, false otherwise
bool Terminal::DeleteCharacter(const size_t count) noexcept
try
// - <none>
void Terminal::DeleteCharacter(const size_t count)
{
SHORT dist;
if (!SUCCEEDED(SizeTToShort(count, &dist)))
{
return false;
}
THROW_IF_FAILED(SizeTToShort(count, &dist));
const auto cursorPos = _buffer->GetCursor().GetPosition();
const auto copyToPos = cursorPos;
const COORD copyFromPos{ cursorPos.X + dist, cursorPos.Y };
const auto sourceWidth = _mutableViewport.RightExclusive() - copyFromPos.X;
SHORT width;
if (!SUCCEEDED(UIntToShort(sourceWidth, &width)))
{
return false;
}
THROW_IF_FAILED(UIntToShort(sourceWidth, &width));
// Get a rectangle of the source
auto source = Viewport::FromDimensions(copyFromPos, width, 1);
@@ -140,10 +119,7 @@ try
const auto data = OutputCell(*(_buffer->GetCellDataAt(sourcePos)));
_buffer->Write(OutputCellIterator({ &data, 1 }), targetPos);
} while (source.WalkInBounds(sourcePos, walkDirection) && target.WalkInBounds(targetPos, walkDirection));
return true;
}
CATCH_RETURN_FALSE()
// Method Description:
// - Inserts count spaces starting from the cursor's current position, moving over the existing text
@@ -153,28 +129,21 @@ CATCH_RETURN_FALSE()
// Arguments:
// - count, the number of spaces to insert
// Return value:
// - true if succeeded, false otherwise
bool Terminal::InsertCharacter(const size_t count) noexcept
try
// - <none>
void Terminal::InsertCharacter(const size_t count)
{
// NOTE: the code below is _extremely_ similar to DeleteCharacter
// We will want to use this same logic and implement a helper function instead
// that does the 'move a region from here to there' operation
// TODO: Github issue #2163
SHORT dist;
if (!SUCCEEDED(SizeTToShort(count, &dist)))
{
return false;
}
THROW_IF_FAILED(SizeTToShort(count, &dist));
const auto cursorPos = _buffer->GetCursor().GetPosition();
const auto copyFromPos = cursorPos;
const COORD copyToPos{ cursorPos.X + dist, cursorPos.Y };
const auto sourceWidth = _mutableViewport.RightExclusive() - copyFromPos.X;
SHORT width;
if (!SUCCEEDED(UIntToShort(sourceWidth, &width)))
{
return false;
}
THROW_IF_FAILED(UIntToShort(sourceWidth, &width));
// Get a rectangle of the source
auto source = Viewport::FromDimensions(copyFromPos, width, 1);
@@ -195,13 +164,9 @@ try
} while (source.WalkInBounds(sourcePos, walkDirection) && target.WalkInBounds(targetPos, walkDirection));
const auto eraseIter = OutputCellIterator(UNICODE_SPACE, _buffer->GetCurrentAttributes(), dist);
_buffer->Write(eraseIter, cursorPos);
return true;
}
CATCH_RETURN_FALSE()
bool Terminal::EraseCharacters(const size_t numChars) noexcept
try
void Terminal::EraseCharacters(const size_t numChars)
{
const auto absoluteCursorPos = _buffer->GetCursor().GetPosition();
const auto viewport = _GetMutableViewport();
@@ -209,9 +174,7 @@ try
const short fillLimit = std::min(static_cast<short>(numChars), distanceToRight);
const auto eraseIter = OutputCellIterator(UNICODE_SPACE, _buffer->GetCurrentAttributes(), fillLimit);
_buffer->Write(eraseIter, absoluteCursorPos);
return true;
}
CATCH_RETURN_FALSE()
// Method description:
// - erases a line of text, either from
@@ -223,8 +186,7 @@ CATCH_RETURN_FALSE()
// - the erase type
// Return value:
// - true if succeeded, false otherwise
bool Terminal::EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept
try
bool Terminal::EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType)
{
const auto cursorPos = _buffer->GetCursor().GetPosition();
const auto viewport = _GetMutableViewport();
@@ -257,7 +219,6 @@ try
_buffer->Write(eraseIter, startPos, false);
return true;
}
CATCH_RETURN_FALSE()
// Method description:
// - erases text in the buffer in two ways depending on erase type
@@ -267,8 +228,7 @@ CATCH_RETURN_FALSE()
// - the erase type
// Return Value:
// - true if succeeded, false otherwise
bool Terminal::EraseInDisplay(const DispatchTypes::EraseType eraseType) noexcept
try
bool Terminal::EraseInDisplay(const DispatchTypes::EraseType eraseType)
{
// Store the relative cursor position so we can restore it later after we move the viewport
const auto cursorPos = _buffer->GetCursor().GetPosition();
@@ -341,27 +301,20 @@ try
return true;
}
CATCH_RETURN_FALSE()
bool Terminal::WarningBell() noexcept
try
void Terminal::WarningBell()
{
_pfnWarningBell();
return true;
}
CATCH_RETURN_FALSE()
bool Terminal::SetWindowTitle(std::wstring_view title) noexcept
try
void Terminal::SetWindowTitle(std::wstring_view title)
{
if (!_suppressApplicationTitle)
{
_title.emplace(title);
_pfnTitleChanged(_title.value());
}
return true;
}
CATCH_RETURN_FALSE()
// Method Description:
// - Retrieves the value in the colortable at the specified index.
@@ -369,15 +322,10 @@ CATCH_RETURN_FALSE()
// - tableIndex: the index of the color table to retrieve.
// Return Value:
// - the COLORREF value for the color at that index in the table.
COLORREF Terminal::GetColorTableEntry(const size_t tableIndex) const noexcept
try
COLORREF Terminal::GetColorTableEntry(const size_t tableIndex) const
{
return _renderSettings.GetColorTableEntry(tableIndex);
}
catch (...)
{
return INVALID_COLOR;
}
// Method Description:
// - Updates the value in the colortable at index tableIndex to the new color
@@ -386,9 +334,8 @@ catch (...)
// - tableIndex: the index of the color table to update.
// - color: the new COLORREF to use as that color table value.
// Return Value:
// - true iff we successfully updated the color table entry.
bool Terminal::SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept
try
// - <none>
void Terminal::SetColorTableEntry(const size_t tableIndex, const COLORREF color)
{
_renderSettings.SetColorTableEntry(tableIndex, color);
@@ -399,9 +346,7 @@ try
// Repaint everything - the colors might have changed
_buffer->GetRenderTarget().TriggerRedrawAll();
return true;
}
CATCH_RETURN_FALSE()
// Method Description:
// - Sets the position in the color table for the given color alias.
@@ -410,7 +355,7 @@ CATCH_RETURN_FALSE()
// - tableIndex: the new position of the alias in the color table.
// Return Value:
// - <none>
void Terminal::SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex) noexcept
void Terminal::SetColorAliasIndex(const ColorAlias alias, const size_t tableIndex)
{
_renderSettings.SetColorAliasIndex(alias, tableIndex);
}
@@ -420,8 +365,8 @@ void Terminal::SetColorAliasIndex(const ColorAlias alias, const size_t tableInde
// Arguments:
// - cursorStyle: the style to be set for the cursor
// Return Value:
// - true iff we successfully set the cursor style
bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noexcept
// - <none>
void Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle)
{
CursorType finalCursorType = CursorType::Legacy;
bool shouldBlink = false;
@@ -459,58 +404,48 @@ bool Terminal::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noex
default:
// Invalid argument should be ignored.
return true;
return;
}
_buffer->GetCursor().SetType(finalCursorType);
_buffer->GetCursor().SetBlinkingAllowed(shouldBlink);
return true;
}
bool Terminal::SetInputMode(const TerminalInput::Mode mode, const bool enabled) noexcept
try
void Terminal::SetInputMode(const TerminalInput::Mode mode, const bool enabled)
{
_terminalInput->SetInputMode(mode, enabled);
return true;
}
CATCH_RETURN_FALSE()
bool Terminal::SetRenderMode(const RenderSettings::Mode mode, const bool enabled) noexcept
try
void Terminal::SetRenderMode(const RenderSettings::Mode mode, const bool enabled)
{
_renderSettings.SetRenderMode(mode, enabled);
// Repaint everything - the colors will have changed
_buffer->GetRenderTarget().TriggerRedrawAll();
return true;
}
CATCH_RETURN_FALSE()
bool Terminal::EnableXtermBracketedPasteMode(const bool enabled) noexcept
void Terminal::EnableXtermBracketedPasteMode(const bool enabled)
{
_bracketedPasteMode = enabled;
return true;
}
bool Terminal::IsXtermBracketedPasteModeEnabled() const noexcept
bool Terminal::IsXtermBracketedPasteModeEnabled() const
{
return _bracketedPasteMode;
}
bool Terminal::IsVtInputEnabled() const noexcept
bool Terminal::IsVtInputEnabled() const
{
// We should never be getting this call in Terminal.
FAIL_FAST();
}
bool Terminal::SetCursorVisibility(const bool visible) noexcept
void Terminal::SetCursorVisibility(const bool visible)
{
_buffer->GetCursor().SetIsVisible(visible);
return true;
}
bool Terminal::EnableCursorBlinking(const bool enable) noexcept
void Terminal::EnableCursorBlinking(const bool enable)
{
_buffer->GetCursor().SetBlinkingAllowed(enable);
@@ -521,17 +456,12 @@ bool Terminal::EnableCursorBlinking(const bool enable) noexcept
// cursor visibility property controls whether the user can see it or not.
// (Yes, the cursor can be On and NOT Visible)
_buffer->GetCursor().SetIsOn(true);
return true;
}
bool Terminal::CopyToClipboard(std::wstring_view content) noexcept
try
void Terminal::CopyToClipboard(std::wstring_view content)
{
_pfnCopyToClipboard(content);
return true;
}
CATCH_RETURN_FALSE()
// Method Description:
// - Updates the buffer's current text attributes to start a hyperlink
@@ -539,27 +469,25 @@ CATCH_RETURN_FALSE()
// - The hyperlink URI
// - The customID provided (if there was one)
// Return Value:
// - true
bool Terminal::AddHyperlink(std::wstring_view uri, std::wstring_view params) noexcept
// - <none>
void Terminal::AddHyperlink(std::wstring_view uri, std::wstring_view params)
{
auto attr = _buffer->GetCurrentAttributes();
const auto id = _buffer->GetHyperlinkId(uri, params);
attr.SetHyperlinkId(id);
_buffer->SetCurrentAttributes(attr);
_buffer->AddHyperlinkToMap(uri, id);
return true;
}
// Method Description:
// - Updates the buffer's current text attributes to end a hyperlink
// Return Value:
// - true
bool Terminal::EndHyperlink() noexcept
// - <none>
void Terminal::EndHyperlink()
{
auto attr = _buffer->GetCurrentAttributes();
attr.SetHyperlinkId(0);
_buffer->SetCurrentAttributes(attr);
return true;
}
// Method Description:
@@ -568,8 +496,8 @@ bool Terminal::EndHyperlink() noexcept
// - state: indicates the progress state
// - progress: indicates the progress value
// Return Value:
// - true
bool Terminal::SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress) noexcept
// - <none>
void Terminal::SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState state, const size_t progress)
{
_taskbarState = static_cast<size_t>(state);
@@ -610,16 +538,14 @@ bool Terminal::SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::D
{
_pfnTaskbarProgressChanged();
}
return true;
}
bool Terminal::SetWorkingDirectory(std::wstring_view uri) noexcept
void Terminal::SetWorkingDirectory(std::wstring_view uri)
{
_workingDirectory = uri;
return true;
}
std::wstring_view Terminal::GetWorkingDirectory() noexcept
std::wstring_view Terminal::GetWorkingDirectory()
{
return _workingDirectory;
}
@@ -631,11 +557,10 @@ std::wstring_view Terminal::GetWorkingDirectory() noexcept
// should be saved. Only a small subset of GraphicsOptions are actually supported;
// others are ignored. If no options are specified, all attributes are stored.
// Return Value:
// - true
bool Terminal::PushGraphicsRendition(const VTParameters options) noexcept
// - <none>
void Terminal::PushGraphicsRendition(const VTParameters options)
{
_sgrStack.Push(_buffer->GetCurrentAttributes(), options);
return true;
}
// Method Description:
@@ -644,10 +569,9 @@ bool Terminal::PushGraphicsRendition(const VTParameters options) noexcept
// Arguments:
// - <none>
// Return Value:
// - true
bool Terminal::PopGraphicsRendition() noexcept
// - <none>
void Terminal::PopGraphicsRendition()
{
const TextAttribute current = _buffer->GetCurrentAttributes();
_buffer->SetCurrentAttributes(_sgrStack.Pop(current));
return true;
}

View File

@@ -19,77 +19,74 @@ TerminalDispatch::TerminalDispatch(ITerminalApi& terminalApi) noexcept :
{
}
void TerminalDispatch::Execute(const wchar_t wchControl) noexcept
void TerminalDispatch::Execute(const wchar_t wchControl)
{
_terminalApi.ExecuteChar(wchControl);
}
void TerminalDispatch::Print(const wchar_t wchPrintable) noexcept
void TerminalDispatch::Print(const wchar_t wchPrintable)
{
_terminalApi.PrintString({ &wchPrintable, 1 });
}
void TerminalDispatch::PrintString(const std::wstring_view string) noexcept
void TerminalDispatch::PrintString(const std::wstring_view string)
{
_terminalApi.PrintString(string);
}
bool TerminalDispatch::CursorPosition(const size_t line,
const size_t column) noexcept
try
const size_t column)
{
SHORT x{ 0 };
SHORT y{ 0 };
RETURN_BOOL_IF_FALSE(SUCCEEDED(SizeTToShort(column, &x)) &&
SUCCEEDED(SizeTToShort(line, &y)));
THROW_IF_FAILED(SizeTToShort(column, &x));
THROW_IF_FAILED(SizeTToShort(line, &y));
RETURN_BOOL_IF_FALSE(SUCCEEDED(ShortSub(x, 1, &x)) &&
SUCCEEDED(ShortSub(y, 1, &y)));
THROW_IF_FAILED(ShortSub(x, 1, &x));
THROW_IF_FAILED(ShortSub(y, 1, &y));
return _terminalApi.SetCursorPosition(x, y);
_terminalApi.SetCursorPosition(x, y);
return true;
}
CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::CursorVisibility(const bool isVisible) noexcept
bool TerminalDispatch::CursorVisibility(const bool isVisible)
{
return _terminalApi.SetCursorVisibility(isVisible);
_terminalApi.SetCursorVisibility(isVisible);
return true;
}
bool TerminalDispatch::EnableCursorBlinking(const bool enable) noexcept
bool TerminalDispatch::EnableCursorBlinking(const bool enable)
{
return _terminalApi.EnableCursorBlinking(enable);
_terminalApi.EnableCursorBlinking(enable);
return true;
}
bool TerminalDispatch::CursorForward(const size_t distance) noexcept
try
bool TerminalDispatch::CursorForward(const size_t distance)
{
const auto cursorPos = _terminalApi.GetCursorPosition();
const COORD newCursorPos{ cursorPos.X + gsl::narrow<short>(distance), cursorPos.Y };
return _terminalApi.SetCursorPosition(newCursorPos.X, newCursorPos.Y);
_terminalApi.SetCursorPosition(newCursorPos.X, newCursorPos.Y);
return true;
}
CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::CursorBackward(const size_t distance) noexcept
try
bool TerminalDispatch::CursorBackward(const size_t distance)
{
const auto cursorPos = _terminalApi.GetCursorPosition();
const COORD newCursorPos{ cursorPos.X - gsl::narrow<short>(distance), cursorPos.Y };
return _terminalApi.SetCursorPosition(newCursorPos.X, newCursorPos.Y);
_terminalApi.SetCursorPosition(newCursorPos.X, newCursorPos.Y);
return true;
}
CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::CursorUp(const size_t distance) noexcept
try
bool TerminalDispatch::CursorUp(const size_t distance)
{
const auto cursorPos = _terminalApi.GetCursorPosition();
const COORD newCursorPos{ cursorPos.X, cursorPos.Y + gsl::narrow<short>(distance) };
return _terminalApi.SetCursorPosition(newCursorPos.X, newCursorPos.Y);
_terminalApi.SetCursorPosition(newCursorPos.X, newCursorPos.Y);
return true;
}
CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::LineFeed(const DispatchTypes::LineFeedType lineFeedType) noexcept
try
bool TerminalDispatch::LineFeed(const DispatchTypes::LineFeedType lineFeedType)
{
switch (lineFeedType)
{
@@ -97,45 +94,42 @@ try
// There is currently no need for mode-specific line feeds in the Terminal,
// so for now we just treat them as a line feed without carriage return.
case DispatchTypes::LineFeedType::WithoutReturn:
return _terminalApi.CursorLineFeed(false);
_terminalApi.CursorLineFeed(false);
return true;
case DispatchTypes::LineFeedType::WithReturn:
return _terminalApi.CursorLineFeed(true);
_terminalApi.CursorLineFeed(true);
return true;
default:
return false;
}
}
CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::EraseCharacters(const size_t numChars) noexcept
try
bool TerminalDispatch::EraseCharacters(const size_t numChars)
{
return _terminalApi.EraseCharacters(numChars);
_terminalApi.EraseCharacters(numChars);
return true;
}
CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::WarningBell() noexcept
try
bool TerminalDispatch::WarningBell()
{
return _terminalApi.WarningBell();
_terminalApi.WarningBell();
return true;
}
CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::CarriageReturn() noexcept
try
bool TerminalDispatch::CarriageReturn()
{
const auto cursorPos = _terminalApi.GetCursorPosition();
return _terminalApi.SetCursorPosition(0, cursorPos.Y);
_terminalApi.SetCursorPosition(0, cursorPos.Y);
return true;
}
CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetWindowTitle(std::wstring_view title) noexcept
try
bool TerminalDispatch::SetWindowTitle(std::wstring_view title)
{
return _terminalApi.SetWindowTitle(title);
_terminalApi.SetWindowTitle(title);
return true;
}
CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::HorizontalTabSet() noexcept
bool TerminalDispatch::HorizontalTabSet()
{
const auto width = _terminalApi.GetBufferSize().Dimensions().X;
const auto column = _terminalApi.GetCursorPosition().X;
@@ -145,7 +139,7 @@ bool TerminalDispatch::HorizontalTabSet() noexcept
return true;
}
bool TerminalDispatch::ForwardTab(const size_t numTabs) noexcept
bool TerminalDispatch::ForwardTab(const size_t numTabs)
{
const auto width = _terminalApi.GetBufferSize().Dimensions().X;
const auto cursorPosition = _terminalApi.GetCursorPosition();
@@ -162,10 +156,11 @@ bool TerminalDispatch::ForwardTab(const size_t numTabs) noexcept
}
}
return _terminalApi.SetCursorPosition(column, row);
_terminalApi.SetCursorPosition(column, row);
return true;
}
bool TerminalDispatch::BackwardsTab(const size_t numTabs) noexcept
bool TerminalDispatch::BackwardsTab(const size_t numTabs)
{
const auto width = _terminalApi.GetBufferSize().Dimensions().X;
const auto cursorPosition = _terminalApi.GetCursorPosition();
@@ -182,25 +177,23 @@ bool TerminalDispatch::BackwardsTab(const size_t numTabs) noexcept
}
}
return _terminalApi.SetCursorPosition(column, row);
_terminalApi.SetCursorPosition(column, row);
return true;
}
bool TerminalDispatch::TabClear(const DispatchTypes::TabClearType clearType) noexcept
bool TerminalDispatch::TabClear(const DispatchTypes::TabClearType clearType)
{
bool success = false;
switch (clearType)
{
case DispatchTypes::TabClearType::ClearCurrentColumn:
success = _ClearSingleTabStop();
break;
_ClearSingleTabStop();
return true;
case DispatchTypes::TabClearType::ClearAllColumns:
success = _ClearAllTabStops();
break;
_ClearAllTabStops();
return true;
default:
success = false;
break;
return false;
}
return success;
}
// Method Description:
@@ -209,63 +202,57 @@ bool TerminalDispatch::TabClear(const DispatchTypes::TabClearType clearType) noe
// - tableIndex: The VT color table index
// - color: The new RGB color value to use.
// Return Value:
// True if handled successfully. False otherwise.
// - True.
bool TerminalDispatch::SetColorTableEntry(const size_t tableIndex,
const DWORD color) noexcept
try
const DWORD color)
{
return _terminalApi.SetColorTableEntry(tableIndex, color);
_terminalApi.SetColorTableEntry(tableIndex, color);
return true;
}
CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle) noexcept
try
bool TerminalDispatch::SetCursorStyle(const DispatchTypes::CursorStyle cursorStyle)
{
return _terminalApi.SetCursorStyle(cursorStyle);
_terminalApi.SetCursorStyle(cursorStyle);
return true;
}
CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetCursorColor(const DWORD color) noexcept
try
bool TerminalDispatch::SetCursorColor(const DWORD color)
{
return _terminalApi.SetColorTableEntry(TextColor::CURSOR_COLOR, color);
_terminalApi.SetColorTableEntry(TextColor::CURSOR_COLOR, color);
return true;
}
CATCH_LOG_RETURN_FALSE()
bool TerminalDispatch::SetClipboard(std::wstring_view content) noexcept
try
bool TerminalDispatch::SetClipboard(std::wstring_view content)
{
return _terminalApi.CopyToClipboard(content);
_terminalApi.CopyToClipboard(content);
return true;
}
CATCH_LOG_RETURN_FALSE()
// Method Description:
// - Sets the default foreground color to a new value
// Arguments:
// - color: The new RGB color value to use, in 0x00BBGGRR form
// Return Value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::SetDefaultForeground(const DWORD color) noexcept
try
// - True.
bool TerminalDispatch::SetDefaultForeground(const DWORD color)
{
_terminalApi.SetColorAliasIndex(ColorAlias::DefaultForeground, TextColor::DEFAULT_FOREGROUND);
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, color);
_terminalApi.SetColorTableEntry(TextColor::DEFAULT_FOREGROUND, color);
return true;
}
CATCH_LOG_RETURN_FALSE()
// Method Description:
// - Sets the default background color to a new value
// Arguments:
// - color: The new RGB color value to use, in 0x00BBGGRR form
// Return Value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::SetDefaultBackground(const DWORD color) noexcept
try
// - True.
bool TerminalDispatch::SetDefaultBackground(const DWORD color)
{
_terminalApi.SetColorAliasIndex(ColorAlias::DefaultBackground, TextColor::DEFAULT_BACKGROUND);
return _terminalApi.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, color);
_terminalApi.SetColorTableEntry(TextColor::DEFAULT_BACKGROUND, color);
return true;
}
CATCH_LOG_RETURN_FALSE()
// Method Description:
// - Erases characters in the buffer depending on the erase type
@@ -273,38 +260,34 @@ CATCH_LOG_RETURN_FALSE()
// - eraseType: the erase type (from beginning, to end, or all)
// Return Value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::EraseInLine(const DispatchTypes::EraseType eraseType) noexcept
try
bool TerminalDispatch::EraseInLine(const DispatchTypes::EraseType eraseType)
{
return _terminalApi.EraseInLine(eraseType);
}
CATCH_LOG_RETURN_FALSE()
// Method Description:
// - Deletes count number of characters starting from where the cursor is currently
// Arguments:
// - count, the number of characters to delete
// Return Value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::DeleteCharacter(const size_t count) noexcept
try
// - True.
bool TerminalDispatch::DeleteCharacter(const size_t count)
{
return _terminalApi.DeleteCharacter(count);
_terminalApi.DeleteCharacter(count);
return true;
}
CATCH_LOG_RETURN_FALSE()
// Method Description:
// - Adds count number of spaces starting from where the cursor is currently
// Arguments:
// - count, the number of spaces to add
// Return Value:
// True if handled successfully, false otherwise
bool TerminalDispatch::InsertCharacter(const size_t count) noexcept
try
// - True.
bool TerminalDispatch::InsertCharacter(const size_t count)
{
return _terminalApi.InsertCharacter(count);
_terminalApi.InsertCharacter(count);
return true;
}
CATCH_LOG_RETURN_FALSE()
// Method Description:
// - Moves the viewport and erases text from the buffer depending on the eraseType
@@ -312,19 +295,17 @@ CATCH_LOG_RETURN_FALSE()
// - eraseType: the desired erase type
// Return Value:
// True if handled successfully. False otherwise
bool TerminalDispatch::EraseInDisplay(const DispatchTypes::EraseType eraseType) noexcept
try
bool TerminalDispatch::EraseInDisplay(const DispatchTypes::EraseType eraseType)
{
return _terminalApi.EraseInDisplay(eraseType);
}
CATCH_LOG_RETURN_FALSE()
// - DECKPAM, DECKPNM - Sets the keypad input mode to either Application mode or Numeric mode (true, false respectively)
// Arguments:
// - applicationMode - set to true to enable Application Mode Input, false for Numeric Mode Input.
// Return Value:
// - True if handled successfully. False otherwise.
bool TerminalDispatch::SetKeypadMode(const bool applicationMode) noexcept
// - True.
bool TerminalDispatch::SetKeypadMode(const bool applicationMode)
{
_terminalApi.SetInputMode(TerminalInput::Mode::Keypad, applicationMode);
return true;
@@ -334,8 +315,8 @@ bool TerminalDispatch::SetKeypadMode(const bool applicationMode) noexcept
// Arguments:
// - applicationMode - set to true to enable Application Mode Input, false for Normal Mode Input.
// Return Value:
// - True if handled successfully. False otherwise.
bool TerminalDispatch::SetCursorKeysMode(const bool applicationMode) noexcept
// - True.
bool TerminalDispatch::SetCursorKeysMode(const bool applicationMode)
{
_terminalApi.SetInputMode(TerminalInput::Mode::CursorKey, applicationMode);
return true;
@@ -347,10 +328,11 @@ bool TerminalDispatch::SetCursorKeysMode(const bool applicationMode) noexcept
// Arguments:
// - reverseMode - set to true to enable reverse screen mode, false for normal mode.
// Return Value:
// - True if handled successfully. False otherwise.
bool TerminalDispatch::SetScreenMode(const bool reverseMode) noexcept
// - True.
bool TerminalDispatch::SetScreenMode(const bool reverseMode)
{
return _terminalApi.SetRenderMode(RenderSettings::Mode::ScreenReversed, reverseMode);
_terminalApi.SetRenderMode(RenderSettings::Mode::ScreenReversed, reverseMode);
return true;
}
// Method Description:
@@ -359,8 +341,8 @@ bool TerminalDispatch::SetScreenMode(const bool reverseMode) noexcept
// Arguments:
// - win32InputMode - set to true to enable win32-input-mode, false to disable.
// Return Value:
// - True if handled successfully. False otherwise.
bool TerminalDispatch::EnableWin32InputMode(const bool win32Mode) noexcept
// - True.
bool TerminalDispatch::EnableWin32InputMode(const bool win32Mode)
{
_terminalApi.SetInputMode(TerminalInput::Mode::Win32, win32Mode);
return true;
@@ -371,8 +353,8 @@ bool TerminalDispatch::EnableWin32InputMode(const bool win32Mode) noexcept
//Arguments:
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableVT200MouseMode(const bool enabled) noexcept
// - True.
bool TerminalDispatch::EnableVT200MouseMode(const bool enabled)
{
_terminalApi.SetInputMode(TerminalInput::Mode::DefaultMouseTracking, enabled);
return true;
@@ -384,8 +366,8 @@ bool TerminalDispatch::EnableVT200MouseMode(const bool enabled) noexcept
//Arguments:
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableUTF8ExtendedMouseMode(const bool enabled) noexcept
// - True.
bool TerminalDispatch::EnableUTF8ExtendedMouseMode(const bool enabled)
{
_terminalApi.SetInputMode(TerminalInput::Mode::Utf8MouseEncoding, enabled);
return true;
@@ -397,8 +379,8 @@ bool TerminalDispatch::EnableUTF8ExtendedMouseMode(const bool enabled) noexcept
//Arguments:
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableSGRExtendedMouseMode(const bool enabled) noexcept
// - True.
bool TerminalDispatch::EnableSGRExtendedMouseMode(const bool enabled)
{
_terminalApi.SetInputMode(TerminalInput::Mode::SgrMouseEncoding, enabled);
return true;
@@ -409,8 +391,8 @@ bool TerminalDispatch::EnableSGRExtendedMouseMode(const bool enabled) noexcept
//Arguments:
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableButtonEventMouseMode(const bool enabled) noexcept
// - True.
bool TerminalDispatch::EnableButtonEventMouseMode(const bool enabled)
{
_terminalApi.SetInputMode(TerminalInput::Mode::ButtonEventMouseTracking, enabled);
return true;
@@ -422,8 +404,8 @@ bool TerminalDispatch::EnableButtonEventMouseMode(const bool enabled) noexcept
//Arguments:
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableAnyEventMouseMode(const bool enabled) noexcept
// - True.
bool TerminalDispatch::EnableAnyEventMouseMode(const bool enabled)
{
_terminalApi.SetInputMode(TerminalInput::Mode::AnyEventMouseTracking, enabled);
return true;
@@ -435,8 +417,8 @@ bool TerminalDispatch::EnableAnyEventMouseMode(const bool enabled) noexcept
//Arguments:
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableAlternateScroll(const bool enabled) noexcept
// - True.
bool TerminalDispatch::EnableAlternateScroll(const bool enabled)
{
_terminalApi.SetInputMode(TerminalInput::Mode::AlternateScroll, enabled);
return true;
@@ -448,19 +430,19 @@ bool TerminalDispatch::EnableAlternateScroll(const bool enabled) noexcept
//Arguments:
// - enabled - true to enable, false to disable.
// Return value:
// True if handled successfully. False otherwise.
bool TerminalDispatch::EnableXtermBracketedPasteMode(const bool enabled) noexcept
// - True.
bool TerminalDispatch::EnableXtermBracketedPasteMode(const bool enabled)
{
_terminalApi.EnableXtermBracketedPasteMode(enabled);
return true;
}
bool TerminalDispatch::SetMode(const DispatchTypes::ModeParams param) noexcept
bool TerminalDispatch::SetMode(const DispatchTypes::ModeParams param)
{
return _ModeParamsHelper(param, true);
}
bool TerminalDispatch::ResetMode(const DispatchTypes::ModeParams param) noexcept
bool TerminalDispatch::ResetMode(const DispatchTypes::ModeParams param)
{
return _ModeParamsHelper(param, false);
}
@@ -472,18 +454,20 @@ bool TerminalDispatch::ResetMode(const DispatchTypes::ModeParams param) noexcept
// - params - the optional custom ID
// Return Value:
// - true
bool TerminalDispatch::AddHyperlink(const std::wstring_view uri, const std::wstring_view params) noexcept
bool TerminalDispatch::AddHyperlink(const std::wstring_view uri, const std::wstring_view params)
{
return _terminalApi.AddHyperlink(uri, params);
_terminalApi.AddHyperlink(uri, params);
return true;
}
// Method Description:
// - End a hyperlink
// Return Value:
// - true
bool TerminalDispatch::EndHyperlink() noexcept
bool TerminalDispatch::EndHyperlink()
{
return _terminalApi.EndHyperlink();
_terminalApi.EndHyperlink();
return true;
}
// Method Description:
@@ -493,7 +477,7 @@ bool TerminalDispatch::EndHyperlink() noexcept
// - string: contains the parameters that define which action we do
// Return Value:
// - true
bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept
bool TerminalDispatch::DoConEmuAction(const std::wstring_view string)
{
unsigned int state = 0;
unsigned int progress = 0;
@@ -538,7 +522,8 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept
// progress is greater than the maximum allowed value, clamp it to the max
progress = TaskbarMaxProgress;
}
return _terminalApi.SetTaskbarProgress(static_cast<DispatchTypes::TaskbarState>(state), progress);
_terminalApi.SetTaskbarProgress(static_cast<DispatchTypes::TaskbarState>(state), progress);
return true;
}
// 9 is SetWorkingDirectory, which informs the terminal about the current working directory.
else if (subParam == 9)
@@ -550,14 +535,15 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept
// An example: 9;"D:/"
if (path.at(0) == L'"' && path.at(path.size() - 1) == L'"' && path.size() >= 3)
{
return _terminalApi.SetWorkingDirectory(path.substr(1, path.size() - 2));
_terminalApi.SetWorkingDirectory(path.substr(1, path.size() - 2));
}
else
{
// If we fail to find the surrounding quotation marks, we'll give the path a try anyway.
// ConEmu also does this.
return _terminalApi.SetWorkingDirectory(path);
_terminalApi.SetWorkingDirectory(path);
}
return true;
}
}
@@ -571,7 +557,7 @@ bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept
// - enable - True for set, false for unset.
// Return Value:
// - True if handled successfully. False otherwise.
bool TerminalDispatch::_ModeParamsHelper(const DispatchTypes::ModeParams param, const bool enable) noexcept
bool TerminalDispatch::_ModeParamsHelper(const DispatchTypes::ModeParams param, const bool enable)
{
bool success = false;
switch (param)
@@ -621,24 +607,22 @@ bool TerminalDispatch::_ModeParamsHelper(const DispatchTypes::ModeParams param,
return success;
}
bool TerminalDispatch::_ClearSingleTabStop() noexcept
void TerminalDispatch::_ClearSingleTabStop()
{
const auto width = _terminalApi.GetBufferSize().Dimensions().X;
const auto column = _terminalApi.GetCursorPosition().X;
_InitTabStopsForWidth(width);
_tabStopColumns.at(column) = false;
return true;
}
bool TerminalDispatch::_ClearAllTabStops() noexcept
void TerminalDispatch::_ClearAllTabStops()
{
_tabStopColumns.clear();
_initDefaultTabStops = false;
return true;
}
void TerminalDispatch::_ResetTabStops() noexcept
void TerminalDispatch::_ResetTabStops()
{
_tabStopColumns.clear();
_initDefaultTabStops = true;
@@ -663,7 +647,7 @@ void TerminalDispatch::_InitTabStopsForWidth(const size_t width)
}
}
bool TerminalDispatch::SoftReset() noexcept
bool TerminalDispatch::SoftReset()
{
// TODO:GH#1883 much of this method is not yet implemented in the Terminal,
// because the Terminal _doesn't need to_ yet. The terminal is only ever
@@ -675,23 +659,23 @@ bool TerminalDispatch::SoftReset() noexcept
// This code is left here (from its original form in conhost) as a reminder
// of what needs to be done.
bool success = CursorVisibility(true); // Cursor enabled.
// success = SetOriginMode(false) && success; // Absolute cursor addressing.
// success = SetAutoWrapMode(true) && success; // Wrap at end of line.
success = SetCursorKeysMode(false) && success; // Normal characters.
success = SetKeypadMode(false) && success; // Numeric characters.
CursorVisibility(true); // Cursor enabled.
// SetOriginMode(false); // Absolute cursor addressing.
// SetAutoWrapMode(true); // Wrap at end of line.
SetCursorKeysMode(false); // Normal characters.
SetKeypadMode(false); // Numeric characters.
// // Top margin = 1; bottom margin = page length.
// success = _DoSetTopBottomScrollingMargins(0, 0) && success;
// _DoSetTopBottomScrollingMargins(0, 0);
// _termOutput = {}; // Reset all character set designations.
// if (_initialCodePage.has_value())
// {
// // Restore initial code page if previously changed by a DOCS sequence.
// success = _pConApi->SetConsoleOutputCP(_initialCodePage.value()) && success;
// _pConApi->SetConsoleOutputCP(_initialCodePage.value());
// }
success = SetGraphicsRendition({}) && success; // Normal rendition.
SetGraphicsRendition({}); // Normal rendition.
// // Reset the saved cursor state.
// // Note that XTerm only resets the main buffer state, but that
@@ -699,10 +683,10 @@ bool TerminalDispatch::SoftReset() noexcept
// _savedCursorState.at(0) = {}; // Main buffer
// _savedCursorState.at(1) = {}; // Alt buffer
return success;
return true;
}
bool TerminalDispatch::HardReset() noexcept
bool TerminalDispatch::HardReset()
{
// TODO:GH#1883 much of this method is not yet implemented in the Terminal,
// because the Terminal _doesn't need to_ yet. The terminal is only ever
@@ -713,35 +697,33 @@ bool TerminalDispatch::HardReset() noexcept
// This code is left here (from its original form in conhost) as a reminder
// of what needs to be done.
bool success = true;
// // If in the alt buffer, switch back to main before doing anything else.
// if (_usingAltBuffer)
// {
// success = _pConApi->PrivateUseMainScreenBuffer();
// _usingAltBuffer = !success;
// _pConApi->PrivateUseMainScreenBuffer();
// _usingAltBuffer = false;
// }
// Sets the SGR state to normal - this must be done before EraseInDisplay
// to ensure that it clears with the default background color.
success = SoftReset() && success;
SoftReset();
// Clears the screen - Needs to be done in two operations.
success = EraseInDisplay(DispatchTypes::EraseType::All) && success;
success = EraseInDisplay(DispatchTypes::EraseType::Scrollback) && success;
EraseInDisplay(DispatchTypes::EraseType::All);
EraseInDisplay(DispatchTypes::EraseType::Scrollback);
// Set the DECSCNM screen mode back to normal.
success = SetScreenMode(false) && success;
SetScreenMode(false);
// Cursor to 1,1 - the Soft Reset guarantees this is absolute
success = CursorPosition(1, 1) && success;
CursorPosition(1, 1);
// Reset the mouse mode
success = EnableSGRExtendedMouseMode(false) && success;
success = EnableAnyEventMouseMode(false) && success;
EnableSGRExtendedMouseMode(false);
EnableAnyEventMouseMode(false);
// Delete all current tab stops and reapply
_ResetTabStops();
return success;
return true;
}

View File

@@ -12,74 +12,74 @@ class TerminalDispatch : public Microsoft::Console::VirtualTerminal::TermDispatc
public:
TerminalDispatch(::Microsoft::Terminal::Core::ITerminalApi& terminalApi) noexcept;
void Execute(const wchar_t wchControl) noexcept override;
void Print(const wchar_t wchPrintable) noexcept override;
void PrintString(const std::wstring_view string) noexcept override;
void Execute(const wchar_t wchControl) override;
void Print(const wchar_t wchPrintable) override;
void PrintString(const std::wstring_view string) override;
bool SetGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) noexcept override;
bool SetGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) override;
bool PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) noexcept override;
bool PopGraphicsRendition() noexcept override;
bool PushGraphicsRendition(const ::Microsoft::Console::VirtualTerminal::VTParameters options) override;
bool PopGraphicsRendition() override;
bool CursorPosition(const size_t line,
const size_t column) noexcept override; // CUP
const size_t column) override; // CUP
bool EnableWin32InputMode(const bool win32InputMode) noexcept override; // win32-input-mode
bool EnableWin32InputMode(const bool win32InputMode) override; // win32-input-mode
bool CursorVisibility(const bool isVisible) noexcept override; // DECTCEM
bool EnableCursorBlinking(const bool enable) noexcept override; // ATT610
bool CursorVisibility(const bool isVisible) override; // DECTCEM
bool EnableCursorBlinking(const bool enable) override; // ATT610
bool CursorForward(const size_t distance) noexcept override;
bool CursorBackward(const size_t distance) noexcept override;
bool CursorUp(const size_t distance) noexcept override;
bool CursorForward(const size_t distance) override;
bool CursorBackward(const size_t distance) override;
bool CursorUp(const size_t distance) override;
bool LineFeed(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::LineFeedType lineFeedType) noexcept override;
bool LineFeed(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::LineFeedType lineFeedType) override;
bool EraseCharacters(const size_t numChars) noexcept override;
bool WarningBell() noexcept override;
bool CarriageReturn() noexcept override;
bool SetWindowTitle(std::wstring_view title) noexcept override;
bool EraseCharacters(const size_t numChars) override;
bool WarningBell() override;
bool CarriageReturn() override;
bool SetWindowTitle(std::wstring_view title) override;
bool HorizontalTabSet() noexcept override; // HTS
bool ForwardTab(const size_t numTabs) noexcept override; // CHT, HT
bool BackwardsTab(const size_t numTabs) noexcept override; // CBT
bool TabClear(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TabClearType clearType) noexcept override; // TBC
bool HorizontalTabSet() override; // HTS
bool ForwardTab(const size_t numTabs) override; // CHT, HT
bool BackwardsTab(const size_t numTabs) override; // CBT
bool TabClear(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TabClearType clearType) override; // TBC
bool SetColorTableEntry(const size_t tableIndex, const DWORD color) noexcept override;
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept override;
bool SetCursorColor(const DWORD color) noexcept override;
bool SetColorTableEntry(const size_t tableIndex, const DWORD color) override;
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) override;
bool SetCursorColor(const DWORD color) override;
bool SetClipboard(std::wstring_view content) noexcept override;
bool SetClipboard(std::wstring_view content) override;
bool SetDefaultForeground(const DWORD color) noexcept override;
bool SetDefaultBackground(const DWORD color) noexcept override;
bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override; // ED
bool DeleteCharacter(const size_t count) noexcept override;
bool InsertCharacter(const size_t count) noexcept override;
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
bool SetDefaultForeground(const DWORD color) override;
bool SetDefaultBackground(const DWORD color) override;
bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) override; // ED
bool DeleteCharacter(const size_t count) override;
bool InsertCharacter(const size_t count) override;
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) override;
bool SetCursorKeysMode(const bool applicationMode) noexcept override; // DECCKM
bool SetKeypadMode(const bool applicationMode) noexcept override; // DECKPAM, DECKPNM
bool SetScreenMode(const bool reverseMode) noexcept override; // DECSCNM
bool SetCursorKeysMode(const bool applicationMode) override; // DECCKM
bool SetKeypadMode(const bool applicationMode) override; // DECKPAM, DECKPNM
bool SetScreenMode(const bool reverseMode) override; // DECSCNM
bool SoftReset() noexcept override; // DECSTR
bool HardReset() noexcept override; // RIS
bool SoftReset() override; // DECSTR
bool HardReset() override; // RIS
bool EnableVT200MouseMode(const bool enabled) noexcept override; // ?1000
bool EnableUTF8ExtendedMouseMode(const bool enabled) noexcept override; // ?1005
bool EnableSGRExtendedMouseMode(const bool enabled) noexcept override; // ?1006
bool EnableButtonEventMouseMode(const bool enabled) noexcept override; // ?1002
bool EnableAnyEventMouseMode(const bool enabled) noexcept override; // ?1003
bool EnableAlternateScroll(const bool enabled) noexcept override; // ?1007
bool EnableXtermBracketedPasteMode(const bool enabled) noexcept override; // ?2004
bool EnableVT200MouseMode(const bool enabled) override; // ?1000
bool EnableUTF8ExtendedMouseMode(const bool enabled) override; // ?1005
bool EnableSGRExtendedMouseMode(const bool enabled) override; // ?1006
bool EnableButtonEventMouseMode(const bool enabled) override; // ?1002
bool EnableAnyEventMouseMode(const bool enabled) override; // ?1003
bool EnableAlternateScroll(const bool enabled) override; // ?1007
bool EnableXtermBracketedPasteMode(const bool enabled) override; // ?2004
bool SetMode(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams /*param*/) noexcept override; // DECSET
bool ResetMode(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams /*param*/) noexcept override; // DECRST
bool SetMode(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams /*param*/) override; // DECSET
bool ResetMode(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams /*param*/) override; // DECRST
bool AddHyperlink(const std::wstring_view uri, const std::wstring_view params) noexcept override;
bool EndHyperlink() noexcept override;
bool AddHyperlink(const std::wstring_view uri, const std::wstring_view params) override;
bool EndHyperlink() override;
bool DoConEmuAction(const std::wstring_view string) noexcept override;
bool DoConEmuAction(const std::wstring_view string) override;
private:
::Microsoft::Terminal::Core::ITerminalApi& _terminalApi;
@@ -89,12 +89,12 @@ private:
size_t _SetRgbColorsHelper(const ::Microsoft::Console::VirtualTerminal::VTParameters options,
TextAttribute& attr,
const bool isForeground) noexcept;
const bool isForeground);
bool _ModeParamsHelper(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams param, const bool enable) noexcept;
bool _ModeParamsHelper(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::ModeParams param, const bool enable);
bool _ClearSingleTabStop() noexcept;
bool _ClearAllTabStops() noexcept;
void _ResetTabStops() noexcept;
void _ClearSingleTabStop();
void _ClearAllTabStops();
void _ResetTabStops();
void _InitTabStopsForWidth(const size_t width);
};

View File

@@ -20,7 +20,7 @@ using namespace Microsoft::Console::VirtualTerminal::DispatchTypes;
// - The number of options consumed, not including the initial 38/48.
size_t TerminalDispatch::_SetRgbColorsHelper(const VTParameters options,
TextAttribute& attr,
const bool isForeground) noexcept
const bool isForeground)
{
size_t optionsConsumed = 1;
const DispatchTypes::GraphicsOptions typeOpt = options.at(0);
@@ -67,7 +67,7 @@ size_t TerminalDispatch::_SetRgbColorsHelper(const VTParameters options,
// one at a time by setting or removing flags in the font style properties.
// Return Value:
// - True if handled successfully. False otherwise.
bool TerminalDispatch::SetGraphicsRendition(const VTParameters options) noexcept
bool TerminalDispatch::SetGraphicsRendition(const VTParameters options)
{
TextAttribute attr = _terminalApi.GetTextAttributes();
@@ -254,12 +254,14 @@ bool TerminalDispatch::SetGraphicsRendition(const VTParameters options) noexcept
return true;
}
bool TerminalDispatch::PushGraphicsRendition(const VTParameters options) noexcept
bool TerminalDispatch::PushGraphicsRendition(const VTParameters options)
{
return _terminalApi.PushGraphicsRendition(options);
_terminalApi.PushGraphicsRendition(options);
return true;
}
bool TerminalDispatch::PopGraphicsRendition() noexcept
bool TerminalDispatch::PopGraphicsRendition()
{
return _terminalApi.PopGraphicsRendition();
_terminalApi.PopGraphicsRendition();
return true;
}

View File

@@ -375,29 +375,30 @@
</Page.Resources>
<ScrollViewer ViewChanging="ViewChanging">
<StackPanel MaxWidth="600"
HorizontalAlignment="Left"
Spacing="8"
Style="{StaticResource SettingsStackStyle}">
<!-- Add New Button -->
<Button x:Name="AddNewButton"
Click="AddNew_Click">
<Button.Content>
<StackPanel Orientation="Horizontal">
<FontIcon FontSize="{StaticResource StandardIconSize}"
Glyph="&#xE710;" />
<TextBlock x:Uid="Actions_AddNewTextBlock"
Style="{StaticResource IconButtonTextBlockStyle}" />
</StackPanel>
</Button.Content>
</Button>
<!-- Keybindings -->
<ListView x:Name="KeyBindingsListView"
ItemTemplate="{StaticResource KeyBindingTemplate}"
ItemsSource="{x:Bind KeyBindingList, Mode=OneWay}"
SelectionMode="None" />
</StackPanel>
<Border MaxWidth="{StaticResource StandardControlMaxWidth}">
<StackPanel MaxWidth="600"
HorizontalAlignment="Left"
Spacing="8"
Style="{StaticResource SettingsStackStyle}">
<!-- Add New Button -->
<Button x:Name="AddNewButton"
Click="AddNew_Click">
<Button.Content>
<StackPanel Orientation="Horizontal">
<FontIcon FontSize="{StaticResource StandardIconSize}"
Glyph="&#xE710;" />
<TextBlock x:Uid="Actions_AddNewTextBlock"
Style="{StaticResource IconButtonTextBlockStyle}" />
</StackPanel>
</Button.Content>
</Button>
<!-- Keybindings -->
<ListView x:Name="KeyBindingsListView"
ItemTemplate="{StaticResource KeyBindingTemplate}"
ItemsSource="{x:Bind KeyBindingList, Mode=OneWay}"
SelectionMode="None" />
</StackPanel>
</Border>
</ScrollViewer>
</Page>

View File

@@ -7,9 +7,12 @@
#include "AddProfilePageNavigationState.g.cpp"
#include "EnumEntry.h"
#include <LibraryResources.h>
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Navigation;
using namespace winrt::Microsoft::Terminal::Settings::Model;
@@ -18,6 +21,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
AddProfile::AddProfile()
{
InitializeComponent();
Automation::AutomationProperties::SetName(AddNewButton(), RS_(L"AddProfile_AddNewTextBlock/Text"));
Automation::AutomationProperties::SetName(DuplicateButton(), RS_(L"AddProfile_DuplicateTextBlock/Text"));
}
void AddProfile::OnNavigatedTo(const NavigationEventArgs& e)

View File

@@ -23,27 +23,29 @@
<ScrollViewer ViewChanging="ViewChanging">
<StackPanel Style="{StaticResource SettingsStackStyle}">
<Button x:Uid="AddProfile_AddNewButton"
AutomationProperties.AutomationId="AddProfile_AddNewButton"
AutomationProperties.Name="{Binding Tag, RelativeSource={RelativeSource Self}}"
Click="AddNewClick"
Style="{StaticResource AccentButtonStyle}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<FontIcon FontSize="{StaticResource StandardIconSize}"
Glyph="&#xE710;" />
<TextBlock x:Uid="AddProfile_AddNewTextBlock"
Style="{StaticResource IconButtonTextBlockStyle}" />
</StackPanel>
</Button.Content>
</Button>
<Border MaxWidth="{StaticResource StandardControlMaxWidth}">
<Button x:Name="AddNewButton"
Click="AddNewClick"
Style="{StaticResource AccentButtonStyle}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<FontIcon FontSize="{StaticResource StandardIconSize}"
Glyph="&#xE710;" />
<TextBlock x:Uid="AddProfile_AddNewTextBlock"
Style="{StaticResource IconButtonTextBlockStyle}" />
</StackPanel>
</Button.Content>
</Button>
</Border>
<StackPanel Margin="{StaticResource StandardControlMargin}">
<local:SettingContainer x:Uid="AddProfile_Duplicate">
<muxc:RadioButtons x:Name="Profiles"
AutomationProperties.AccessibilityView="Content"
ItemsSource="{x:Bind State.Settings.AllProfiles, Mode=OneWay}"
SelectionChanged="ProfilesSelectionChanged">
<muxc:RadioButtons.ItemTemplate>
<ComboBox x:Name="Profiles"
AutomationProperties.AccessibilityView="Content"
ItemsSource="{x:Bind State.Settings.AllProfiles, Mode=OneWay}"
SelectedIndex="0"
SelectionChanged="ProfilesSelectionChanged"
Style="{StaticResource ComboBoxSettingStyle}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="model:Profile">
<Grid HorizontalAlignment="Stretch"
ColumnSpacing="8">
@@ -65,25 +67,25 @@
</Grid>
</DataTemplate>
</muxc:RadioButtons.ItemTemplate>
</muxc:RadioButtons>
</ComboBox.ItemTemplate>
</ComboBox>
</local:SettingContainer>
<Button x:Uid="AddProfile_DuplicateButton"
Margin="{StaticResource StandardControlMargin}"
AutomationProperties.AutomationId="AddProfile_DuplicateButton"
AutomationProperties.Name="{Binding Tag, RelativeSource={RelativeSource Self}}"
Click="DuplicateClick"
IsEnabled="{x:Bind IsProfileSelected, Mode=OneWay}"
Style="{StaticResource AccentButtonStyle}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<FontIcon FontSize="{StaticResource StandardIconSize}"
Glyph="&#xE8C8;" />
<TextBlock x:Uid="AddProfile_DuplicateTextBlock"
Style="{StaticResource IconButtonTextBlockStyle}" />
</StackPanel>
</Button.Content>
</Button>
<Border MaxWidth="{StaticResource StandardControlMaxWidth}">
<Button x:Name="DuplicateButton"
Margin="{StaticResource StandardControlMargin}"
Click="DuplicateClick"
IsEnabled="{x:Bind IsProfileSelected, Mode=OneWay}"
Style="{StaticResource AccentButtonStyle}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<FontIcon FontSize="{StaticResource StandardIconSize}"
Glyph="&#xE8C8;" />
<TextBlock x:Uid="AddProfile_DuplicateTextBlock"
Style="{StaticResource IconButtonTextBlockStyle}" />
</StackPanel>
</Button.Content>
</Button>
</Border>
</StackPanel>
</StackPanel>
</ScrollViewer>

View File

@@ -41,7 +41,7 @@
<StackPanel Style="{StaticResource PivotStackStyle}">
<!-- Grouping: Text -->
<TextBlock x:Uid="Profile_TextHeader"
Style="{StaticResource SubtitleTextBlockStyle}" />
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Color Scheme -->
<local:SettingContainer x:Uid="Profile_ColorScheme"
@@ -170,7 +170,7 @@
<!-- Grouping: Cursor -->
<StackPanel Style="{StaticResource PivotStackStyle}">
<TextBlock x:Uid="Profile_CursorHeader"
Style="{StaticResource SubtitleTextBlockStyle}" />
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Cursor Shape -->
<local:SettingContainer x:Uid="Profile_CursorShape"
@@ -210,7 +210,7 @@
<!-- Grouping: Background -->
<StackPanel Style="{StaticResource PivotStackStyle}">
<TextBlock x:Uid="Profile_BackgroundHeader"
Style="{StaticResource SubtitleTextBlockStyle}" />
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Background Image -->
<local:SettingContainer x:Name="BackgroundImageContainer"
@@ -292,7 +292,7 @@
<x:Int32>17</x:Int32>
</ToggleButton.Tag>
<ToggleButton.Content>
<FontIcon FontFamily="Segoe Fluent Icons"
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
Glyph="&#xE744;"
RenderTransformOrigin="0.5,0.5">
<FontIcon.RenderTransform>
@@ -312,7 +312,7 @@
<x:Int32>16</x:Int32>
</ToggleButton.Tag>
<ToggleButton.Content>
<FontIcon FontFamily="Segoe Fluent Icons"
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
Glyph="&#xE745;"
RenderTransformOrigin="0.5,0.5">
<FontIcon.RenderTransform>
@@ -332,7 +332,7 @@
<x:Int32>18</x:Int32>
</ToggleButton.Tag>
<ToggleButton.Content>
<FontIcon FontFamily="Segoe Fluent Icons"
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
Glyph="&#xEA5F;"
RenderTransformOrigin="0.5,0.5">
<FontIcon.RenderTransform>
@@ -354,7 +354,7 @@
<x:Int32>1</x:Int32>
</ToggleButton.Tag>
<ToggleButton.Content>
<FontIcon FontFamily="Segoe Fluent Icons"
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
Glyph="&#xE746;" />
</ToggleButton.Content>
</ToggleButton>
@@ -369,7 +369,7 @@
<x:Int32>0</x:Int32>
</ToggleButton.Tag>
<ToggleButton.Content>
<FontIcon FontFamily="Segoe Fluent Icons"
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
Glyph="&#xF16E;" />
</ToggleButton.Content>
</ToggleButton>
@@ -384,7 +384,7 @@
<x:Int32>2</x:Int32>
</ToggleButton.Tag>
<ToggleButton.Content>
<FontIcon FontFamily="Segoe Fluent Icons"
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
Glyph="&#xEA61;" />
</ToggleButton.Content>
</ToggleButton>
@@ -401,7 +401,7 @@
<x:Int32>33</x:Int32>
</ToggleButton.Tag>
<ToggleButton.Content>
<FontIcon FontFamily="Segoe Fluent Icons"
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
Glyph="&#xE744;" />
</ToggleButton.Content>
</ToggleButton>
@@ -416,7 +416,7 @@
<x:Int32>32</x:Int32>
</ToggleButton.Tag>
<ToggleButton.Content>
<FontIcon FontFamily="Segoe Fluent Icons"
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
Glyph="&#xE745;" />
</ToggleButton.Content>
</ToggleButton>
@@ -431,7 +431,7 @@
<x:Int32>34</x:Int32>
</ToggleButton.Tag>
<ToggleButton.Content>
<FontIcon FontFamily="Segoe Fluent Icons"
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
Glyph="&#xEA5F;" />
</ToggleButton.Content>
</ToggleButton>
@@ -464,7 +464,7 @@
<!-- Grouping: Text Formatting -->
<StackPanel Style="{StaticResource PivotStackStyle}">
<TextBlock x:Uid="Appearance_TextFormattingHeader"
Style="{StaticResource SubtitleTextBlockStyle}" />
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Intense is bold, bright -->
<local:SettingContainer x:Uid="Appearance_IntenseTextStyle"

View File

@@ -94,11 +94,13 @@
</Page.Resources>
<ScrollViewer ViewChanging="ViewChanging">
<StackPanel Margin="{StaticResource StandardIndentMargin}"
<StackPanel MaxWidth="{StaticResource StandardControlMaxWidth}"
Margin="{StaticResource StandardIndentMargin}"
Spacing="24">
<!-- Select Color and Add New Button -->
<StackPanel Orientation="Horizontal">
<StackPanel Margin="0,5,0,0"
Orientation="Horizontal">
<StackPanel Orientation="Horizontal"
Visibility="{x:Bind local:Converters.InvertedBooleanToVisibility(IsRenaming), Mode=OneWay}">

View File

@@ -15,6 +15,7 @@
<Thickness x:Key="StandardIndentMargin">13,0,0,0</Thickness>
<Thickness x:Key="StandardControlMargin">0,24,0,0</Thickness>
<x:Double x:Key="StandardBoxMinWidth">250</x:Double>
<x:Double x:Key="StandardControlMaxWidth">1000</x:Double>
<!--
This is for styling the entire items control used on the
@@ -48,16 +49,24 @@
<Style x:Key="TextBoxSettingStyle"
BasedOn="{StaticResource DefaultTextBoxStyle}"
TargetType="TextBox">
<Setter Property="Width" Value="{StaticResource StandardBoxMinWidth}" />
<Setter Property="MinWidth" Value="{StaticResource StandardBoxMinWidth}" />
<Setter Property="MaxWidth" Value="500" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
<Style x:Key="TextBlockSubHeaderStyle"
BasedOn="{StaticResource SubtitleTextBlockStyle}"
TargetType="TextBlock">
<Setter Property="MaxWidth" Value="{StaticResource StandardControlMaxWidth}" />
</Style>
<!-- Used for disclaimers -->
<Style x:Key="DisclaimerStyle"
TargetType="TextBlock">
<Setter Property="FontStyle" Value="Italic" />
<Setter Property="TextWrapping" Value="WrapWholeWords" />
<Setter Property="MaxWidth" Value="1000" />
</Style>
<!-- Used for flyout messages -->
@@ -71,7 +80,7 @@
<!-- Number Box -->
<Style x:Key="NumberBoxSettingStyle"
TargetType="muxc:NumberBox">
<Setter Property="SpinButtonPlacementMode" Value="Compact" />
<Setter Property="SpinButtonPlacementMode" Value="Inline" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
@@ -159,7 +168,8 @@
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="MinWidth" Value="{StaticResource ToggleSwitchThemeMinWidth}" />
<Setter Property="FocusVisualMargin" Value="-7,-3,-7,-3" />
<Setter Property="Margin" Value="0,0,-80,0" />
<Setter Property="Margin" Value="0,0,10,0" />
<Setter Property="MinWidth" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleSwitch">

View File

@@ -24,6 +24,23 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// --> "und" is synonymous for "Use system language".
constexpr std::wstring_view systemLanguageTag{ L"und" };
static constexpr std::array appLanguageTags{
L"en-US",
L"de-DE",
L"es-ES",
L"fr-FR",
L"it-IT",
L"ja",
L"ko",
L"pt-BR",
L"qps-PLOC",
L"qps-PLOCA",
L"qps-PLOCM",
L"ru",
L"zh-Hans-CN",
L"zh-Hant-TW",
};
GlobalAppearance::GlobalAppearance()
{
InitializeComponent();
@@ -88,43 +105,22 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// [1]:
{
// ManifestLanguages contains languages the app ships with.
//
// Languages is a computed list that merges the ManifestLanguages with the
// user's ranked list of preferred languages taken from the system settings.
// As is tradition the API documentation is incomplete though, as it can also
// contain regional language variants. If our app supports en-US, but the user
// has en-GB or en-DE in their system's preferred language list, Languages will
// contain those as well, as they're variants from a supported language. We should
// allow a user to select those, as regional formattings can vary significantly.
const std::array tagSources{
winrt::Windows::Globalization::ApplicationLanguages::ManifestLanguages(),
winrt::Windows::Globalization::ApplicationLanguages::Languages()
};
// tags will hold all the flattened results from tagSources.
// We resize() the vector to the proper size in order to efficiently GetMany() all items.
tags.resize(std::accumulate(
tagSources.begin(),
tagSources.end(),
// tags[0] will be "und" - the "Use system language" item
// tags[1..n] will contain tags from tagSources.
// --> totalTags is offset by 1
1,
[](uint32_t sum, const auto& v) -> uint32_t {
return sum + v.Size();
}));
// Unfortunately, we cannot use this source. Our manifest must contain the
// ~100 languages that are localized for the shell extension and start menu
// presentation so we align with Windows display languages for those surfaces.
// However, the actual content of our application is limited to a much smaller
// subset of approximately 14 languages. As such, we will code the limited
// subset of languages that we support for selection within the Settings
// dropdown to steer users towards the ones that we can display in the app.
// As per the function definition, the first item
// is always "Use system language" ("und").
auto data = tags.data();
*data++ = systemLanguageTag;
tags.emplace_back(systemLanguageTag);
// Finally GetMany() all the tags from tagSources.
for (const auto& v : tagSources)
// Add our hardcoded languages after the system definition.
for (const auto& v : appLanguageTags)
{
const auto size = v.Size();
v.GetMany(0, winrt::array_view(data, size));
data += size;
tags.push_back(v);
}
}

View File

@@ -476,15 +476,18 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void MainPage::BreadcrumbBar_ItemClicked(Microsoft::UI::Xaml::Controls::BreadcrumbBar const& /*sender*/, Microsoft::UI::Xaml::Controls::BreadcrumbBarItemClickedEventArgs const& args)
{
const auto tag = args.Item().as<Breadcrumb>()->Tag();
const auto subPage = args.Item().as<Breadcrumb>()->SubPage();
if (const auto profileViewModel = tag.try_as<ProfileViewModel>())
if (gsl::narrow_cast<uint32_t>(args.Index()) < (_breadcrumbs.Size() - 1))
{
_Navigate(*profileViewModel, subPage);
}
else
{
_Navigate(tag.as<hstring>(), subPage);
const auto tag = args.Item().as<Breadcrumb>()->Tag();
const auto subPage = args.Item().as<Breadcrumb>()->SubPage();
if (const auto profileViewModel = tag.try_as<ProfileViewModel>())
{
_Navigate(*profileViewModel, subPage);
}
else
{
_Navigate(tag.as<hstring>(), subPage);
}
}
}

View File

@@ -42,9 +42,14 @@
ItemInvoked="SettingsNav_ItemInvoked"
Loaded="SettingsNav_Loaded"
TabFocusNavigation="Cycle">
<muxc:NavigationView.Resources>
<ResourceDictionary>
<Thickness x:Key="NavigationViewHeaderMargin">15,0,0,0</Thickness>
</ResourceDictionary>
</muxc:NavigationView.Resources>
<muxc:NavigationView.Header>
<muxc:BreadcrumbBar x:Name="NavigationBreadcrumbBar"
Margin="-40,-40,0,16"
MaxWidth="{StaticResource StandardControlMaxWidth}"
ItemClicked="BreadcrumbBar_ItemClicked"
ItemsSource="{x:Bind Breadcrumbs}">
<muxc:BreadcrumbBar.ItemTemplate>
@@ -131,7 +136,7 @@
</muxc:NavigationViewItem>
</muxc:NavigationView.FooterMenuItems>
<Grid Margin="0,-30,0,0">
<Grid Margin="0,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />

View File

@@ -45,13 +45,15 @@
ViewChanging="ViewChanging">
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Control Preview -->
<Border x:Name="ControlPreview"
Width="350"
Height="160"
Margin="0,0,0,12"
HorizontalAlignment="Left"
BorderBrush="{ThemeResource SystemControlForegroundBaseMediumLowBrush}"
BorderThickness="1" />
<Border MaxWidth="{StaticResource StandardControlMaxWidth}">
<Border x:Name="ControlPreview"
Width="350"
Height="160"
Margin="0,0,0,12"
HorizontalAlignment="Left"
BorderBrush="{ThemeResource SystemControlForegroundBaseMediumLowBrush}"
BorderThickness="1" />
</Border>
<local:Appearances Appearance="{x:Bind Profile.DefaultAppearance, Mode=OneWay}"
SourceProfile="{x:Bind Profile, Mode=OneWay}" />
@@ -59,7 +61,7 @@
<!-- Grouping: Transparency -->
<StackPanel Style="{StaticResource PivotStackStyle}">
<TextBlock x:Uid="Profile_TransparencyHeader"
Style="{StaticResource SubtitleTextBlockStyle}" />
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Opacity -->
<local:SettingContainer x:Name="OpacityContainer"
@@ -99,7 +101,7 @@
<!-- Grouping: Window -->
<StackPanel Style="{StaticResource PivotStackStyle}">
<TextBlock x:Uid="Profile_WindowHeader"
Style="{StaticResource SubtitleTextBlockStyle}" />
Style="{StaticResource TextBlockSubHeaderStyle}" />
<!-- Padding -->
<local:SettingContainer x:Uid="Profile_Padding"
@@ -133,7 +135,7 @@
SelectedItem="{x:Bind Profile.CurrentScrollState, Mode=TwoWay}" />
</local:SettingContainer>
</StackPanel>
<StackPanel>
<StackPanel MaxWidth="{StaticResource StandardControlMaxWidth}">
<StackPanel Orientation="Horizontal"
Visibility="{x:Bind Profile.EditableUnfocusedAppearance, Mode=OneWay}">
<TextBlock x:Uid="Profile_UnfocusedAppearanceTextBlock"

View File

@@ -144,7 +144,7 @@
<TextBlock x:Uid="Profile_AdditionalSettingsHeader"
Margin="0,48,0,0"
Style="{StaticResource SubtitleTextBlockStyle}" />
Style="{StaticResource TextBlockSubHeaderStyle}" />
<Button x:Name="AppearanceNavigator"
Click="Appearance_Click"
@@ -159,77 +159,79 @@
Text="Advanced" />
</Button>
<!-- Delete Button -->
<Button x:Name="DeleteButton"
Margin="{StaticResource StandardControlMargin}"
Style="{StaticResource DeleteButtonStyle}"
Visibility="{x:Bind Profile.CanDeleteProfile}">
<Button.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="ButtonBackground"
Color="Firebrick" />
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
Color="#C23232" />
<SolidColorBrush x:Key="ButtonBackgroundPressed"
Color="#A21212" />
<SolidColorBrush x:Key="ButtonForeground"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPressed"
Color="White" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="ButtonBackground"
Color="Firebrick" />
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
Color="#C23232" />
<SolidColorBrush x:Key="ButtonBackgroundPressed"
Color="#A21212" />
<SolidColorBrush x:Key="ButtonForeground"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPressed"
Color="White" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="ButtonBackground"
Color="{ThemeResource SystemColorButtonFaceColor}" />
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
Color="{ThemeResource SystemColorHighlightColor}" />
<SolidColorBrush x:Key="ButtonBackgroundPressed"
Color="{ThemeResource SystemColorHighlightColor}" />
<SolidColorBrush x:Key="ButtonForeground"
Color="{ThemeResource SystemColorButtonTextColor}" />
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Color="{ThemeResource SystemColorHighlightTextColor}" />
<SolidColorBrush x:Key="ButtonForegroundPressed"
Color="{ThemeResource SystemColorHighlightTextColor}" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Button.Resources>
<Button.Content>
<StackPanel Orientation="Horizontal">
<FontIcon FontSize="{StaticResource StandardIconSize}"
Glyph="&#xE74D;" />
<TextBlock x:Uid="Profile_DeleteButton"
Margin="10,0,0,0" />
</StackPanel>
</Button.Content>
<Button.Flyout>
<Flyout>
<StackPanel>
<TextBlock x:Uid="Profile_DeleteConfirmationMessage"
Style="{StaticResource CustomFlyoutTextStyle}" />
<Button x:Uid="Profile_DeleteConfirmationButton"
Click="DeleteConfirmation_Click" />
<Border MaxWidth="{StaticResource StandardControlMaxWidth}">
<Button x:Name="DeleteButton"
Margin="{StaticResource StandardControlMargin}"
Style="{StaticResource DeleteButtonStyle}"
Visibility="{x:Bind Profile.CanDeleteProfile}">
<Button.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="ButtonBackground"
Color="Firebrick" />
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
Color="#C23232" />
<SolidColorBrush x:Key="ButtonBackgroundPressed"
Color="#A21212" />
<SolidColorBrush x:Key="ButtonForeground"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPressed"
Color="White" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="ButtonBackground"
Color="Firebrick" />
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
Color="#C23232" />
<SolidColorBrush x:Key="ButtonBackgroundPressed"
Color="#A21212" />
<SolidColorBrush x:Key="ButtonForeground"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Color="White" />
<SolidColorBrush x:Key="ButtonForegroundPressed"
Color="White" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="ButtonBackground"
Color="{ThemeResource SystemColorButtonFaceColor}" />
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
Color="{ThemeResource SystemColorHighlightColor}" />
<SolidColorBrush x:Key="ButtonBackgroundPressed"
Color="{ThemeResource SystemColorHighlightColor}" />
<SolidColorBrush x:Key="ButtonForeground"
Color="{ThemeResource SystemColorButtonTextColor}" />
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
Color="{ThemeResource SystemColorHighlightTextColor}" />
<SolidColorBrush x:Key="ButtonForegroundPressed"
Color="{ThemeResource SystemColorHighlightTextColor}" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Button.Resources>
<Button.Content>
<StackPanel Orientation="Horizontal">
<FontIcon FontSize="{StaticResource StandardIconSize}"
Glyph="&#xE74D;" />
<TextBlock x:Uid="Profile_DeleteButton"
Margin="10,0,0,0" />
</StackPanel>
</Flyout>
</Button.Flyout>
</Button>
</Button.Content>
<Button.Flyout>
<Flyout>
<StackPanel>
<TextBlock x:Uid="Profile_DeleteConfirmationMessage"
Style="{StaticResource CustomFlyoutTextStyle}" />
<Button x:Uid="Profile_DeleteConfirmationButton"
Click="DeleteConfirmation_Click" />
</StackPanel>
</Flyout>
</Button.Flyout>
</Button>
</Border>
</StackPanel>
</ScrollViewer>
</Grid>

View File

@@ -68,7 +68,7 @@
TargetType="FontIcon">
<Setter Property="Foreground" Value="{StaticResource SystemAccentColor}" />
<Setter Property="FontSize" Value="11" />
<Setter Property="FontFamily" Value="Segoe Fluent Icons" />
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
</Style>
<Style x:Key="NonExpanderGrid"

View File

@@ -130,7 +130,7 @@ namespace Microsoft.Terminal.Settings.Model
String ColorScheme;
// This needs to be an optional so that the default value (null) does
// not modify whatever the profile's value is (either true or false)
Windows.Foundation.IReference<Boolean> Elevate { get; };
Windows.Foundation.IReference<Boolean> Elevate;
Boolean Equals(NewTerminalArgs other);
String GenerateName();

View File

@@ -593,7 +593,7 @@ Model::Profile CascadiaSettings::GetProfileForArgs(const Model::NewTerminalArgs&
Model::Profile CascadiaSettings::_getProfileForCommandLine(const winrt::hstring& commandLine) const
{
// We're going to cache all the command lines we got, as
// _normalizeCommandLine is a relatively heavy operation.
// NormalizeCommandLine is a relatively heavy operation.
std::call_once(_commandLinesCacheOnce, [this]() {
_commandLinesCache.reserve(_allProfiles.Size());
@@ -612,7 +612,7 @@ Model::Profile CascadiaSettings::_getProfileForCommandLine(const winrt::hstring&
try
{
_commandLinesCache.emplace_back(_normalizeCommandLine(cmd.c_str()), profile);
_commandLinesCache.emplace_back(NormalizeCommandLine(cmd.c_str()), profile);
}
CATCH_LOG()
}
@@ -631,7 +631,7 @@ Model::Profile CascadiaSettings::_getProfileForCommandLine(const winrt::hstring&
try
{
const auto needle = _normalizeCommandLine(commandLine.c_str());
const auto needle = NormalizeCommandLine(commandLine.c_str());
// til::starts_with(string, prefix) will always return false if prefix.size() > string.size().
// --> Using binary search we can safely skip all items in _commandLinesCache where .first.size() > needle.size().
@@ -678,7 +678,7 @@ Model::Profile CascadiaSettings::_getProfileForCommandLine(const winrt::hstring&
// is considered a compatible profile with
// "C:\Program Files\PowerShell\7\pwsh.exe -WorkingDirectory ~"
// as it shares the same (normalized) prefix.
std::wstring CascadiaSettings::_normalizeCommandLine(LPCWSTR commandLine)
std::wstring CascadiaSettings::NormalizeCommandLine(LPCWSTR commandLine)
{
// Turn "%SystemRoot%\System32\cmd.exe" into "C:\WINDOWS\System32\cmd.exe".
// We do this early, as environment variables might occur anywhere in the commandLine.
@@ -692,6 +692,15 @@ std::wstring CascadiaSettings::_normalizeCommandLine(LPCWSTR commandLine)
wil::unique_hlocal_ptr<PWSTR[]> argv{ CommandLineToArgvW(normalized.c_str(), &argc) };
THROW_LAST_ERROR_IF(!argc);
// The index of the first argument in argv for our executable in argv[0].
// Given {"C:\Program Files\PowerShell\7\pwsh.exe", "-WorkingDirectory", "~"} this will be 1.
int startOfArguments = 1;
// Returns true if the executable in argv[0] to argv[startOfArguments - 1]
// has any further arguments in argv[startOfArguments] to argv[argc - 1].
const auto hasTrailingArguments = [&]() noexcept {
return (argc - startOfArguments) > 1;
};
// The given commandLine should start with an executable name or path.
// For instance given the following argv arrays:
// * {"C:\WINDOWS\System32\cmd.exe"}
@@ -713,39 +722,39 @@ std::wstring CascadiaSettings::_normalizeCommandLine(LPCWSTR commandLine)
// CreateProcessW uses RtlGetExePath to get the lpPath for SearchPathW.
// The difference between the behavior of SearchPathW if lpPath is nullptr and what RtlGetExePath returns
// seems to be mostly whether SafeProcessSearchMode is respected and the support for relative paths.
// Windows Terminal makes the use relative paths rather impractical which is why we simply dropped the call to RtlGetExePath.
// Windows Terminal makes the use of relative paths rather impractical which is why we simply dropped the call to RtlGetExePath.
const auto status = wil::SearchPathW(nullptr, argv[0], L".exe", normalized);
if (status == S_OK)
{
std::filesystem::path path{ std::move(normalized) };
const auto attributes = GetFileAttributesW(normalized.c_str());
// ExpandEnvironmentStringsW() might have returned a string that's not in the canonical capitalization.
// For instance %SystemRoot% is set to C:\WINDOWS on my system (ugh), even though the path is actually C:\Windows.
// We need to fix this as case-sensitive path comparisons will fail otherwise (Windows supports case-sensitive file systems).
// If we fail to resolve the path for whatever reason (pretty unlikely given that SearchPathW found it)
// we fall back to leaving the path as is. Better than throwing a random exception and making this unusable.
if (attributes != INVALID_FILE_ATTRIBUTES && WI_IsFlagClear(attributes, FILE_ATTRIBUTE_DIRECTORY))
{
std::error_code ec;
auto canonicalPath = std::filesystem::canonical(path, ec);
if (!ec)
std::filesystem::path path{ std::move(normalized) };
// canonical() will resolve symlinks, etc. for us.
{
path = std::move(canonicalPath);
std::error_code ec;
auto canonicalPath = std::filesystem::canonical(path, ec);
if (!ec)
{
path = std::move(canonicalPath);
}
}
// std::filesystem::path has no way to extract the internal path.
// So about that.... I own you, computer. Give me that path.
normalized = std::move(const_cast<std::wstring&>(path.native()));
break;
}
// std::filesystem::path has no way to extract the internal path.
// So about that.... I own you, computer. Give me that path.
normalized = std::move(const_cast<std::wstring&>(path.native()));
break;
}
// If the file path couldn't be found by SearchPathW this could be the result of us being given a commandLine
// like "C:\foo bar\baz.exe -arg" which is resolved to the argv array {"C:\foo", "bar\baz.exe", "-arg"}.
// Just like CreateProcessW() we thus try to concatenate arguments until we successfully resolve a valid path.
// Of course we can only do that if we have at least 2 remaining arguments in argv.
// All other error types aren't handled at the moment.
if (argc < 2 || status != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
else if (!hasTrailingArguments() || status != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
{
break;
}
@@ -753,19 +762,19 @@ std::wstring CascadiaSettings::_normalizeCommandLine(LPCWSTR commandLine)
// As described in the comment right above, we concatenate arguments in an attempt to resolve a valid path.
// The code below turns argv from {"C:\foo", "bar\baz.exe", "-arg"} into {"C:\foo bar\baz.exe", "-arg"}.
// The code abuses the fact that CommandLineToArgvW allocates all arguments back-to-back on the heap separated by '\0'.
argv[1][-1] = L' ';
--argc;
argv[startOfArguments][-1] = L' ';
++startOfArguments;
}
// We've (hopefully) finished resolving the path to the executable.
// We're now going to append all remaining arguments to the resulting string.
// If argv is {"C:\Program Files\PowerShell\7\pwsh.exe", "-WorkingDirectory", "~"},
// then we'll get "C:\Program Files\PowerShell\7\pwsh.exe\0-WorkingDirectory\0~"
if (argc > 1)
if (hasTrailingArguments())
{
// normalized contains a canonical form of argv[0] at this point.
// -1 allows us to include the \0 between argv[0] and argv[1] in the call to append().
const auto beg = argv[1] - 1;
const auto beg = argv[startOfArguments] - 1;
const auto lastArg = argv[argc - 1];
const auto end = lastArg + wcslen(lastArg);
normalized.append(beg, end);

View File

@@ -134,6 +134,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
winrt::hstring GetSerializationErrorMessage() const;
// defterm
static std::wstring NormalizeCommandLine(LPCWSTR commandLine);
static bool IsDefaultTerminalAvailable() noexcept;
static bool IsDefaultTerminalSet() noexcept;
winrt::Windows::Foundation::Collections::IObservableVector<Model::DefaultTerminal> DefaultTerminals() noexcept;
@@ -142,7 +143,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
private:
static const std::filesystem::path& _settingsPath();
static std::wstring _normalizeCommandLine(LPCWSTR commandLine);
winrt::com_ptr<implementation::Profile> _createNewProfile(const std::wstring_view& name) const;
Model::Profile _getProfileForCommandLine(const winrt::hstring& commandLine) const;

View File

@@ -55,11 +55,11 @@ void TerminalApiTest::SetColorTableEntry()
auto settings = winrt::make<MockTermSettings>(100, 100, 100);
term.UpdateSettings(settings);
VERIFY_IS_TRUE(term.SetColorTableEntry(0, 100));
VERIFY_IS_TRUE(term.SetColorTableEntry(128, 100));
VERIFY_IS_TRUE(term.SetColorTableEntry(255, 100));
VERIFY_NO_THROW(term.SetColorTableEntry(0, 100));
VERIFY_NO_THROW(term.SetColorTableEntry(128, 100));
VERIFY_NO_THROW(term.SetColorTableEntry(255, 100));
VERIFY_IS_FALSE(term.SetColorTableEntry(512, 100));
VERIFY_THROWS(term.SetColorTableEntry(512, 100), std::exception);
}
// Terminal::_WriteBuffer used to enter infinite loops under certain conditions.

View File

@@ -90,7 +90,29 @@ class Microsoft::Console::Render::VtRendererTest
void TestPaint(VtEngine& engine, std::function<void()> pfn);
Viewport SetUpViewport();
void VerifyExpectedInputsDrained();
void VerifyFirstPaint(VtEngine& engine)
{
// Verify the first BeginPaint emits a clear and go home
qExpectedInput.push_back("\x1b[2J");
// Verify the first EndPaint sets the cursor state
qExpectedInput.push_back("\x1b[?25l");
VERIFY_IS_TRUE(engine._firstPaint);
TestPaint(engine, [&]() {
VERIFY_IS_FALSE(engine._firstPaint);
});
}
void VerifyExpectedInputsDrained()
{
if (!qExpectedInput.empty())
{
for (const auto& exp : qExpectedInput)
{
Log::Error(NoThrowString().Format(L"EXPECTED INPUT NEVER RECEIVED: %hs", exp.c_str()));
}
VERIFY_FAIL(L"there should be no remaining un-drained expected input");
}
}
};
Viewport VtRendererTest::SetUpViewport()
@@ -103,18 +125,6 @@ Viewport VtRendererTest::SetUpViewport()
return Viewport::FromInclusive(view);
}
void VtRendererTest::VerifyExpectedInputsDrained()
{
if (!qExpectedInput.empty())
{
for (const auto& exp : qExpectedInput)
{
Log::Error(NoThrowString().Format(L"EXPECTED INPUT NEVER RECEIVED: %hs", exp.c_str()));
}
VERIFY_FAIL(L"there should be no remaining un-drained expected input");
}
}
bool VtRendererTest::WriteCallback(const char* const pch, size_t const cch)
{
std::string actualString = std::string(pch, cch);
@@ -212,12 +222,7 @@ void VtRendererTest::Xterm256TestInvalidate()
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn);
// Verify the first paint emits a clear and go home
qExpectedInput.push_back("\x1b[2J");
VERIFY_IS_TRUE(engine->_firstPaint);
TestPaint(*engine, [&]() {
VERIFY_IS_FALSE(engine->_firstPaint);
});
VerifyFirstPaint(*engine);
const Viewport view = SetUpViewport();
@@ -402,12 +407,7 @@ void VtRendererTest::Xterm256TestColors()
RenderSettings renderSettings;
RenderData renderData;
// Verify the first paint emits a clear and go home
qExpectedInput.push_back("\x1b[2J");
VERIFY_IS_TRUE(engine->_firstPaint);
TestPaint(*engine, [&]() {
VERIFY_IS_FALSE(engine->_firstPaint);
});
VerifyFirstPaint(*engine);
Viewport view = SetUpViewport();
@@ -585,12 +585,7 @@ void VtRendererTest::Xterm256TestCursor()
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn);
// Verify the first paint emits a clear and go home
qExpectedInput.push_back("\x1b[2J");
VERIFY_IS_TRUE(engine->_firstPaint);
TestPaint(*engine, [&]() {
VERIFY_IS_FALSE(engine->_firstPaint);
});
VerifyFirstPaint(*engine);
Viewport view = SetUpViewport();
@@ -766,12 +761,7 @@ void VtRendererTest::Xterm256TestExtendedAttributes()
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn);
// Verify the first paint emits a clear and go home
qExpectedInput.push_back("\x1b[2J");
VERIFY_IS_TRUE(engine->_firstPaint);
TestPaint(*engine, [&]() {
VERIFY_IS_FALSE(engine->_firstPaint);
});
VerifyFirstPaint(*engine);
Viewport view = SetUpViewport();
@@ -907,12 +897,7 @@ void VtRendererTest::XtermTestInvalidate()
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn);
// Verify the first paint emits a clear and go home
qExpectedInput.push_back("\x1b[2J");
VERIFY_IS_TRUE(engine->_firstPaint);
TestPaint(*engine, [&]() {
VERIFY_IS_FALSE(engine->_firstPaint);
});
VerifyFirstPaint(*engine);
Viewport view = SetUpViewport();
@@ -1096,12 +1081,7 @@ void VtRendererTest::XtermTestColors()
RenderSettings renderSettings;
RenderData renderData;
// Verify the first paint emits a clear and go home
qExpectedInput.push_back("\x1b[2J");
VERIFY_IS_TRUE(engine->_firstPaint);
TestPaint(*engine, [&]() {
VERIFY_IS_FALSE(engine->_firstPaint);
});
VerifyFirstPaint(*engine);
Viewport view = SetUpViewport();
@@ -1234,12 +1214,7 @@ void VtRendererTest::XtermTestCursor()
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn);
// Verify the first paint emits a clear and go home
qExpectedInput.push_back("\x1b[2J");
VERIFY_IS_TRUE(engine->_firstPaint);
TestPaint(*engine, [&]() {
VERIFY_IS_FALSE(engine->_firstPaint);
});
VerifyFirstPaint(*engine);
Viewport view = SetUpViewport();
@@ -1412,12 +1387,7 @@ void VtRendererTest::TestWrapping()
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn);
// Verify the first paint emits a clear and go home
qExpectedInput.push_back("\x1b[2J");
VERIFY_IS_TRUE(engine->_firstPaint);
TestPaint(*engine, [&]() {
VERIFY_IS_FALSE(engine->_firstPaint);
});
VerifyFirstPaint(*engine);
Viewport view = SetUpViewport();
@@ -1465,8 +1435,10 @@ void VtRendererTest::TestResize()
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn);
// Verify the first paint emits a clear and go home
// Verify the first BeginPaint emits a clear and go home
qExpectedInput.push_back("\x1b[2J");
// Verify the first EndPaint sets the cursor state
qExpectedInput.push_back("\x1b[?25l");
VERIFY_IS_TRUE(engine->_firstPaint);
VERIFY_IS_TRUE(engine->_suppressResizeRepaint);
@@ -1502,21 +1474,6 @@ void VtRendererTest::TestCursorVisibility()
auto pfn = std::bind(&VtRendererTest::WriteCallback, this, std::placeholders::_1, std::placeholders::_2);
engine->SetTestCallback(pfn);
// Verify the first paint emits a clear
qExpectedInput.push_back("\x1b[2J");
VERIFY_IS_TRUE(engine->_firstPaint);
VERIFY_IS_FALSE(engine->_lastCursorIsVisible);
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
TestPaint(*engine, [&]() {
// During StartPaint, we'll mark the cursor as off. make sure that happens.
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_firstPaint);
});
// The cursor wasn't painted in the last frame.
VERIFY_IS_FALSE(engine->_lastCursorIsVisible);
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
COORD origin{ 0, 0 };
VERIFY_ARE_NOT_EQUAL(origin, engine->_lastText);
@@ -1527,8 +1484,8 @@ void VtRendererTest::TestCursorVisibility()
// Frame 1: Paint the cursor at the home position. At the end of the frame,
// the cursor should be on. Because we're moving the cursor with CUP, we
// need to disable the cursor during this frame.
qExpectedInput.push_back("\x1b[2J");
TestPaint(*engine, [&]() {
VERIFY_IS_FALSE(engine->_lastCursorIsVisible);
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
@@ -1539,10 +1496,13 @@ void VtRendererTest::TestCursorVisibility()
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
VERIFY_IS_TRUE(engine->_needToDisableCursor);
// GH#12401:
// The other tests verify that the cursor is explicitly hidden on the
// first frame (VerifyFirstPaint). This test on the other hand does
// the opposite by calling PaintCursor() during the first paint cycle.
qExpectedInput.push_back("\x1b[?25h");
});
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
@@ -1550,7 +1510,6 @@ void VtRendererTest::TestCursorVisibility()
// frame, the cursor should be on, the same as before. We aren't moving the
// cursor during this frame, so _needToDisableCursor will stay false.
TestPaint(*engine, [&]() {
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
@@ -1561,7 +1520,6 @@ void VtRendererTest::TestCursorVisibility()
VERIFY_IS_FALSE(engine->_needToDisableCursor);
});
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
@@ -1569,7 +1527,6 @@ void VtRendererTest::TestCursorVisibility()
// should be on, the same as before. Because we're moving the cursor with
// CUP, we need to disable the cursor during this frame.
TestPaint(*engine, [&]() {
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
@@ -1580,7 +1537,6 @@ void VtRendererTest::TestCursorVisibility()
VERIFY_SUCCEEDED(engine->PaintCursor(options));
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
VERIFY_IS_TRUE(engine->_needToDisableCursor);
@@ -1590,7 +1546,6 @@ void VtRendererTest::TestCursorVisibility()
qExpectedInput.push_back("\x1b[?25h");
});
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_TRUE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
@@ -1598,14 +1553,12 @@ void VtRendererTest::TestCursorVisibility()
// should be off.
Log::Comment(NoThrowString().Format(L"Painting without calling PaintCursor will hide the cursor"));
TestPaint(*engine, [&]() {
VERIFY_IS_TRUE(engine->_lastCursorIsVisible);
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
qExpectedInput.push_back("\x1b[?25l");
});
VERIFY_IS_FALSE(engine->_lastCursorIsVisible);
VERIFY_IS_FALSE(engine->_nextCursorIsVisible);
VERIFY_IS_FALSE(engine->_needToDisableCursor);
}

View File

@@ -15,7 +15,9 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
VtEngine(std::move(hPipe), initialViewport),
_fUseAsciiOnly(fUseAsciiOnly),
_needToDisableCursor(false),
_lastCursorIsVisible(false),
// GH#12401: Ensure a DECTCEM cursor show/hide sequence
// is emitted on the first frame no matter what.
_lastCursorIsVisible(Tribool::Invalid),
_nextCursorIsVisible(true)
{
// Set out initial cursor position to -1, -1. This will force our initial
@@ -98,31 +100,20 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
{
// If the cursor was previously visible, let's hide it for this frame,
// by prepending a cursor off.
if (_lastCursorIsVisible)
if (_lastCursorIsVisible != Tribool::False)
{
_buffer.insert(0, "\x1b[?25l");
_lastCursorIsVisible = false;
_lastCursorIsVisible = Tribool::False;
}
// If the cursor was NOT previously visible, then that's fine! we don't
// need to worry, it's already off.
}
// If the cursor is moving from off -> on (including cases where we just
// disabled if for this frame), show the cursor at the end of the frame
if (_nextCursorIsVisible && !_lastCursorIsVisible)
if (_lastCursorIsVisible != static_cast<Tribool>(_nextCursorIsVisible))
{
RETURN_IF_FAILED(_ShowCursor());
RETURN_IF_FAILED(_nextCursorIsVisible ? _ShowCursor() : _HideCursor());
_lastCursorIsVisible = static_cast<Tribool>(_nextCursorIsVisible);
}
// Otherwise, if the cursor previously was visible, and it should be hidden
// (on -> off), hide it at the end of the frame.
else if (!_nextCursorIsVisible && _lastCursorIsVisible)
{
RETURN_IF_FAILED(_HideCursor());
}
// Update our tracker of what we thought the last cursor state of the
// terminal was.
_lastCursorIsVisible = _nextCursorIsVisible;
RETURN_IF_FAILED(VtEngine::EndPaint());

View File

@@ -54,9 +54,18 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT WriteTerminalW(const std::wstring_view str) noexcept override;
protected:
// I'm using a non-class enum here, so that the values
// are trivially convertible and comparable to bool.
enum class Tribool : uint8_t
{
False = 0,
True,
Invalid,
};
const bool _fUseAsciiOnly;
bool _needToDisableCursor;
bool _lastCursorIsVisible;
Tribool _lastCursorIsVisible;
bool _nextCursorIsVisible;
[[nodiscard]] HRESULT _MoveCursor(const COORD coord) noexcept override;

View File

@@ -17,6 +17,8 @@ namespace Microsoft::Console::VirtualTerminal
class TermDispatch;
};
#pragma warning(disable : 26440) // Making these methods noexcept would require the same of all derived classes
class Microsoft::Console::VirtualTerminal::TermDispatch : public Microsoft::Console::VirtualTerminal::ITermDispatch
{
public:
@@ -24,106 +26,106 @@ public:
void Print(const wchar_t wchPrintable) override = 0;
void PrintString(const std::wstring_view string) override = 0;
bool CursorUp(const size_t /*distance*/) noexcept override { return false; } // CUU
bool CursorDown(const size_t /*distance*/) noexcept override { return false; } // CUD
bool CursorForward(const size_t /*distance*/) noexcept override { return false; } // CUF
bool CursorBackward(const size_t /*distance*/) noexcept override { return false; } // CUB, BS
bool CursorNextLine(const size_t /*distance*/) noexcept override { return false; } // CNL
bool CursorPrevLine(const size_t /*distance*/) noexcept override { return false; } // CPL
bool CursorHorizontalPositionAbsolute(const size_t /*column*/) noexcept override { return false; } // HPA, CHA
bool VerticalLinePositionAbsolute(const size_t /*line*/) noexcept override { return false; } // VPA
bool HorizontalPositionRelative(const size_t /*distance*/) noexcept override { return false; } // HPR
bool VerticalPositionRelative(const size_t /*distance*/) noexcept override { return false; } // VPR
bool CursorPosition(const size_t /*line*/, const size_t /*column*/) noexcept override { return false; } // CUP, HVP
bool CursorSaveState() noexcept override { return false; } // DECSC
bool CursorRestoreState() noexcept override { return false; } // DECRC
bool CursorVisibility(const bool /*isVisible*/) noexcept override { return false; } // DECTCEM
bool InsertCharacter(const size_t /*count*/) noexcept override { return false; } // ICH
bool DeleteCharacter(const size_t /*count*/) noexcept override { return false; } // DCH
bool ScrollUp(const size_t /*distance*/) noexcept override { return false; } // SU
bool ScrollDown(const size_t /*distance*/) noexcept override { return false; } // SD
bool InsertLine(const size_t /*distance*/) noexcept override { return false; } // IL
bool DeleteLine(const size_t /*distance*/) noexcept override { return false; } // DL
bool SetColumns(const size_t /*columns*/) noexcept override { return false; } // DECCOLM
bool SetCursorKeysMode(const bool /*applicationMode*/) noexcept override { return false; } // DECCKM
bool SetKeypadMode(const bool /*applicationMode*/) noexcept override { return false; } // DECKPAM, DECKPNM
bool EnableWin32InputMode(const bool /*win32InputMode*/) noexcept override { return false; } // win32-input-mode
bool EnableCursorBlinking(const bool /*enable*/) noexcept override { return false; } // ATT610
bool SetAnsiMode(const bool /*ansiMode*/) noexcept override { return false; } // DECANM
bool SetScreenMode(const bool /*reverseMode*/) noexcept override { return false; } // DECSCNM
bool SetOriginMode(const bool /*relativeMode*/) noexcept override { return false; }; // DECOM
bool SetAutoWrapMode(const bool /*wrapAtEOL*/) noexcept override { return false; }; // DECAWM
bool SetTopBottomScrollingMargins(const size_t /*topMargin*/, const size_t /*bottomMargin*/) noexcept override { return false; } // DECSTBM
bool WarningBell() noexcept override { return false; } // BEL
bool CarriageReturn() noexcept override { return false; } // CR
bool LineFeed(const DispatchTypes::LineFeedType /*lineFeedType*/) noexcept override { return false; } // IND, NEL, LF, FF, VT
bool ReverseLineFeed() noexcept override { return false; } // RI
bool SetWindowTitle(std::wstring_view /*title*/) noexcept override { return false; } // OscWindowTitle
bool UseAlternateScreenBuffer() noexcept override { return false; } // ASBSET
bool UseMainScreenBuffer() noexcept override { return false; } // ASBRST
bool HorizontalTabSet() noexcept override { return false; } // HTS
bool ForwardTab(const size_t /*numTabs*/) noexcept override { return false; } // CHT, HT
bool BackwardsTab(const size_t /*numTabs*/) noexcept override { return false; } // CBT
bool TabClear(const DispatchTypes::TabClearType /*clearType*/) noexcept override { return false; } // TBC
bool EnableDECCOLMSupport(const bool /*enabled*/) noexcept override { return false; } // ?40
bool EnableVT200MouseMode(const bool /*enabled*/) noexcept override { return false; } // ?1000
bool EnableUTF8ExtendedMouseMode(const bool /*enabled*/) noexcept override { return false; } // ?1005
bool EnableSGRExtendedMouseMode(const bool /*enabled*/) noexcept override { return false; } // ?1006
bool EnableButtonEventMouseMode(const bool /*enabled*/) noexcept override { return false; } // ?1002
bool EnableAnyEventMouseMode(const bool /*enabled*/) noexcept override { return false; } // ?1003
bool EnableAlternateScroll(const bool /*enabled*/) noexcept override { return false; } // ?1007
bool EnableXtermBracketedPasteMode(const bool /*enabled*/) noexcept override { return false; } // ?2004
bool SetColorTableEntry(const size_t /*tableIndex*/, const DWORD /*color*/) noexcept override { return false; } // OSCColorTable
bool SetDefaultForeground(const DWORD /*color*/) noexcept override { return false; } // OSCDefaultForeground
bool SetDefaultBackground(const DWORD /*color*/) noexcept override { return false; } // OSCDefaultBackground
bool CursorUp(const size_t /*distance*/) override { return false; } // CUU
bool CursorDown(const size_t /*distance*/) override { return false; } // CUD
bool CursorForward(const size_t /*distance*/) override { return false; } // CUF
bool CursorBackward(const size_t /*distance*/) override { return false; } // CUB, BS
bool CursorNextLine(const size_t /*distance*/) override { return false; } // CNL
bool CursorPrevLine(const size_t /*distance*/) override { return false; } // CPL
bool CursorHorizontalPositionAbsolute(const size_t /*column*/) override { return false; } // HPA, CHA
bool VerticalLinePositionAbsolute(const size_t /*line*/) override { return false; } // VPA
bool HorizontalPositionRelative(const size_t /*distance*/) override { return false; } // HPR
bool VerticalPositionRelative(const size_t /*distance*/) override { return false; } // VPR
bool CursorPosition(const size_t /*line*/, const size_t /*column*/) override { return false; } // CUP, HVP
bool CursorSaveState() override { return false; } // DECSC
bool CursorRestoreState() override { return false; } // DECRC
bool CursorVisibility(const bool /*isVisible*/) override { return false; } // DECTCEM
bool InsertCharacter(const size_t /*count*/) override { return false; } // ICH
bool DeleteCharacter(const size_t /*count*/) override { return false; } // DCH
bool ScrollUp(const size_t /*distance*/) override { return false; } // SU
bool ScrollDown(const size_t /*distance*/) override { return false; } // SD
bool InsertLine(const size_t /*distance*/) override { return false; } // IL
bool DeleteLine(const size_t /*distance*/) override { return false; } // DL
bool SetColumns(const size_t /*columns*/) override { return false; } // DECCOLM
bool SetCursorKeysMode(const bool /*applicationMode*/) override { return false; } // DECCKM
bool SetKeypadMode(const bool /*applicationMode*/) override { return false; } // DECKPAM, DECKPNM
bool EnableWin32InputMode(const bool /*win32InputMode*/) override { return false; } // win32-input-mode
bool EnableCursorBlinking(const bool /*enable*/) override { return false; } // ATT610
bool SetAnsiMode(const bool /*ansiMode*/) override { return false; } // DECANM
bool SetScreenMode(const bool /*reverseMode*/) override { return false; } // DECSCNM
bool SetOriginMode(const bool /*relativeMode*/) override { return false; }; // DECOM
bool SetAutoWrapMode(const bool /*wrapAtEOL*/) override { return false; }; // DECAWM
bool SetTopBottomScrollingMargins(const size_t /*topMargin*/, const size_t /*bottomMargin*/) override { return false; } // DECSTBM
bool WarningBell() override { return false; } // BEL
bool CarriageReturn() override { return false; } // CR
bool LineFeed(const DispatchTypes::LineFeedType /*lineFeedType*/) override { return false; } // IND, NEL, LF, FF, VT
bool ReverseLineFeed() override { return false; } // RI
bool SetWindowTitle(std::wstring_view /*title*/) override { return false; } // OscWindowTitle
bool UseAlternateScreenBuffer() override { return false; } // ASBSET
bool UseMainScreenBuffer() override { return false; } // ASBRST
bool HorizontalTabSet() override { return false; } // HTS
bool ForwardTab(const size_t /*numTabs*/) override { return false; } // CHT, HT
bool BackwardsTab(const size_t /*numTabs*/) override { return false; } // CBT
bool TabClear(const DispatchTypes::TabClearType /*clearType*/) override { return false; } // TBC
bool EnableDECCOLMSupport(const bool /*enabled*/) override { return false; } // ?40
bool EnableVT200MouseMode(const bool /*enabled*/) override { return false; } // ?1000
bool EnableUTF8ExtendedMouseMode(const bool /*enabled*/) override { return false; } // ?1005
bool EnableSGRExtendedMouseMode(const bool /*enabled*/) override { return false; } // ?1006
bool EnableButtonEventMouseMode(const bool /*enabled*/) override { return false; } // ?1002
bool EnableAnyEventMouseMode(const bool /*enabled*/) override { return false; } // ?1003
bool EnableAlternateScroll(const bool /*enabled*/) override { return false; } // ?1007
bool EnableXtermBracketedPasteMode(const bool /*enabled*/) override { return false; } // ?2004
bool SetColorTableEntry(const size_t /*tableIndex*/, const DWORD /*color*/) override { return false; } // OSCColorTable
bool SetDefaultForeground(const DWORD /*color*/) override { return false; } // OSCDefaultForeground
bool SetDefaultBackground(const DWORD /*color*/) override { return false; } // OSCDefaultBackground
bool EraseInDisplay(const DispatchTypes::EraseType /* eraseType*/) noexcept override { return false; } // ED
bool EraseInLine(const DispatchTypes::EraseType /* eraseType*/) noexcept override { return false; } // EL
bool EraseCharacters(const size_t /*numChars*/) noexcept override { return false; } // ECH
bool EraseInDisplay(const DispatchTypes::EraseType /* eraseType*/) override { return false; } // ED
bool EraseInLine(const DispatchTypes::EraseType /* eraseType*/) override { return false; } // EL
bool EraseCharacters(const size_t /*numChars*/) override { return false; } // ECH
bool SetGraphicsRendition(const VTParameters /*options*/) noexcept override { return false; } // SGR
bool SetLineRendition(const LineRendition /*rendition*/) noexcept override { return false; } // DECSWL, DECDWL, DECDHL
bool SetGraphicsRendition(const VTParameters /*options*/) override { return false; } // SGR
bool SetLineRendition(const LineRendition /*rendition*/) override { return false; } // DECSWL, DECDWL, DECDHL
bool PushGraphicsRendition(const VTParameters /*options*/) noexcept override { return false; } // XTPUSHSGR
bool PopGraphicsRendition() noexcept override { return false; } // XTPOPSGR
bool PushGraphicsRendition(const VTParameters /*options*/) override { return false; } // XTPUSHSGR
bool PopGraphicsRendition() override { return false; } // XTPOPSGR
bool SetMode(const DispatchTypes::ModeParams /*param*/) noexcept override { return false; } // DECSET
bool SetMode(const DispatchTypes::ModeParams /*param*/) override { return false; } // DECSET
bool ResetMode(const DispatchTypes::ModeParams /*param*/) noexcept override { return false; } // DECRST
bool ResetMode(const DispatchTypes::ModeParams /*param*/) override { return false; } // DECRST
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType /*statusType*/) noexcept override { return false; } // DSR, DSR-OS, DSR-CPR
bool DeviceAttributes() noexcept override { return false; } // DA1
bool SecondaryDeviceAttributes() noexcept override { return false; } // DA2
bool TertiaryDeviceAttributes() noexcept override { return false; } // DA3
bool Vt52DeviceAttributes() noexcept override { return false; } // VT52 Identify
bool RequestTerminalParameters(const DispatchTypes::ReportingPermission /*permission*/) noexcept override { return false; } // DECREQTPARM
bool DeviceStatusReport(const DispatchTypes::AnsiStatusType /*statusType*/) override { return false; } // DSR, DSR-OS, DSR-CPR
bool DeviceAttributes() override { return false; } // DA1
bool SecondaryDeviceAttributes() override { return false; } // DA2
bool TertiaryDeviceAttributes() override { return false; } // DA3
bool Vt52DeviceAttributes() override { return false; } // VT52 Identify
bool RequestTerminalParameters(const DispatchTypes::ReportingPermission /*permission*/) override { return false; } // DECREQTPARM
bool DesignateCodingSystem(const VTID /*codingSystem*/) noexcept override { return false; } // DOCS
bool Designate94Charset(const size_t /*gsetNumber*/, const VTID /*charset*/) noexcept override { return false; } // SCS
bool Designate96Charset(const size_t /*gsetNumber*/, const VTID /*charset*/) noexcept override { return false; } // SCS
bool LockingShift(const size_t /*gsetNumber*/) noexcept override { return false; } // LS0, LS1, LS2, LS3
bool LockingShiftRight(const size_t /*gsetNumber*/) noexcept override { return false; } // LS1R, LS2R, LS3R
bool SingleShift(const size_t /*gsetNumber*/) noexcept override { return false; } // SS2, SS3
bool AcceptC1Controls(const bool /*enabled*/) noexcept override { return false; } // DECAC1
bool DesignateCodingSystem(const VTID /*codingSystem*/) override { return false; } // DOCS
bool Designate94Charset(const size_t /*gsetNumber*/, const VTID /*charset*/) override { return false; } // SCS
bool Designate96Charset(const size_t /*gsetNumber*/, const VTID /*charset*/) override { return false; } // SCS
bool LockingShift(const size_t /*gsetNumber*/) override { return false; } // LS0, LS1, LS2, LS3
bool LockingShiftRight(const size_t /*gsetNumber*/) override { return false; } // LS1R, LS2R, LS3R
bool SingleShift(const size_t /*gsetNumber*/) override { return false; } // SS2, SS3
bool AcceptC1Controls(const bool /*enabled*/) override { return false; } // DECAC1
bool SoftReset() noexcept override { return false; } // DECSTR
bool HardReset() noexcept override { return false; } // RIS
bool ScreenAlignmentPattern() noexcept override { return false; } // DECALN
bool SoftReset() override { return false; } // DECSTR
bool HardReset() override { return false; } // RIS
bool ScreenAlignmentPattern() override { return false; } // DECALN
bool SetCursorStyle(const DispatchTypes::CursorStyle /*cursorStyle*/) noexcept override { return false; } // DECSCUSR
bool SetCursorColor(const COLORREF /*color*/) noexcept override { return false; } // OSCSetCursorColor, OSCResetCursorColor
bool SetCursorStyle(const DispatchTypes::CursorStyle /*cursorStyle*/) override { return false; } // DECSCUSR
bool SetCursorColor(const COLORREF /*color*/) override { return false; } // OSCSetCursorColor, OSCResetCursorColor
bool SetClipboard(std::wstring_view /*content*/) noexcept override { return false; } // OscSetClipboard
bool SetClipboard(std::wstring_view /*content*/) override { return false; } // OscSetClipboard
// DTTERM_WindowManipulation
bool WindowManipulation(const DispatchTypes::WindowManipulationType /*function*/,
const VTParameter /*parameter1*/,
const VTParameter /*parameter2*/) noexcept override { return false; }
const VTParameter /*parameter2*/) override { return false; }
bool AddHyperlink(const std::wstring_view /*uri*/, const std::wstring_view /*params*/) noexcept override { return false; }
bool EndHyperlink() noexcept override { return false; }
bool AddHyperlink(const std::wstring_view /*uri*/, const std::wstring_view /*params*/) override { return false; }
bool EndHyperlink() override { return false; }
bool DoConEmuAction(const std::wstring_view /*string*/) noexcept override { return false; }
bool DoConEmuAction(const std::wstring_view /*string*/) override { return false; }
StringHandler DownloadDRCS(const size_t /*fontNumber*/,
const VTParameter /*startChar*/,
@@ -132,7 +134,9 @@ public:
const DispatchTypes::DrcsFontSet /*fontSet*/,
const DispatchTypes::DrcsFontUsage /*fontUsage*/,
const VTParameter /*cellHeight*/,
const DispatchTypes::DrcsCharsetSize /*charsetSize*/) noexcept override { return nullptr; }
const DispatchTypes::DrcsCharsetSize /*charsetSize*/) override { return nullptr; }
StringHandler RequestSetting() noexcept override { return nullptr; }; // DECRQSS
StringHandler RequestSetting() override { return nullptr; }; // DECRQSS
};
#pragma warning(default : 26440) // Restore "can be declared noexcept" warning

View File

@@ -42,9 +42,15 @@ HRESULT UiaTextRangeBase::RuntimeClassInitialize(_In_ IUiaData* pData,
_In_ std::wstring_view wordDelimiters) noexcept
try
{
RETURN_HR_IF_NULL(E_INVALIDARG, pData);
RETURN_IF_FAILED(RuntimeClassInitialize(pData, pProvider, wordDelimiters));
// GH#8730: The cursor position may be in a delayed state, resulting in it being out of bounds.
// If that's the case, clamp it to be within bounds.
// TODO GH#12440: We should be able to just check some fields off of the Cursor object,
// but Windows Terminal isn't updating those flags properly.
_start = cursor.GetPosition();
pData->GetTextBuffer().GetSize().Clamp(_start);
_end = _start;
UiaTracing::TextRange::Constructor(*this);

View File

@@ -479,5 +479,29 @@ void UtilsTests::TestMangleWSLPaths()
VERIFY_ARE_EQUAL(LR"("wsl" --cd "\\wsl.localhost\Ubuntu\home\user" -d Ubuntu)", commandline);
VERIFY_ARE_EQUAL(L"", path);
}
/// Tests for GH #12353
const auto expectedUserProfilePath = wil::ExpandEnvironmentStringsW<std::wstring>(L"%USERPROFILE%");
{
auto [commandline, path] = MangleStartingDirectoryForWSL(LR"(wsl -d Ubuntu)", L"~");
VERIFY_ARE_EQUAL(LR"("wsl" --cd "~" -d Ubuntu)", commandline);
VERIFY_ARE_EQUAL(L"", path);
}
{
auto [commandline, path] = MangleStartingDirectoryForWSL(LR"(wsl ~ -d Ubuntu)", L"~");
VERIFY_ARE_EQUAL(LR"(wsl ~ -d Ubuntu)", commandline);
VERIFY_ARE_EQUAL(expectedUserProfilePath, path);
}
{
auto [commandline, path] = MangleStartingDirectoryForWSL(LR"(ubuntu ~ -d Ubuntu)", L"~");
VERIFY_ARE_EQUAL(LR"(ubuntu ~ -d Ubuntu)", commandline);
VERIFY_ARE_EQUAL(expectedUserProfilePath, path);
}
{
auto [commandline, path] = MangleStartingDirectoryForWSL(LR"(powershell.exe)", L"~");
VERIFY_ARE_EQUAL(LR"(powershell.exe)", commandline);
VERIFY_ARE_EQUAL(expectedUserProfilePath, path);
}
}
#endif

View File

@@ -670,8 +670,15 @@ std::tuple<std::wstring, std::wstring> Utils::MangleStartingDirectoryForWSL(std:
}
} while (false);
// GH #12353: `~` is never a valid windows path. We can only accept that as
// a startingDirectory when the exe is specifically wsl.exe, because that
// can override the real startingDirectory. If the user set the
// startingDirectory to ~, but the commandline to something like pwsh.exe,
// that won't actually work. In that case, mangle the startingDirectory to
// %userprofile%, so it's at least something reasonable.
return {
std::wstring{ commandLine },
std::wstring{ startingDirectory }
startingDirectory == L"~" ? wil::ExpandEnvironmentStringsW<std::wstring>(L"%USERPROFILE%") :
std::wstring{ startingDirectory }
};
}