mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-12 01:01:05 +00:00
Compare commits
101 Commits
dev/lhecke
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8474eb8329 | ||
|
|
d069ea6c29 | ||
|
|
36bc972e88 | ||
|
|
6fb0a8f513 | ||
|
|
88a2f94f98 | ||
|
|
5f7237b0b9 | ||
|
|
09caec957a | ||
|
|
96347843d6 | ||
|
|
1ad126985e | ||
|
|
e0514ffc2d | ||
|
|
87e44682af | ||
|
|
d310d07598 | ||
|
|
bf21a15844 | ||
|
|
621e1846a1 | ||
|
|
0e2ef991bf | ||
|
|
4f490d9216 | ||
|
|
d8efeed904 | ||
|
|
70b1eacf57 | ||
|
|
785dceaa2f | ||
|
|
d8b5a488a2 | ||
|
|
88891804a8 | ||
|
|
558b90f6bb | ||
|
|
9be0bc6cb9 | ||
|
|
eeeb126ab3 | ||
|
|
1e70e182f2 | ||
|
|
48e2d93330 | ||
|
|
6ba10c13d6 | ||
|
|
51fd044bd2 | ||
|
|
633cd6e9dc | ||
|
|
a3d508a487 | ||
|
|
0d2e8cecd0 | ||
|
|
fb3971f681 | ||
|
|
6115cf31f5 | ||
|
|
b277e4b515 | ||
|
|
8a8d02f7e1 | ||
|
|
1ba28b298f | ||
|
|
ba6cd3ebd5 | ||
|
|
5c543bb2be | ||
|
|
8b07837fdd | ||
|
|
4fd7751d83 | ||
|
|
47da5a11b2 | ||
|
|
08a981d7b7 | ||
|
|
7e69a2e96f | ||
|
|
5205575d4d | ||
|
|
7a34181fc7 | ||
|
|
b38489b67b | ||
|
|
d25b84d4c1 | ||
|
|
9ab1b7ba3b | ||
|
|
d35bc4cee6 | ||
|
|
77ee52b872 | ||
|
|
671552671d | ||
|
|
58a5088735 | ||
|
|
c5f99b69d5 | ||
|
|
6f5b293a56 | ||
|
|
e33bc3d137 | ||
|
|
6aae2d0b72 | ||
|
|
148a86c81c | ||
|
|
94e96ca048 | ||
|
|
b53d7df066 | ||
|
|
1194ad0343 | ||
|
|
04e1290102 | ||
|
|
f5083714c1 | ||
|
|
7642eec206 | ||
|
|
37c674dd6e | ||
|
|
3a57ba54a0 | ||
|
|
fc465bdae6 | ||
|
|
04a5dffdcd | ||
|
|
894e57769b | ||
|
|
eb206177a4 | ||
|
|
ad48162f02 | ||
|
|
6771470c8b | ||
|
|
21cfbf170c | ||
|
|
4f391c5e42 | ||
|
|
d61ad2d9cd | ||
|
|
7578209be5 | ||
|
|
2c666aa292 | ||
|
|
68b723c16c | ||
|
|
642a2aa41e | ||
|
|
7055b99acc | ||
|
|
837e86c18c | ||
|
|
e97388cb27 | ||
|
|
1b2aad6504 | ||
|
|
abaa9488d9 | ||
|
|
6b19d21845 | ||
|
|
0d23624fa9 | ||
|
|
8a05910e3c | ||
|
|
a0f7b332fa | ||
|
|
0c064905b3 | ||
|
|
e2f3e53064 | ||
|
|
5b41f14660 | ||
|
|
514da89b63 | ||
|
|
6c2f38c732 | ||
|
|
6fb70eb510 | ||
|
|
c55aca508b | ||
|
|
666a75bc70 | ||
|
|
c0f9a198c6 | ||
|
|
a258d7d3df | ||
|
|
0a6394270e | ||
|
|
88ab154f22 | ||
|
|
dbf740cf2c | ||
|
|
9ab7cf312f |
@@ -3,7 +3,7 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"XamlStyler.Console": {
|
||||
"version": "3.2311.2",
|
||||
"version": "3.2501.8",
|
||||
"commands": [
|
||||
"xstyler"
|
||||
]
|
||||
|
||||
2
.github/actions/spelling/allow/apis.txt
vendored
2
.github/actions/spelling/allow/apis.txt
vendored
@@ -174,9 +174,11 @@ tokeninfo
|
||||
tolower
|
||||
toupper
|
||||
TRACKMOUSEEVENT
|
||||
ubrk
|
||||
UChar
|
||||
UFIELD
|
||||
ULARGE
|
||||
UNCEx
|
||||
UOI
|
||||
UPDATEINIFILE
|
||||
urlmon
|
||||
|
||||
1
.github/actions/spelling/allow/microsoft.txt
vendored
1
.github/actions/spelling/allow/microsoft.txt
vendored
@@ -34,6 +34,7 @@ issecret
|
||||
libucrt
|
||||
libucrtd
|
||||
LOCKFILE
|
||||
LTCG
|
||||
Lxss
|
||||
makepri
|
||||
microsoft
|
||||
|
||||
1
.github/actions/spelling/allow/names.txt
vendored
1
.github/actions/spelling/allow/names.txt
vendored
@@ -28,6 +28,7 @@ jerrysh
|
||||
Kaiyu
|
||||
leonardder
|
||||
lhecker
|
||||
Lovecraft
|
||||
masserano
|
||||
menger
|
||||
migrie
|
||||
|
||||
14
.github/actions/spelling/expect/expect.txt
vendored
14
.github/actions/spelling/expect/expect.txt
vendored
@@ -141,6 +141,7 @@ BValue
|
||||
Cacafire
|
||||
CALLCONV
|
||||
CANDRABINDU
|
||||
CANTCALLOUT
|
||||
capslock
|
||||
CARETBLINKINGENABLED
|
||||
CARRIAGERETURN
|
||||
@@ -809,6 +810,7 @@ inclusivity
|
||||
INCONTEXT
|
||||
INFOEX
|
||||
inheritcursor
|
||||
ININPUTSYNCCALL
|
||||
INITCOMMONCONTROLSEX
|
||||
INITDIALOG
|
||||
INITGUID
|
||||
@@ -822,6 +824,7 @@ INPUTSCOPE
|
||||
INSERTMODE
|
||||
INTERACTIVITYBASE
|
||||
INTERCEPTCOPYPASTE
|
||||
internalevent
|
||||
INTERNALNAME
|
||||
intsafe
|
||||
INVALIDARG
|
||||
@@ -960,6 +963,7 @@ lstatus
|
||||
lstrcmp
|
||||
lstrcmpi
|
||||
LTEXT
|
||||
lto
|
||||
ltsc
|
||||
LUID
|
||||
luma
|
||||
@@ -1059,6 +1063,7 @@ Mypair
|
||||
Myval
|
||||
NAMELENGTH
|
||||
namestream
|
||||
NCACTIVATE
|
||||
NCCALCSIZE
|
||||
NCCREATE
|
||||
NCLBUTTONDOWN
|
||||
@@ -1089,6 +1094,8 @@ NEXTLINE
|
||||
nfe
|
||||
NLSMODE
|
||||
NOACTIVATE
|
||||
NOACTIVATEKEYBOARDLAYOUT
|
||||
NOACTIVATETIP
|
||||
NOAPPLYNOW
|
||||
NOCLIP
|
||||
NOCOMM
|
||||
@@ -1503,7 +1510,6 @@ scrolllock
|
||||
scrolloffset
|
||||
SCROLLSCALE
|
||||
SCROLLSCREENBUFFER
|
||||
scursor
|
||||
sddl
|
||||
SDKDDK
|
||||
segfault
|
||||
@@ -1701,13 +1707,16 @@ TEXTMETRIC
|
||||
TEXTMETRICW
|
||||
textmode
|
||||
texttests
|
||||
TFCAT
|
||||
THUMBPOSITION
|
||||
THUMBTRACK
|
||||
tilunittests
|
||||
TIPCAP
|
||||
titlebars
|
||||
TITLEISLINKNAME
|
||||
TLDP
|
||||
TLEN
|
||||
Tlgg
|
||||
TMAE
|
||||
TMPF
|
||||
tmultiple
|
||||
@@ -1754,6 +1763,8 @@ UIACCESS
|
||||
uiacore
|
||||
uiautomationcore
|
||||
uielem
|
||||
UIELEMENTENABLED
|
||||
UIELEMENTENABLEDONLY
|
||||
UINTs
|
||||
uld
|
||||
uldash
|
||||
@@ -1970,6 +1981,7 @@ WRITECONSOLEOUTPUT
|
||||
WRITECONSOLEOUTPUTSTRING
|
||||
wrkstr
|
||||
WRL
|
||||
wrl
|
||||
wrp
|
||||
WRunoff
|
||||
WSLENV
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
"Microsoft.VisualStudio.Component.AppInsights.Tools",
|
||||
"Microsoft.Net.Component.4.8.TargetingPack",
|
||||
"Microsoft.VisualStudio.Component.DiagnosticTools",
|
||||
"Microsoft.NetCore.Component.Runtime.6.0",
|
||||
"Microsoft.VisualStudio.Component.ClassDesigner",
|
||||
"Microsoft.VisualStudio.Component.GraphDocument",
|
||||
"Microsoft.VisualStudio.Component.CodeMap",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<clear />
|
||||
<!-- Dependencies that we can turn on to force override for testing purposes before uploading. -->
|
||||
<!--<add key="Static Package Dependencies" value="dep\packages" />-->
|
||||
<add key="TerminalDependencies" value="https://pkgs.dev.azure.com/shine-oss/terminal/_packaging/TerminalDependencies/nuget/v3/index.json" />
|
||||
<add key="TerminalDependencies" value="https://pkgs.dev.azure.com/shine-oss/terminal/_packaging/TerminalDependencies%40Local/nuget/v3/index.json" />
|
||||
</packageSources>
|
||||
<disabledPackageSources>
|
||||
<clear />
|
||||
|
||||
@@ -309,11 +309,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{D3EF
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winconpty.Tests.Feature", "src\winconpty\ft_pty\winconpty.FeatureTests.vcxproj", "{024052DE-83FB-4653-AEA4-90790D29D5BD}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAzBridge", "src\cascadia\TerminalAzBridge\TerminalAzBridge.vcxproj", "{067F0A06-FCB7-472C-96E9-B03B54E8E18D}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTerminalTestNetCore", "src\cascadia\WpfTerminalTestNetCore\WpfTerminalTestNetCore.csproj", "{1588FD7C-241E-4E7D-9113-43735F3E6BAD}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070}
|
||||
@@ -1703,30 +1698,6 @@ Global
|
||||
{024052DE-83FB-4653-AEA4-90790D29D5BD}.Release|x64.Build.0 = Release|x64
|
||||
{024052DE-83FB-4653-AEA4-90790D29D5BD}.Release|x86.ActiveCfg = Release|Win32
|
||||
{024052DE-83FB-4653-AEA4-90790D29D5BD}.Release|x86.Build.0 = Release|Win32
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.AuditMode|x64.ActiveCfg = Release|x64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Debug|x64.Build.0 = Debug|x64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Debug|x86.Build.0 = Debug|Win32
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Release|x64.ActiveCfg = Release|x64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Release|x64.Build.0 = Release|x64
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Release|x86.ActiveCfg = Release|Win32
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Release|x86.Build.0 = Release|Win32
|
||||
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.AuditMode|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.AuditMode|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.AuditMode|x64.ActiveCfg = Debug|Any CPU
|
||||
@@ -2303,7 +2274,6 @@ Global
|
||||
{6B5A44ED-918D-4747-BFB1-2472A1FCA173} = {04170EEF-983A-4195-BFEF-2321E5E38A1E}
|
||||
{D3EF7B96-CD5E-47C9-B9A9-136259563033} = {04170EEF-983A-4195-BFEF-2321E5E38A1E}
|
||||
{024052DE-83FB-4653-AEA4-90790D29D5BD} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
|
||||
{067F0A06-FCB7-472C-96E9-B03B54E8E18D} = {61901E80-E97D-4D61-A9BB-E8F2FDA8B40C}
|
||||
{1588FD7C-241E-4E7D-9113-43735F3E6BAD} = {4DAF0299-495E-4CD1-A982-9BAC16A45932}
|
||||
{506FD703-BAA7-4F6E-9361-64F550EC8FCA} = {61901E80-E97D-4D61-A9BB-E8F2FDA8B40C}
|
||||
{416FD703-BAA7-4F6E-9361-64F550EC8FCA} = {61901E80-E97D-4D61-A9BB-E8F2FDA8B40C}
|
||||
|
||||
@@ -56,9 +56,9 @@ This is an open source project and we welcome community participation. To partic
|
||||
<ReleaseNotes _locID="App_ReleaseNotes">
|
||||
<!-- _locComment_text="{MaxLength=1500} {Locked=__VERSION_NUMBER__}{Locked=wt.exe} App Release Note" -->Version __VERSION_NUMBER__
|
||||
|
||||
- We've added dozens of settings to the UI that once only existed in the JSON file, including a new page for customizing the layout of your New Tab menu!
|
||||
- We have rearchitected window management to improve reliability; please file any bugs you encounter with the wt.exe alias
|
||||
- Profiles now show an icon if they've been hidden or refer to programs which were uninstalled.
|
||||
- A whole new Extensions page that shows what has been installed into your Terminal
|
||||
- Command Palette now shows up in your native language as well as English
|
||||
- New VT features such as synchronized rendering, new color schemes, configuration for quick mouse actions like zooming, and more
|
||||
|
||||
Please see our GitHub releases page for additional details.
|
||||
</ReleaseNotes>
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"DisableAutoPackageNameFormatting": false
|
||||
},
|
||||
"appSubmission": {
|
||||
"appId": "9N8G5RFZ9XK3",
|
||||
"productId": "00014050269303149694",
|
||||
"targetPublishMode": "NotSet",
|
||||
"targetPublishDate": null,
|
||||
|
||||
@@ -54,14 +54,11 @@ This is an open source project and we welcome community participation. To partic
|
||||
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
|
||||
</DevStudio>
|
||||
<ReleaseNotes _locID="App_ReleaseNotes">
|
||||
<!-- _locComment_text="{MaxLength=1500} {Locked=__VERSION_NUMBER__} App Release Note" -->Version __VERSION_NUMBER__
|
||||
<!-- _locComment_text="{MaxLength=1500} {Locked=__VERSION_NUMBER__}{Locked=wt.exe} App Release Note" -->Version __VERSION_NUMBER__
|
||||
|
||||
- We've rewritten how console applications are hosted inside Terminal! Please report any bugs you encounter.
|
||||
- Terminal now supports Sixels!
|
||||
- You can now open a docked panel containing snippets of commands you have saved to use later
|
||||
- Command Prompt users on the latest Windows 11 release may see a "quick tip" icon that suggests installable software from WinGet
|
||||
- Selected text will now be much more visible (and customizable!)
|
||||
- A number of reliabilty bugs, convenience issues and annoyances have been fixed.
|
||||
- We've added dozens of settings to the UI that once only existed in the JSON file, including a new page for customizing the layout of your New Tab menu!
|
||||
- We have rearchitected window management to improve reliability; please file any bugs you encounter with the wt.exe alias
|
||||
- Profiles now show an icon if they've been hidden or refer to programs which were uninstalled.
|
||||
|
||||
Please see our GitHub releases page for additional details.
|
||||
</ReleaseNotes>
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"DisableAutoPackageNameFormatting": false
|
||||
},
|
||||
"appSubmission": {
|
||||
"appId": "9N0DX20HK701",
|
||||
"productId": "00013926773940052066",
|
||||
"targetPublishMode": "NotSet",
|
||||
"targetPublishDate": null,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"collection": "microsoft",
|
||||
"project": "OS",
|
||||
"repo": "os.2020",
|
||||
"name": "official/rs_we_adept_e4d2",
|
||||
"name": "official/ge_current_directwinpd_deep",
|
||||
"workitem": "38106206",
|
||||
"CheckinFiles": [
|
||||
{
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
"PackageContents/WindowsTerminalShellExt.dll",
|
||||
|
||||
// The rest
|
||||
"PackageContents/TerminalAzBridge.exe",
|
||||
"PackageContents/wt.exe",
|
||||
"PackageContents/WindowsTerminal.exe",
|
||||
"PackageContents/elevate-shim.exe"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"MatchedPath": [
|
||||
"WpfTerminalControl/net472/Microsoft.Terminal.Wpf.dll",
|
||||
"WpfTerminalControl/net6.0-windows/Microsoft.Terminal.Wpf.dll"
|
||||
"WpfTerminalControl/net8.0-windows/Microsoft.Terminal.Wpf.dll"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
|
||||
@@ -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.24</PGOBranch>
|
||||
|
||||
<!-- Mandatory. Name of the NuGet package which will contain PGO databases for consumption by build system. -->
|
||||
<PGOPackageName>Microsoft.Internal.Windows.Terminal.PGODatabase</PGOPackageName>
|
||||
|
||||
@@ -53,8 +53,12 @@ parameters:
|
||||
displayName: "Publish Symbols to MSDL"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: createVpack
|
||||
displayName: "Create a VPack for Windows"
|
||||
type: boolean
|
||||
default: false
|
||||
- name: publishVpackToWindows
|
||||
displayName: "Publish VPack to Windows"
|
||||
displayName: "Publish above VPack to Windows"
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
@@ -89,6 +93,7 @@ extends:
|
||||
clientId: $(SigningOriginalClientId)
|
||||
terminalInternalPackageVersion: ${{ parameters.terminalInternalPackageVersion }}
|
||||
publishSymbolsToPublic: ${{ parameters.publishSymbolsToPublic }}
|
||||
createVpack: ${{ parameters.createVpack }}
|
||||
publishVpackToWindows: ${{ parameters.publishVpackToWindows }}
|
||||
symbolPublishingSubscription: $(SymbolPublishingServiceConnection)
|
||||
symbolPublishingProject: $(SymbolPublishingProject)
|
||||
|
||||
@@ -50,6 +50,7 @@ stages:
|
||||
buildEverything: true
|
||||
pgoBuildMode: Instrument
|
||||
artifactStem: -instrumentation
|
||||
keepAllExpensiveBuildOutputs: false # the ARM64 build agent runs out of memory downloading the artifacts...
|
||||
|
||||
- stage: RunPGO
|
||||
displayName: Run PGO
|
||||
|
||||
@@ -86,7 +86,7 @@ jobs:
|
||||
$MachineToken = $env:SYSTEM_ACCESSTOKEN | ConvertTo-SecureString -AsPlainText -Force
|
||||
$Credential = [PSCredential]::new("ONEBRANCH_TOKEN", $MachineToken)
|
||||
$MachineToken = $null
|
||||
$Feed = "https://pkgs.dev.azure.com/shine-oss/terminal/_packaging/TerminalDependencies/nuget/v3/index.json"
|
||||
$Feed = "https://pkgs.dev.azure.com/shine-oss/terminal/_packaging/TerminalDependencies%40Local/nuget/v3/index.json"
|
||||
Register-PSResourceRepository -Name "PSGalleryUpstream" -Uri $Feed -Trusted
|
||||
Get-PSResourceRepository
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ jobs:
|
||||
pgoToolsPath: $(Build.SourcesDirectory)\build\PGO
|
||||
nuspecPath: $(pgoToolsPath)\NuSpecs
|
||||
nuspecFilename: PGO.nuspec
|
||||
nugetFeed: "https://pkgs.dev.azure.com/shine-oss/terminal/_packaging/TerminalDependencies/nuget/v3/index.json"
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
@@ -45,7 +46,8 @@ jobs:
|
||||
|
||||
- task: NuGetAuthenticate@1
|
||||
inputs:
|
||||
nuGetServiceConnections: 'Terminal Public Artifact Feed'
|
||||
azureDevOpsServiceConnection: 'Terminal Public Artifact Feed'
|
||||
feedUrl: $(nugetFeed)
|
||||
|
||||
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
|
||||
# This should be `task: NuGetCommand@2`
|
||||
@@ -68,15 +70,7 @@ jobs:
|
||||
artifact: pgo-nupkg-${{ parameters.buildConfiguration }}${{ parameters.artifactStem }}
|
||||
displayName: "Publish Pipeline Artifact"
|
||||
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: 'NuGet push'
|
||||
inputs:
|
||||
command: push
|
||||
nuGetFeedType: external
|
||||
packagesToPush: $(Build.ArtifactStagingDirectory)/*.nupkg
|
||||
# The actual URL and PAT for this feed is configured at
|
||||
# https://microsoft.visualstudio.com/Dart/_settings/adminservices
|
||||
# This is the name of that connection
|
||||
publishFeedCredentials: 'Terminal Public Artifact Feed'
|
||||
feedsToUse: config
|
||||
nugetConfigPath: '$(Build.SourcesDirectory)/NuGet.config'
|
||||
- pwsh: |-
|
||||
$nupkg = Get-Item "$(Build.ArtifactStagingDirectory)/*.nupkg"
|
||||
& nuget push -ApiKey az -Source "$(nugetFeed)" "$nupkg"
|
||||
displayName: NuGet push
|
||||
|
||||
@@ -45,6 +45,10 @@ jobs:
|
||||
displayName: Extract the unpackaged build for PGO
|
||||
|
||||
- template: steps-ensure-nuget-version.yml
|
||||
parameters:
|
||||
${{ if eq(parameters.buildPlatform, 'arm64') }}:
|
||||
# The ARM64 agents do not seem to have NuGet installed
|
||||
forceNugetInstallation: true
|
||||
|
||||
- powershell: |-
|
||||
$Package = 'Microsoft.Internal.Windows.Terminal.TestContent'
|
||||
|
||||
@@ -69,10 +69,3 @@ jobs:
|
||||
artifact: $(JobOutputArtifactName)
|
||||
displayName: 'Publish VPack Manifest to Drop'
|
||||
|
||||
- task: PkgESFCIBGit@12
|
||||
displayName: 'Submit VPack Manifest to Windows'
|
||||
inputs:
|
||||
configPath: '$(Build.SourcesDirectory)\build\config\GitCheckin.json'
|
||||
artifactsDirectory: $(XES_VPACKMANIFESTDIRECTORY)
|
||||
prTimeOut: 5
|
||||
|
||||
|
||||
@@ -49,6 +49,9 @@ parameters:
|
||||
- name: symbolExpiryTime
|
||||
type: string
|
||||
default: 36530 # This is the default from PublishSymbols@2
|
||||
- name: createVpack
|
||||
type: boolean
|
||||
default: false
|
||||
- name: publishVpackToWindows
|
||||
type: boolean
|
||||
default: false
|
||||
@@ -192,8 +195,8 @@ extends:
|
||||
ob_outputDirectory: $(JobOutputDirectory)
|
||||
ob_artifactBaseName: $(JobOutputArtifactName)
|
||||
### This job is also in charge of submitting the vpack to Windows if it's enabled
|
||||
ob_createvpack_enabled: ${{ and(parameters.buildTerminal, parameters.publishVpackToWindows) }}
|
||||
ob_updateOSManifest_enabled: ${{ and(parameters.buildTerminal, parameters.publishVpackToWindows) }}
|
||||
ob_createvpack_enabled: ${{ and(parameters.buildTerminal, parameters.createVpack) }}
|
||||
ob_updateOSManifest_enabled: ${{ and(parameters.buildTerminal, parameters.createVpack, parameters.publishVpackToWindows) }}
|
||||
### If enabled above, these options are in play.
|
||||
ob_createvpack_packagename: 'WindowsTerminal.app'
|
||||
ob_createvpack_owneralias: 'conhost@microsoft.com'
|
||||
@@ -207,6 +210,8 @@ extends:
|
||||
ob_createvpack_taskLogVerbosity: Detailed
|
||||
ob_createvpack_verbose: true
|
||||
ob_createvpack_vpackdirectory: '$(JobOutputDirectory)\vpack'
|
||||
ob_createvpack_versionAs: string
|
||||
ob_createvpack_version: '$(XES_PACKAGEVERSIONNUMBER)'
|
||||
ob_updateOSManifest_gitcheckinConfigPath: '$(Build.SourcesDirectory)\build\config\GitCheckin.json'
|
||||
# We're skipping the 'fetch' part of the OneBranch rules, but that doesn't mean
|
||||
# that it doesn't expect to have downloaded a manifest directly to some 'destination'
|
||||
@@ -229,7 +234,7 @@ extends:
|
||||
New-Item "$(JobOutputDirectory)/vpack" -Type Directory
|
||||
displayName: Make sure the vpack directory exists
|
||||
|
||||
- ${{ if parameters.publishVpackToWindows }}:
|
||||
- ${{ if parameters.createVpack }}:
|
||||
- pwsh: |-
|
||||
Copy-Item -Verbose -Path "$(MsixBundlePath)" -Destination (Join-Path "$(JobOutputDirectory)/vpack" 'Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle')
|
||||
displayName: Stage msixbundle for vpack
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
parameters:
|
||||
- name: forceNugetInstallation
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
steps:
|
||||
- ${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
|
||||
- ${{ if and(ne(parameters.forceNugetInstallation, true), eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564')) }}:
|
||||
- pwsh: |-
|
||||
Write-Host "Assuming NuGet is already installed..."
|
||||
& nuget.exe help
|
||||
@@ -7,6 +12,6 @@ steps:
|
||||
|
||||
- ${{ else }}:
|
||||
- task: NuGetToolInstaller@1
|
||||
displayName: Use NuGet 6.6.1
|
||||
displayName: Use NuGet 7.0.1
|
||||
inputs:
|
||||
versionSpec: 6.6.1
|
||||
versionSpec: 7.0.1
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<!-- Native packages -->
|
||||
<package id="Microsoft.Internal.PGO-Helpers.Cpp" version="0.2.34" targetFramework="native" />
|
||||
<package id="Microsoft.Taef" version="10.93.240607003" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.230207.1" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.Windows.Terminal.ThemeHelpers" version="0.7.230706001" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.250303.1" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.Windows.Terminal.ThemeHelpers" version="0.8.250811004" targetFramework="native" />
|
||||
<package id="Microsoft.VisualStudio.Setup.Configuration.Native" version="2.3.2262" targetFramework="native" developmentDependency="true" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.8.4" targetFramework="native" />
|
||||
<package id="Microsoft.Web.WebView2" version="1.0.1661.34" targetFramework="native" />
|
||||
|
||||
@@ -2302,8 +2302,15 @@
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "The ID of the command this keybinding should execute.",
|
||||
"type": "string"
|
||||
"description": "The ID of the command this keybinding should execute (or null to disable a default).",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"keys": {
|
||||
"description": "Defines the key combinations used to call the command. It must be composed of...\n -any number of modifiers (ctrl/alt/shift)\n -a non-modifier key",
|
||||
@@ -2459,6 +2466,7 @@
|
||||
"description": "Direct3D 11 provides a more performant and feature-rich experience, whereas Direct2D is more stable. The default option \"Automatic\" will pick the API that best fits your graphics hardware. If you experience significant issues, consider using Direct2D.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"automatic",
|
||||
"direct2d",
|
||||
"direct3d11"
|
||||
]
|
||||
@@ -2472,8 +2480,9 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.input.forceVT": {
|
||||
"description": "Force the terminal to use the legacy input encoding. Certain keys in some applications may stop working when enabling this setting.",
|
||||
"type": "boolean"
|
||||
"type": "boolean",
|
||||
"description": "[Deprecated] Replaced with the \"compatibility.input.forceVT\" profile setting.",
|
||||
"deprecated": true
|
||||
},
|
||||
"experimental.useBackgroundImageForWindow": {
|
||||
"default": false,
|
||||
@@ -2520,14 +2529,14 @@
|
||||
"type": "string"
|
||||
},
|
||||
"rowsToScroll": {
|
||||
"default": "system",
|
||||
"description": "This parameter once allowed you to override the systemwide \"choose how many lines to scroll at one time\" setting. It no longer does so. However, you can customize the number of lines to scroll in \"scrollUp\" and \"scrollDown\" bindings.",
|
||||
"maximum": 999,
|
||||
"minimum": 0,
|
||||
"type": [
|
||||
"integer",
|
||||
"string"
|
||||
],
|
||||
"description": "[Deprecated] This setting no longer has any effect. However, you can customize the number of lines to scroll using the \"rowsToScroll\" argument on the \"scrollUp\" and \"scrollDown\" actions.",
|
||||
"default": "system",
|
||||
"minimum": 0,
|
||||
"maximum": 999,
|
||||
"deprecated": true
|
||||
},
|
||||
"minimizeToNotificationArea": {
|
||||
@@ -2573,9 +2582,12 @@
|
||||
"$ref": "#/$defs/NewTabMenu"
|
||||
},
|
||||
"language": {
|
||||
"default": "",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"description": "Sets an override for the app's preferred language, expressed as a BCP-47 language tag like en-US.",
|
||||
"type": "string"
|
||||
"default": null
|
||||
},
|
||||
"theme": {
|
||||
"default": "dark",
|
||||
@@ -2639,19 +2651,19 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"useTabSwitcher": {
|
||||
"description": "[Deprecated] Replaced with the \"tabSwitcherMode\" setting.",
|
||||
"default": true,
|
||||
"description": "Deprecated. Please use \"tabSwitcherMode\" instead.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"mru",
|
||||
"inOrder",
|
||||
"disabled"
|
||||
],
|
||||
"type": "string"
|
||||
]
|
||||
}
|
||||
],
|
||||
"deprecated": true
|
||||
@@ -2708,12 +2720,12 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"acrylicOpacity": {
|
||||
"type": "number",
|
||||
"description": "[Deprecated] Replaced with the \"opacity\" setting.",
|
||||
"default": 0.5,
|
||||
"description": "[deprecated] Please use `opacity` instead.",
|
||||
"deprecated": true,
|
||||
"maximum": 1,
|
||||
"minimum": 0,
|
||||
"type": "number"
|
||||
"maximum": 1,
|
||||
"deprecated": true
|
||||
},
|
||||
"antialiasingMode": {
|
||||
"default": "grayscale",
|
||||
@@ -2739,6 +2751,11 @@
|
||||
"description": "When set to true, when opening a new tab or pane it will get reloaded environment variables.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"compatibility.input.forceVT": {
|
||||
"default": false,
|
||||
"description": "Force the terminal to use the legacy input encoding. Certain keys in some applications may stop working when enabling this setting.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"compatibility.allowDECRQCRA": {
|
||||
"default": false,
|
||||
"description": "When set to true, the terminal will support the DECRQCRA (Request Checksum of Rectangular Area) escape sequence.",
|
||||
@@ -2910,24 +2927,29 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.autoMarkPrompts": {
|
||||
"deprecated": true,
|
||||
"description": "This has been replaced by autoMarkPrompts in 1.21",
|
||||
"type": "boolean"
|
||||
"type": "boolean",
|
||||
"description": "[Deprecated] Replaced with the \"autoMarkPrompts\" setting.",
|
||||
"deprecated": true
|
||||
},
|
||||
"experimental.retroTerminalEffect": {
|
||||
"description": "When set to true, enable retro terminal effects. This is an experimental feature, and its continued existence is not guaranteed.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.showMarksOnScrollbar": {
|
||||
"deprecated": true,
|
||||
"description": "This has been replaced by showMarksOnScrollbar in 1.21",
|
||||
"type": "boolean"
|
||||
"type": "boolean",
|
||||
"description": "[Deprecated] Replaced with the \"showMarksOnScrollbar\" setting.",
|
||||
"deprecated": true
|
||||
},
|
||||
"showMarksOnScrollbar": {
|
||||
"default": false,
|
||||
"description": "When set to true, marks added to the buffer via the addMark action will appear on the scrollbar.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.rainbowSuggestions": {
|
||||
"type": "boolean",
|
||||
"description": "Enables displaying command suggestions in the terminal in RGB (all the colors of the rainbow!).",
|
||||
"default": false
|
||||
},
|
||||
"experimental.rightClickContextMenu": {
|
||||
"default": false,
|
||||
"description": "When true, right-click shows a context menu; otherwise, it pastes from the clipboard or copies selection.",
|
||||
@@ -2943,23 +2965,29 @@
|
||||
"type": "string"
|
||||
},
|
||||
"fontFace": {
|
||||
"default": "Cascadia Mono",
|
||||
"description": "[deprecated] Define 'face' within the 'font' object instead.",
|
||||
"type": "string",
|
||||
"description": "[Deprecated] Replaced with the \"face\" setting within the \"font\" object.",
|
||||
"default": "Cascadia Mono",
|
||||
"deprecated": true
|
||||
},
|
||||
"fontSize": {
|
||||
"default": 12,
|
||||
"description": "[deprecated] Define 'size' within the 'font' object instead.",
|
||||
"minimum": 1,
|
||||
"type": "number",
|
||||
"description": "[Deprecated] Replaced with the \"size\" setting within the \"font\" object.",
|
||||
"default": 12,
|
||||
"minimum": 1,
|
||||
"deprecated": true
|
||||
},
|
||||
"fontWeight": {
|
||||
"description": "[Deprecated] Replaced with the \"weight\" setting within the \"font\" object.",
|
||||
"default": "normal",
|
||||
"description": "[deprecated] Define 'weight' within the 'font' object instead.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer",
|
||||
"minimum": 100,
|
||||
"maximum": 990
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"thin",
|
||||
"extra-light",
|
||||
@@ -2972,13 +3000,7 @@
|
||||
"extra-bold",
|
||||
"black",
|
||||
"extra-black"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"maximum": 990,
|
||||
"minimum": 100,
|
||||
"type": "integer"
|
||||
]
|
||||
}
|
||||
],
|
||||
"deprecated": true
|
||||
@@ -3089,7 +3111,10 @@
|
||||
},
|
||||
"answerbackMessage": {
|
||||
"description": "The response that is sent when an ENQ control character is received.",
|
||||
"type": "string"
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"source": {
|
||||
"description": "Stores the name of the profile generator that originated this profile.",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.230207.1" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.250303.1" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.8.4" targetFramework="native" />
|
||||
<package id="Microsoft.Web.WebView2" version="1.0.1661.34" targetFramework="native" />
|
||||
</packages>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.230207.1" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.250303.1" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.8.4" targetFramework="native" />
|
||||
<package id="Microsoft.Web.WebView2" version="1.0.1661.34" targetFramework="native" />
|
||||
</packages>
|
||||
|
||||
@@ -942,12 +942,12 @@ void ROW::_resizeChars(uint16_t colEndDirty, uint16_t chBegDirty, size_t chEndDi
|
||||
}
|
||||
}
|
||||
|
||||
til::small_rle<TextAttribute, uint16_t, 1>& ROW::Attributes() noexcept
|
||||
RowAttributes& ROW::Attributes() noexcept
|
||||
{
|
||||
return _attr;
|
||||
}
|
||||
|
||||
const til::small_rle<TextAttribute, uint16_t, 1>& ROW::Attributes() const noexcept
|
||||
const RowAttributes& ROW::Attributes() const noexcept
|
||||
{
|
||||
return _attr;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
class ROW;
|
||||
class TextBuffer;
|
||||
|
||||
// Because MarkKind::Output gets set only on the actually written text,
|
||||
// most rows will end up having at least 2 runs: The start of the line
|
||||
// with MarkKind::Output and the rest of the line with MarkKind::None.
|
||||
using RowAttributes = til::small_rle<TextAttribute, uint16_t, 2>;
|
||||
|
||||
enum class DelimiterClass
|
||||
{
|
||||
ControlChar,
|
||||
@@ -149,8 +154,8 @@ public:
|
||||
void ReplaceText(RowWriteState& state);
|
||||
void CopyTextFrom(RowCopyTextFromState& state);
|
||||
|
||||
til::small_rle<TextAttribute, uint16_t, 1>& Attributes() noexcept;
|
||||
const til::small_rle<TextAttribute, uint16_t, 1>& Attributes() const noexcept;
|
||||
RowAttributes& Attributes() noexcept;
|
||||
const RowAttributes& Attributes() const noexcept;
|
||||
TextAttribute GetAttrByColumn(til::CoordType column) const;
|
||||
std::vector<uint16_t> GetHyperlinks() const;
|
||||
ImageSlice* SetImageSlice(ImageSlice::Pointer imageSlice) noexcept;
|
||||
@@ -298,7 +303,7 @@ private:
|
||||
std::span<uint16_t> _charOffsets;
|
||||
// _attr is a run-length-encoded vector of TextAttribute with a decompressed
|
||||
// length equal to _columnCount (= 1 TextAttribute per column).
|
||||
til::small_rle<TextAttribute, uint16_t, 1> _attr;
|
||||
RowAttributes _attr;
|
||||
// The width of the row in visual columns.
|
||||
uint16_t _columnCount = 0;
|
||||
// Stores double-width/height (DECSWL/DECDWL/DECDHL) attributes.
|
||||
|
||||
@@ -77,9 +77,6 @@
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj">
|
||||
<Project>{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalAzBridge\TerminalAzBridge.vcxproj">
|
||||
<Project>{067F0A06-FCB7-472C-96E9-B03B54E8E18D}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\ShellExtension\WindowsTerminalShellExt.vcxproj">
|
||||
<Project>{f2ed628a-db22-446f-a081-4cc845b51a2b}</Project>
|
||||
</ProjectReference>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<!-- TerminalCppWinrt is intentionally not set -->
|
||||
<TerminalMUX>true</TerminalMUX>
|
||||
<TerminalThemeHelpers>true</TerminalThemeHelpers>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(SolutionDir)\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
|
||||
@@ -548,7 +548,9 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (const auto& realArgs = args.ActionArgs().try_as<CopyTextArgs>())
|
||||
{
|
||||
const auto handled = _CopyText(realArgs.DismissSelection(), realArgs.SingleLine(), realArgs.WithControlSequences(), realArgs.CopyFormatting());
|
||||
const auto copyFormatting = realArgs.CopyFormatting();
|
||||
const auto format = copyFormatting ? copyFormatting.Value() : _settings.GlobalSettings().CopyFormatting();
|
||||
const auto handled = _CopyText(realArgs.DismissSelection(), realArgs.SingleLine(), realArgs.WithControlSequences(), format);
|
||||
args.Handled(handled);
|
||||
}
|
||||
}
|
||||
@@ -898,7 +900,10 @@ namespace winrt::TerminalApp::implementation
|
||||
co_return;
|
||||
}
|
||||
|
||||
// Hop to the BG thread
|
||||
// ShellExecuteExW may block, so do it on a background thread.
|
||||
//
|
||||
// NOTE: All remaining code of this function doesn't touch `this`, so we don't need weak/strong_ref.
|
||||
// NOTE NOTE: Don't touch `this` when you make changes here.
|
||||
co_await winrt::resume_background();
|
||||
|
||||
// This will get us the correct exe for dev/preview/release. If you
|
||||
@@ -1451,6 +1456,8 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
safe_void_coroutine TerminalPage::_doHandleSuggestions(SuggestionsArgs realArgs)
|
||||
{
|
||||
const auto weak = get_weak();
|
||||
const auto dispatcher = Dispatcher();
|
||||
const auto source = realArgs.Source();
|
||||
std::vector<Command> commandsCollection;
|
||||
Control::CommandHistoryContext context{ nullptr };
|
||||
@@ -1517,7 +1524,12 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
co_await wil::resume_foreground(Dispatcher());
|
||||
co_await wil::resume_foreground(dispatcher);
|
||||
const auto strong = weak.get();
|
||||
if (!strong)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
// Open the palette with all these commands in it.
|
||||
_OpenSuggestions(_GetActiveControl(),
|
||||
|
||||
@@ -135,15 +135,24 @@ namespace winrt::TerminalApp::implementation
|
||||
_isElevated = ::Microsoft::Console::Utils::IsRunningElevated();
|
||||
_canDragDrop = ::Microsoft::Console::Utils::CanUwpDragDrop();
|
||||
|
||||
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
|
||||
if (auto self{ weakSelf.get() })
|
||||
{
|
||||
self->ReloadSettings();
|
||||
}
|
||||
});
|
||||
_reloadSettings = std::make_shared<ThrottledFunc<>>(
|
||||
DispatcherQueue::GetForCurrentThread(),
|
||||
til::throttled_func_options{
|
||||
.delay = std::chrono::milliseconds{ 100 },
|
||||
.debounce = true,
|
||||
.trailing = true,
|
||||
},
|
||||
[weakSelf = get_weak()]() {
|
||||
if (auto self{ weakSelf.get() })
|
||||
{
|
||||
self->ReloadSettings();
|
||||
}
|
||||
});
|
||||
|
||||
_languageProfileNotifier = winrt::make_self<LanguageProfileNotifier>([this]() {
|
||||
_reloadSettings->Run();
|
||||
// TODO: This is really bad, because we reset any current user customizations.
|
||||
// See GH#11522.
|
||||
ReloadSettingsThrottled();
|
||||
});
|
||||
|
||||
// Do this here, rather than at the top of main. This will prevent us from
|
||||
@@ -323,7 +332,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
if (modifiedBasename == settingsBasename)
|
||||
{
|
||||
_reloadSettings->Run();
|
||||
ReloadSettingsThrottled();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -429,6 +438,11 @@ namespace winrt::TerminalApp::implementation
|
||||
SettingsChanged.raise(*this, *ev);
|
||||
}
|
||||
|
||||
void AppLogic::ReloadSettingsThrottled()
|
||||
{
|
||||
_reloadSettings->Run();
|
||||
}
|
||||
|
||||
// This is a continuation of AppLogic::Create() and includes the more expensive parts.
|
||||
void AppLogic::NotifyRootInitialized()
|
||||
{
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace winrt::TerminalApp::implementation
|
||||
bool IsRunningElevated() const noexcept;
|
||||
bool CanDragDrop() const noexcept;
|
||||
void ReloadSettings();
|
||||
void ReloadSettingsThrottled();
|
||||
void NotifyRootInitialized();
|
||||
|
||||
bool HasSettingsStartupActions() const noexcept;
|
||||
@@ -64,7 +65,7 @@ namespace winrt::TerminalApp::implementation
|
||||
bool _hasSettingsStartupActions{ false };
|
||||
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
|
||||
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _reloadSettings;
|
||||
std::shared_ptr<ThrottledFunc<>> _reloadSettings;
|
||||
|
||||
std::vector<Microsoft::Terminal::Settings::Model::SettingsLoadWarnings> _warnings{};
|
||||
|
||||
@@ -80,7 +81,6 @@ namespace winrt::TerminalApp::implementation
|
||||
[[nodiscard]] HRESULT _TryLoadSettings() noexcept;
|
||||
void _ProcessLazySettingsChanges();
|
||||
void _RegisterSettingsChange();
|
||||
safe_void_coroutine _DispatchReloadSettings();
|
||||
|
||||
void _setupFolderPathEnvVar();
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace TerminalApp
|
||||
Boolean HasSettingsStartupActions();
|
||||
|
||||
void ReloadSettings();
|
||||
void ReloadSettingsThrottled();
|
||||
Microsoft.Terminal.Settings.Model.CascadiaSettings Settings { get; };
|
||||
|
||||
TerminalWindow CreateNewWindow();
|
||||
|
||||
@@ -929,6 +929,17 @@ namespace winrt::TerminalApp::implementation
|
||||
void CommandPalette::_filterTextChanged(const IInspectable& /*sender*/,
|
||||
const Windows::UI::Xaml::RoutedEventArgs& /*args*/)
|
||||
{
|
||||
// GH#18737: Only respond to this change if we are visible:
|
||||
// _close calls _searchBox().Text(L"") to reset the search text, which lands us
|
||||
// in here after the command palette is dismissed. Since we have a code path here that
|
||||
// could potentially lead to an action being previewed (specifically if there is a
|
||||
// preview-able action as the first entry in the command list), that preview will
|
||||
// appear after the palette is dismissed without this check.
|
||||
if (Visibility() != Visibility::Visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// When we are executing the _SelectNextTab in the TabManagement.cpp, this method
|
||||
// is getting triggered because we set up the default value for that CommandPalette
|
||||
// with an empty string. Therefore, to avoid the reset of the index when executing
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
winrt::hstring Icon()
|
||||
{
|
||||
return _Command.IconPath();
|
||||
return _Command.Icon().Resolved();
|
||||
}
|
||||
|
||||
WINRT_PROPERTY(Microsoft::Terminal::Settings::Model::Command, Command, nullptr);
|
||||
|
||||
@@ -34,9 +34,15 @@ namespace winrt::Microsoft::TerminalApp::implementation
|
||||
// before actually starting the connection to the client app. This
|
||||
// will ensure both controls are initialized before the client app
|
||||
// is.
|
||||
const auto weak = get_weak();
|
||||
co_await winrt::resume_background();
|
||||
_pairedTap->_start.wait();
|
||||
const auto strong = weak.get();
|
||||
if (!strong)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
_pairedTap->_start.wait();
|
||||
_wrappedConnection.Start();
|
||||
}
|
||||
void WriteInput(const winrt::array_view<const char16_t> buffer)
|
||||
|
||||
@@ -19,41 +19,6 @@ DEFINE_PROPERTYKEY(PKEY_AppUserModel_DestListLogoUri, 0x9F4C2855, 0x9F79, 0x4B39
|
||||
{ 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 }, 29 \
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - This function guesses whether a string is a file path.
|
||||
static constexpr bool _isProbableFilePath(std::wstring_view path)
|
||||
{
|
||||
// "C:X", "C:\X", "\\?", "\\."
|
||||
// _this function rejects \??\ as a path_
|
||||
if (path.size() >= 3)
|
||||
{
|
||||
const auto firstColon{ path.find(L':') };
|
||||
if (firstColon == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto prefix{ path.substr(0, 2) };
|
||||
return prefix == LR"(//)" || prefix == LR"(\\)";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - DestListLogoUri cannot take paths that are separated by / unless they're URLs.
|
||||
// This function uses std::filesystem to normalize strings that appear to be file
|
||||
// paths to have the "correct" slash direction.
|
||||
static std::wstring _normalizeIconPath(std::wstring_view path)
|
||||
{
|
||||
const auto fullPath{ wil::ExpandEnvironmentStringsW<std::wstring>(path.data()) };
|
||||
if (_isProbableFilePath(fullPath))
|
||||
{
|
||||
std::filesystem::path asPath{ fullPath };
|
||||
return asPath.make_preferred().wstring();
|
||||
}
|
||||
return std::wstring{ fullPath };
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Updates the items of the Jumplist based on the given settings.
|
||||
// Arguments:
|
||||
@@ -78,6 +43,9 @@ safe_void_coroutine Jumplist::UpdateJumplist(const CascadiaSettings& settings) n
|
||||
// make sure to capture the settings _before_ the co_await
|
||||
const auto strongSettings = settings;
|
||||
|
||||
// Explorer APIs may block, so do it on a background thread.
|
||||
//
|
||||
// NOTE: Jumplist has no members, so we don't need to hold onto `this` here.
|
||||
co_await winrt::resume_background();
|
||||
|
||||
try
|
||||
@@ -124,7 +92,7 @@ void Jumplist::_updateProfiles(IObjectCollection* jumplistItems, winrt::Windows:
|
||||
auto args = fmt::format(FMT_COMPILE(L"-p {}"), to_hstring(profile.Guid()));
|
||||
|
||||
// Create the shell link object for the profile
|
||||
const auto normalizedIconPath{ _normalizeIconPath(profile.Icon()) };
|
||||
const auto normalizedIconPath{ profile.Icon().Resolved() };
|
||||
const auto shLink = _createShellLink(profile.Name(), normalizedIconPath, args);
|
||||
THROW_IF_FAILED(jumplistItems->AddObject(shLink.get()));
|
||||
}
|
||||
|
||||
@@ -35,17 +35,23 @@ namespace winrt::TerminalApp::implementation
|
||||
// (which should be the default, see:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-trackmouseevent#remarks)
|
||||
unsigned int hoverTimeoutMillis{ 400 };
|
||||
LOG_IF_WIN32_BOOL_FALSE(SystemParametersInfoW(SPI_GETMOUSEHOVERTIME, 0, &hoverTimeoutMillis, 0));
|
||||
const auto toolTipInterval = std::chrono::milliseconds(hoverTimeoutMillis);
|
||||
if (FAILED(SystemParametersInfoW(SPI_GETMOUSEHOVERTIME, 0, &hoverTimeoutMillis, 0)))
|
||||
{
|
||||
hoverTimeoutMillis = 400;
|
||||
}
|
||||
|
||||
// Create a ThrottledFunc for opening the tooltip after the hover
|
||||
// timeout. If we hover another button, we should make sure to call
|
||||
// Run() with the new button. Calling `_displayToolTip.Run(nullptr)`,
|
||||
// which will cause us to not display a tooltip, which is used when we
|
||||
// leave the control entirely.
|
||||
_displayToolTip = std::make_shared<ThrottledFuncTrailing<Controls::Button>>(
|
||||
_displayToolTip = std::make_shared<ThrottledFunc<Controls::Button>>(
|
||||
dispatcher,
|
||||
toolTipInterval,
|
||||
til::throttled_func_options{
|
||||
.delay = std::chrono::milliseconds{ hoverTimeoutMillis },
|
||||
.debounce = true,
|
||||
.trailing = true,
|
||||
},
|
||||
[weakThis = get_weak()](Controls::Button button) {
|
||||
// If we provide a button, then open the tooltip on that button.
|
||||
// We can "dismiss" this throttled func by calling it with null,
|
||||
@@ -83,6 +89,18 @@ namespace winrt::TerminalApp::implementation
|
||||
CloseClick.raise(*this, e);
|
||||
}
|
||||
|
||||
bool MinMaxCloseControl::Focused() const
|
||||
{
|
||||
return _focused;
|
||||
}
|
||||
|
||||
void MinMaxCloseControl::Focused(bool focused)
|
||||
{
|
||||
_focused = focused;
|
||||
|
||||
ReleaseButtons();
|
||||
}
|
||||
|
||||
void MinMaxCloseControl::SetWindowVisualState(WindowVisualState visualState)
|
||||
{
|
||||
// Look up the heights we should use for the caption buttons from our
|
||||
@@ -164,25 +182,25 @@ namespace winrt::TerminalApp::implementation
|
||||
// animate the fade in/out transition between colors.
|
||||
case CaptionButton::Minimize:
|
||||
VisualStateManager::GoToState(MinimizeButton(), L"PointerOver", true);
|
||||
VisualStateManager::GoToState(MaximizeButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(CloseButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(MaximizeButton(), _normalState(), true);
|
||||
VisualStateManager::GoToState(CloseButton(), _normalState(), true);
|
||||
|
||||
_displayToolTip->Run(MinimizeButton());
|
||||
closeToolTipForButton(MaximizeButton());
|
||||
closeToolTipForButton(CloseButton());
|
||||
break;
|
||||
case CaptionButton::Maximize:
|
||||
VisualStateManager::GoToState(MinimizeButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(MinimizeButton(), _normalState(), true);
|
||||
VisualStateManager::GoToState(MaximizeButton(), L"PointerOver", true);
|
||||
VisualStateManager::GoToState(CloseButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(CloseButton(), _normalState(), true);
|
||||
|
||||
closeToolTipForButton(MinimizeButton());
|
||||
_displayToolTip->Run(MaximizeButton());
|
||||
closeToolTipForButton(CloseButton());
|
||||
break;
|
||||
case CaptionButton::Close:
|
||||
VisualStateManager::GoToState(MinimizeButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(MaximizeButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(MinimizeButton(), _normalState(), true);
|
||||
VisualStateManager::GoToState(MaximizeButton(), _normalState(), true);
|
||||
VisualStateManager::GoToState(CloseButton(), L"PointerOver", true);
|
||||
|
||||
closeToolTipForButton(MinimizeButton());
|
||||
@@ -205,17 +223,17 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
case CaptionButton::Minimize:
|
||||
VisualStateManager::GoToState(MinimizeButton(), L"Pressed", true);
|
||||
VisualStateManager::GoToState(MaximizeButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(CloseButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(MaximizeButton(), _normalState(), true);
|
||||
VisualStateManager::GoToState(CloseButton(), _normalState(), true);
|
||||
break;
|
||||
case CaptionButton::Maximize:
|
||||
VisualStateManager::GoToState(MinimizeButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(MinimizeButton(), _normalState(), true);
|
||||
VisualStateManager::GoToState(MaximizeButton(), L"Pressed", true);
|
||||
VisualStateManager::GoToState(CloseButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(CloseButton(), _normalState(), true);
|
||||
break;
|
||||
case CaptionButton::Close:
|
||||
VisualStateManager::GoToState(MinimizeButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(MaximizeButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(MinimizeButton(), _normalState(), true);
|
||||
VisualStateManager::GoToState(MaximizeButton(), _normalState(), true);
|
||||
VisualStateManager::GoToState(CloseButton(), L"Pressed", true);
|
||||
break;
|
||||
}
|
||||
@@ -228,9 +246,9 @@ namespace winrt::TerminalApp::implementation
|
||||
void MinMaxCloseControl::ReleaseButtons()
|
||||
{
|
||||
_displayToolTip->Run(nullptr);
|
||||
VisualStateManager::GoToState(MinimizeButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(MaximizeButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(CloseButton(), L"Normal", true);
|
||||
VisualStateManager::GoToState(MinimizeButton(), _normalState(), true);
|
||||
VisualStateManager::GoToState(MaximizeButton(), _normalState(), true);
|
||||
VisualStateManager::GoToState(CloseButton(), _normalState(), true);
|
||||
|
||||
closeToolTipForButton(MinimizeButton());
|
||||
closeToolTipForButton(MaximizeButton());
|
||||
@@ -238,4 +256,11 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
_lastPressedButton = std::nullopt;
|
||||
}
|
||||
|
||||
const winrt::param::hstring& MinMaxCloseControl::_normalState() const
|
||||
{
|
||||
static const winrt::param::hstring normal = L"Normal";
|
||||
static const winrt::param::hstring unfocused = L"Unfocused";
|
||||
return (_focused ? normal : unfocused);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ namespace winrt::TerminalApp::implementation
|
||||
void PressButton(CaptionButton button);
|
||||
void ReleaseButtons();
|
||||
|
||||
bool Focused() const;
|
||||
void Focused(bool focused);
|
||||
|
||||
void _MinimizeClick(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
void _MaximizeClick(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
@@ -32,8 +35,12 @@ namespace winrt::TerminalApp::implementation
|
||||
til::typed_event<TerminalApp::MinMaxCloseControl, winrt::Windows::UI::Xaml::RoutedEventArgs> MaximizeClick;
|
||||
til::typed_event<TerminalApp::MinMaxCloseControl, winrt::Windows::UI::Xaml::RoutedEventArgs> CloseClick;
|
||||
|
||||
std::shared_ptr<ThrottledFuncTrailing<winrt::Windows::UI::Xaml::Controls::Button>> _displayToolTip{ nullptr };
|
||||
bool _focused{ false };
|
||||
std::shared_ptr<ThrottledFunc<winrt::Windows::UI::Xaml::Controls::Button>> _displayToolTip{ nullptr };
|
||||
std::optional<CaptionButton> _lastPressedButton{ std::nullopt };
|
||||
|
||||
private:
|
||||
const winrt::param::hstring& _normalState() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace TerminalApp
|
||||
void HoverButton(CaptionButton button);
|
||||
void PressButton(CaptionButton button);
|
||||
void ReleaseButtons();
|
||||
Boolean Focused { get; set; };
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<MinMaxCloseControl, Windows.UI.Xaml.RoutedEventArgs> MinimizeClick;
|
||||
event Windows.Foundation.TypedEventHandler<MinMaxCloseControl, Windows.UI.Xaml.RoutedEventArgs> MaximizeClick;
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
ResourceKey="SystemControlForegroundBaseHighBrush" />
|
||||
<StaticResource x:Key="CaptionButtonForegroundPressed"
|
||||
ResourceKey="SystemControlForegroundBaseHighBrush" />
|
||||
<StaticResource x:Key="CaptionButtonForegroundUnfocusedColor"
|
||||
ResourceKey="TextFillColorDisabled" />
|
||||
<SolidColorBrush x:Key="CaptionButtonForegroundUnfocused"
|
||||
Color="{ThemeResource CaptionButtonForegroundUnfocusedColor}" />
|
||||
<SolidColorBrush x:Key="CaptionButtonBackground"
|
||||
Color="Transparent" />
|
||||
<Color x:Key="CaptionButtonBackgroundColor">Transparent</Color>
|
||||
@@ -66,6 +70,10 @@
|
||||
ResourceKey="SystemControlForegroundBaseHighBrush" />
|
||||
<StaticResource x:Key="CaptionButtonForegroundPressed"
|
||||
ResourceKey="SystemControlForegroundBaseHighBrush" />
|
||||
<StaticResource x:Key="CaptionButtonForegroundUnfocusedColor"
|
||||
ResourceKey="TextFillColorDisabled" />
|
||||
<SolidColorBrush x:Key="CaptionButtonForegroundUnfocused"
|
||||
Color="{ThemeResource CaptionButtonForegroundUnfocusedColor}" />
|
||||
<SolidColorBrush x:Key="CaptionButtonBackground"
|
||||
Color="Transparent" />
|
||||
<Color x:Key="CaptionButtonBackgroundColor">Transparent</Color>
|
||||
@@ -103,6 +111,10 @@
|
||||
Color="{ThemeResource SystemColorHighlightTextColor}" />
|
||||
<SolidColorBrush x:Key="CaptionButtonForegroundPressed"
|
||||
Color="{ThemeResource SystemColorHighlightTextColor}" />
|
||||
<SolidColorBrush x:Key="CaptionButtonForegroundUnfocused"
|
||||
Color="{ThemeResource SystemColorButtonTextColor}" />
|
||||
<StaticResource x:Key="CaptionButtonForegroundUnfocusedColor"
|
||||
ResourceKey="SystemColorButtonTextColor" />
|
||||
<SolidColorBrush x:Key="CloseButtonBackgroundPointerOver"
|
||||
Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
<SolidColorBrush x:Key="CloseButtonForegroundPointerOver"
|
||||
@@ -189,6 +201,20 @@
|
||||
Duration="0:0:0.1" />
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
|
||||
<VisualTransition From="PointerOver"
|
||||
To="Unfocused">
|
||||
<Storyboard>
|
||||
<ColorAnimation Storyboard.TargetName="ButtonBaseElement"
|
||||
Storyboard.TargetProperty="(UIElement.Background).(SolidColorBrush.Color)"
|
||||
To="{ThemeResource CaptionButtonBackgroundColor}"
|
||||
Duration="0:0:0.15" />
|
||||
<ColorAnimation Storyboard.TargetName="ButtonIcon"
|
||||
Storyboard.TargetProperty="(UIElement.Foreground).(SolidColorBrush.Color)"
|
||||
To="{ThemeResource CaptionButtonForegroundUnfocusedColor}"
|
||||
Duration="0:0:0.1" />
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
</VisualStateGroup.Transitions>
|
||||
|
||||
<VisualState x:Name="Normal">
|
||||
@@ -198,6 +224,13 @@
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Unfocused">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBaseElement.Background" Value="{ThemeResource CaptionButtonBackground}" />
|
||||
<Setter Target="ButtonIcon.Foreground" Value="{ThemeResource CaptionButtonForegroundUnfocused}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="PointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBaseElement.Background" Value="{ThemeResource CaptionButtonBackgroundPointerOver}" />
|
||||
|
||||
@@ -1161,10 +1161,12 @@ void Pane::SetActive()
|
||||
// focused, else the profile of the last control to be focused
|
||||
Profile Pane::GetFocusedProfile()
|
||||
{
|
||||
auto lastFocused = GetActivePane();
|
||||
if (const auto& terminalPane{ lastFocused->_getTerminalContent() })
|
||||
if (auto lastFocused{ GetActivePane() })
|
||||
{
|
||||
return terminalPane.GetProfile();
|
||||
if (const auto& terminalPane{ lastFocused->_getTerminalContent() })
|
||||
{
|
||||
return terminalPane.GetProfile();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -44,10 +44,6 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
_args = { value.begin(), value.end() };
|
||||
_parseResult = _parsed.ParseArgs(_args);
|
||||
if (_parseResult == 0)
|
||||
{
|
||||
_parsed.ValidateStartupCommands();
|
||||
}
|
||||
}
|
||||
|
||||
winrt::com_array<winrt::hstring> CommandlineArgs::Commandline()
|
||||
|
||||
@@ -270,13 +270,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>Registerkarte kopieren</value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>Profil mit einem ungültigen "backgroundImage" gefunden. Dieses Profil hat standardmäßig kein Hintergrundbild. Stellen Sie sicher, dass beim Festlegen eines "backgroundImage" der Wert ein gültiger Dateipfad zu einem Bild ist.</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>Profil mit einem ungültigen "icon" gefunden. Dieses Profil hat standardmäßig kein Symbol. Stellen Sie sicher, dass beim Festlegen eines "icon" der Wert ein gültiger Dateipfad zu einem Bild ist.</value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>Mindestens eine in den Einstellungen angegebene Ressource (z. B. icon oder backgroundImage) wurde nicht gefunden.</value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>Beim Analysieren Ihrer Tastenzuordnungen wurden Warnungen gefunden:</value>
|
||||
|
||||
@@ -271,13 +271,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>Duplicate tab</value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>Found a profile with an invalid "backgroundImage". Defaulting that profile to have no background image. Make sure that when setting a "backgroundImage", the value is a valid file path to an image.</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>Found a profile with an invalid "icon". Defaulting that profile to have no icon. Make sure that when setting an "icon", the value is a valid file path to an image.</value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>One or more resources (such as icon or backgroundImage) specified in your settings could not be found.</value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>Warnings were found while parsing your keybindings:</value>
|
||||
|
||||
@@ -267,13 +267,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>Duplicar pestaña</value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>Se encontró un perfil con un "backgroundImage" no válido. Si se predetermina que ese perfil no tiene imagen de fondo. Asegúrese de que al establecer "backgroundImage", el valor sea una ruta de acceso de archivo válida a una imagen.</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>Se encontró un perfil con un "icon" no válido. Estableciendo ese perfil para no tener icono. Asegúrese de que, al establecer un "icon", el valor es una ruta de acceso de archivo válida a una imagen.</value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>No se encontraron uno o varios recursos (como icon o backgroundImage) especificados en la configuración.</value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>Se encontraron advertencias al analizar los enlaces de teclado:</value>
|
||||
|
||||
@@ -267,13 +267,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>Dupliquer l’onglet</value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>Profil détecté avec une "backgroundImage" non valide. Par défaut, ce profil ne possède pas d’image d’arrière-plan. Assurez-vous que lorsque vous définissez une "backgroundImage", la valeur est un chemin d’accès de fichier valide vers une image.</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>Profil détecté avec une "icon" non valide. Par défaut, ce profil ne possède pas d’icône. Assurez-vous que lorsque vous définissez une "icon", la valeur est un chemin d’accès de fichier valide vers une image.</value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>Une ou plusieurs ressources (telles que icon ou backgroundImage) spécifiées dans vos paramètres sont introuvables.</value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>Des avertissements ont été détectés lors de l’analyse de vos combinaisons de touches :</value>
|
||||
@@ -891,7 +887,7 @@
|
||||
<value>Déplacer l'onglet vers une nouvelle fenêtre </value>
|
||||
</data>
|
||||
<data name="RunAsAdminFlyout.Text" xml:space="preserve">
|
||||
<value>Exécuter en temps qu'administrateur (restreint)</value>
|
||||
<value>Exécuter en tant qu'administrateur (restreint)</value>
|
||||
<comment>This text is displayed on context menu for profile entries in add new tab button.</comment>
|
||||
</data>
|
||||
<data name="TerminalPage_PaneMovedAnnouncement_ExistingTab" xml:space="preserve">
|
||||
|
||||
@@ -267,13 +267,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>Duplica scheda</value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>È stato trovato un profilo con un "backgroundImage" non valido. Impostazione predefinita per il profilo non è disponibile un'immagine di sfondo. Accertarsi che quando si imposta un "backgroundImage", il valore è un percorso di file valido per un'immagine.</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>Trovato un profilo con "icon" non valida. Impostare il profilo senza icon. Assicurarsi che, quando si imposta una "icon", il valore abbia un percorso file valido per un'immagine.</value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>Impossibile trovare una o più risorse, ad esempio icon o backgroundImage, specificate nelle impostazioni.</value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>Sono stati trovati avvisi durante l'analisi delle associazioni di tasti:</value>
|
||||
|
||||
@@ -185,7 +185,7 @@
|
||||
<value>終了</value>
|
||||
</data>
|
||||
<data name="MultiplePanes" xml:space="preserve">
|
||||
<value>複数ウィンドウ</value>
|
||||
<value>複数ペイン</value>
|
||||
</data>
|
||||
<data name="TabCloseSubMenu" xml:space="preserve">
|
||||
<value>閉じる</value>
|
||||
@@ -203,13 +203,13 @@
|
||||
<value>タブを閉じる</value>
|
||||
</data>
|
||||
<data name="PaneClose" xml:space="preserve">
|
||||
<value>ウィンドウを閉じる</value>
|
||||
<value>ペインを閉じる</value>
|
||||
</data>
|
||||
<data name="SplitTabText" xml:space="preserve">
|
||||
<value>タブを分割</value>
|
||||
</data>
|
||||
<data name="SplitPaneText" xml:space="preserve">
|
||||
<value>ウィンドウを分割する</value>
|
||||
<value>ペインを分割する</value>
|
||||
</data>
|
||||
<data name="SplitPaneToolTipText" xml:space="preserve">
|
||||
<value>分割する方向を右クリック - 右/下/上/左</value>
|
||||
@@ -230,7 +230,7 @@
|
||||
<value>複製</value>
|
||||
</data>
|
||||
<data name="SwapPaneText" xml:space="preserve">
|
||||
<value>ウィンドウを入れ替える</value>
|
||||
<value>ペインを入れ替える</value>
|
||||
</data>
|
||||
<data name="SwapPaneDownText" xml:space="preserve">
|
||||
<value>下とペインを入れ替え</value>
|
||||
@@ -245,10 +245,10 @@
|
||||
<value>左とペインを入れ替え</value>
|
||||
</data>
|
||||
<data name="TogglePaneZoomText" xml:space="preserve">
|
||||
<value>ウィンドウのズームの切り替え</value>
|
||||
<value>ペインのズームの切り替え</value>
|
||||
</data>
|
||||
<data name="CloseOtherPanesText" xml:space="preserve">
|
||||
<value>他のウィンドウを閉じる</value>
|
||||
<value>他のペインを閉じる</value>
|
||||
</data>
|
||||
<data name="SearchWebText" xml:space="preserve">
|
||||
<value>Web 検索</value>
|
||||
@@ -268,13 +268,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>タブを複製する</value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>無効な "backgroundImage" を持つプロファイルが見つかりました。既定では、そのプロファイルに背景画像はありません。"backgroundImage" を設定するときに、値が画像への有効なファイル パスとなっていることをご確認ください。</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>無効な "icon" を持つプロファイルが見つかりました。既定では、そのプロファイルにアイコンはありません。"icon" を設定するときに、値が画像への有効なファイル パスとなっていることをご確認ください。</value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>設定で指定された 1 つ以上のリソース (icon や backgroundImage など) が見つかりませんでした。</value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>キー バインドの解析中に警告が検出されました:</value>
|
||||
@@ -321,7 +317,7 @@
|
||||
<value>同じ名前ですが大文字と小文字が異なる環境変数が複数見つかりました。使用される値は 1 つだけです。</value>
|
||||
</data>
|
||||
<data name="CmdCommandArgDesc" xml:space="preserve">
|
||||
<value>新しいタブまたはウィンドウで生成されるオプションのコマンドと引数</value>
|
||||
<value>新しいタブまたはペインで生成されるオプションのコマンドと引数</value>
|
||||
</data>
|
||||
<data name="SaveSnippetDesc" xml:space="preserve">
|
||||
<value>コマンド ラインを入力アクションとして保存する</value>
|
||||
@@ -349,17 +345,17 @@
|
||||
<value>指定されたインデックスのタブにフォーカスを移動する</value>
|
||||
</data>
|
||||
<data name="CmdMovePaneTabArgDesc" xml:space="preserve">
|
||||
<value>フォーカスされたウィンドウを指定されたインデックスのタブに移動する</value>
|
||||
<value>フォーカスされたペインを指定されたインデックスのタブに移動する</value>
|
||||
</data>
|
||||
<data name="CmdMovePaneDesc" xml:space="preserve">
|
||||
<value>フォーカスされたウィンドウを別のタブに移動する</value>
|
||||
<value>フォーカスされたペインを別のタブに移動する</value>
|
||||
</data>
|
||||
<data name="CmdMPDesc" xml:space="preserve">
|
||||
<value>"move-pane" サブコマンドのエイリアス。</value>
|
||||
<comment>{Locked="\"move-pane\""}</comment>
|
||||
</data>
|
||||
<data name="CmdSplitPaneSizeArgDesc" xml:space="preserve">
|
||||
<value>サイズを親ウィンドウに対する割合として指定します。有効な値は (0,1) の間で、排他的です。</value>
|
||||
<value>サイズを親ペインに対する割合として指定します。有効な値は (0,1) の間で、排他的です。</value>
|
||||
</data>
|
||||
<data name="CmdNewTabDesc" xml:space="preserve">
|
||||
<value>新しいタブの作成</value>
|
||||
@@ -369,14 +365,14 @@
|
||||
<comment>{Locked="\"new-tab\""}</comment>
|
||||
</data>
|
||||
<data name="CmdFocusPaneDesc" xml:space="preserve">
|
||||
<value>別のウィンドウにフォーカスを移動する</value>
|
||||
<value>別のペインにフォーカスを移動する</value>
|
||||
</data>
|
||||
<data name="CmdFPDesc" xml:space="preserve">
|
||||
<value>"focus-pane" サブコマンドのエイリアス。</value>
|
||||
<comment>{Locked="\"focus-pane\""}</comment>
|
||||
</data>
|
||||
<data name="CmdFocusPaneTargetArgDesc" xml:space="preserve">
|
||||
<value>指定されたインデックスのウィンドウをフォーカスする</value>
|
||||
<value>指定されたインデックスのペインをフォーカスする</value>
|
||||
</data>
|
||||
<data name="CmdProfileArgDesc" xml:space="preserve">
|
||||
<value>指定されたプロファイルで開きます。プロファイルの名前または GUID を指定できます</value>
|
||||
@@ -385,20 +381,20 @@
|
||||
<value>WT_SESSION 変数を設定します; GUID である必要があります</value>
|
||||
</data>
|
||||
<data name="CmdSplitPaneDesc" xml:space="preserve">
|
||||
<value>新しい分割ウィンドウの作成</value>
|
||||
<value>新しい分割ペインの作成</value>
|
||||
</data>
|
||||
<data name="CmdSPDesc" xml:space="preserve">
|
||||
<value>"split-pane" サブコマンドのエイリアス。</value>
|
||||
<comment>{Locked="\"split-pane\""}</comment>
|
||||
</data>
|
||||
<data name="CmdSplitPaneHorizontalArgDesc" xml:space="preserve">
|
||||
<value>新しいウィンドウを水平方向に分割して作成します ([-]と考えてください)</value>
|
||||
<value>新しいペインを水平方向に分割して作成します ([-]と考えてください)</value>
|
||||
</data>
|
||||
<data name="CmdSplitPaneVerticalArgDesc" xml:space="preserve">
|
||||
<value>新しいウィンドウを垂直方向に分割して作成します ([|]と考えてください)</value>
|
||||
<value>新しいペインを垂直方向に分割して作成します ([|]と考えてください)</value>
|
||||
</data>
|
||||
<data name="CmdSplitPaneDuplicateArgDesc" xml:space="preserve">
|
||||
<value>フォーカスされたウィンドウのプロファイルを複製して、新しいウィンドウを作成します</value>
|
||||
<value>フォーカスされたペインのプロファイルを複製して、新しいペインを作成します</value>
|
||||
</data>
|
||||
<data name="CmdStartingDirArgDesc" xml:space="preserve">
|
||||
<value>プロファイルの "startingDirectory" の設定ではなく、指定されたディレクトリで開きます</value>
|
||||
@@ -416,7 +412,7 @@
|
||||
<comment>{Locked="\"tabTitle\""}</comment>
|
||||
</data>
|
||||
<data name="CmdInheritEnvDesc" xml:space="preserve">
|
||||
<value>新しい環境ブロックを作成するのではなく、新しいタブまたはウィンドウを作成するときに、ターミナル独自の環境変数を継承します。これは、"command" が渡されたときに既定で設定されます。 </value>
|
||||
<value>新しい環境ブロックを作成するのではなく、新しいタブまたはペインを作成するときに、ターミナル独自の環境変数を継承します。これは、"command" が渡されたときに既定で設定されます。 </value>
|
||||
<comment>{Locked="\"command\""}</comment>
|
||||
</data>
|
||||
<data name="CmdColorSchemeArgDesc" xml:space="preserve">
|
||||
@@ -433,7 +429,7 @@
|
||||
<value>ウィンドウを全画面表示モードで起動する</value>
|
||||
</data>
|
||||
<data name="CmdMoveFocusDesc" xml:space="preserve">
|
||||
<value>指定した方向にある隣のウィンドウにフォーカスを移動する</value>
|
||||
<value>指定した方向にある隣のペインにフォーカスを移動する</value>
|
||||
</data>
|
||||
<data name="CmdMFDesc" xml:space="preserve">
|
||||
<value>"move-focus" サブコマンドのエイリアス。</value>
|
||||
@@ -443,10 +439,10 @@
|
||||
<value>フォーカスを移動する方向</value>
|
||||
</data>
|
||||
<data name="CmdSwapPaneDesc" xml:space="preserve">
|
||||
<value>フォーカスされたウィンドウを、指定された方向の隣接するウィンドウと入れ替える</value>
|
||||
<value>フォーカスされたペインを、指定された方向の隣接するペインと入れ替える</value>
|
||||
</data>
|
||||
<data name="CmdSwapPaneDirectionArgDesc" xml:space="preserve">
|
||||
<value>フォーカスされたウィンドウを移動する方向</value>
|
||||
<value>フォーカスされたペインを移動する方向</value>
|
||||
</data>
|
||||
<data name="CmdFocusDesc" xml:space="preserve">
|
||||
<value>ウィンドウをフォーカス モードで起動</value>
|
||||
@@ -861,7 +857,7 @@
|
||||
<value>設定ページを開きます</value>
|
||||
</data>
|
||||
<data name="SplitTabToolTip" xml:space="preserve">
|
||||
<value>現在のディレクトリのアクティブなプロファイルを使用して新しいウィンドウを開きます</value>
|
||||
<value>現在のディレクトリのアクティブなプロファイルを使用して新しいペインを開きます</value>
|
||||
</data>
|
||||
<data name="TabCloseAfterToolTip" xml:space="preserve">
|
||||
<value>このタブの右側にあるすべてのタブを閉じます</value>
|
||||
@@ -876,10 +872,10 @@
|
||||
<value>なし</value>
|
||||
</data>
|
||||
<data name="ClosePaneText" xml:space="preserve">
|
||||
<value>ウィンドウを閉じる</value>
|
||||
<value>ペインを閉じる</value>
|
||||
</data>
|
||||
<data name="ClosePaneToolTip" xml:space="preserve">
|
||||
<value>複数のウィンドウが存在する場合は、アクティブなウィンドウを閉じます</value>
|
||||
<value>複数のペインが存在する場合は、アクティブなペインを閉じます</value>
|
||||
</data>
|
||||
<data name="TabColorClearButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.FullDescription" xml:space="preserve">
|
||||
<value>タブの色をリセット</value>
|
||||
@@ -896,7 +892,7 @@
|
||||
<comment>This text is displayed on context menu for profile entries in add new tab button.</comment>
|
||||
</data>
|
||||
<data name="TerminalPage_PaneMovedAnnouncement_ExistingTab" xml:space="preserve">
|
||||
<value>アクティブなウィンドウを [{0}] タブに移動しました</value>
|
||||
<value>アクティブなペインを [{0}] タブに移動しました</value>
|
||||
<comment>{Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to.</comment>
|
||||
</data>
|
||||
<data name="TerminalPage_TabMovedAnnouncement_Default" xml:space="preserve">
|
||||
@@ -912,19 +908,19 @@
|
||||
<comment>{Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the new tab index in the tab row.</comment>
|
||||
</data>
|
||||
<data name="TerminalPage_PaneMovedAnnouncement_ExistingWindow" xml:space="preserve">
|
||||
<value>アクティブなウィンドウを "{1}" ウィンドウの [{0}] タブに移動しました</value>
|
||||
<value>アクティブなペインを "{1}" ウィンドウの [{0}] タブに移動しました</value>
|
||||
<comment>{Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. {1} is the name of the window the pane was moved to. Replaced in 1.19 by TerminalPage_PaneMovedAnnouncement_ExistingWindow2</comment>
|
||||
</data>
|
||||
<data name="TerminalPage_PaneMovedAnnouncement_ExistingWindow2" xml:space="preserve">
|
||||
<value>アクティブなウィンドウを "{0}" ウィンドウに移動しました</value>
|
||||
<value>アクティブなペインを "{0}" ウィンドウに移動しました</value>
|
||||
<comment>{Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the window the pane was moved to.</comment>
|
||||
</data>
|
||||
<data name="TerminalPage_PaneMovedAnnouncement_NewWindow" xml:space="preserve">
|
||||
<value>アクティブなウィンドウを新しいウィンドウに移動しました</value>
|
||||
<value>アクティブなペインを新しいウィンドウに移動しました</value>
|
||||
<comment>This text is read out by screen readers upon a successful pane movement to a new window.</comment>
|
||||
</data>
|
||||
<data name="TerminalPage_PaneMovedAnnouncement_NewTab" xml:space="preserve">
|
||||
<value>アクティブなウィンドウを新しいタブに移動しました</value>
|
||||
<value>アクティブなペインを新しいタブに移動しました</value>
|
||||
<comment>This text is read out by screen readers upon a successful pane movement to a new tab within the existing window.</comment>
|
||||
</data>
|
||||
<data name="CmdAppendCommandLineDesc" xml:space="preserve">
|
||||
@@ -934,7 +930,7 @@
|
||||
<value>接続の再起動</value>
|
||||
</data>
|
||||
<data name="RestartConnectionToolTip" xml:space="preserve">
|
||||
<value>アクティブウィンドウ接続を再起動します</value>
|
||||
<value>アクティブ ペイン接続を再起動します</value>
|
||||
</data>
|
||||
<data name="SnippetPaneTitle.Text" xml:space="preserve">
|
||||
<value>抜粋</value>
|
||||
@@ -965,10 +961,10 @@
|
||||
<value>操作の保存に失敗しました</value>
|
||||
</data>
|
||||
<data name="CloseSnippetsPaneButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>ウィンドウを閉じる</value>
|
||||
<value>ペインを閉じる</value>
|
||||
</data>
|
||||
<data name="CloseSnippetsPaneButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>ウィンドウを閉じる</value>
|
||||
<value>ペインを閉じる</value>
|
||||
</data>
|
||||
<data name="TabMoveLeft" xml:space="preserve">
|
||||
<value>左へ移動</value>
|
||||
|
||||
@@ -267,13 +267,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>탭 복제</value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>잘못된 "backgroundImage" 프로필을 찾았습니다. 해당 프로필을 배경 이미지가 없는 기본값으로 설정합니다. "backgroundImage"를 설정할 때 값이 이미지에 대한 유효한 파일 경로인지 확인합니다.</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>잘못된 "icon"이 있는 프로필을 발견했습니다. 해당 프로필에 아이콘이 없도록 기본값을 설정합니다. "icon" 설정 시 값이 이미지에 대한 올바른 파일 경로인지 확인합니다.</value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>설정에 지정된 하나 이상의 리소스(예: icon 또는 backgroundImage)를 찾을 수 없습니다.</value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>키 바인딩 구문을 분석하는 동안 경고를 발견했습니다.</value>
|
||||
|
||||
@@ -267,13 +267,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>Duplicar guia</value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>Foi encontrado um perfil com um "backgroundImage" inválido. O perfil deve ser o padrão para que não haja nenhuma imagem de tela de fundo. Certifique-se de que, ao definir um "backgroundImage", o valor é um caminho de arquivo válido para uma imagem.</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>Foi encontrado um perfil com um "icon" inválido. Padronize esse perfil para ele não ter ícone. Certifique-se de que, ao definir um "icon", o valor seja um caminho de arquivo válido para uma imagem.</value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>Um ou mais recursos (como icon ou backgroundImage) especificados em suas configurações não foram encontrados.</value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>Os avisos foram encontrados durante a análise das suas ligações de teclas:</value>
|
||||
|
||||
@@ -271,13 +271,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>Ďϋφľіčάтέ τàв !!! </value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>₣σúŋδ ą φѓοƒĩļé ẃϊţħ äй ïηνàĺìď "backgroundImage". Đēƒãųŀŧϊпğ ťнªт φѓőƒĭļè το нªνе πō ьąçќġгθúпδ ιмãġė. Маĸē śμѓē ŧћäţ ẁђēή šêťτϊлġ å "backgroundImage", ţĥě νаłųё ïŝ ά νάľîď ƒĩŀê φąťħ ţŏ άń ΐмąġė. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>₣ǿũиđ à рřöƒϊℓз ŵĩţн аñ įņνàŀїδ "icon". Ðěƒаúľτīŋğ ţħаτ ρřόƒìŀё тб ђâνє пǿ íčой. Мàĸë ŝùřë ŧĥаţ ωĥĕл ŝеτŧīлĝ ăй "icon", τħε νāłϋë ïŝ ă νàľīđ ƒïŀè рªтн ţő äи ïмäģё. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! </value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>Ωňę бг mθгě яėŝǿüґсėş (šυćн âş icon ōя backgroundImage) ŝрěçìƒįєð ίπ ýőūŕ ŝėтťīлġš ċòŭĺð йöŧ вέ ƒòúпď. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! </value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>Щαѓńΐňģš ώĕřе ƒбŭπδ ώħīļë рăяşìⁿġ ўσυŕ κёỳвĩиðīήġş: !!! !!! !!! !!! !!!</value>
|
||||
|
||||
@@ -271,13 +271,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>Ďϋφľіčάтέ τàв !!! </value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>₣σúŋδ ą φѓοƒĩļé ẃϊţħ äй ïηνàĺìď "backgroundImage". Đēƒãųŀŧϊпğ ťнªт φѓőƒĭļè το нªνе πō ьąçќġгθúпδ ιмãġė. Маĸē śμѓē ŧћäţ ẁђēή šêťτϊлġ å "backgroundImage", ţĥě νаłųё ïŝ ά νάľîď ƒĩŀê φąťħ ţŏ άń ΐмąġė. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>₣ǿũиđ à рřöƒϊℓз ŵĩţн аñ įņνàŀїδ "icon". Ðěƒаúľτīŋğ ţħаτ ρřόƒìŀё тб ђâνє пǿ íčой. Мàĸë ŝùřë ŧĥаţ ωĥĕл ŝеτŧīлĝ ăй "icon", τħε νāłϋë ïŝ ă νàľīđ ƒïŀè рªтн ţő äи ïмäģё. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! </value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>Ωňę бг mθгě яėŝǿüґсėş (šυćн âş icon ōя backgroundImage) ŝрěçìƒįєð ίπ ýőūŕ ŝėтťīлġš ċòŭĺð йöŧ вέ ƒòúпď. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! </value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>Щαѓńΐňģš ώĕřе ƒбŭπδ ώħīļë рăяşìⁿġ ўσυŕ κёỳвĩиðīήġş: !!! !!! !!! !!! !!!</value>
|
||||
|
||||
@@ -271,13 +271,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>Ďϋφľіčάтέ τàв !!! </value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>₣σúŋδ ą φѓοƒĩļé ẃϊţħ äй ïηνàĺìď "backgroundImage". Đēƒãųŀŧϊпğ ťнªт φѓőƒĭļè το нªνе πō ьąçќġгθúпδ ιмãġė. Маĸē śμѓē ŧћäţ ẁђēή šêťτϊлġ å "backgroundImage", ţĥě νаłųё ïŝ ά νάľîď ƒĩŀê φąťħ ţŏ άń ΐмąġė. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>₣ǿũиđ à рřöƒϊℓз ŵĩţн аñ įņνàŀїδ "icon". Ðěƒаúľτīŋğ ţħаτ ρřόƒìŀё тб ђâνє пǿ íčой. Мàĸë ŝùřë ŧĥаţ ωĥĕл ŝеτŧīлĝ ăй "icon", τħε νāłϋë ïŝ ă νàľīđ ƒïŀè рªтн ţő äи ïмäģё. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! </value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>Ωňę бг mθгě яėŝǿüґсėş (šυćн âş icon ōя backgroundImage) ŝрěçìƒįєð ίπ ýőūŕ ŝėтťīлġš ċòŭĺð йöŧ вέ ƒòúпď. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! </value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>Щαѓńΐňģš ώĕřе ƒбŭπδ ώħīļë рăяşìⁿġ ўσυŕ κёỳвĩиðīήġş: !!! !!! !!! !!! !!!</value>
|
||||
|
||||
@@ -267,13 +267,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>Дублировать вкладку</value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>Найден профиль с недопустимым объектом "backgroundImage". По умолчанию для этого профиля не используется фоновое изображение. Убедитесь, что значение, заданное для "backgroundImage", является допустимым путем файла к изображению.</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>Найден профиль с недопустимым объектом "icon". По умолчанию для этого профиля не используется значок. Убедитесь, что значение, заданное для "icon", является допустимым путем файла к изображению.</value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>Не удалось найти один или несколько ресурсов (icon или backgroundImage), указанных в параметрах.</value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>При анализе настраиваемых сочетаний клавиш найдены предупреждения:</value>
|
||||
|
||||
@@ -267,13 +267,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>复制标签页</value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>找到一个具有无效 "backgroundImage" 的配置文件。将该配置文件设置为默认设置为不包含背景图像。请确保在设置 "backgroundImage" 时,该值是指向图像的有效文件路径。</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>找到一个带有无效 "icon" 的配置文件。将该配置文件默认为无图标。确保设置 "icon" 时,该值是图像的有效文件路径。</value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>找不到设置中指定的一个或多个资源 (,如 icon 或 backgroundImage)。</value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>分析键绑定时发现警告:</value>
|
||||
|
||||
@@ -267,13 +267,9 @@
|
||||
<data name="DuplicateTabText" xml:space="preserve">
|
||||
<value>複製索引標籤</value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>找到具有無效 "backgroundImage" 的設定檔。將該設定檔的預設值設為沒有背景影像。請確定設定 "backgroundImage" 時,該值是影像的有效檔案路徑。</value>
|
||||
<comment>{Locked="\"backgroundImage\""}</comment>
|
||||
</data>
|
||||
<data name="InvalidIcon" xml:space="preserve">
|
||||
<value>已發現具有無效 "icon" 的設定檔。將該設定檔預設為無圖示。設定 "icon" 時,請確認值是有效的影像檔案路徑。</value>
|
||||
<comment>{Locked="\"icon\""} The word "icon" in quotes is locked, the word icon OUTSIDE of quotes should be localized.</comment>
|
||||
<data name="InvalidMediaResource" xml:space="preserve">
|
||||
<value>找不到一或多個資源 (,例如在您的設定中指定的 icon 或 backgroundImage)。</value>
|
||||
<comment>{Locked="icon","backgroundImage"} Indicates that something has gone wrong while reading a user's settings.</comment>
|
||||
</data>
|
||||
<data name="AtLeastOneKeybindingWarning" xml:space="preserve">
|
||||
<value>剖析金鑰繫結時發現警告:</value>
|
||||
|
||||
@@ -48,13 +48,22 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
_settings = settings;
|
||||
|
||||
const auto dispatcher = Dispatcher();
|
||||
const auto weak = get_weak();
|
||||
|
||||
// You'd think that `FilterToSendInput(queryString)` would work. It
|
||||
// doesn't! That uses the queryString as the current command the user
|
||||
// has typed, then relies on the suggestions UI to _also_ filter with that
|
||||
// string.
|
||||
|
||||
const auto tasks = co_await _settings.GlobalSettings().ActionMap().FilterToSnippets(winrt::hstring{}, winrt::hstring{}); // IVector<Model::Command>
|
||||
co_await wil::resume_foreground(Dispatcher());
|
||||
co_await wil::resume_foreground(dispatcher);
|
||||
|
||||
const auto strong = weak.get();
|
||||
if (!strong)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
_allTasks.Clear();
|
||||
for (const auto& t : tasks)
|
||||
|
||||
@@ -1035,27 +1035,48 @@ namespace winrt::TerminalApp::implementation
|
||||
void Tab::_AttachEventHandlersToContent(const uint32_t paneId, const TerminalApp::IPaneContent& content)
|
||||
{
|
||||
auto weakThis{ get_weak() };
|
||||
auto dispatcher = TabViewItem().Dispatcher();
|
||||
auto dispatcher = DispatcherQueue::GetForCurrentThread();
|
||||
ContentEventTokens events{};
|
||||
|
||||
auto throttledTitleChanged = std::make_shared<ThrottledFunc<>>(
|
||||
dispatcher,
|
||||
til::throttled_func_options{
|
||||
.delay = std::chrono::milliseconds{ 200 },
|
||||
.leading = true,
|
||||
.trailing = true,
|
||||
},
|
||||
[weakThis]() {
|
||||
if (const auto tab = weakThis.get())
|
||||
{
|
||||
tab->UpdateTitle();
|
||||
}
|
||||
});
|
||||
|
||||
events.TitleChanged = content.TitleChanged(
|
||||
winrt::auto_revoke,
|
||||
[dispatcher, weakThis](auto&&, auto&&) -> safe_void_coroutine {
|
||||
// The lambda lives in the `std::function`-style container owned by `control`. That is, when the
|
||||
// `control` gets destroyed the lambda struct also gets destroyed. In other words, we need to
|
||||
// copy `weakThis` onto the stack, because that's the only thing that gets captured in coroutines.
|
||||
// See: https://devblogs.microsoft.com/oldnewthing/20211103-00/?p=105870
|
||||
const auto weakThisCopy = weakThis;
|
||||
co_await wil::resume_foreground(dispatcher);
|
||||
// Check if Tab's lifetime has expired
|
||||
if (auto tab{ weakThisCopy.get() })
|
||||
[func = std::move(throttledTitleChanged)](auto&&, auto&&) {
|
||||
func->Run();
|
||||
});
|
||||
|
||||
auto throttledTaskbarProgressChanged = std::make_shared<ThrottledFunc<>>(
|
||||
dispatcher,
|
||||
til::throttled_func_options{
|
||||
.delay = std::chrono::milliseconds{ 200 },
|
||||
.trailing = true,
|
||||
},
|
||||
[weakThis]() {
|
||||
if (const auto tab = weakThis.get())
|
||||
{
|
||||
// The title of the control changed, but not necessarily the title of the tab.
|
||||
// Set the tab's text to the active panes' text.
|
||||
tab->UpdateTitle();
|
||||
tab->_UpdateProgressState();
|
||||
}
|
||||
});
|
||||
|
||||
events.TaskbarProgressChanged = content.TaskbarProgressChanged(
|
||||
winrt::auto_revoke,
|
||||
[func = std::move(throttledTaskbarProgressChanged)](auto&&, auto&&) {
|
||||
func->Run();
|
||||
});
|
||||
|
||||
events.TabColorChanged = content.TabColorChanged(
|
||||
winrt::auto_revoke,
|
||||
[dispatcher, weakThis](auto&&, auto&&) -> safe_void_coroutine {
|
||||
@@ -1071,18 +1092,6 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
});
|
||||
|
||||
events.TaskbarProgressChanged = content.TaskbarProgressChanged(
|
||||
winrt::auto_revoke,
|
||||
[dispatcher, weakThis](auto&&, auto&&) -> safe_void_coroutine {
|
||||
const auto weakThisCopy = weakThis;
|
||||
co_await wil::resume_foreground(dispatcher);
|
||||
// Check if Tab's lifetime has expired
|
||||
if (auto tab{ weakThisCopy.get() })
|
||||
{
|
||||
tab->_UpdateProgressState();
|
||||
}
|
||||
});
|
||||
|
||||
events.ConnectionStateChanged = content.ConnectionStateChanged(
|
||||
winrt::auto_revoke,
|
||||
[dispatcher, weakThis](auto&&, auto&&) -> safe_void_coroutine {
|
||||
@@ -2117,9 +2126,9 @@ namespace winrt::TerminalApp::implementation
|
||||
// - The value to populate in the title run of the tool tip
|
||||
winrt::hstring Tab::_CreateToolTipTitle()
|
||||
{
|
||||
if (const auto& control{ GetActiveTerminalControl() })
|
||||
if (const auto profile{ GetFocusedProfile() })
|
||||
{
|
||||
const auto profileName{ control.Settings().ProfileName() };
|
||||
const auto profileName{ profile.Name() };
|
||||
if (profileName != Title())
|
||||
{
|
||||
return winrt::hstring{ fmt::format(FMT_COMPILE(L"{}: {}"), profileName, Title()) };
|
||||
@@ -2408,7 +2417,7 @@ namespace winrt::TerminalApp::implementation
|
||||
const auto& currentDictionary = v.as<ResourceDictionary>();
|
||||
|
||||
// TabViewItem.Background
|
||||
currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackground"), deselectedTabBrush);
|
||||
currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackground"), selectedTabBrush);
|
||||
currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackgroundSelected"), selectedTabBrush);
|
||||
currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPointerOver"), isHighContrast ? fontBrush : hoverTabBrush);
|
||||
currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPressed"), selectedTabBrush);
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace TerminalApp
|
||||
UInt32 TabViewIndex;
|
||||
UInt32 TabViewNumTabs;
|
||||
|
||||
overridable void Focus(Windows.UI.Xaml.FocusState focusState);
|
||||
overridable void Shutdown();
|
||||
void Focus(Windows.UI.Xaml.FocusState focusState);
|
||||
void Shutdown();
|
||||
|
||||
void SetDispatch(ShortcutActionDispatch dispatch);
|
||||
}
|
||||
|
||||
@@ -157,12 +157,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// Set this tab's icon to the icon from the content
|
||||
_UpdateTabIcon(*newTabImpl);
|
||||
|
||||
// This is necessary, because WinUI does not have support for middle clicks.
|
||||
// Its Tapped event doesn't provide the information what button was used either.
|
||||
tabViewItem.PointerPressed({ this, &TerminalPage::_OnTabPointerPressed });
|
||||
tabViewItem.PointerReleased({ this, &TerminalPage::_OnTabPointerReleased });
|
||||
tabViewItem.PointerExited({ this, &TerminalPage::_OnTabPointerExited });
|
||||
tabViewItem.PointerEntered({ this, &TerminalPage::_OnTabPointerEntered });
|
||||
|
||||
// When the tab requests close, try to close it (prompt for approval, if required)
|
||||
newTabImpl->CloseRequested([weakTab, weakThis{ get_weak() }](auto&& /*s*/, auto&& /*e*/) {
|
||||
@@ -402,12 +397,18 @@ namespace winrt::TerminalApp::implementation
|
||||
// - tab: the tab to remove
|
||||
winrt::Windows::Foundation::IAsyncAction TerminalPage::_HandleCloseTabRequested(winrt::TerminalApp::Tab tab)
|
||||
{
|
||||
winrt::com_ptr<TerminalPage> strong;
|
||||
|
||||
if (tab.ReadOnly())
|
||||
{
|
||||
const auto weak = get_weak();
|
||||
|
||||
auto warningResult = co_await _ShowCloseReadOnlyDialog();
|
||||
|
||||
strong = weak.get();
|
||||
|
||||
// If the user didn't explicitly click on close tab - leave
|
||||
if (warningResult != ContentDialogResult::Primary)
|
||||
if (!strong || warningResult != ContentDialogResult::Primary)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
@@ -664,7 +665,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// Method Description:
|
||||
// - returns a tab corresponding to a view item. This might return null,
|
||||
// so make sure to check the result!
|
||||
winrt::TerminalApp::Tab TerminalPage::_GetTabByTabViewItem(const Microsoft::UI::Xaml::Controls::TabViewItem& tabViewItem) const noexcept
|
||||
winrt::TerminalApp::Tab TerminalPage::_GetTabByTabViewItem(const IInspectable& tabViewItem) const noexcept
|
||||
{
|
||||
uint32_t tabIndexFromControl{};
|
||||
const auto items{ _tabView.TabItems() };
|
||||
@@ -718,10 +719,14 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (pane->ContainsReadOnly())
|
||||
{
|
||||
const auto weak = get_weak();
|
||||
|
||||
auto warningResult = co_await _ShowCloseReadOnlyDialog();
|
||||
|
||||
const auto strong = weak.get();
|
||||
|
||||
// If the user didn't explicitly click on close tab - leave
|
||||
if (warningResult != ContentDialogResult::Primary)
|
||||
if (!strong || warningResult != ContentDialogResult::Primary)
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
@@ -779,9 +784,13 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
if (const auto pane{ activeTab->GetActivePane() })
|
||||
{
|
||||
const auto weak = get_weak();
|
||||
if (co_await _PaneConfirmCloseReadOnly(pane))
|
||||
{
|
||||
_HandleClosePaneRequested(pane);
|
||||
if (const auto strong = weak.get())
|
||||
{
|
||||
_HandleClosePaneRequested(pane);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -839,9 +848,22 @@ namespace winrt::TerminalApp::implementation
|
||||
// - tabs - tabs to remove
|
||||
safe_void_coroutine TerminalPage::_RemoveTabs(const std::vector<winrt::TerminalApp::Tab> tabs)
|
||||
{
|
||||
const auto weak = get_weak();
|
||||
|
||||
for (auto& tab : tabs)
|
||||
{
|
||||
co_await _HandleCloseTabRequested(tab);
|
||||
winrt::Windows::Foundation::IAsyncAction action{ nullptr };
|
||||
if (const auto strong = weak.get())
|
||||
{
|
||||
action = _HandleCloseTabRequested(tab);
|
||||
}
|
||||
|
||||
if (!action)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await action;
|
||||
}
|
||||
}
|
||||
// Method Description:
|
||||
@@ -876,60 +898,69 @@ namespace winrt::TerminalApp::implementation
|
||||
_UpdateTabView();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Additional responses to clicking on a TabView's item. Currently, just remove tab with middle click
|
||||
// Arguments:
|
||||
// - sender: the control that originated this event (TabViewItem)
|
||||
// - eventArgs: the event's constituent arguments
|
||||
void TerminalPage::_OnTabPointerPressed(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs)
|
||||
void TerminalPage::_OnTabPointerPressed(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& e)
|
||||
{
|
||||
if (eventArgs.GetCurrentPoint(nullptr).Properties().IsMiddleButtonPressed())
|
||||
if (!_tabItemMiddleClickHookEnabled || !e.GetCurrentPoint(nullptr).Properties().IsMiddleButtonPressed())
|
||||
{
|
||||
if (const auto tabViewItem{ sender.try_as<MUX::Controls::TabViewItem>() })
|
||||
{
|
||||
_tabPointerMiddleButtonPressed = tabViewItem.CapturePointer(eventArgs.Pointer());
|
||||
_tabPointerMiddleButtonExited = false;
|
||||
}
|
||||
eventArgs.Handled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto tabViewItem = sender.try_as<MUX::Controls::TabViewItem>();
|
||||
if (!tabViewItem || !tabViewItem.CapturePointer(e.Pointer()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_tabItemMiddleClickExited = false;
|
||||
|
||||
_tabItemMiddleClickPointerEntered = tabViewItem.PointerEntered(winrt::auto_revoke, [this](auto&&, auto&& e) {
|
||||
_tabItemMiddleClickExited = false;
|
||||
e.Handled(true);
|
||||
});
|
||||
_tabItemMiddleClickPointerExited = tabViewItem.PointerExited(winrt::auto_revoke, [this](auto&&, auto&& e) {
|
||||
_tabItemMiddleClickExited = true;
|
||||
e.Handled(true);
|
||||
});
|
||||
_tabItemMiddleClickPointerCaptureLost = tabViewItem.PointerCaptureLost(winrt::auto_revoke, [this](auto&& sender, auto&& e) {
|
||||
// The WinUI TabView calls CapturePointer() internally and it's not reference counted,
|
||||
// so when it calls ReleasePointerCapture() in its PointerReleased handler,
|
||||
// we get a PointerCaptureLost before we receive the PointerReleased event.
|
||||
// This makes typical handling of PointerReleased events on our side difficult.
|
||||
// Well, whatever, now we just hook PointerCaptureLost because we know WinUI will trigger it.
|
||||
|
||||
_tabItemMiddleClickPointerEntered.revoke();
|
||||
_tabItemMiddleClickPointerExited.revoke();
|
||||
_tabItemMiddleClickPointerCaptureLost.revoke();
|
||||
|
||||
if (!_tabItemMiddleClickExited && !e.GetCurrentPoint(nullptr).Properties().IsMiddleButtonPressed())
|
||||
{
|
||||
_OnTabPointerReleasedCloseTab(std::move(sender));
|
||||
}
|
||||
|
||||
e.Handled(true);
|
||||
});
|
||||
e.Handled(true);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Tracking pointer state for tab remove
|
||||
// Arguments:
|
||||
// - sender: the control that originated this event (TabViewItem)
|
||||
// - eventArgs: the event's constituent arguments
|
||||
void TerminalPage::_OnTabPointerReleased(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs)
|
||||
safe_void_coroutine TerminalPage::_OnTabPointerReleasedCloseTab(IInspectable sender)
|
||||
{
|
||||
if (_tabPointerMiddleButtonPressed && !eventArgs.GetCurrentPoint(nullptr).Properties().IsMiddleButtonPressed())
|
||||
// WinUI asynchronously updates its tab view items, so it may happen that we're given a
|
||||
// `TabViewItem` that still contains a `Tab` which has actually already been removed.
|
||||
// First we must yield once, to flush out whatever TabView is currently doing.
|
||||
const auto weak = get_weak();
|
||||
co_await wil::resume_foreground(Dispatcher());
|
||||
const auto strong = weak.get();
|
||||
if (!strong)
|
||||
{
|
||||
_tabPointerMiddleButtonPressed = false;
|
||||
if (auto tabViewItem{ sender.try_as<MUX::Controls::TabViewItem>() })
|
||||
{
|
||||
tabViewItem.ReleasePointerCapture(eventArgs.Pointer());
|
||||
if (!_tabPointerMiddleButtonExited)
|
||||
{
|
||||
_OnTabPointerReleasedCloseTab(std::move(tabViewItem));
|
||||
}
|
||||
}
|
||||
eventArgs.Handled(true);
|
||||
co_return;
|
||||
}
|
||||
}
|
||||
|
||||
safe_void_coroutine TerminalPage::_OnTabPointerReleasedCloseTab(winrt::Microsoft::UI::Xaml::Controls::TabViewItem sender)
|
||||
{
|
||||
const auto tab = _GetTabByTabViewItem(sender);
|
||||
if (!tab)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
// WinUI asynchronously updates its tab view items, so it may happen that we're given a
|
||||
// `TabViewItem` that still contains a `Tab` which has actually already been removed.
|
||||
// First we must yield once, to flush out whatever TabView is currently doing.
|
||||
const auto strong = get_strong();
|
||||
co_await wil::resume_foreground(Dispatcher());
|
||||
|
||||
// `tab.Shutdown()` in `_RemoveTab()` sets the content to null = This checks if the tab is closed.
|
||||
if (tab.Content())
|
||||
{
|
||||
@@ -937,34 +968,6 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Tracking pointer state for tab remove
|
||||
// Arguments:
|
||||
// - sender: the control that originated this event (TabViewItem)
|
||||
// - eventArgs: the event's constituent arguments
|
||||
void TerminalPage::_OnTabPointerEntered(const IInspectable& /*sender*/, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs)
|
||||
{
|
||||
if (eventArgs.GetCurrentPoint(nullptr).Properties().IsMiddleButtonPressed())
|
||||
{
|
||||
_tabPointerMiddleButtonExited = false;
|
||||
eventArgs.Handled(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Tracking pointer state for tab remove
|
||||
// Arguments:
|
||||
// - sender: the control that originated this event (TabViewItem)
|
||||
// - eventArgs: the event's constituent arguments
|
||||
void TerminalPage::_OnTabPointerExited(const IInspectable& /*sender*/, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs)
|
||||
{
|
||||
if (eventArgs.GetCurrentPoint(nullptr).Properties().IsMiddleButtonPressed())
|
||||
{
|
||||
_tabPointerMiddleButtonExited = true;
|
||||
eventArgs.Handled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_UpdatedSelectedTab(const winrt::TerminalApp::Tab& tab)
|
||||
{
|
||||
// Unfocus all the tabs.
|
||||
@@ -999,10 +1002,7 @@ namespace winrt::TerminalApp::implementation
|
||||
tab.TabViewItem().StartBringIntoView();
|
||||
|
||||
// Raise an event that our title changed
|
||||
if (_settings.GlobalSettings().ShowTitleInTitlebar())
|
||||
{
|
||||
TitleChanged.raise(*this, tab.Title());
|
||||
}
|
||||
TitleChanged.raise(*this, nullptr);
|
||||
|
||||
_updateThemeColors();
|
||||
|
||||
@@ -1012,6 +1012,8 @@ namespace winrt::TerminalApp::implementation
|
||||
auto profile = tabImpl->GetFocusedProfile();
|
||||
_UpdateBackground(profile);
|
||||
}
|
||||
|
||||
_adjustProcessPriorityThrottled->Run();
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
<TerminalCppWinrt>true</TerminalCppWinrt>
|
||||
<TerminalMUX>true</TerminalMUX>
|
||||
<TerminalWinGetInterop>true</TerminalWinGetInterop>
|
||||
<TerminalThemeHelpers>true</TerminalThemeHelpers>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
|
||||
@@ -173,9 +174,7 @@
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Toast.h" />
|
||||
<ClInclude Include="TerminalSettingsCache.h">
|
||||
<DependentUpon>TerminalSettingsCache.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TerminalSettingsCache.h" />
|
||||
<ClInclude Include="SuggestionsControl.h">
|
||||
<DependentUpon>SuggestionsControl.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
@@ -288,9 +287,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="Toast.cpp" />
|
||||
<ClCompile Include="TerminalSettingsCache.cpp">
|
||||
<DependentUpon>TerminalSettingsCache.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TerminalSettingsCache.cpp" />
|
||||
<ClCompile Include="SuggestionsControl.cpp">
|
||||
<DependentUpon>SuggestionsControl.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
@@ -365,7 +362,6 @@
|
||||
<DependentUpon>TaskPaneContent.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="TerminalSettingsCache.idl" />
|
||||
<Midl Include="MarkdownPaneContent.idl">
|
||||
<DependentUpon>MarkdownPaneContent.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
|
||||
@@ -90,7 +90,6 @@
|
||||
<Midl Include="TerminalWindow.idl" />
|
||||
<Midl Include="TaskbarState.idl" />
|
||||
<Midl Include="IPaneContent.idl" />
|
||||
<Midl Include="TerminalSettingsCache.idl" />
|
||||
<Midl Include="Monarch.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "TerminalPage.h"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
#include <TerminalThemeHelpers.h>
|
||||
#include <til/unicode.h>
|
||||
#include <Utils.h>
|
||||
#include <TerminalCore/ControlKeyStates.hpp>
|
||||
|
||||
@@ -17,6 +19,7 @@
|
||||
#include "SettingsPaneContent.h"
|
||||
#include "SnippetsPaneContent.h"
|
||||
#include "TabRowControl.h"
|
||||
#include "TerminalSettingsCache.h"
|
||||
#include "../../types/inc/ColorFix.hpp"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
@@ -56,6 +59,160 @@ namespace winrt
|
||||
using VirtualKeyModifiers = Windows::System::VirtualKeyModifiers;
|
||||
}
|
||||
|
||||
namespace clipboard
|
||||
{
|
||||
static SRWLOCK lock = SRWLOCK_INIT;
|
||||
|
||||
struct ClipboardHandle
|
||||
{
|
||||
explicit ClipboardHandle(bool open) :
|
||||
_open{ open }
|
||||
{
|
||||
}
|
||||
|
||||
~ClipboardHandle()
|
||||
{
|
||||
if (_open)
|
||||
{
|
||||
ReleaseSRWLockExclusive(&lock);
|
||||
CloseClipboard();
|
||||
}
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return _open;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _open = false;
|
||||
};
|
||||
|
||||
ClipboardHandle open(HWND hwnd)
|
||||
{
|
||||
// Turns out, OpenClipboard/CloseClipboard are not thread-safe whatsoever,
|
||||
// and on CloseClipboard, the GetClipboardData handle may get freed.
|
||||
// The problem is that WinUI also uses OpenClipboard (through WinRT which uses OLE),
|
||||
// and so even with this mutex we can still crash randomly if you copy something via WinUI.
|
||||
// Makes you wonder how many Windows apps are subtly broken, huh.
|
||||
AcquireSRWLockExclusive(&lock);
|
||||
|
||||
bool success = false;
|
||||
|
||||
// OpenClipboard may fail to acquire the internal lock --> retry.
|
||||
for (DWORD sleep = 10;; sleep *= 2)
|
||||
{
|
||||
if (OpenClipboard(hwnd))
|
||||
{
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
// 10 iterations
|
||||
if (sleep > 10000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Sleep(sleep);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
ReleaseSRWLockExclusive(&lock);
|
||||
}
|
||||
|
||||
return ClipboardHandle{ success };
|
||||
}
|
||||
|
||||
void write(wil::zwstring_view text, std::string_view html, std::string_view rtf)
|
||||
{
|
||||
static const auto regular = [](const UINT format, const void* src, const size_t bytes) {
|
||||
wil::unique_hglobal handle{ THROW_LAST_ERROR_IF_NULL(GlobalAlloc(GMEM_MOVEABLE, bytes)) };
|
||||
|
||||
const auto locked = GlobalLock(handle.get());
|
||||
memcpy(locked, src, bytes);
|
||||
GlobalUnlock(handle.get());
|
||||
|
||||
THROW_LAST_ERROR_IF_NULL(SetClipboardData(format, handle.get()));
|
||||
handle.release();
|
||||
};
|
||||
static const auto registered = [](const wchar_t* format, const void* src, size_t bytes) {
|
||||
const auto id = RegisterClipboardFormatW(format);
|
||||
if (!id)
|
||||
{
|
||||
LOG_LAST_ERROR();
|
||||
return;
|
||||
}
|
||||
regular(id, src, bytes);
|
||||
};
|
||||
|
||||
EmptyClipboard();
|
||||
|
||||
if (!text.empty())
|
||||
{
|
||||
// As per: https://learn.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats
|
||||
// CF_UNICODETEXT: [...] A null character signals the end of the data.
|
||||
// --> We add +1 to the length. This works because .c_str() is null-terminated.
|
||||
regular(CF_UNICODETEXT, text.c_str(), (text.size() + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
if (!html.empty())
|
||||
{
|
||||
registered(L"HTML Format", html.data(), html.size());
|
||||
}
|
||||
|
||||
if (!rtf.empty())
|
||||
{
|
||||
registered(L"Rich Text Format", rtf.data(), rtf.size());
|
||||
}
|
||||
}
|
||||
|
||||
winrt::hstring read()
|
||||
{
|
||||
// This handles most cases of pasting text as the OS converts most formats to CF_UNICODETEXT automatically.
|
||||
if (const auto handle = GetClipboardData(CF_UNICODETEXT))
|
||||
{
|
||||
const wil::unique_hglobal_locked lock{ handle };
|
||||
const auto str = static_cast<const wchar_t*>(lock.get());
|
||||
if (!str)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto maxLen = GlobalSize(handle) / sizeof(wchar_t);
|
||||
const auto len = wcsnlen(str, maxLen);
|
||||
return winrt::hstring{ str, gsl::narrow_cast<uint32_t>(len) };
|
||||
}
|
||||
|
||||
// We get CF_HDROP when a user copied a file with Ctrl+C in Explorer and pastes that into the terminal (among others).
|
||||
if (const auto handle = GetClipboardData(CF_HDROP))
|
||||
{
|
||||
const wil::unique_hglobal_locked lock{ handle };
|
||||
const auto drop = static_cast<HDROP>(lock.get());
|
||||
if (!drop)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto cap = DragQueryFileW(drop, 0, nullptr, 0);
|
||||
if (cap == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto buffer = winrt::impl::hstring_builder{ cap };
|
||||
const auto len = DragQueryFileW(drop, 0, buffer.data(), cap + 1);
|
||||
if (len == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return buffer.to_hstring();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
} // namespace clipboard
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
TerminalPage::TerminalPage(TerminalApp::WindowProperties properties, const TerminalApp::ContentManager& manager) :
|
||||
@@ -102,6 +259,17 @@ namespace winrt::TerminalApp::implementation
|
||||
// before restoring previous tabs in that scenario.
|
||||
}
|
||||
}
|
||||
|
||||
_adjustProcessPriorityThrottled = std::make_shared<ThrottledFunc<>>(
|
||||
DispatcherQueue::GetForCurrentThread(),
|
||||
til::throttled_func_options{
|
||||
.delay = std::chrono::milliseconds{ 100 },
|
||||
.debounce = true,
|
||||
.trailing = true,
|
||||
},
|
||||
[=]() {
|
||||
_adjustProcessPriority();
|
||||
});
|
||||
_hostingHwnd = hwnd;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -113,7 +281,7 @@ namespace winrt::TerminalApp::implementation
|
||||
if (_settings == nullptr)
|
||||
{
|
||||
// Create this only on the first time we load the settings.
|
||||
_terminalSettingsCache = TerminalApp::TerminalSettingsCache{ settings, *_bindings };
|
||||
_terminalSettingsCache = std::make_shared<TerminalSettingsCache>(settings, *_bindings);
|
||||
}
|
||||
_settings = settings;
|
||||
|
||||
@@ -216,6 +384,8 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
const auto visibility = theme.Tab() ? theme.Tab().ShowCloseButton() : Settings::Model::TabCloseButtonVisibility::Always;
|
||||
|
||||
_tabItemMiddleClickHookEnabled = visibility == Settings::Model::TabCloseButtonVisibility::Never;
|
||||
|
||||
switch (visibility)
|
||||
{
|
||||
case Settings::Model::TabCloseButtonVisibility::Never:
|
||||
@@ -545,22 +715,32 @@ namespace winrt::TerminalApp::implementation
|
||||
_WindowProperties.VirtualEnvVars(env);
|
||||
}
|
||||
|
||||
// The current TerminalWindow & TerminalPage architecture is rather instable
|
||||
// and fails to start up if the first tab isn't created synchronously.
|
||||
//
|
||||
// While that's a fair assumption in on itself, simultaneously WinUI will
|
||||
// not assign tab contents a size if they're not shown at least once,
|
||||
// which we need however in order to initialize ControlCore with a size.
|
||||
//
|
||||
// So, we do two things here:
|
||||
// * DO NOT suspend if this is the first tab.
|
||||
// * DO suspend between the creation of panes (or tabs) in order to allow
|
||||
// WinUI to layout the new controls and for ControlCore to get a size.
|
||||
//
|
||||
// This same logic is also applied to CreateTabFromConnection.
|
||||
//
|
||||
// See GH#13136.
|
||||
auto suspend = _tabs.Size() > 0;
|
||||
|
||||
for (size_t i = 0; i < actions.size(); ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
if (suspend)
|
||||
{
|
||||
// Each action may rely on the XAML layout of a preceding action.
|
||||
// Most importantly, this is the case for the combination of NewTab + SplitPane,
|
||||
// as the former appears to only have a layout size after at least 1 resume_foreground,
|
||||
// while the latter relies on that information. This is also why it uses Low priority.
|
||||
//
|
||||
// Curiously, this does not seem to be required when using startupActions, but only when
|
||||
// tearing out a tab (this currently creates a new window with injected startup actions).
|
||||
// This indicates that this is really more of an architectural issue and not a fundamental one.
|
||||
co_await wil::resume_foreground(Dispatcher(), CoreDispatcherPriority::Low);
|
||||
}
|
||||
|
||||
_actionDispatch->DoAction(actions[i]);
|
||||
suspend = true;
|
||||
}
|
||||
|
||||
// GH#6586: now that we're done processing all startup commands,
|
||||
@@ -575,8 +755,16 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::CreateTabFromConnection(ITerminalConnection connection)
|
||||
safe_void_coroutine TerminalPage::CreateTabFromConnection(ITerminalConnection connection)
|
||||
{
|
||||
const auto strong = get_strong();
|
||||
|
||||
// This is the exact same logic as in ProcessStartupActions.
|
||||
if (_tabs.Size() > 0)
|
||||
{
|
||||
co_await wil::resume_foreground(Dispatcher(), CoreDispatcherPriority::Low);
|
||||
}
|
||||
|
||||
NewTerminalArgs newTerminalArgs;
|
||||
|
||||
if (const auto conpty = connection.try_as<ConptyConnection>())
|
||||
@@ -591,6 +779,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// 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);
|
||||
|
||||
const auto newPane = _MakePane(newTerminalArgs, nullptr, std::move(connection));
|
||||
newPane->WalkTree([](const auto& pane) {
|
||||
pane->FinalizeConfigurationGivenDefault();
|
||||
@@ -923,7 +1112,7 @@ namespace winrt::TerminalApp::implementation
|
||||
auto folderEntryItems = _CreateNewTabFlyoutItems(folderEntries);
|
||||
|
||||
// If the folder should auto-inline and there is only one item, do so.
|
||||
if (folderEntry.Inlining() == FolderEntryInlining::Auto && folderEntries.Size() == 1)
|
||||
if (folderEntry.Inlining() == FolderEntryInlining::Auto && folderEntryItems.size() == 1)
|
||||
{
|
||||
for (auto const& folderEntryItem : folderEntryItems)
|
||||
{
|
||||
@@ -937,7 +1126,7 @@ namespace winrt::TerminalApp::implementation
|
||||
auto folderItem = WUX::Controls::MenuFlyoutSubItem{};
|
||||
folderItem.Text(folderEntry.Name());
|
||||
|
||||
auto icon = _CreateNewTabFlyoutIcon(folderEntry.Icon());
|
||||
auto icon = _CreateNewTabFlyoutIcon(folderEntry.Icon().Resolved());
|
||||
folderItem.Icon(icon);
|
||||
|
||||
for (const auto& folderEntryItem : folderEntryItems)
|
||||
@@ -987,7 +1176,7 @@ namespace winrt::TerminalApp::implementation
|
||||
break;
|
||||
}
|
||||
|
||||
auto profileItem = _CreateNewTabFlyoutProfile(profileEntry.Profile(), profileEntry.ProfileIndex(), profileEntry.Icon());
|
||||
auto profileItem = _CreateNewTabFlyoutProfile(profileEntry.Profile(), profileEntry.ProfileIndex(), profileEntry.Icon().Resolved());
|
||||
items.push_back(profileItem);
|
||||
break;
|
||||
}
|
||||
@@ -997,7 +1186,7 @@ namespace winrt::TerminalApp::implementation
|
||||
const auto actionId = actionEntry.ActionId();
|
||||
if (_settings.ActionMap().GetActionByID(actionId))
|
||||
{
|
||||
auto actionItem = _CreateNewTabFlyoutAction(actionId, actionEntry.Icon());
|
||||
auto actionItem = _CreateNewTabFlyoutAction(actionId, actionEntry.Icon().Resolved());
|
||||
items.push_back(actionItem);
|
||||
}
|
||||
|
||||
@@ -1036,7 +1225,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// If a custom icon path has been specified, set it as the icon for
|
||||
// this flyout item. Otherwise, if an icon is set for this profile, set that icon
|
||||
// for this flyout item.
|
||||
const auto& iconPath = iconPathOverride.empty() ? profile.EvaluatedIcon() : iconPathOverride;
|
||||
const auto& iconPath = iconPathOverride.empty() ? profile.Icon().Resolved() : iconPathOverride;
|
||||
if (!iconPath.empty())
|
||||
{
|
||||
const auto icon = _CreateNewTabFlyoutIcon(iconPath);
|
||||
@@ -1122,7 +1311,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// If a custom icon path has been specified, set it as the icon for
|
||||
// this flyout item. Otherwise, if an icon is set for this action, set that icon
|
||||
// for this flyout item.
|
||||
const auto& iconPath = iconPathOverride.empty() ? action.IconPath() : iconPathOverride;
|
||||
const auto& iconPath = iconPathOverride.empty() ? action.Icon().Resolved() : iconPathOverride;
|
||||
if (!iconPath.empty())
|
||||
{
|
||||
const auto icon = _CreateNewTabFlyoutIcon(iconPath);
|
||||
@@ -1301,18 +1490,8 @@ namespace winrt::TerminalApp::implementation
|
||||
if (connectionType == TerminalConnection::AzureConnection::ConnectionType() &&
|
||||
TerminalConnection::AzureConnection::IsAzureConnectionAvailable())
|
||||
{
|
||||
std::filesystem::path azBridgePath{ wil::GetModuleFileNameW<std::wstring>(nullptr) };
|
||||
azBridgePath.replace_filename(L"TerminalAzBridge.exe");
|
||||
if constexpr (Feature_AzureConnectionInProc::IsEnabled())
|
||||
{
|
||||
connection = TerminalConnection::AzureConnection{};
|
||||
}
|
||||
else
|
||||
{
|
||||
connection = TerminalConnection::ConptyConnection{};
|
||||
}
|
||||
|
||||
valueSet = TerminalConnection::ConptyConnection::CreateSettings(azBridgePath.native(),
|
||||
connection = TerminalConnection::AzureConnection{};
|
||||
valueSet = TerminalConnection::ConptyConnection::CreateSettings(winrt::hstring{},
|
||||
L".",
|
||||
L"Azure",
|
||||
false,
|
||||
@@ -1757,11 +1936,9 @@ namespace winrt::TerminalApp::implementation
|
||||
// - tab: the Tab to update the title for.
|
||||
void TerminalPage::_UpdateTitle(const Tab& tab)
|
||||
{
|
||||
auto newTabTitle = tab.Title();
|
||||
|
||||
if (tab == _GetFocusedTab())
|
||||
{
|
||||
TitleChanged.raise(*this, newTabTitle);
|
||||
TitleChanged.raise(*this, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1776,7 +1953,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
term.RaiseNotice({ this, &TerminalPage::_ControlNoticeRaisedHandler });
|
||||
|
||||
// Add an event handler when the terminal wants to paste data from the Clipboard.
|
||||
term.WriteToClipboard({ get_weak(), &TerminalPage::_copyToClipboard });
|
||||
term.PasteFromClipboard({ this, &TerminalPage::_PasteFromClipboardHandler });
|
||||
|
||||
term.OpenHyperlink({ this, &TerminalPage::_OpenHyperlinkHandler });
|
||||
@@ -1798,9 +1975,7 @@ namespace winrt::TerminalApp::implementation
|
||||
});
|
||||
|
||||
term.ShowWindowChanged({ get_weak(), &TerminalPage::_ShowWindowChangedHandler });
|
||||
|
||||
term.SearchMissingCommand({ get_weak(), &TerminalPage::_SearchMissingCommandHandler });
|
||||
|
||||
term.WindowSizeChanged({ get_weak(), &TerminalPage::_WindowSizeChanged });
|
||||
|
||||
// Don't even register for the event if the feature is compiled off.
|
||||
@@ -1946,7 +2121,7 @@ namespace winrt::TerminalApp::implementation
|
||||
return false;
|
||||
}
|
||||
|
||||
TermControl TerminalPage::_GetActiveControl()
|
||||
TermControl TerminalPage::_GetActiveControl() const
|
||||
{
|
||||
if (const auto tabImpl{ _GetFocusedTabImpl() })
|
||||
{
|
||||
@@ -2031,7 +2206,15 @@ namespace winrt::TerminalApp::implementation
|
||||
if (!_displayingCloseDialog)
|
||||
{
|
||||
_displayingCloseDialog = true;
|
||||
|
||||
const auto weak = get_weak();
|
||||
auto warningResult = co_await _ShowQuitDialog();
|
||||
const auto strong = weak.get();
|
||||
if (!strong)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
_displayingCloseDialog = false;
|
||||
|
||||
if (warningResult != ContentDialogResult::Primary)
|
||||
@@ -2407,6 +2590,8 @@ namespace winrt::TerminalApp::implementation
|
||||
auto profile = tab->GetFocusedProfile();
|
||||
_UpdateBackground(profile);
|
||||
}
|
||||
|
||||
_adjustProcessPriorityThrottled->Run();
|
||||
}
|
||||
|
||||
uint32_t TerminalPage::NumberOfTabs() const
|
||||
@@ -2625,17 +2810,9 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (_settings.GlobalSettings().ShowTitleInTitlebar())
|
||||
{
|
||||
auto selectedIndex = _tabView.SelectedIndex();
|
||||
if (selectedIndex >= 0)
|
||||
if (const auto tab{ _GetFocusedTab() })
|
||||
{
|
||||
try
|
||||
{
|
||||
if (auto focusedControl{ _GetActiveControl() })
|
||||
{
|
||||
return focusedControl.Title();
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
return tab.Title();
|
||||
}
|
||||
}
|
||||
return { L"Terminal" };
|
||||
@@ -2730,75 +2907,6 @@ namespace winrt::TerminalApp::implementation
|
||||
return dimension;
|
||||
}
|
||||
|
||||
static wil::unique_close_clipboard_call _openClipboard(HWND hwnd)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
// OpenClipboard may fail to acquire the internal lock --> retry.
|
||||
for (DWORD sleep = 10;; sleep *= 2)
|
||||
{
|
||||
if (OpenClipboard(hwnd))
|
||||
{
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
// 10 iterations
|
||||
if (sleep > 10000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Sleep(sleep);
|
||||
}
|
||||
|
||||
return wil::unique_close_clipboard_call{ success };
|
||||
}
|
||||
|
||||
static winrt::hstring _extractClipboard()
|
||||
{
|
||||
// This handles most cases of pasting text as the OS converts most formats to CF_UNICODETEXT automatically.
|
||||
if (const auto handle = GetClipboardData(CF_UNICODETEXT))
|
||||
{
|
||||
const wil::unique_hglobal_locked lock{ handle };
|
||||
const auto str = static_cast<const wchar_t*>(lock.get());
|
||||
if (!str)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto maxLen = GlobalSize(handle) / sizeof(wchar_t);
|
||||
const auto len = wcsnlen(str, maxLen);
|
||||
return winrt::hstring{ str, gsl::narrow_cast<uint32_t>(len) };
|
||||
}
|
||||
|
||||
// We get CF_HDROP when a user copied a file with Ctrl+C in Explorer and pastes that into the terminal (among others).
|
||||
if (const auto handle = GetClipboardData(CF_HDROP))
|
||||
{
|
||||
const wil::unique_hglobal_locked lock{ handle };
|
||||
const auto drop = static_cast<HDROP>(lock.get());
|
||||
if (!drop)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto cap = DragQueryFileW(drop, 0, nullptr, 0);
|
||||
if (cap == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto buffer = winrt::impl::hstring_builder{ cap };
|
||||
const auto len = DragQueryFileW(drop, 0, buffer.data(), cap + 1);
|
||||
if (len == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return buffer.to_hstring();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - This function is called when the `TermControl` requests that we send
|
||||
// it the clipboard's content.
|
||||
@@ -2818,36 +2926,55 @@ namespace winrt::TerminalApp::implementation
|
||||
const auto weakThis = get_weak();
|
||||
const auto dispatcher = Dispatcher();
|
||||
const auto globalSettings = _settings.GlobalSettings();
|
||||
const auto bracketedPaste = eventArgs.BracketedPasteEnabled();
|
||||
|
||||
// GetClipboardData might block for up to 30s for delay-rendered contents.
|
||||
co_await winrt::resume_background();
|
||||
|
||||
winrt::hstring text;
|
||||
if (const auto clipboard = _openClipboard(nullptr))
|
||||
if (const auto clipboard = clipboard::open(nullptr))
|
||||
{
|
||||
text = _extractClipboard();
|
||||
text = clipboard::read();
|
||||
}
|
||||
|
||||
if (globalSettings.TrimPaste())
|
||||
if (!bracketedPaste && globalSettings.TrimPaste())
|
||||
{
|
||||
text = { Utils::TrimPaste(text) };
|
||||
if (text.empty())
|
||||
{
|
||||
// Text is all white space, nothing to paste
|
||||
co_return;
|
||||
}
|
||||
text = winrt::hstring{ Utils::TrimPaste(text) };
|
||||
}
|
||||
|
||||
// LOAD BEARING: Send an empty bracketed paste even if the clipboard was empty.
|
||||
// Bracketed Paste provides an application a way to know whether the
|
||||
// user pasted, even if there was no applicable content on it. This
|
||||
// behavior is observed in GNOME Terminal, among others.
|
||||
if (!bracketedPaste && text.empty())
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
bool warnMultiLine = false;
|
||||
switch (globalSettings.WarnAboutMultiLinePaste())
|
||||
{
|
||||
case WarnAboutMultiLinePaste::Automatic:
|
||||
// NOTE that this is unsafe, because a shell that doesn't support bracketed paste
|
||||
// will allow an attacker to enable the mode, not realize that, and then accept
|
||||
// the paste as if it was a series of legitimate commands. See GH#13014.
|
||||
warnMultiLine = !bracketedPaste;
|
||||
break;
|
||||
case WarnAboutMultiLinePaste::Always:
|
||||
warnMultiLine = true;
|
||||
break;
|
||||
default:
|
||||
warnMultiLine = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// If the requesting terminal is in bracketed paste mode, then we don't need to warn about a multi-line paste.
|
||||
auto warnMultiLine = globalSettings.WarnAboutMultiLinePaste() && !eventArgs.BracketedPasteEnabled();
|
||||
if (warnMultiLine)
|
||||
{
|
||||
const auto isNewLineLambda = [](auto c) { return c == L'\n' || c == L'\r'; };
|
||||
const auto hasNewLine = std::find_if(text.cbegin(), text.cend(), isNewLineLambda) != text.cend();
|
||||
warnMultiLine = hasNewLine;
|
||||
const std::wstring_view view{ text };
|
||||
warnMultiLine = view.find_first_of(L"\r\n") != std::wstring_view::npos;
|
||||
}
|
||||
|
||||
constexpr const std::size_t minimumSizeForWarning = 1024 * 5; // 5 KiB
|
||||
constexpr std::size_t minimumSizeForWarning = 1024 * 5; // 5 KiB
|
||||
const auto warnLargeText = text.size() > minimumSizeForWarning && globalSettings.WarnAboutLargePaste();
|
||||
|
||||
if (warnMultiLine || warnLargeText)
|
||||
@@ -2857,8 +2984,20 @@ namespace winrt::TerminalApp::implementation
|
||||
if (const auto strongThis = weakThis.get())
|
||||
{
|
||||
// We have to initialize the dialog here to be able to change the text of the text block within it
|
||||
FindName(L"MultiLinePasteDialog").try_as<WUX::Controls::ContentDialog>();
|
||||
ClipboardText().Text(text);
|
||||
std::ignore = FindName(L"MultiLinePasteDialog");
|
||||
|
||||
// WinUI absolutely cannot deal with large amounts of text (at least O(n), possibly O(n^2),
|
||||
// so we limit the string length here and add an ellipsis if necessary.
|
||||
auto clipboardText = text;
|
||||
if (clipboardText.size() > 1024)
|
||||
{
|
||||
const std::wstring_view view{ text };
|
||||
// Make sure we don't cut in the middle of a surrogate pair
|
||||
const auto len = til::utf16_iterate_prev(view, 512);
|
||||
clipboardText = til::hstring_format(FMT_COMPILE(L"{}\n…"), view.substr(0, len));
|
||||
}
|
||||
|
||||
ClipboardText().Text(std::move(clipboardText));
|
||||
|
||||
// The vertical offset on the scrollbar does not reset automatically, so reset it manually
|
||||
ClipboardContentScrollViewer().ScrollToVerticalOffset(0);
|
||||
@@ -2874,7 +3013,7 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
// Clear the clipboard text so it doesn't lie around in memory
|
||||
ClipboardText().Text(L"");
|
||||
ClipboardText().Text({});
|
||||
|
||||
if (warningResult != ContentDialogResult::Primary)
|
||||
{
|
||||
@@ -3038,7 +3177,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// - formats: dictate which formats need to be copied
|
||||
// Return Value:
|
||||
// - true iff we we able to copy text (if a selection was active)
|
||||
bool TerminalPage::_CopyText(const bool dismissSelection, const bool singleLine, const bool withControlSequences, const Windows::Foundation::IReference<CopyFormat>& formats)
|
||||
bool TerminalPage::_CopyText(const bool dismissSelection, const bool singleLine, const bool withControlSequences, const CopyFormat formats)
|
||||
{
|
||||
if (const auto& control{ _GetActiveControl() })
|
||||
{
|
||||
@@ -3054,8 +3193,12 @@ namespace winrt::TerminalApp::implementation
|
||||
// - eventArgs: the arguments specifying how to set the progress indicator
|
||||
safe_void_coroutine TerminalPage::_SetTaskbarProgressHandler(const IInspectable /*sender*/, const IInspectable /*eventArgs*/)
|
||||
{
|
||||
const auto weak = get_weak();
|
||||
co_await wil::resume_foreground(Dispatcher());
|
||||
SetTaskbarProgress.raise(*this, nullptr);
|
||||
if (const auto strong = weak.get())
|
||||
{
|
||||
SetTaskbarProgress.raise(*this, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -3092,33 +3235,17 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
PackageCatalog catalog = connectResult.PackageCatalog();
|
||||
// clang-format off
|
||||
static constexpr std::array<WinGetSearchParams, 3> searches{ {
|
||||
{ .Field = PackageMatchField::Command, .MatchOption = PackageFieldMatchOption::StartsWithCaseInsensitive },
|
||||
{ .Field = PackageMatchField::Name, .MatchOption = PackageFieldMatchOption::ContainsCaseInsensitive },
|
||||
{ .Field = PackageMatchField::Moniker, .MatchOption = PackageFieldMatchOption::ContainsCaseInsensitive } } };
|
||||
// clang-format on
|
||||
|
||||
PackageMatchFilter filter = WindowsPackageManagerFactory::CreatePackageMatchFilter();
|
||||
filter.Value(query);
|
||||
filter.Field(PackageMatchField::Command);
|
||||
filter.Option(PackageFieldMatchOption::Equals);
|
||||
|
||||
FindPackagesOptions options = WindowsPackageManagerFactory::CreateFindPackagesOptions();
|
||||
options.Filters().Append(filter);
|
||||
options.ResultLimit(20);
|
||||
|
||||
IVectorView<MatchResult> pkgList;
|
||||
for (const auto& search : searches)
|
||||
{
|
||||
filter.Field(search.Field);
|
||||
filter.Option(search.MatchOption);
|
||||
|
||||
const auto result = co_await catalog.FindPackagesAsync(options);
|
||||
pkgList = result.Matches();
|
||||
if (pkgList.Size() > 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
const auto result = co_await catalog.FindPackagesAsync(options);
|
||||
const IVectorView<MatchResult> pkgList = result.Matches();
|
||||
co_return pkgList;
|
||||
}
|
||||
|
||||
@@ -3128,6 +3255,12 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
const auto weak = get_weak();
|
||||
const auto dispatcher = Dispatcher();
|
||||
|
||||
// All of the code until resume_foreground is static and
|
||||
// doesn't touch `this`, so we don't need weak/strong_ref.
|
||||
co_await winrt::resume_background();
|
||||
|
||||
// no packages were found, nothing to suggest
|
||||
@@ -3145,7 +3278,12 @@ namespace winrt::TerminalApp::implementation
|
||||
suggestions.emplace_back(fmt::format(FMT_COMPILE(L"winget install --id {} -s winget"), pkg.CatalogPackage().Id()));
|
||||
}
|
||||
|
||||
co_await wil::resume_foreground(Dispatcher());
|
||||
co_await wil::resume_foreground(dispatcher);
|
||||
const auto strong = weak.get();
|
||||
if (!strong)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
auto term = _GetActiveControl();
|
||||
if (!term)
|
||||
@@ -3181,6 +3319,21 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_copyToClipboard(const IInspectable, const WriteToClipboardEventArgs args) const
|
||||
{
|
||||
if (const auto clipboard = clipboard::open(_hostingHwnd.value_or(nullptr)))
|
||||
{
|
||||
const auto plain = args.Plain();
|
||||
const auto html = args.Html();
|
||||
const auto rtf = args.Rtf();
|
||||
|
||||
clipboard::write(
|
||||
{ plain.data(), plain.size() },
|
||||
{ reinterpret_cast<const char*>(html.data()), html.size() },
|
||||
{ reinterpret_cast<const char*>(rtf.data()), rtf.size() });
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Paste text from the Windows Clipboard to the focused terminal
|
||||
void TerminalPage::_PasteText()
|
||||
@@ -3225,6 +3378,9 @@ namespace winrt::TerminalApp::implementation
|
||||
// UI) thread. This is IMPORTANT, because the Windows.Storage API's
|
||||
// (used for retrieving the path to the file) will crash on the UI
|
||||
// thread, because the main thread is a STA.
|
||||
//
|
||||
// NOTE: All remaining code of this function doesn't touch `this`, so we don't need weak/strong_ref.
|
||||
// NOTE NOTE: Don't touch `this` when you make changes here.
|
||||
co_await winrt::resume_background();
|
||||
|
||||
auto openFile = [](const auto& filePath) {
|
||||
@@ -3551,7 +3707,13 @@ namespace winrt::TerminalApp::implementation
|
||||
// for nulls
|
||||
if (const auto& connection{ _duplicateConnectionForRestart(paneContent) })
|
||||
{
|
||||
paneContent.GetTermControl().Connection(connection);
|
||||
// Reset the terminal's VT state before attaching the new connection.
|
||||
// The previous client may have left dirty modes (e.g., bracketed
|
||||
// paste, mouse tracking, alternate buffer, kitty keyboard) that
|
||||
// would corrupt input/output for the new shell process.
|
||||
const auto& termControl = paneContent.GetTermControl();
|
||||
termControl.HardResetWithoutErase();
|
||||
termControl.Connection(connection);
|
||||
connection.Start();
|
||||
}
|
||||
}
|
||||
@@ -3571,7 +3733,7 @@ namespace winrt::TerminalApp::implementation
|
||||
return;
|
||||
}
|
||||
|
||||
const auto path = newAppearance.ExpandedBackgroundImagePath();
|
||||
const auto path = newAppearance.BackgroundImagePath().Resolved();
|
||||
if (path.empty())
|
||||
{
|
||||
_tabContent.Background(nullptr);
|
||||
@@ -3636,7 +3798,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// updating terminal panes, so that we don't have to build a _new_
|
||||
// TerminalSettings for every profile we update - we can just look them
|
||||
// up the previous ones we built.
|
||||
_terminalSettingsCache.Reset(_settings, *_bindings);
|
||||
_terminalSettingsCache->Reset(_settings, *_bindings);
|
||||
|
||||
for (const auto& tab : _tabs)
|
||||
{
|
||||
@@ -3694,6 +3856,9 @@ namespace winrt::TerminalApp::implementation
|
||||
_updateThemeColors();
|
||||
|
||||
_updateAllTabCloseButtons();
|
||||
|
||||
// The user may have changed the "show title in titlebar" setting.
|
||||
TitleChanged.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
void TerminalPage::_updateAllTabCloseButtons()
|
||||
@@ -3707,6 +3872,8 @@ namespace winrt::TerminalApp::implementation
|
||||
theme.Tab().ShowCloseButton() :
|
||||
Settings::Model::TabCloseButtonVisibility::Always;
|
||||
|
||||
_tabItemMiddleClickHookEnabled = visibility == Settings::Model::TabCloseButtonVisibility::Never;
|
||||
|
||||
for (const auto& tab : _tabs)
|
||||
{
|
||||
tab.CloseButtonVisibility(visibility);
|
||||
@@ -4578,14 +4745,23 @@ namespace winrt::TerminalApp::implementation
|
||||
// - sender: the ICoreState instance containing the connection state
|
||||
// Return Value:
|
||||
// - <none>
|
||||
safe_void_coroutine TerminalPage::_ConnectionStateChangedHandler(const IInspectable& sender, const IInspectable& /*args*/) const
|
||||
safe_void_coroutine TerminalPage::_ConnectionStateChangedHandler(const IInspectable& sender, const IInspectable& /*args*/)
|
||||
{
|
||||
if (const auto coreState{ sender.try_as<winrt::Microsoft::Terminal::Control::ICoreState>() })
|
||||
{
|
||||
const auto newConnectionState = coreState.ConnectionState();
|
||||
const auto weak = get_weak();
|
||||
co_await wil::resume_foreground(Dispatcher());
|
||||
const auto strong = weak.get();
|
||||
if (!strong)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
_adjustProcessPriorityThrottled->Run();
|
||||
|
||||
if (newConnectionState == ConnectionState::Failed && !_IsMessageDismissed(InfoBarMessage::CloseOnExitInfo))
|
||||
{
|
||||
co_await wil::resume_foreground(Dispatcher());
|
||||
if (const auto infoBar = FindName(L"CloseOnExitInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||
{
|
||||
infoBar.IsOpen(true);
|
||||
@@ -4718,8 +4894,18 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
if (_settings.GlobalSettings().UseAcrylicInTabRow())
|
||||
// GH#19604: Get the theme's tabRow color to use as the acrylic tint.
|
||||
const auto tabRowBg{ theme.TabRow() ? (_activated ? theme.TabRow().Background() :
|
||||
theme.TabRow().UnfocusedBackground()) :
|
||||
ThemeColor{ nullptr } };
|
||||
|
||||
if (_settings.GlobalSettings().UseAcrylicInTabRow() && (_activated || _settings.GlobalSettings().EnableUnfocusedAcrylic()))
|
||||
{
|
||||
if (tabRowBg)
|
||||
{
|
||||
bgColor = ThemeColor::ColorFromBrush(tabRowBg.Evaluate(res, terminalBrush, true));
|
||||
}
|
||||
|
||||
const auto acrylicBrush = Media::AcrylicBrush();
|
||||
acrylicBrush.BackgroundSource(Media::AcrylicBackgroundSource::HostBackdrop);
|
||||
acrylicBrush.FallbackColor(bgColor);
|
||||
@@ -4728,9 +4914,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
TitlebarBrush(acrylicBrush);
|
||||
}
|
||||
else if (auto tabRowBg{ theme.TabRow() ? (_activated ? theme.TabRow().Background() :
|
||||
theme.TabRow().UnfocusedBackground()) :
|
||||
ThemeColor{ nullptr } })
|
||||
else if (tabRowBg)
|
||||
{
|
||||
const auto themeBrush{ tabRowBg.Evaluate(res, terminalBrush, true) };
|
||||
bgColor = ThemeColor::ColorFromBrush(themeBrush);
|
||||
@@ -4850,6 +5034,94 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_adjustProcessPriority() const
|
||||
{
|
||||
// Windowing is single-threaded, so this will not cause a race condition.
|
||||
static bool supported{ true };
|
||||
|
||||
if (!supported || !_hostingHwnd.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::array<HANDLE, 32> processes;
|
||||
auto it = processes.begin();
|
||||
const auto end = processes.end();
|
||||
|
||||
auto&& appendFromControl = [&](auto&& control) {
|
||||
if (it == end)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (control)
|
||||
{
|
||||
if (const auto conn{ control.Connection() })
|
||||
{
|
||||
if (const auto pty{ conn.try_as<winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection>() })
|
||||
{
|
||||
if (const uint64_t process{ pty.RootProcessHandle() }; process != 0)
|
||||
{
|
||||
*it++ = reinterpret_cast<HANDLE>(process);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto&& appendFromTab = [&](auto&& tabImpl) {
|
||||
if (const auto pane{ tabImpl->GetRootPane() })
|
||||
{
|
||||
pane->WalkTree([&](auto&& child) {
|
||||
if (const auto& control{ child->GetTerminalControl() })
|
||||
{
|
||||
appendFromControl(control);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (!_activated)
|
||||
{
|
||||
// When a window is out of focus, we want to attach all of the processes
|
||||
// under it to the window so they all go into the background at the same time.
|
||||
for (auto&& tab : _tabs)
|
||||
{
|
||||
if (auto tabImpl{ _GetTabImpl(tab) })
|
||||
{
|
||||
appendFromTab(tabImpl);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// When a window is in focus, propagate our foreground boost (if we have one)
|
||||
// to current all panes in the current tab.
|
||||
if (auto tabImpl{ _GetFocusedTabImpl() })
|
||||
{
|
||||
appendFromTab(tabImpl);
|
||||
}
|
||||
}
|
||||
|
||||
const auto count{ gsl::narrow_cast<DWORD>(it - processes.begin()) };
|
||||
const auto hr = TerminalTrySetWindowAssociatedProcesses(_hostingHwnd.value(), count, count ? processes.data() : nullptr);
|
||||
if (S_FALSE == hr)
|
||||
{
|
||||
// Don't bother trying again or logging. The wrapper tells us it's unsupported.
|
||||
supported = false;
|
||||
return;
|
||||
}
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider,
|
||||
"CalledNewQoSAPI",
|
||||
TraceLoggingValue(reinterpret_cast<uintptr_t>(_hostingHwnd.value()), "hwnd"),
|
||||
TraceLoggingValue(count),
|
||||
TraceLoggingHResult(hr));
|
||||
#ifdef _DEBUG
|
||||
OutputDebugStringW(fmt::format(FMT_COMPILE(L"Submitted {} processes to TerminalTrySetWindowAssociatedProcesses; return=0x{:08x}\n"), count, hr).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
void TerminalPage::WindowActivated(const bool activated)
|
||||
{
|
||||
// Stash if we're activated. Use that when we reload
|
||||
@@ -4857,6 +5129,8 @@ namespace winrt::TerminalApp::implementation
|
||||
_activated = activated;
|
||||
_updateThemeColors();
|
||||
|
||||
_adjustProcessPriorityThrottled->Run();
|
||||
|
||||
if (const auto& tab{ _GetFocusedTabImpl() })
|
||||
{
|
||||
if (tab->TabStatus().IsInputBroadcastActive())
|
||||
@@ -4876,8 +5150,6 @@ namespace winrt::TerminalApp::implementation
|
||||
safe_void_coroutine TerminalPage::_ControlCompletionsChangedHandler(const IInspectable sender,
|
||||
const CompletionsChangedEventArgs args)
|
||||
{
|
||||
// This will come in on a background (not-UI, not output) thread.
|
||||
|
||||
// This won't even get hit if the velocity flag is disabled - we gate
|
||||
// registering for the event based off of
|
||||
// Feature_ShellCompletions::IsEnabled back in _RegisterTerminalEvents
|
||||
@@ -5051,7 +5323,7 @@ namespace winrt::TerminalApp::implementation
|
||||
makeItem(RS_(L"DuplicateTabText"), L"\xF5ED", ActionAndArgs{ ShortcutAction::DuplicateTab, nullptr }, menu);
|
||||
|
||||
const auto focusedProfileName = focusedProfile.Name();
|
||||
const auto focusedProfileIcon = focusedProfile.Icon();
|
||||
const auto focusedProfileIcon = focusedProfile.Icon().Resolved();
|
||||
const auto splitPaneDuplicateText = RS_(L"SplitPaneDuplicateText") + L" " + focusedProfileName; // SplitPaneDuplicateText
|
||||
|
||||
const auto splitPaneRightText = RS_(L"SplitPaneRightText");
|
||||
@@ -5077,7 +5349,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
const auto profile = activeProfiles.GetAt(profileIndex);
|
||||
const auto profileName = profile.Name();
|
||||
const auto profileIcon = profile.Icon();
|
||||
const auto profileIcon = profile.Icon().Resolved();
|
||||
|
||||
NewTerminalArgs args{};
|
||||
args.Profile(profileName);
|
||||
@@ -5112,22 +5384,22 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
if (auto neighbor = rootPane->NavigateDirection(activePane, FocusDirection::Down, mruPanes))
|
||||
{
|
||||
makeItem(RS_(L"SwapPaneDownText"), neighbor->GetProfile().Icon(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Down } }, swapPaneMenu);
|
||||
makeItem(RS_(L"SwapPaneDownText"), neighbor->GetProfile().Icon().Resolved(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Down } }, swapPaneMenu);
|
||||
}
|
||||
|
||||
if (auto neighbor = rootPane->NavigateDirection(activePane, FocusDirection::Right, mruPanes))
|
||||
{
|
||||
makeItem(RS_(L"SwapPaneRightText"), neighbor->GetProfile().Icon(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Right } }, swapPaneMenu);
|
||||
makeItem(RS_(L"SwapPaneRightText"), neighbor->GetProfile().Icon().Resolved(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Right } }, swapPaneMenu);
|
||||
}
|
||||
|
||||
if (auto neighbor = rootPane->NavigateDirection(activePane, FocusDirection::Up, mruPanes))
|
||||
{
|
||||
makeItem(RS_(L"SwapPaneUpText"), neighbor->GetProfile().Icon(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Up } }, swapPaneMenu);
|
||||
makeItem(RS_(L"SwapPaneUpText"), neighbor->GetProfile().Icon().Resolved(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Up } }, swapPaneMenu);
|
||||
}
|
||||
|
||||
if (auto neighbor = rootPane->NavigateDirection(activePane, FocusDirection::Left, mruPanes))
|
||||
{
|
||||
makeItem(RS_(L"SwapPaneLeftText"), neighbor->GetProfile().Icon(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Left } }, swapPaneMenu);
|
||||
makeItem(RS_(L"SwapPaneLeftText"), neighbor->GetProfile().Icon().Resolved(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Left } }, swapPaneMenu);
|
||||
}
|
||||
|
||||
makeMenuItem(RS_(L"SwapPaneText"), L"\xF1CB", swapPaneMenu, menu);
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ThrottledFunc.h>
|
||||
|
||||
#include "TerminalPage.g.h"
|
||||
#include "Tab.h"
|
||||
#include "AppKeyBindings.h"
|
||||
@@ -29,6 +31,8 @@ namespace Microsoft::Terminal::Core
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct TerminalSettingsCache;
|
||||
|
||||
inline constexpr uint32_t DefaultRowsToScroll{ 3 };
|
||||
inline constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
|
||||
|
||||
@@ -149,7 +153,7 @@ namespace winrt::TerminalApp::implementation
|
||||
safe_void_coroutine ProcessStartupActions(std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> actions,
|
||||
const winrt::hstring cwd = winrt::hstring{},
|
||||
const winrt::hstring env = winrt::hstring{});
|
||||
void CreateTabFromConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection);
|
||||
safe_void_coroutine CreateTabFromConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection);
|
||||
|
||||
TerminalApp::WindowProperties WindowProperties() const noexcept { return _WindowProperties; };
|
||||
|
||||
@@ -169,7 +173,7 @@ namespace winrt::TerminalApp::implementation
|
||||
til::property_changed_event PropertyChanged;
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
til::typed_event<IInspectable, winrt::hstring> TitleChanged;
|
||||
til::typed_event<IInspectable, IInspectable> TitleChanged;
|
||||
til::typed_event<IInspectable, IInspectable> CloseWindowRequested;
|
||||
til::typed_event<IInspectable, winrt::Windows::UI::Xaml::UIElement> SetTitleBarContent;
|
||||
til::typed_event<IInspectable, IInspectable> FocusModeChanged;
|
||||
@@ -273,7 +277,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
TerminalApp::ContentManager _manager{ nullptr };
|
||||
|
||||
TerminalApp::TerminalSettingsCache _terminalSettingsCache{ nullptr };
|
||||
std::shared_ptr<TerminalSettingsCache> _terminalSettingsCache{};
|
||||
|
||||
struct StashedDragData
|
||||
{
|
||||
@@ -359,8 +363,11 @@ namespace winrt::TerminalApp::implementation
|
||||
bool _MovePane(const Microsoft::Terminal::Settings::Model::MovePaneArgs args);
|
||||
bool _MoveTab(winrt::com_ptr<Tab> tab, const Microsoft::Terminal::Settings::Model::MoveTabArgs args);
|
||||
|
||||
std::shared_ptr<ThrottledFunc<>> _adjustProcessPriorityThrottled;
|
||||
void _adjustProcessPriority() const;
|
||||
|
||||
template<typename F>
|
||||
bool _ApplyToActiveControls(F f)
|
||||
bool _ApplyToActiveControls(F f) const
|
||||
{
|
||||
if (const auto tab{ _GetFocusedTabImpl() })
|
||||
{
|
||||
@@ -379,12 +386,12 @@ namespace winrt::TerminalApp::implementation
|
||||
return false;
|
||||
}
|
||||
|
||||
winrt::Microsoft::Terminal::Control::TermControl _GetActiveControl();
|
||||
winrt::Microsoft::Terminal::Control::TermControl _GetActiveControl() const;
|
||||
std::optional<uint32_t> _GetFocusedTabIndex() const noexcept;
|
||||
std::optional<uint32_t> _GetTabIndex(const TerminalApp::Tab& tab) const noexcept;
|
||||
TerminalApp::Tab _GetFocusedTab() const noexcept;
|
||||
winrt::com_ptr<Tab> _GetFocusedTabImpl() const noexcept;
|
||||
TerminalApp::Tab _GetTabByTabViewItem(const Microsoft::UI::Xaml::Controls::TabViewItem& tabViewItem) const noexcept;
|
||||
TerminalApp::Tab _GetTabByTabViewItem(const IInspectable& tabViewItem) const noexcept;
|
||||
|
||||
void _HandleClosePaneRequested(std::shared_ptr<Pane> pane);
|
||||
safe_void_coroutine _SetFocusedTab(const winrt::TerminalApp::Tab tab);
|
||||
@@ -413,10 +420,11 @@ namespace winrt::TerminalApp::implementation
|
||||
bool _IsUriSupported(const winrt::Windows::Foundation::Uri& parsedUri);
|
||||
|
||||
void _ShowCouldNotOpenDialog(winrt::hstring reason, winrt::hstring uri);
|
||||
bool _CopyText(const bool dismissSelection, const bool singleLine, const bool withControlSequences, const Windows::Foundation::IReference<Microsoft::Terminal::Control::CopyFormat>& formats);
|
||||
bool _CopyText(bool dismissSelection, bool singleLine, bool withControlSequences, Microsoft::Terminal::Control::CopyFormat formats);
|
||||
|
||||
safe_void_coroutine _SetTaskbarProgressHandler(const IInspectable sender, const IInspectable eventArgs);
|
||||
|
||||
void _copyToClipboard(IInspectable, Microsoft::Terminal::Control::WriteToClipboardEventArgs args) const;
|
||||
void _PasteText();
|
||||
|
||||
safe_void_coroutine _ControlNoticeRaisedHandler(const IInspectable sender, const Microsoft::Terminal::Control::NoticeEventArgs eventArgs);
|
||||
@@ -427,13 +435,18 @@ namespace winrt::TerminalApp::implementation
|
||||
void _TabDragStarted(const IInspectable& sender, const IInspectable& eventArgs);
|
||||
void _TabDragCompleted(const IInspectable& sender, const IInspectable& eventArgs);
|
||||
|
||||
bool _tabPointerMiddleButtonPressed{ false };
|
||||
bool _tabPointerMiddleButtonExited{ false };
|
||||
// BODGY: WinUI's TabView has a broken close event handler:
|
||||
// If the close button is disabled, middle-clicking the tab raises no close
|
||||
// event. Because that's dumb, we implement our own middle-click handling.
|
||||
// `_tabItemMiddleClickHookEnabled` is true whenever the close button is hidden,
|
||||
// and that enables all of the rest of this machinery (and this workaround).
|
||||
bool _tabItemMiddleClickHookEnabled = false;
|
||||
bool _tabItemMiddleClickExited = false;
|
||||
PointerEntered_revoker _tabItemMiddleClickPointerEntered;
|
||||
PointerExited_revoker _tabItemMiddleClickPointerExited;
|
||||
PointerCaptureLost_revoker _tabItemMiddleClickPointerCaptureLost;
|
||||
void _OnTabPointerPressed(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs);
|
||||
void _OnTabPointerReleased(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs);
|
||||
safe_void_coroutine _OnTabPointerReleasedCloseTab(winrt::Microsoft::UI::Xaml::Controls::TabViewItem sender);
|
||||
void _OnTabPointerEntered(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs);
|
||||
void _OnTabPointerExited(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs);
|
||||
safe_void_coroutine _OnTabPointerReleasedCloseTab(IInspectable sender);
|
||||
|
||||
void _OnTabSelectionChanged(const IInspectable& sender, const Windows::UI::Xaml::Controls::SelectionChangedEventArgs& eventArgs);
|
||||
void _OnTabItemsChanged(const IInspectable& sender, const Windows::Foundation::Collections::IVectorChangedEventArgs& eventArgs);
|
||||
@@ -507,7 +520,7 @@ namespace winrt::TerminalApp::implementation
|
||||
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile);
|
||||
void _OpenElevatedWT(winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs);
|
||||
|
||||
safe_void_coroutine _ConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||
safe_void_coroutine _ConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||
void _CloseOnExitInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||
void _KeyboardServiceWarningInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||
static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||
@@ -523,7 +536,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void _ShowWindowChangedHandler(const IInspectable sender, const winrt::Microsoft::Terminal::Control::ShowWindowArgs args);
|
||||
Windows::Foundation::IAsyncAction _SearchMissingCommandHandler(const IInspectable sender, const winrt::Microsoft::Terminal::Control::SearchMissingCommandEventArgs args);
|
||||
Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Management::Deployment::MatchResult>> _FindPackageAsync(hstring query);
|
||||
static Windows::Foundation::IAsyncOperation<Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Management::Deployment::MatchResult>> _FindPackageAsync(hstring query);
|
||||
|
||||
void _WindowSizeChanged(const IInspectable sender, const winrt::Microsoft::Terminal::Control::WindowSizeChangedEventArgs args);
|
||||
void _windowPropertyChanged(const IInspectable& sender, const winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs& args);
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace TerminalApp
|
||||
void WindowActivated(Boolean activated);
|
||||
void SendContentToOther(RequestReceiveContentArgs args);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> CloseWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.UIElement> SetTitleBarContent;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FocusModeChanged;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <mmsystem.h>
|
||||
|
||||
#include "TerminalSettingsCache.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
#include "BellEventArgs.g.cpp"
|
||||
@@ -20,7 +21,7 @@ using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
TerminalPaneContent::TerminalPaneContent(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
||||
const TerminalApp::TerminalSettingsCache& cache,
|
||||
const std::shared_ptr<TerminalSettingsCache>& cache,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control) :
|
||||
_control{ control },
|
||||
_cache{ cache },
|
||||
@@ -82,7 +83,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
winrt::hstring TerminalPaneContent::Icon() const
|
||||
{
|
||||
return _profile.EvaluatedIcon();
|
||||
return _profile.Icon().Resolved();
|
||||
}
|
||||
|
||||
Windows::Foundation::IReference<winrt::Windows::UI::Color> TerminalPaneContent::TabColor() const noexcept
|
||||
@@ -278,7 +279,7 @@ namespace winrt::TerminalApp::implementation
|
||||
auto sounds{ _profile.BellSound() };
|
||||
if (sounds && sounds.Size() > 0)
|
||||
{
|
||||
winrt::hstring soundPath{ wil::ExpandEnvironmentStringsW<std::wstring>(sounds.GetAt(rand() % sounds.Size()).c_str()) };
|
||||
winrt::hstring soundPath{ sounds.GetAt(rand() % sounds.Size()).Resolved() };
|
||||
winrt::Windows::Foundation::Uri uri{ soundPath };
|
||||
_playBellSound(uri);
|
||||
}
|
||||
@@ -340,9 +341,13 @@ namespace winrt::TerminalApp::implementation
|
||||
RestartTerminalRequested.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
void TerminalPaneContent::UpdateSettings(const CascadiaSettings& /*settings*/)
|
||||
void TerminalPaneContent::UpdateSettings(const CascadiaSettings& settings)
|
||||
{
|
||||
if (const auto& settings{ _cache.TryLookup(_profile) })
|
||||
// Reload our profile from the settings model to propagate bell mode, icon, and close on exit mode (anything that uses _profile).
|
||||
const auto profile{ settings.FindProfile(_profile.Guid()) };
|
||||
_profile = profile ? profile : settings.ProfileDefaults();
|
||||
|
||||
if (const auto& settings{ _cache->TryLookup(_profile) })
|
||||
{
|
||||
_control.UpdateControlSettings(settings.DefaultSettings(), settings.UnfocusedSettings());
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct TerminalSettingsCache;
|
||||
|
||||
struct BellEventArgs : public BellEventArgsT<BellEventArgs>
|
||||
{
|
||||
public:
|
||||
@@ -20,7 +22,7 @@ namespace winrt::TerminalApp::implementation
|
||||
struct TerminalPaneContent : TerminalPaneContentT<TerminalPaneContent>, BasicPaneEvents
|
||||
{
|
||||
TerminalPaneContent(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
||||
const TerminalApp::TerminalSettingsCache& cache,
|
||||
const std::shared_ptr<TerminalSettingsCache>& cache,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
|
||||
winrt::Windows::UI::Xaml::FrameworkElement GetRoot();
|
||||
@@ -59,7 +61,7 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState _connectionState{ winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::NotConnected };
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile _profile{ nullptr };
|
||||
TerminalApp::TerminalSettingsCache _cache{ nullptr };
|
||||
std::shared_ptr<TerminalSettingsCache> _cache{};
|
||||
bool _isDefTermSession{ false };
|
||||
|
||||
winrt::Windows::Media::Playback::MediaPlayer _bellPlayer{ nullptr };
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "IPaneContent.idl";
|
||||
import "TerminalSettingsCache.idl";
|
||||
import "FilteredCommand.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "pch.h"
|
||||
#include "TerminalSettingsCache.h"
|
||||
#include "TerminalSettingsCache.g.cpp"
|
||||
|
||||
namespace winrt
|
||||
{
|
||||
|
||||
@@ -13,14 +13,13 @@ Abstract:
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "TerminalSettingsCache.g.h"
|
||||
#include <inc/cppwinrt_utils.h>
|
||||
#include "winrt/Microsoft.Terminal.Settings.Model.h"
|
||||
#include "winrt/TerminalApp.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
class TerminalSettingsCache : public TerminalSettingsCacheT<TerminalSettingsCache>
|
||||
struct TerminalSettingsCache
|
||||
{
|
||||
public:
|
||||
TerminalSettingsCache(const Microsoft::Terminal::Settings::Model::CascadiaSettings& settings, const TerminalApp::AppKeyBindings& bindings);
|
||||
Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult TryLookup(const Microsoft::Terminal::Settings::Model::Profile& profile);
|
||||
void Reset(const Microsoft::Terminal::Settings::Model::CascadiaSettings& settings, const TerminalApp::AppKeyBindings& bindings);
|
||||
@@ -31,8 +30,3 @@ namespace winrt::TerminalApp::implementation
|
||||
std::unordered_map<winrt::guid, std::pair<Microsoft::Terminal::Settings::Model::Profile, Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult>> profileGuidSettingsMap;
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(TerminalSettingsCache);
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import "AppKeyBindings.idl";
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass TerminalSettingsCache
|
||||
{
|
||||
TerminalSettingsCache(Microsoft.Terminal.Settings.Model.CascadiaSettings settings, AppKeyBindings bindings);
|
||||
Microsoft.Terminal.Settings.Model.TerminalSettingsCreateResult TryLookup(Microsoft.Terminal.Settings.Model.Profile profile);
|
||||
void Reset(Microsoft.Terminal.Settings.Model.CascadiaSettings settings, AppKeyBindings bindings);
|
||||
}
|
||||
}
|
||||
@@ -40,8 +40,7 @@ static const std::array settingsLoadWarningsLabels{
|
||||
USES_RESOURCE(L"MissingDefaultProfileText"),
|
||||
USES_RESOURCE(L"DuplicateProfileText"),
|
||||
USES_RESOURCE(L"UnknownColorSchemeText"),
|
||||
USES_RESOURCE(L"InvalidBackgroundImage"),
|
||||
USES_RESOURCE(L"InvalidIcon"),
|
||||
USES_RESOURCE(L"InvalidMediaResource"),
|
||||
USES_RESOURCE(L"AtLeastOneKeybindingWarning"),
|
||||
USES_RESOURCE(L"TooManyKeysForChord"),
|
||||
USES_RESOURCE(L"MissingRequiredParameter"),
|
||||
@@ -323,6 +322,10 @@ namespace winrt::TerminalApp::implementation
|
||||
// - an IAsyncOperation with the dialog result
|
||||
winrt::Windows::Foundation::IAsyncOperation<ContentDialogResult> TerminalWindow::ShowDialog(winrt::WUX::Controls::ContentDialog dialog)
|
||||
{
|
||||
const auto weak = get_weak();
|
||||
const auto dispatcher = _root->Dispatcher();
|
||||
const auto root = _root->XamlRoot();
|
||||
|
||||
// As mentioned on s_activeDialog, dismissing the active dialog is necessary.
|
||||
// We repeat it a few times in case the resume_foreground failed to work,
|
||||
// but I found that one iteration will always be enough in practice.
|
||||
@@ -336,7 +339,7 @@ namespace winrt::TerminalApp::implementation
|
||||
s_activeDialog.Hide();
|
||||
|
||||
// Wait for the current dialog to be hidden.
|
||||
co_await wil::resume_foreground(_root->Dispatcher(), CoreDispatcherPriority::Low);
|
||||
co_await wil::resume_foreground(dispatcher, CoreDispatcherPriority::Low);
|
||||
}
|
||||
|
||||
// If two sources call ShowDialog() simultaneously, it may happen that both enter the above loop,
|
||||
@@ -353,7 +356,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// IMPORTANT: This is necessary as documented in the ContentDialog MSDN docs.
|
||||
// Since we're hosting the dialog in a Xaml island, we need to connect it to the
|
||||
// xaml tree somehow.
|
||||
dialog.XamlRoot(_root->XamlRoot());
|
||||
dialog.XamlRoot(root);
|
||||
|
||||
// IMPORTANT: Set the requested theme of the dialog, because the
|
||||
// PopupRoot isn't directly in the Xaml tree of our root. So the dialog
|
||||
@@ -367,14 +370,17 @@ namespace winrt::TerminalApp::implementation
|
||||
// theme on each element up to the root. We're relying a bit on Xaml's implementation
|
||||
// details here, but it does have the desired effect.
|
||||
// It's not enough to set the theme on the dialog alone.
|
||||
auto themingLambda{ [this](const Windows::Foundation::IInspectable& sender, const RoutedEventArgs&) {
|
||||
auto theme{ _settings.GlobalSettings().CurrentTheme() };
|
||||
auto requestedTheme{ theme.RequestedTheme() };
|
||||
auto element{ sender.try_as<winrt::Windows::UI::Xaml::FrameworkElement>() };
|
||||
while (element)
|
||||
auto themingLambda{ [weak](const Windows::Foundation::IInspectable& sender, const RoutedEventArgs&) {
|
||||
if (const auto strong = weak.get())
|
||||
{
|
||||
element.RequestedTheme(requestedTheme);
|
||||
element = element.Parent().try_as<winrt::Windows::UI::Xaml::FrameworkElement>();
|
||||
auto theme{ strong->_settings.GlobalSettings().CurrentTheme() };
|
||||
auto requestedTheme{ theme.RequestedTheme() };
|
||||
auto element{ sender.try_as<winrt::Windows::UI::Xaml::FrameworkElement>() };
|
||||
while (element)
|
||||
{
|
||||
element.RequestedTheme(requestedTheme);
|
||||
element = element.Parent().try_as<winrt::Windows::UI::Xaml::FrameworkElement>();
|
||||
}
|
||||
}
|
||||
} };
|
||||
|
||||
@@ -889,6 +895,11 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// Manually bubble the OnDirectKeyEvent event up through the focus tree.
|
||||
auto xamlRoot{ _root->XamlRoot() };
|
||||
if (!xamlRoot)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto focusedObject{ Windows::UI::Xaml::Input::FocusManager::GetFocusedElement(xamlRoot) };
|
||||
do
|
||||
{
|
||||
@@ -1049,6 +1060,11 @@ namespace winrt::TerminalApp::implementation
|
||||
// (or called TerminalWindow::Initialize)
|
||||
if (_appArgs->ExitCode() == 0)
|
||||
{
|
||||
// The existing logic (before this commit) strictly relied on
|
||||
// ValidateStartupCommands() only to be called for new windows.
|
||||
// It modifies the actions it stores.
|
||||
parsedArgs.ValidateStartupCommands();
|
||||
|
||||
// If the size of the arguments list is 1,
|
||||
// then it contains only the executable name and no other arguments.
|
||||
_hasCommandLineArguments = _appArgs->CommandlineRef().size() > 1;
|
||||
|
||||
@@ -210,7 +210,7 @@ namespace winrt::TerminalApp::implementation
|
||||
FORWARDED_TYPED_EVENT(Initialized, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, Initialized);
|
||||
|
||||
FORWARDED_TYPED_EVENT(SetTitleBarContent, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement, _root, SetTitleBarContent);
|
||||
FORWARDED_TYPED_EVENT(TitleChanged, winrt::Windows::Foundation::IInspectable, winrt::hstring, _root, TitleChanged);
|
||||
FORWARDED_TYPED_EVENT(TitleChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, TitleChanged);
|
||||
FORWARDED_TYPED_EVENT(CloseWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, CloseWindowRequested);
|
||||
FORWARDED_TYPED_EVENT(FocusModeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FocusModeChanged);
|
||||
FORWARDED_TYPED_EVENT(FullscreenChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FullscreenChanged);
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace TerminalApp
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> Initialized;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.UIElement> SetTitleBarContent;
|
||||
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> CloseWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Settings.Model.Theme> RequestedThemeChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FocusModeChanged;
|
||||
|
||||
@@ -53,6 +53,16 @@ namespace winrt::TerminalApp::implementation
|
||||
return static_cast<float>(minMaxCloseWidth) / 3.0f;
|
||||
}
|
||||
|
||||
bool TitlebarControl::Focused()
|
||||
{
|
||||
return MinMaxCloseControl().Focused();
|
||||
}
|
||||
|
||||
void TitlebarControl::Focused(bool focused)
|
||||
{
|
||||
MinMaxCloseControl().Focused(focused);
|
||||
}
|
||||
|
||||
IInspectable TitlebarControl::Content()
|
||||
{
|
||||
return ContentRoot().Content();
|
||||
|
||||
@@ -17,6 +17,9 @@ namespace winrt::TerminalApp::implementation
|
||||
void ReleaseButtons();
|
||||
float CaptionButtonWidth();
|
||||
|
||||
bool Focused();
|
||||
void Focused(bool focused);
|
||||
|
||||
IInspectable Content();
|
||||
void Content(IInspectable content);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace TerminalApp
|
||||
void ClickButton(CaptionButton button);
|
||||
void ReleaseButtons();
|
||||
Single CaptionButtonWidth { get; };
|
||||
Boolean Focused { get; set; };
|
||||
|
||||
IInspectable Content;
|
||||
Windows.UI.Xaml.Controls.Border DragBar { get; };
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<TerminalCppWinrt>true</TerminalCppWinrt>
|
||||
<TerminalMUX>true</TerminalMUX>
|
||||
<TerminalThemeHelpers>true</TerminalThemeHelpers>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "ConsoleInputReader.h"
|
||||
#include "unicode.hpp"
|
||||
|
||||
ConsoleInputReader::ConsoleInputReader(HANDLE handle) :
|
||||
_handle(handle)
|
||||
{
|
||||
_buffer.resize(BufferSize);
|
||||
_convertedString.reserve(BufferSize);
|
||||
}
|
||||
|
||||
void ConsoleInputReader::SetWindowSizeChangedCallback(std::function<void()> callback)
|
||||
{
|
||||
_windowSizeChangedCallback = std::move(callback);
|
||||
}
|
||||
|
||||
std::optional<std::wstring_view> ConsoleInputReader::Read()
|
||||
{
|
||||
DWORD readCount{ 0 };
|
||||
|
||||
_convertedString.clear();
|
||||
while (_convertedString.empty())
|
||||
{
|
||||
_buffer.resize(BufferSize);
|
||||
auto succeeded =
|
||||
ReadConsoleInputW(_handle, _buffer.data(), gsl::narrow_cast<DWORD>(_buffer.size()), &readCount);
|
||||
if (!succeeded)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
_buffer.resize(readCount);
|
||||
for (auto it = _buffer.begin(); it != _buffer.end(); ++it)
|
||||
{
|
||||
if (it->EventType == WINDOW_BUFFER_SIZE_EVENT && _windowSizeChangedCallback)
|
||||
{
|
||||
_windowSizeChangedCallback();
|
||||
}
|
||||
else if (it->EventType == KEY_EVENT)
|
||||
{
|
||||
const auto& keyEvent = it->Event.KeyEvent;
|
||||
if (keyEvent.bKeyDown || (!keyEvent.bKeyDown && keyEvent.wVirtualKeyCode == VK_MENU))
|
||||
{
|
||||
// Got a high surrogate at the end of the buffer
|
||||
if (IS_HIGH_SURROGATE(keyEvent.uChar.UnicodeChar))
|
||||
{
|
||||
_highSurrogate.emplace(keyEvent.uChar.UnicodeChar);
|
||||
continue; // we've consumed it -- only dispatch it if we get a low
|
||||
}
|
||||
|
||||
if (IS_LOW_SURROGATE(keyEvent.uChar.UnicodeChar))
|
||||
{
|
||||
// No matter what we do, we want to destructively consume the high surrogate
|
||||
if (const auto oldHighSurrogate{ std::exchange(_highSurrogate, std::nullopt) })
|
||||
{
|
||||
_convertedString.push_back(*_highSurrogate);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we get a low without a high surrogate, we've done everything we can.
|
||||
// This is an illegal state.
|
||||
_convertedString.push_back(UNICODE_REPLACEMENT);
|
||||
continue; // onto the next event
|
||||
}
|
||||
}
|
||||
|
||||
// (\0 with a scancode is probably a modifier key, not a VT input key)
|
||||
if (keyEvent.uChar.UnicodeChar != L'\0' || keyEvent.wVirtualScanCode == 0)
|
||||
{
|
||||
if (_highSurrogate) // non-destructive: we don't want to set it to nullopt needlessly for every character
|
||||
{
|
||||
// If we get a high surrogate *here*, we didn't find a low surrogate.
|
||||
// This state is also illegal.
|
||||
_convertedString.push_back(UNICODE_REPLACEMENT);
|
||||
_highSurrogate.reset();
|
||||
}
|
||||
_convertedString.push_back(keyEvent.uChar.UnicodeChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return _convertedString;
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
|
||||
ConsoleInputReader.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This file contains a class whose sole purpose is to
|
||||
abstract away a bunch of details you usually need to
|
||||
know to read VT from a console input handle.
|
||||
|
||||
--*/
|
||||
|
||||
class ConsoleInputReader
|
||||
{
|
||||
public:
|
||||
explicit ConsoleInputReader(HANDLE handle);
|
||||
void SetWindowSizeChangedCallback(std::function<void()> callback);
|
||||
std::optional<std::wstring_view> Read();
|
||||
|
||||
private:
|
||||
static constexpr size_t BufferSize{ 128 };
|
||||
|
||||
HANDLE _handle;
|
||||
std::wstring _convertedString;
|
||||
std::vector<INPUT_RECORD> _buffer;
|
||||
std::optional<wchar_t> _highSurrogate;
|
||||
std::function<void()> _windowSizeChangedCallback;
|
||||
};
|
||||
@@ -1,93 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{067F0A06-FCB7-472C-96E9-B03B54E8E18D}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>TerminalAzBridge</RootNamespace>
|
||||
<ProjectName>TerminalAzBridge</ProjectName>
|
||||
<TargetName>TerminalAzBridge</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<OpenConsoleUniversalApp>false</OpenConsoleUniversalApp>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<TargetPlatformIdentifier>Windows</TargetPlatformIdentifier>
|
||||
<VersionInfoFileDescription>Windows Terminal Azure Cloud Shell Connector</VersionInfoFileDescription>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<TerminalCppWinrt>true</TerminalCppWinrt>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<GenerateManifest>true</GenerateManifest>
|
||||
<EmbedManifest>true</EmbedManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Source Files -->
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="ConsoleInputReader.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="ConsoleInputReader.cpp" />
|
||||
</ItemGroup>
|
||||
<!-- Dependencies -->
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalConnection\TerminalConnection.vcxproj">
|
||||
<Project>{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
This ItemGroup and the Globals PropertyGroup below it are required in order
|
||||
to enable F5 debugging for the unpackaged application
|
||||
-->
|
||||
<ItemGroup>
|
||||
<PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\debugger_general.xml" />
|
||||
<PropertyPageSchema Include="$(VCTargetsPath)$(LangID)\debugger_local_windows.xml" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
|
||||
|
||||
<!-- These have to come after post.props because the Cpp common targets will inexplicably overwrite them. -->
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!--
|
||||
BODGY
|
||||
|
||||
The wapproj `GetResolvedWinMD` target tries to get a winmd from every cppwinrt
|
||||
executable we put in the package. But we DON'T produce a winmd. This makes the
|
||||
FastUpToDate check fail every time, and leads to the whole wapproj build
|
||||
running even if you're just f5'ing the package. EVEN AFTER A SUCCESSFUL BUILD.
|
||||
|
||||
Setting GenerateWindowsMetadata=false is enough to tell the build system that
|
||||
we don't produce one, and get it off our backs.
|
||||
-->
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
|
||||
</Project>
|
||||
@@ -1,108 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "winrt/Microsoft.Terminal.TerminalConnection.h"
|
||||
#include "ConsoleInputReader.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
||||
|
||||
static til::size GetConsoleScreenSize(HANDLE outputHandle)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFOEX csbiex{};
|
||||
csbiex.cbSize = sizeof(csbiex);
|
||||
GetConsoleScreenBufferInfoEx(outputHandle, &csbiex);
|
||||
return {
|
||||
(csbiex.srWindow.Right - csbiex.srWindow.Left) + 1,
|
||||
(csbiex.srWindow.Bottom - csbiex.srWindow.Top) + 1
|
||||
};
|
||||
}
|
||||
|
||||
static ConnectionState RunConnectionToCompletion(const ITerminalConnection& connection, HANDLE outputHandle, HANDLE inputHandle)
|
||||
{
|
||||
connection.TerminalOutput([outputHandle](const winrt::hstring& output) {
|
||||
WriteConsoleW(outputHandle, output.data(), output.size(), nullptr, nullptr);
|
||||
});
|
||||
|
||||
// Detach a thread to spin the console read indefinitely.
|
||||
// This application exits when the connection is closed, so
|
||||
// the connection's lifetime will outlast this thread.
|
||||
std::thread([connection, outputHandle, inputHandle] {
|
||||
ConsoleInputReader reader{ inputHandle };
|
||||
reader.SetWindowSizeChangedCallback([&]() {
|
||||
const auto size = GetConsoleScreenSize(outputHandle);
|
||||
|
||||
connection.Resize(size.height, size.width);
|
||||
});
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto input = reader.Read();
|
||||
if (input)
|
||||
{
|
||||
connection.WriteInput(winrt_wstring_to_array_view(*input));
|
||||
}
|
||||
}
|
||||
}).detach();
|
||||
|
||||
std::condition_variable stateChangeVar;
|
||||
std::optional<ConnectionState> state;
|
||||
std::mutex stateMutex;
|
||||
|
||||
connection.StateChanged([&](auto&& /*s*/, auto&& /*e*/) {
|
||||
std::unique_lock<std::mutex> lg{ stateMutex };
|
||||
state = connection.State();
|
||||
stateChangeVar.notify_all();
|
||||
});
|
||||
|
||||
connection.Start();
|
||||
|
||||
std::unique_lock<std::mutex> lg{ stateMutex };
|
||||
stateChangeVar.wait(lg, [&]() {
|
||||
if (!state.has_value())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return state.value() == ConnectionState::Closed || state.value() == ConnectionState::Failed;
|
||||
});
|
||||
|
||||
return state.value();
|
||||
}
|
||||
|
||||
int wmain(int /*argc*/, wchar_t** /*argv*/)
|
||||
{
|
||||
winrt::init_apartment(winrt::apartment_type::single_threaded);
|
||||
|
||||
DWORD inputMode{}, outputMode{};
|
||||
auto conIn{ GetStdHandle(STD_INPUT_HANDLE) }, conOut{ GetStdHandle(STD_OUTPUT_HANDLE) };
|
||||
auto codepage{ GetConsoleCP() }, outputCodepage{ GetConsoleOutputCP() };
|
||||
|
||||
RETURN_IF_WIN32_BOOL_FALSE(GetConsoleMode(conIn, &inputMode));
|
||||
RETURN_IF_WIN32_BOOL_FALSE(GetConsoleMode(conOut, &outputMode));
|
||||
|
||||
RETURN_IF_WIN32_BOOL_FALSE(SetConsoleMode(conIn, ENABLE_WINDOW_INPUT | ENABLE_VIRTUAL_TERMINAL_INPUT));
|
||||
RETURN_IF_WIN32_BOOL_FALSE(SetConsoleMode(conOut, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_WRAP_AT_EOL_OUTPUT | DISABLE_NEWLINE_AUTO_RETURN));
|
||||
RETURN_IF_WIN32_BOOL_FALSE(SetConsoleCP(CP_UTF8));
|
||||
RETURN_IF_WIN32_BOOL_FALSE(SetConsoleOutputCP(CP_UTF8));
|
||||
|
||||
auto restoreConsoleModes = wil::scope_exit([&]() {
|
||||
SetConsoleMode(conIn, inputMode);
|
||||
SetConsoleMode(conOut, outputMode);
|
||||
SetConsoleCP(codepage);
|
||||
SetConsoleOutputCP(outputCodepage);
|
||||
});
|
||||
|
||||
const auto size = GetConsoleScreenSize(conOut);
|
||||
|
||||
AzureConnection azureConn{};
|
||||
winrt::Windows::Foundation::Collections::ValueSet vs{};
|
||||
vs.Insert(L"initialRows", winrt::Windows::Foundation::PropertyValue::CreateUInt32(gsl::narrow_cast<uint32_t>(size.height)));
|
||||
vs.Insert(L"initialCols", winrt::Windows::Foundation::PropertyValue::CreateUInt32(gsl::narrow_cast<uint32_t>(size.width)));
|
||||
azureConn.Initialize(vs);
|
||||
|
||||
const auto state = RunConnectionToCompletion(azureConn, conOut, conIn);
|
||||
|
||||
return state == ConnectionState::Closed ? 0 : 1;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
@@ -1,40 +0,0 @@
|
||||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- pch.h
|
||||
|
||||
Abstract:
|
||||
- Contains external headers to include in the precompile phase of console build process.
|
||||
- Avoid including internal project headers. Instead include them only in the classes that need them (helps with test project building).
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Ignore checked iterators warning from VC compiler.
|
||||
#define _SCL_SECURE_NO_WARNINGS
|
||||
|
||||
// Block minwindef.h min/max macros to prevent <algorithm> conflict
|
||||
#define NOMINMAX
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMCX
|
||||
#define NOHELP
|
||||
#define NOCOMM
|
||||
#include <Unknwn.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "../inc/LibraryIncludes.h"
|
||||
|
||||
#include <wil/cppwinrt.h>
|
||||
|
||||
#include <winrt/Windows.system.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
|
||||
#include <wil/resource.h>
|
||||
#include <wil/win32_helpers.h>
|
||||
|
||||
#include <cppwinrt_utils.h>
|
||||
@@ -30,8 +30,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
{
|
||||
// Function Description:
|
||||
// - launches the client application attached to the new pseudoconsole
|
||||
HRESULT ConptyConnection::_LaunchAttachedClient() noexcept
|
||||
try
|
||||
void ConptyConnection::_LaunchAttachedClient()
|
||||
{
|
||||
STARTUPINFOEX siEx{ 0 };
|
||||
siEx.StartupInfo.cb = sizeof(STARTUPINFOEX);
|
||||
@@ -43,15 +42,16 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
auto attrList{ std::make_unique<std::byte[]>(size) };
|
||||
#pragma warning(suppress : 26490) // We have to use reinterpret_cast because we allocated a byte array as a proxy for the adjustable size list.
|
||||
siEx.lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(attrList.get());
|
||||
RETURN_IF_WIN32_BOOL_FALSE(InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, &size));
|
||||
THROW_IF_WIN32_BOOL_FALSE(InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, &size));
|
||||
|
||||
RETURN_IF_WIN32_BOOL_FALSE(UpdateProcThreadAttribute(siEx.lpAttributeList,
|
||||
0,
|
||||
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
|
||||
_hPC.get(),
|
||||
sizeof(HPCON),
|
||||
nullptr,
|
||||
nullptr));
|
||||
THROW_IF_WIN32_BOOL_FALSE(UpdateProcThreadAttribute(
|
||||
siEx.lpAttributeList,
|
||||
0,
|
||||
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
|
||||
_hPC.get(),
|
||||
sizeof(HPCON),
|
||||
nullptr,
|
||||
nullptr));
|
||||
|
||||
auto cmdline{ wil::ExpandEnvironmentStringsW<std::wstring>(_commandline.c_str()) }; // mutable copy -- required for CreateProcessW
|
||||
auto environment = _initialEnv;
|
||||
@@ -72,7 +72,11 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
std::wstring additionalWslEnv;
|
||||
|
||||
// WSLENV.2: Figure out what variables are already in WSLENV.
|
||||
std::unordered_set<std::wstring_view> wslEnvVars;
|
||||
std::unordered_set<std::wstring> wslEnvVars{
|
||||
// We never want to put a custom Windows PATH variable into WSLENV,
|
||||
// because that would override WSL's computation of the NIX PATH.
|
||||
L"PATH",
|
||||
};
|
||||
for (const auto& part : til::split_iterator{ std::wstring_view{ wslEnv }, L':' })
|
||||
{
|
||||
// Each part may contain a variable name and flags (e.g., /p, /l, etc.)
|
||||
@@ -97,25 +101,19 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
}
|
||||
}
|
||||
|
||||
// add additional env vars
|
||||
if (_environment)
|
||||
{
|
||||
// Order the environment variable names so that resolution order is consistent
|
||||
// NOTE(lhecker): I'm like 99% sure that this is unnecessary.
|
||||
std::set<std::wstring, til::env_key_sorter> keys{};
|
||||
for (const auto item : _environment)
|
||||
{
|
||||
keys.insert(std::wstring{ item.Key() });
|
||||
}
|
||||
// add additional env vars
|
||||
for (const auto& key : keys)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto key = item.Key();
|
||||
// This will throw if the value isn't a string. If that
|
||||
// happens, then just skip this entry.
|
||||
const auto value = winrt::unbox_value<hstring>(_environment.Lookup(key));
|
||||
|
||||
environment.set_user_environment_var(key.c_str(), value.c_str());
|
||||
environment.set_user_environment_var(key, value);
|
||||
|
||||
// WSLENV.4: Add custom user environment variables to WSLENV.
|
||||
if (wslEnvVars.emplace(key).second)
|
||||
@@ -166,7 +164,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
auto [newCommandLine, newStartingDirectory] = Utils::MangleStartingDirectoryForWSL(cmdline, _startingDirectory);
|
||||
const auto startingDirectory = newStartingDirectory.size() > 0 ? newStartingDirectory.c_str() : nullptr;
|
||||
|
||||
RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(
|
||||
THROW_IF_WIN32_BOOL_FALSE(CreateProcessW(
|
||||
nullptr,
|
||||
newCommandLine.data(),
|
||||
nullptr, // lpProcessAttributes
|
||||
@@ -193,10 +191,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
TraceLoggingWideString(_clientName.c_str(), "Client", "The attached client process"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
// Who decided that?
|
||||
#pragma warning(suppress : 26455) // Default constructor should not throw. Declare it 'noexcept' (f.6).
|
||||
@@ -345,7 +340,13 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
auto ownedSignal = duplicateHandle(signal);
|
||||
auto ownedReference = duplicateHandle(reference);
|
||||
auto ownedServer = duplicateHandle(server);
|
||||
auto ownedClient = duplicateHandle(client);
|
||||
wil::unique_hfile ownedClient;
|
||||
LOG_IF_WIN32_BOOL_FALSE(DuplicateHandle(GetCurrentProcess(), client, GetCurrentProcess(), ownedClient.addressof(), PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_SET_INFORMATION | SYNCHRONIZE, FALSE, 0));
|
||||
if (!ownedClient)
|
||||
{
|
||||
// If we couldn't reopen the handle with SET_INFORMATION, which may be required to do things like QoS management, fall back.
|
||||
ownedClient = duplicateHandle(client);
|
||||
}
|
||||
|
||||
THROW_IF_FAILED(ConptyPackPseudoConsole(ownedServer.get(), ownedReference.get(), ownedSignal.get(), &_hPC));
|
||||
ownedServer.release();
|
||||
@@ -418,7 +419,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
THROW_IF_FAILED(ConptyShowHidePseudoConsole(_hPC.get(), _initialVisibility));
|
||||
}
|
||||
|
||||
THROW_IF_FAILED(_LaunchAttachedClient());
|
||||
_LaunchAttachedClient();
|
||||
}
|
||||
// But if it was an inbound handoff... attempt to synchronize the size of it with what our connection
|
||||
// window is expecting it to be on the first layout.
|
||||
@@ -538,6 +539,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
DWORD exitCode{ 0 };
|
||||
GetExitCodeProcess(_piClient.hProcess, &exitCode);
|
||||
|
||||
_piClient.reset();
|
||||
|
||||
// Signal the closing or failure of the process.
|
||||
// exitCode might be STILL_ACTIVE if a client has called FreeConsole() and
|
||||
// thus caused the tab to close, even though the CLI app is still running.
|
||||
@@ -654,6 +657,12 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t ConptyConnection::RootProcessHandle() noexcept
|
||||
{
|
||||
#pragma warning(disable : 26490) // Don't use reinterpret_cast (type.1).
|
||||
return reinterpret_cast<uint64_t>(_piClient.hProcess);
|
||||
}
|
||||
|
||||
void ConptyConnection::Close() noexcept
|
||||
try
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
void ShowHide(const bool show);
|
||||
|
||||
void ReparentWindow(const uint64_t newParent);
|
||||
uint64_t RootProcessHandle() noexcept;
|
||||
|
||||
winrt::hstring Commandline() const;
|
||||
winrt::hstring StartingTitle() const;
|
||||
@@ -58,7 +59,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
static HRESULT NewHandoff(HANDLE* in, HANDLE* out, HANDLE signal, HANDLE reference, HANDLE server, HANDLE client, const TERMINAL_STARTUP_INFO* startupInfo) noexcept;
|
||||
static winrt::hstring _commandlineFromProcess(HANDLE process);
|
||||
|
||||
HRESULT _LaunchAttachedClient() noexcept;
|
||||
void _LaunchAttachedClient();
|
||||
void _indicateExitWithStatus(unsigned int status) noexcept;
|
||||
static std::wstring _formatStatus(uint32_t status);
|
||||
void _LastConPtyClientDisconnected() noexcept;
|
||||
|
||||
@@ -21,6 +21,8 @@ namespace Microsoft.Terminal.TerminalConnection
|
||||
|
||||
void ReparentWindow(UInt64 newParent);
|
||||
|
||||
UInt64 RootProcessHandle();
|
||||
|
||||
static event NewConnectionHandler NewConnection;
|
||||
static void StartInboundListener();
|
||||
|
||||
|
||||
@@ -104,8 +104,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// GH#8969: pre-seed working directory to prevent potential races
|
||||
_terminal->SetWorkingDirectory(_settings->StartingDirectory());
|
||||
|
||||
auto pfnCopyToClipboard = [this](auto&& PH1) { _terminalCopyToClipboard(std::forward<decltype(PH1)>(PH1)); };
|
||||
_terminal->SetCopyToClipboardCallback(pfnCopyToClipboard);
|
||||
_terminal->SetCopyToClipboardCallback([this](wil::zwstring_view wstr) {
|
||||
WriteToClipboard.raise(*this, winrt::make<WriteToClipboardEventArgs>(winrt::hstring{ std::wstring_view{ wstr } }, std::string{}, std::string{}));
|
||||
});
|
||||
|
||||
auto pfnWarningBell = [this] { _terminalWarningBell(); };
|
||||
_terminal->SetWarningBellCallback(pfnWarningBell);
|
||||
@@ -148,12 +149,27 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
_renderer->SetBackgroundColorChangedCallback([this]() { _rendererBackgroundColorChanged(); });
|
||||
_renderer->SetFrameColorChangedCallback([this]() { _rendererTabColorChanged(); });
|
||||
_renderer->SetRendererEnteredErrorStateCallback([this]() { RendererEnteredErrorState.raise(nullptr, nullptr); });
|
||||
_renderer->SetRendererEnteredErrorStateCallback([this]() { _rendererEnteredErrorState(); });
|
||||
}
|
||||
|
||||
UpdateSettings(settings, unfocusedAppearance);
|
||||
}
|
||||
|
||||
void ControlCore::_rendererEnteredErrorState()
|
||||
{
|
||||
// The first time the renderer fails out (after all of its own retries), switch it to D2D and WARP
|
||||
// and force it to try again. If it _still_ fails, we can let it halt.
|
||||
if (_renderFailures++ == 0)
|
||||
{
|
||||
const auto lock = _terminal->LockForWriting();
|
||||
_renderEngine->SetGraphicsAPI(parseGraphicsAPI(GraphicsAPI::Direct2D));
|
||||
_renderEngine->SetSoftwareRendering(true);
|
||||
_renderer->EnablePainting();
|
||||
return;
|
||||
}
|
||||
RendererEnteredErrorState.raise(nullptr, nullptr);
|
||||
}
|
||||
|
||||
void ControlCore::_setupDispatcherAndCallbacks()
|
||||
{
|
||||
// Get our dispatcher. If we're hosted in-proc with XAML, this will get
|
||||
@@ -174,8 +190,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
//
|
||||
// NOTE: Calling UpdatePatternLocations from a background
|
||||
// thread is a workaround for us to hit GH#12607 less often.
|
||||
shared->outputIdle = std::make_unique<til::debounced_func_trailing<>>(
|
||||
std::chrono::milliseconds{ 100 },
|
||||
shared->outputIdle = std::make_unique<til::throttled_func<>>(
|
||||
til::throttled_func_options{
|
||||
.delay = std::chrono::milliseconds{ 100 },
|
||||
.debounce = true,
|
||||
.trailing = true,
|
||||
},
|
||||
[this, weakThis = get_weak(), dispatcher = _dispatcher]() {
|
||||
dispatcher.TryEnqueue(DispatcherQueuePriority::Normal, [weakThis]() {
|
||||
if (const auto self = weakThis.get(); self && !self->_IsClosing())
|
||||
@@ -195,8 +215,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
// If you rapidly show/hide Windows Terminal, something about GotFocus()/LostFocus() gets broken.
|
||||
// We'll then receive easily 10+ such calls from WinUI the next time the application is shown.
|
||||
shared->focusChanged = std::make_unique<til::debounced_func_trailing<bool>>(
|
||||
std::chrono::milliseconds{ 25 },
|
||||
shared->focusChanged = std::make_unique<til::throttled_func<bool>>(
|
||||
til::throttled_func_options{
|
||||
.delay = std::chrono::milliseconds{ 25 },
|
||||
.debounce = true,
|
||||
.trailing = true,
|
||||
},
|
||||
[this](const bool focused) {
|
||||
// Theoretically `debounced_func_trailing` should call `WaitForThreadpoolTimerCallbacks()`
|
||||
// with cancel=true on destruction, which should ensure that our use of `this` here is safe.
|
||||
@@ -204,9 +228,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
});
|
||||
|
||||
// Scrollbar updates are also expensive (XAML), so we'll throttle them as well.
|
||||
shared->updateScrollBar = std::make_shared<ThrottledFuncTrailing<Control::ScrollPositionChangedArgs>>(
|
||||
shared->updateScrollBar = std::make_shared<ThrottledFunc<Control::ScrollPositionChangedArgs>>(
|
||||
_dispatcher,
|
||||
std::chrono::milliseconds{ 8 },
|
||||
til::throttled_func_options{
|
||||
.delay = std::chrono::milliseconds{ 8 },
|
||||
.trailing = true,
|
||||
},
|
||||
[weakThis = get_weak()](const auto& update) {
|
||||
if (auto core{ weakThis.get() }; core && !core->_IsClosing())
|
||||
{
|
||||
@@ -322,6 +349,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void ControlCore::HardResetWithoutErase()
|
||||
{
|
||||
const auto lock = _terminal->LockForWriting();
|
||||
_terminal->HardResetWithoutErase();
|
||||
}
|
||||
|
||||
bool ControlCore::Initialize(const float actualWidth,
|
||||
const float actualHeight,
|
||||
const float compositionScale)
|
||||
@@ -588,7 +621,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
else if (vkey == VK_RETURN && !mods.IsCtrlPressed() && !mods.IsAltPressed())
|
||||
{
|
||||
// [Shift +] Enter --> copy text
|
||||
CopySelectionToClipboard(mods.IsShiftPressed(), false, nullptr);
|
||||
CopySelectionToClipboard(mods.IsShiftPressed(), false, _settings->CopyFormatting());
|
||||
_terminal->ClearSelection();
|
||||
_updateSelectionUI();
|
||||
return true;
|
||||
@@ -899,6 +932,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_renderEngine->SetSoftwareRendering(_settings->SoftwareRendering());
|
||||
// Inform the renderer of our opacity
|
||||
_renderEngine->EnableTransparentBackground(_isBackgroundTransparent());
|
||||
_renderFailures = 0; // We may have changed the engine; reset the failure counter.
|
||||
|
||||
// Trigger a redraw to repaint the window background and tab colors.
|
||||
_renderer->TriggerRedrawAll(true, true);
|
||||
@@ -1252,89 +1286,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_updateSelectionUI();
|
||||
}
|
||||
|
||||
static wil::unique_close_clipboard_call _openClipboard(HWND hwnd)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
// OpenClipboard may fail to acquire the internal lock --> retry.
|
||||
for (DWORD sleep = 10;; sleep *= 2)
|
||||
{
|
||||
if (OpenClipboard(hwnd))
|
||||
{
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
// 10 iterations
|
||||
if (sleep > 10000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Sleep(sleep);
|
||||
}
|
||||
|
||||
return wil::unique_close_clipboard_call{ success };
|
||||
}
|
||||
|
||||
static void _copyToClipboard(const UINT format, const void* src, const size_t bytes)
|
||||
{
|
||||
wil::unique_hglobal handle{ THROW_LAST_ERROR_IF_NULL(GlobalAlloc(GMEM_MOVEABLE, bytes)) };
|
||||
|
||||
const auto locked = GlobalLock(handle.get());
|
||||
memcpy(locked, src, bytes);
|
||||
GlobalUnlock(handle.get());
|
||||
|
||||
THROW_LAST_ERROR_IF_NULL(SetClipboardData(format, handle.get()));
|
||||
handle.release();
|
||||
}
|
||||
|
||||
static void _copyToClipboardRegisteredFormat(const wchar_t* format, const void* src, size_t bytes)
|
||||
{
|
||||
const auto id = RegisterClipboardFormatW(format);
|
||||
if (!id)
|
||||
{
|
||||
LOG_LAST_ERROR();
|
||||
return;
|
||||
}
|
||||
_copyToClipboard(id, src, bytes);
|
||||
}
|
||||
|
||||
static void copyToClipboard(wil::zwstring_view text, std::string_view html, std::string_view rtf)
|
||||
{
|
||||
const auto clipboard = _openClipboard(nullptr);
|
||||
if (!clipboard)
|
||||
{
|
||||
LOG_LAST_ERROR();
|
||||
return;
|
||||
}
|
||||
|
||||
EmptyClipboard();
|
||||
|
||||
if (!text.empty())
|
||||
{
|
||||
// As per: https://learn.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats
|
||||
// CF_UNICODETEXT: [...] A null character signals the end of the data.
|
||||
// --> We add +1 to the length. This works because .c_str() is null-terminated.
|
||||
_copyToClipboard(CF_UNICODETEXT, text.c_str(), (text.size() + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
if (!html.empty())
|
||||
{
|
||||
_copyToClipboardRegisteredFormat(L"HTML Format", html.data(), html.size());
|
||||
}
|
||||
|
||||
if (!rtf.empty())
|
||||
{
|
||||
_copyToClipboardRegisteredFormat(L"Rich Text Format", rtf.data(), rtf.size());
|
||||
}
|
||||
}
|
||||
|
||||
// Called when the Terminal wants to set something to the clipboard, i.e.
|
||||
// when an OSC 52 is emitted.
|
||||
void ControlCore::_terminalCopyToClipboard(wil::zwstring_view wstr)
|
||||
{
|
||||
copyToClipboard(wstr, {}, {});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Given a copy-able selection, get the selected text from the buffer and send it to the
|
||||
// Windows Clipboard (CascadiaWin32:main.cpp).
|
||||
@@ -1345,7 +1296,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// if we should defer which formats are copied to the global setting
|
||||
bool ControlCore::CopySelectionToClipboard(bool singleLine,
|
||||
bool withControlSequences,
|
||||
const Windows::Foundation::IReference<CopyFormat>& formats)
|
||||
const CopyFormat formats)
|
||||
{
|
||||
::Microsoft::Terminal::Core::Terminal::TextCopyData payload;
|
||||
{
|
||||
@@ -1357,19 +1308,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return false;
|
||||
}
|
||||
|
||||
// use action's copyFormatting if it's present, else fall back to globally
|
||||
// set copyFormatting.
|
||||
const auto copyFormats = formats != nullptr ? formats.Value() : _settings->CopyFormatting();
|
||||
|
||||
const auto copyHtml = WI_IsFlagSet(copyFormats, CopyFormat::HTML);
|
||||
const auto copyRtf = WI_IsFlagSet(copyFormats, CopyFormat::RTF);
|
||||
const auto copyHtml = WI_IsFlagSet(formats, CopyFormat::HTML);
|
||||
const auto copyRtf = WI_IsFlagSet(formats, CopyFormat::RTF);
|
||||
|
||||
// extract text from buffer
|
||||
// RetrieveSelectedTextFromBuffer will lock while it's reading
|
||||
payload = _terminal->RetrieveSelectedTextFromBuffer(singleLine, withControlSequences, copyHtml, copyRtf);
|
||||
}
|
||||
|
||||
copyToClipboard(payload.plainText, payload.html, payload.rtf);
|
||||
WriteToClipboard.raise(
|
||||
*this,
|
||||
winrt::make<WriteToClipboardEventArgs>(
|
||||
winrt::hstring{ payload.plainText },
|
||||
std::move(payload.html),
|
||||
std::move(payload.rtf)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1738,7 +1690,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - resetOnly: If true, only Reset() will be called, if anything. FindNext() will never be called.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
SearchResults ControlCore::Search(SearchRequest request)
|
||||
SearchResults ControlCore::Search(const SearchRequest& request)
|
||||
{
|
||||
const auto lock = _terminal->LockForWriting();
|
||||
|
||||
@@ -1747,15 +1699,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
WI_SetFlagIf(flags, SearchFlag::RegularExpression, request.RegularExpression);
|
||||
const auto searchInvalidated = _searcher.IsStale(*_terminal.get(), request.Text, flags);
|
||||
|
||||
if (searchInvalidated || !request.ResetOnly)
|
||||
if (searchInvalidated || request.ExecuteSearch)
|
||||
{
|
||||
std::vector<til::point_span> oldResults;
|
||||
til::point_span oldFocused;
|
||||
|
||||
if (const auto focused = _terminal->GetSearchHighlightFocused())
|
||||
{
|
||||
oldFocused = *focused;
|
||||
}
|
||||
|
||||
if (searchInvalidated)
|
||||
{
|
||||
@@ -1764,18 +1710,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_terminal->SetSearchHighlights(_searcher.Results());
|
||||
}
|
||||
|
||||
if (!request.ResetOnly)
|
||||
if (request.ExecuteSearch)
|
||||
{
|
||||
_searcher.FindNext(!request.GoForward);
|
||||
}
|
||||
|
||||
_terminal->SetSearchHighlightFocused(gsl::narrow<size_t>(std::max<ptrdiff_t>(0, _searcher.CurrentMatch())));
|
||||
_renderer->TriggerSearchHighlight(oldResults);
|
||||
}
|
||||
|
||||
if (const auto focused = _terminal->GetSearchHighlightFocused(); focused && *focused != oldFocused)
|
||||
{
|
||||
_terminal->ScrollToSearchHighlight(request.ScrollOffset);
|
||||
}
|
||||
if (request.ScrollIntoView)
|
||||
{
|
||||
_terminal->ScrollToSearchHighlight(request.ScrollOffset);
|
||||
}
|
||||
|
||||
int32_t totalMatches = 0;
|
||||
@@ -1982,6 +1928,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
// The lock must be held, because it calls into IRenderData which is shared state.
|
||||
const auto lock = _terminal->LockForWriting();
|
||||
_renderFailures = 0;
|
||||
_renderer->EnablePainting();
|
||||
}
|
||||
|
||||
@@ -2069,7 +2016,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_terminal->MultiClickSelection(terminalPosition, mode);
|
||||
selectionNeedsToBeCopied = true;
|
||||
}
|
||||
else if (_settings->RepositionCursorWithMouse()) // This is also mode==Char && !shiftEnabled
|
||||
else if (_settings->RepositionCursorWithMouse() && !selectionNeedsToBeCopied) // Don't reposition cursor if this is part of a selection operation
|
||||
{
|
||||
_repositionCursorWithMouse(terminalPosition);
|
||||
}
|
||||
@@ -2757,15 +2704,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
}
|
||||
|
||||
safe_void_coroutine ControlCore::_terminalCompletionsChanged(std::wstring_view menuJson,
|
||||
unsigned int replaceLength)
|
||||
void ControlCore::_terminalCompletionsChanged(std::wstring_view menuJson, unsigned int replaceLength)
|
||||
{
|
||||
auto args = winrt::make_self<CompletionsChangedEventArgs>(winrt::hstring{ menuJson },
|
||||
replaceLength);
|
||||
|
||||
co_await winrt::resume_background();
|
||||
|
||||
CompletionsChanged.raise(*this, *args);
|
||||
CompletionsChanged.raise(*this, winrt::make<CompletionsChangedEventArgs>(winrt::hstring{ menuJson }, replaceLength));
|
||||
}
|
||||
|
||||
// Select the region of text between [s.start, s.end), in buffer space
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void SendInput(std::wstring_view wstr);
|
||||
void PasteText(const winrt::hstring& hstr);
|
||||
bool CopySelectionToClipboard(bool singleLine, bool withControlSequences, const Windows::Foundation::IReference<CopyFormat>& formats);
|
||||
bool CopySelectionToClipboard(bool singleLine, bool withControlSequences, const CopyFormat formats);
|
||||
void SelectAll();
|
||||
void ClearSelection();
|
||||
bool ToggleBlockSelection();
|
||||
@@ -228,7 +228,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void SetSelectionAnchor(const til::point position);
|
||||
void SetEndSelectionPoint(const til::point position);
|
||||
|
||||
SearchResults Search(SearchRequest request);
|
||||
SearchResults Search(const SearchRequest& request);
|
||||
const std::vector<til::point_span>& SearchResultRows() const noexcept;
|
||||
void ClearSearch();
|
||||
|
||||
@@ -260,6 +260,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
TerminalConnection::ITerminalConnection Connection();
|
||||
void Connection(const TerminalConnection::ITerminalConnection& connection);
|
||||
void HardResetWithoutErase();
|
||||
|
||||
void AnchorContextMenu(til::point viewportRelativeCharacterPosition);
|
||||
|
||||
@@ -277,6 +278,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
til::typed_event<IInspectable, Control::FontSizeChangedArgs> FontSizeChanged;
|
||||
|
||||
til::typed_event<IInspectable, Control::TitleChangedEventArgs> TitleChanged;
|
||||
til::typed_event<IInspectable, Control::WriteToClipboardEventArgs> WriteToClipboard;
|
||||
til::typed_event<> WarningBell;
|
||||
til::typed_event<> TabColorChanged;
|
||||
til::typed_event<> BackgroundColorChanged;
|
||||
@@ -307,9 +309,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
private:
|
||||
struct SharedState
|
||||
{
|
||||
std::unique_ptr<til::debounced_func_trailing<>> outputIdle;
|
||||
std::unique_ptr<til::debounced_func_trailing<bool>> focusChanged;
|
||||
std::shared_ptr<ThrottledFuncTrailing<Control::ScrollPositionChangedArgs>> updateScrollBar;
|
||||
std::unique_ptr<til::throttled_func<>> outputIdle;
|
||||
std::unique_ptr<til::throttled_func<bool>> focusChanged;
|
||||
std::shared_ptr<ThrottledFunc<Control::ScrollPositionChangedArgs>> updateScrollBar;
|
||||
};
|
||||
|
||||
void _setupDispatcherAndCallbacks();
|
||||
@@ -325,7 +327,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void _sendInputToConnection(std::wstring_view wstr);
|
||||
|
||||
#pragma region TerminalCoreCallbacks
|
||||
void _terminalCopyToClipboard(wil::zwstring_view wstr);
|
||||
void _terminalWarningBell();
|
||||
void _terminalTitleChanged(std::wstring_view wstr);
|
||||
void _terminalScrollPositionChanged(const int viewTop,
|
||||
@@ -339,7 +340,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void _terminalSearchMissingCommand(std::wstring_view missingCommand, const til::CoordType& bufferRow);
|
||||
void _terminalWindowSizeChanged(int32_t width, int32_t height);
|
||||
|
||||
safe_void_coroutine _terminalCompletionsChanged(std::wstring_view menuJson, unsigned int replaceLength);
|
||||
void _terminalCompletionsChanged(std::wstring_view menuJson, unsigned int replaceLength);
|
||||
#pragma endregion
|
||||
|
||||
#pragma region RendererCallbacks
|
||||
@@ -347,6 +348,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
safe_void_coroutine _renderEngineSwapChainChanged(const HANDLE handle);
|
||||
void _rendererBackgroundColorChanged();
|
||||
void _rendererTabColorChanged();
|
||||
void _rendererEnteredErrorState();
|
||||
#pragma endregion
|
||||
|
||||
void _raiseReadOnlyWarning();
|
||||
@@ -401,6 +403,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
float _panelWidth{ 0 };
|
||||
float _panelHeight{ 0 };
|
||||
float _compositionScale{ 0 };
|
||||
uint8_t _renderFailures{ 0 };
|
||||
|
||||
// Audio stuff.
|
||||
MidiAudio _midiAudio;
|
||||
|
||||
@@ -55,7 +55,8 @@ namespace Microsoft.Terminal.Control
|
||||
Boolean GoForward;
|
||||
Boolean CaseSensitive;
|
||||
Boolean RegularExpression;
|
||||
Boolean ResetOnly;
|
||||
Boolean ExecuteSearch;
|
||||
Boolean ScrollIntoView;
|
||||
Int32 ScrollOffset;
|
||||
};
|
||||
|
||||
@@ -97,6 +98,7 @@ namespace Microsoft.Terminal.Control
|
||||
void ApplyAppearance(Boolean focused);
|
||||
|
||||
Microsoft.Terminal.TerminalConnection.ITerminalConnection Connection;
|
||||
void HardResetWithoutErase();
|
||||
|
||||
IControlSettings Settings { get; };
|
||||
IControlAppearance FocusedAppearance { get; };
|
||||
@@ -185,6 +187,7 @@ namespace Microsoft.Terminal.Control
|
||||
|
||||
// These events are called from some background thread
|
||||
event Windows.Foundation.TypedEventHandler<Object, TitleChangedEventArgs> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, WriteToClipboardEventArgs> WriteToClipboard;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> WarningBell;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TabColorChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> BackgroundColorChanged;
|
||||
|
||||
@@ -55,6 +55,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
self->Attached.raise(*self, nullptr);
|
||||
}
|
||||
});
|
||||
|
||||
// GH#14464: Mark mode and quick-edit (shift+arrow) selections update
|
||||
// the selection through ControlCore, bypassing SetEndSelectionPoint.
|
||||
// Listen for selection changes so _selectionNeedsToBeCopied is set
|
||||
// for ALL selection types, not just mouse drag.
|
||||
_core->UpdateSelectionMarkers([weakThis = get_weak()](auto&&, auto&&) {
|
||||
if (auto self{ weakThis.get() })
|
||||
{
|
||||
if (self->_core->HasSelection())
|
||||
{
|
||||
self->_selectionNeedsToBeCopied = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
uint64_t ControlInteractivity::Id()
|
||||
@@ -199,7 +213,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// if we should defer which formats are copied to the global setting
|
||||
bool ControlInteractivity::CopySelectionToClipboard(bool singleLine,
|
||||
bool withControlSequences,
|
||||
const Windows::Foundation::IReference<CopyFormat>& formats)
|
||||
const CopyFormat formats)
|
||||
{
|
||||
if (_core)
|
||||
{
|
||||
@@ -315,13 +329,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to copy the text and clear the selection
|
||||
const auto successfulCopy = CopySelectionToClipboard(shiftEnabled, false, nullptr);
|
||||
// GH#19942, GH#14464: Don't re-copy a selection that was
|
||||
// already copied via copyOnSelect on mouse-up. But DO copy
|
||||
// if the selection was made via mark mode or modified with
|
||||
// quick-edit keys (shift+arrow), since those paths never
|
||||
// triggered an automatic copy.
|
||||
const auto copied = (_selectionNeedsToBeCopied || !_core->CopyOnSelect()) &&
|
||||
CopySelectionToClipboard(shiftEnabled, false, _core->Settings().CopyFormatting());
|
||||
_core->ClearSelection();
|
||||
if (_core->CopyOnSelect() || !successfulCopy)
|
||||
if (_core->CopyOnSelect() || !copied)
|
||||
{
|
||||
// CopyOnSelect: right click always pastes!
|
||||
// Otherwise: no selection --> paste
|
||||
// CopyOnSelect: right-click always pastes.
|
||||
// Otherwise: no selection → paste.
|
||||
RequestPasteTextFromClipboard();
|
||||
}
|
||||
}
|
||||
@@ -461,7 +480,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// IMPORTANT!
|
||||
// DO NOT clear the selection here!
|
||||
// Otherwise, the selection will be cleared immediately after you make it.
|
||||
CopySelectionToClipboard(false, false, nullptr);
|
||||
CopySelectionToClipboard(false, false, _core->Settings().CopyFormatting());
|
||||
}
|
||||
|
||||
_singleClickTouchdownPos = std::nullopt;
|
||||
@@ -485,7 +504,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - modifiers: The modifiers pressed during this event, in the form of a VirtualKeyModifiers
|
||||
// - delta: the mouse wheel delta that triggered this event.
|
||||
bool ControlInteractivity::MouseWheel(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
|
||||
const int32_t delta,
|
||||
const Core::Point delta,
|
||||
const Core::Point pixelPosition,
|
||||
const Control::MouseButtonState buttonState)
|
||||
{
|
||||
@@ -506,9 +525,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// PointerPoint to work with. So, we're just going to do a
|
||||
// mousewheel event manually
|
||||
return _sendMouseEventHelper(terminalPosition,
|
||||
WM_MOUSEWHEEL,
|
||||
delta.Y != 0 ? WM_MOUSEWHEEL : WM_MOUSEHWHEEL,
|
||||
modifiers,
|
||||
::base::saturated_cast<short>(delta),
|
||||
::base::saturated_cast<short>(delta.Y != 0 ? delta.Y : delta.X),
|
||||
buttonState);
|
||||
}
|
||||
|
||||
@@ -517,15 +536,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
if (ctrlPressed && shiftPressed && _core->Settings().ScrollToChangeOpacity())
|
||||
{
|
||||
_mouseTransparencyHandler(delta);
|
||||
_mouseTransparencyHandler(delta.Y);
|
||||
}
|
||||
else if (ctrlPressed && !shiftPressed && _core->Settings().ScrollToZoom())
|
||||
{
|
||||
_mouseZoomHandler(delta);
|
||||
_mouseZoomHandler(delta.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
_mouseScrollHandler(delta, pixelPosition, WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown));
|
||||
_mouseScrollHandler(delta.Y, pixelPosition, WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -659,7 +678,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return _core->IsVtMouseModeEnabled();
|
||||
}
|
||||
|
||||
bool ControlInteractivity::_shouldSendAlternateScroll(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta)
|
||||
bool ControlInteractivity::_shouldSendAlternateScroll(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const Core::Point delta)
|
||||
{
|
||||
// If the user is holding down Shift, suppress mouse events
|
||||
// TODO GH#4875: disable/customize this functionality
|
||||
@@ -667,7 +686,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _core->ShouldSendAlternateScroll(WM_MOUSEWHEEL, delta);
|
||||
if (delta.Y != 0)
|
||||
{
|
||||
return _core->ShouldSendAlternateScroll(WM_MOUSEWHEEL, delta.Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _core->ShouldSendAlternateScroll(WM_MOUSEHWHEEL, delta.X);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void TouchReleased();
|
||||
|
||||
bool MouseWheel(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
|
||||
const int32_t delta,
|
||||
const Core::Point delta,
|
||||
const Core::Point pixelPosition,
|
||||
const Control::MouseButtonState state);
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
bool CopySelectionToClipboard(bool singleLine,
|
||||
bool withControlSequences,
|
||||
const Windows::Foundation::IReference<CopyFormat>& formats);
|
||||
const CopyFormat formats);
|
||||
void RequestPasteTextFromClipboard();
|
||||
void SetEndSelectionPoint(const Core::Point pixelPosition);
|
||||
|
||||
@@ -153,7 +153,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void _hyperlinkHandler(const std::wstring_view uri);
|
||||
bool _canSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers);
|
||||
bool _shouldSendAlternateScroll(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta);
|
||||
bool _shouldSendAlternateScroll(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const Core::Point delta);
|
||||
|
||||
til::point _getTerminalPosition(const til::point pixelPosition, bool roundToNearestCell);
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Microsoft.Terminal.Control
|
||||
|
||||
InteractivityAutomationPeer OnCreateAutomationPeer();
|
||||
|
||||
Boolean CopySelectionToClipboard(Boolean singleLine, Boolean withControlSequences, Windows.Foundation.IReference<CopyFormat> formats);
|
||||
Boolean CopySelectionToClipboard(Boolean singleLine, Boolean withControlSequences, CopyFormat formats);
|
||||
void RequestPasteTextFromClipboard();
|
||||
void SetEndSelectionPoint(Microsoft.Terminal.Core.Point point);
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Microsoft.Terminal.Control
|
||||
void TouchReleased();
|
||||
|
||||
Boolean MouseWheel(Microsoft.Terminal.Core.ControlKeyStates modifiers,
|
||||
Int32 delta,
|
||||
Microsoft.Terminal.Core.Point delta,
|
||||
Microsoft.Terminal.Core.Point pixelPosition,
|
||||
MouseButtonState state);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "FontSizeChangedArgs.g.cpp"
|
||||
#include "TitleChangedEventArgs.g.cpp"
|
||||
#include "ContextMenuRequestedEventArgs.g.cpp"
|
||||
#include "WriteToClipboardEventArgs.g.cpp"
|
||||
#include "PasteFromClipboardEventArgs.g.cpp"
|
||||
#include "OpenHyperlinkEventArgs.g.cpp"
|
||||
#include "NoticeEventArgs.g.cpp"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "FontSizeChangedArgs.g.h"
|
||||
#include "TitleChangedEventArgs.g.h"
|
||||
#include "ContextMenuRequestedEventArgs.g.h"
|
||||
#include "WriteToClipboardEventArgs.g.h"
|
||||
#include "PasteFromClipboardEventArgs.g.h"
|
||||
#include "OpenHyperlinkEventArgs.g.h"
|
||||
#include "NoticeEventArgs.g.h"
|
||||
@@ -56,6 +57,32 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
WINRT_PROPERTY(winrt::Windows::Foundation::Point, Position);
|
||||
};
|
||||
|
||||
struct WriteToClipboardEventArgs : WriteToClipboardEventArgsT<WriteToClipboardEventArgs>
|
||||
{
|
||||
WriteToClipboardEventArgs(winrt::hstring&& plain, std::string&& html, std::string&& rtf) :
|
||||
_plain(std::move(plain)),
|
||||
_html(std::move(html)),
|
||||
_rtf(std::move(rtf))
|
||||
{
|
||||
}
|
||||
|
||||
winrt::hstring Plain() const noexcept { return _plain; }
|
||||
winrt::com_array<uint8_t> Html() noexcept { return _cast(_html); }
|
||||
winrt::com_array<uint8_t> Rtf() noexcept { return _cast(_rtf); }
|
||||
|
||||
private:
|
||||
static winrt::com_array<uint8_t> _cast(const std::string& str)
|
||||
{
|
||||
const auto beg = reinterpret_cast<const uint8_t*>(str.data());
|
||||
const auto len = str.size();
|
||||
return { beg, beg + len };
|
||||
}
|
||||
|
||||
winrt::hstring _plain;
|
||||
std::string _html;
|
||||
std::string _rtf;
|
||||
};
|
||||
|
||||
struct PasteFromClipboardEventArgs : public PasteFromClipboardEventArgsT<PasteFromClipboardEventArgs>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace Microsoft.Terminal.Control
|
||||
[flags]
|
||||
enum CopyFormat
|
||||
{
|
||||
None = 0x0,
|
||||
HTML = 0x1,
|
||||
RTF = 0x2,
|
||||
All = 0xffffffff
|
||||
@@ -31,6 +32,13 @@ namespace Microsoft.Terminal.Control
|
||||
AlphanumericHalfWidth,
|
||||
};
|
||||
|
||||
enum WarnAboutMultiLinePaste
|
||||
{
|
||||
Automatic,
|
||||
Always,
|
||||
Never,
|
||||
};
|
||||
|
||||
runtimeclass FontSizeChangedArgs
|
||||
{
|
||||
Int32 Width { get; };
|
||||
@@ -47,6 +55,13 @@ namespace Microsoft.Terminal.Control
|
||||
String Title;
|
||||
}
|
||||
|
||||
runtimeclass WriteToClipboardEventArgs
|
||||
{
|
||||
String Plain { get; }; // UTF-16, as required by CF_UNICODETEXT
|
||||
byte[] Html { get; }; // UTF-8, as required by "HTML Format"
|
||||
byte[] Rtf { get; }; // UTF-8, as required by "Rich Text Format"
|
||||
}
|
||||
|
||||
runtimeclass PasteFromClipboardEventArgs
|
||||
{
|
||||
void HandleClipboardData(String data);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user