mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-14 10:11:00 +00:00
Compare commits
4 Commits
dev/migrie
...
dev/miniks
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c41151aba7 | ||
|
|
9dfbdec349 | ||
|
|
9e8f891460 | ||
|
|
0bf347f428 |
@@ -46,14 +46,6 @@ steps:
|
||||
clean: true
|
||||
maximumCpuCount: true
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Check MSIX for common regressions'
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
$Package = Get-ChildItem -Recurse -Filter "CascadiaPackage_*.msix"
|
||||
.\build\scripts\Test-WindowsTerminalPackage.ps1 -Verbose -Path $Package.FullName
|
||||
|
||||
- task: VSTest@2
|
||||
displayName: 'Run Unit Tests'
|
||||
inputs:
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$true, ValueFromPipeline=$true,
|
||||
HelpMessage="Path to the .appx/.msix to validate")]
|
||||
[string]
|
||||
$Path,
|
||||
|
||||
[Parameter(HelpMessage="Path to Windows Kit")]
|
||||
[ValidateScript({Test-Path $_ -Type Leaf})]
|
||||
[string]
|
||||
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
If ($null -Eq (Get-Item $WindowsKitPath -EA:SilentlyContinue)) {
|
||||
Write-Error "Could not find a windows SDK at at `"$WindowsKitPath`".`nMake sure that WindowsKitPath points to a valid SDK."
|
||||
Exit 1
|
||||
}
|
||||
|
||||
$makeAppx = "$WindowsKitPath\x86\MakeAppx.exe"
|
||||
$makePri = "$WindowsKitPath\x86\MakePri.exe"
|
||||
|
||||
Function Expand-ApplicationPackage {
|
||||
Param(
|
||||
[Parameter(Mandatory, ValueFromPipeline)]
|
||||
[string]
|
||||
$Path
|
||||
)
|
||||
|
||||
$sentinelFile = New-TemporaryFile
|
||||
$directory = New-Item -Type Directory "$($sentinelFile.FullName)_Package"
|
||||
Remove-Item $sentinelFile -Force -EA:Ignore
|
||||
|
||||
& $makeAppx unpack /p $Path /d $directory /nv /o
|
||||
|
||||
If ($LastExitCode -Ne 0) {
|
||||
Throw "Failed to expand AppX"
|
||||
}
|
||||
|
||||
$directory
|
||||
}
|
||||
|
||||
Write-Verbose "Expanding $Path"
|
||||
$AppxPackageRoot = Expand-ApplicationPackage $Path
|
||||
$AppxPackageRootPath = $AppxPackageRoot.FullName
|
||||
|
||||
Write-Verbose "Expanded to $AppxPackageRootPath"
|
||||
|
||||
Try {
|
||||
& $makePri dump /if "$AppxPackageRootPath\resources.pri" /of "$AppxPackageRootPath\resources.pri.xml" /o
|
||||
If ($LastExitCode -Ne 0) {
|
||||
Throw "Failed to dump PRI"
|
||||
}
|
||||
|
||||
$Manifest = [xml](Get-Content "$AppxPackageRootPath\AppxManifest.xml")
|
||||
$PRIFile = [xml](Get-Content "$AppxPackageRootPath\resources.pri.xml")
|
||||
|
||||
### Check the activatable class entries for a few DLLs we need.
|
||||
$inProcServers = $Manifest.Package.Extensions.Extension.InProcessServer.Path
|
||||
$RequiredInProcServers = ("TerminalApp.dll", "TerminalControl.dll", "TerminalConnection.dll")
|
||||
|
||||
Write-Verbose "InProc Servers: $inProcServers"
|
||||
|
||||
ForEach ($req in $RequiredInProcServers) {
|
||||
If ($req -NotIn $inProcServers) {
|
||||
Throw "Failed to find $req in InProcServer list $inProcServers"
|
||||
}
|
||||
}
|
||||
|
||||
### Check that we have an App.xbf (which is a proxy for our resources having been merged)
|
||||
$resourceXpath = '/PriInfo/ResourceMap/ResourceMapSubtree[@name="Files"]/NamedResource[@name="App.xbf"]'
|
||||
$AppXbf = $PRIFile.SelectSingleNode($resourceXpath)
|
||||
If ($null -eq $AppXbf) {
|
||||
Throw "Failed to find App.xbf (TerminalApp project) in resources.pri"
|
||||
}
|
||||
} Finally {
|
||||
Remove-Item -Recurse -Force $AppxPackageRootPath
|
||||
}
|
||||
97
conpty.txt
97
conpty.txt
@@ -1,97 +0,0 @@
|
||||
[25l[2J[m[HMicrosoft Windows [Version 10.0.18936.1001]]0;C:\WINDOWS\system32\cmd.exe[?25h
|
||||
(c) 2019 Microsoft Corporation. All rights reserved.
|
||||
[30m[107m
|
||||
[11:54:25.95][97m[46m>c:\Users\migrie\dev\private\OpenConsole[36m[49m>[m [35m
|
||||
[1][m [43m[dev/migrie/f/passthrough-2019][m [94mmigrie[m@[32mMIGRIE-SURFBOOK[m>wsl.exe
|
||||
]0;C:\WINDOWS\system32\cmd.exe - wsl.exe[92mzadjii@migrie-surfbook[m:[94m/mnt/c/Users/migrie/dev/private/OpenConsole[m$ ]0;zadjii@migrie-surfbook: /mnt/c/Users/migrie/dev/private/OpenConsolevi README.md
|
||||
[25l[?2004h[22;0;0t[?2004h[H[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X[H[?25h[25l[38;2;128;128;128m[48;2;28;28;28m[30;1H"README.md" 177L, 11259C[96X[?25h[96C[25l[?2004l[?2004h[30;25H[?25h[25l[?2004l[?2004h[2;1H▽[?25h[25l[>c]10;?]11;?
|
||||
[H[?25h[38;2;0;95;0m[48;2;175;215;0m README.md [38;2;175;215;0m[48;2;18;18;18m [38;2;255;255;255m[97X[38;2;18;18;18m[97C◀[38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m buffers [38;2;78;78;78m[48;2;38;38;38m
|
||||
1 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Welcome\! [22m[38;2;128;128;128m[104X[38;2;78;78;78m[48;2;38;38;38m
|
||||
2 [38;2;128;128;128m[48;2;28;28;28m####[1m[38;2;215;95;0m This repository contains the source code for:[22m[38;2;128;128;128m[66X[38;2;78;78;78m[48;2;38;38;38m
|
||||
3 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
4 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m Windows Terminal[96X[38;2;78;78;78m[48;2;38;38;38m
|
||||
5 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m The Windows console host ([38;2;0;175;175mconhost.exe[38;2;128;128;128m)[74X[38;2;78;78;78m[48;2;38;38;38m
|
||||
6 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m Components shared between the two projects[70X[38;2;78;78;78m[48;2;38;38;38m
|
||||
7 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mColorTool[38;2;128;128;128m[103X[38;2;78;78;78m[48;2;38;38;38m
|
||||
8 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [m[112X[112C[38;2;128;128;128m[48;2;28;28;28m[38;2;78;78;78m[48;2;38;38;38m
|
||||
8 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mSample projects[38;2;128;128;128m that show how to consume the Window[61X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28ms Console APIs[102X[38;2;78;78;78m[48;2;38;38;38m
|
||||
9 [38;2;28;28;28m[48;2;78;78;78m [38;2;128;128;128m[48;2;28;28;28m[114X[38;2;78;78;78m[48;2;38;38;38m
|
||||
10 [38;2;128;128;128m[48;2;28;28;28m####[1m[38;2;215;95;0m Other related repositories include:[22m[38;2;128;128;128m[76X[38;2;78;78;78m[48;2;38;38;38m
|
||||
11 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mConsole API Documentation[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
12 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
13 [38;2;128;128;128m[48;2;28;28;28m###[1m[38;2;215;95;0m Build Status[22m[38;2;128;128;128m[100X[38;2;78;78;78m[48;2;38;38;38m
|
||||
14 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
15 [38;2;128;128;128m[48;2;28;28;28mProject|Build Status[96X[38;2;78;78;78m[48;2;38;38;38m
|
||||
16 [38;2;128;128;128m[48;2;28;28;28m---|---[109X[38;2;78;78;78m[48;2;38;38;38m
|
||||
17 [38;2;128;128;128m[48;2;28;28;28mTerminal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[18X[m[18C[77X[77C[38;2;128;128;128m[48;2;28;28;28m[38;2;78;78;78m[48;2;38;38;38m
|
||||
17 [38;2;128;128;128m[48;2;28;28;28mTerminal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[95X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
18 [38;2;128;128;128m[48;2;28;28;28mColorTool|[106X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
19 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
20 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Terminal & Console Overview[22m[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
21 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
22 [38;2;128;128;128m[48;2;28;28;28mPlease take a few minutes to review the overview below before diving into the code:[33X[38;2;78;78;78m[48;2;38;38;38m
|
||||
23 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
24 [38;2;128;128;128m[48;2;28;28;28m##[1m[38;2;215;95;0m Windows Terminal[22m[38;2;128;128;128m[97X[97C[?2004l[?2004h[?2004l[?2004h[?2004l[?2004h[?2004l[?2004h[?2004l[?2004h[?2004l[?2004h[?2004h[38;2;215;0;0m[48;2;215;95;0m[38;2;0;95;0m[48;2;175;215;0m
|
||||
[1mNORMAL[22m [38;2;175;215;0m[48;2;48;48;48m▶[38;2;158;158;158m ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m [38;2;18;18;18m<[38;2;255;255;255m markdown [38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 3% [1m␊ 6/177 ㏑[22m : 46 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]trailing [38;2;215;0;0m◀]0;/mnt/c/Users/migrie/dev/private/OpenConsole/README.md[25l[38;2;255;255;255m[48;2;18;18;18m[38;2;158;158;158m[48;2;48;48;48m[29;11H+0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m <[7;50H[?25h[25l[38;2;128;128;128m[48;2;28;28;28m[30;110H^[[7;50H[?25h[25l[30;110H [7;50H[?25h[25l[?2004h[30;1H:[109X[?25hq
|
||||
[?2004l]0;[?2004l[120X[120C[25l[23;0;0t[m[HMicrosoft Windows [Version 10.0.18936.1001][77X
|
||||
(c) 2019 Microsoft Corporation. All rights reserved.[68X
|
||||
[120X[30m[107m
|
||||
[11:54:25.95][97m[46m>c:\Users\migrie\dev\private\OpenConsole[36m[49m>[m[66X[35m
|
||||
[1][m [43m[dev/migrie/f/passthrough-2019][m [94mmigrie[m@[32mMIGRIE-SURFBOOK[m>wsl.exe[54X[92m
|
||||
zadjii@migrie-surfbook[m:[94m/mnt/c/Users/migrie/dev/private/OpenConsole[m$ vi README.md [39X[92m
|
||||
zadjii@migrie-surfbook[m:[94m/mnt/c/Users/migrie/dev/private/OpenConsole[m$ [52X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X[7;69H]0;zadjii@migrie-surfbook: /mnt/c/Users/migrie/dev/private/OpenConsole[?25h
|
||||
273
conpty001.txt
273
conpty001.txt
@@ -1,273 +0,0 @@
|
||||
[25l[2J[m[HMicrosoft Windows [Version 10.0.18936.1001]]0;C:\WINDOWS\system32\cmd.exe[?25h
|
||||
(c) 2019 Microsoft Corporation. All rights reserved.
|
||||
[59X[30m[107m
|
||||
[12:00:25.93][97m[46m>c:\Users\migrie\dev\private\OpenConsole[36m[49m>[m [35m
|
||||
[1][m [43m[dev/migrie/f/passthrough-2019][m [94mmigrie[m@[32mMIGRIE-SURFBOOK[m>wsl.exe
|
||||
]0;C:\WINDOWS\system32\cmd.exe - wsl.exe[92mzadjii@migrie-surfbook[m:[94m/mnt/c/Users/migrie/dev/private/OpenConsole[m$ ]0;zadjii@migrie-surfbook: /mnt/c/Users/migrie/dev/private/OpenConsolevi README.md
|
||||
[25l[?2004h[22;0;0t[?2004h[H[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X[H[?25h[25l[38;2;128;128;128m[48;2;28;28;28m[30;1H"README.md" 177L, 11259C[96X[?25h[96C[25l[?2004l[?2004h[30;25H[?25h[25l[?2004l[?2004h[2;1H▽[?25h[25l
|
||||
[H[?25h[>c]10;?]11;?[38;2;0;95;0m[48;2;175;215;0m README.md [38;2;175;215;0m[48;2;18;18;18m [38;2;255;255;255m[97X[38;2;18;18;18m[97C◀[38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m buffers [38;2;78;78;78m[48;2;38;38;38m
|
||||
1 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Welcome\! [22m[38;2;128;128;128m[104X[38;2;78;78;78m[48;2;38;38;38m
|
||||
2 [38;2;128;128;128m[48;2;28;28;28m####[1m[38;2;215;95;0m This repository contains the source code for:[22m[38;2;128;128;128m[66X[38;2;78;78;78m[48;2;38;38;38m
|
||||
3 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
4 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m Windows Terminal[96X[38;2;78;78;78m[48;2;38;38;38m
|
||||
5 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m The Windows console host ([38;2;0;175;175mconhost.exe[38;2;128;128;128m)[74X[38;2;78;78;78m[48;2;38;38;38m
|
||||
6 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m Components shared between the two projects[70X[38;2;78;78;78m[48;2;38;38;38m
|
||||
7 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mColorTool[38;2;128;128;128m[103X[38;2;78;78;78m[48;2;38;38;38m
|
||||
8 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [m[112X[112C[38;2;128;128;128m[48;2;28;28;28m[38;2;78;78;78m[48;2;38;38;38m
|
||||
8 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mSample projects[38;2;128;128;128m that show how to consume the Window[61X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28ms Console APIs[102X[38;2;78;78;78m[48;2;38;38;38m
|
||||
9 [38;2;28;28;28m[48;2;78;78;78m [38;2;128;128;128m[48;2;28;28;28m[114X[38;2;78;78;78m[48;2;38;38;38m
|
||||
10 [38;2;128;128;128m[48;2;28;28;28m####[1m[38;2;215;95;0m Other related repositories include:[22m[38;2;128;128;128m[76X[38;2;78;78;78m[48;2;38;38;38m
|
||||
11 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mConsole API Documentation[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
12 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
13 [38;2;128;128;128m[48;2;28;28;28m###[1m[38;2;215;95;0m Build Status[22m[38;2;128;128;128m[100X[38;2;78;78;78m[48;2;38;38;38m
|
||||
14 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
15 [38;2;128;128;128m[48;2;28;28;28mProject|Build Status[96X[38;2;78;78;78m[48;2;38;38;38m
|
||||
16 [38;2;128;128;128m[48;2;28;28;28m---|---[109X[38;2;78;78;78m[48;2;38;38;38m
|
||||
17 [38;2;128;128;128m[48;2;28;28;28mTerminal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[18X[m[18C[77X[77C[38;2;128;128;128m[48;2;28;28;28m[38;2;78;78;78m[48;2;38;38;38m
|
||||
17 [38;2;128;128;128m[48;2;28;28;28mTerminal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[95X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
18 [38;2;128;128;128m[48;2;28;28;28mColorTool|[106X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
19 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
20 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Terminal & Console Overview[22m[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
21 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
22 [38;2;128;128;128m[48;2;28;28;28mPlease take a few minutes to review the overview below before diving into the code:[33X[38;2;78;78;78m[48;2;38;38;38m
|
||||
23 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
24 [38;2;128;128;128m[48;2;28;28;28m##[1m[38;2;215;95;0m Windows Terminal[22m[38;2;128;128;128m[97X[97C[?2004l[?2004h[?2004l[?2004h[?2004l[?2004h[?2004l[?2004h[?2004l[?2004h[?2004l[?2004h[?2004l[?2004h[?2004l[?2004h[?2004l[?2004h[?2004h[38;2;215;0;0m[48;2;215;95;0m[38;2;0;95;0m[48;2;175;215;0m
|
||||
[1mNORMAL[22m [38;2;175;215;0m[48;2;48;48;48m▶[38;2;158;158;158m ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m [38;2;18;18;18m<[38;2;255;255;255m markdown [38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 3% [1m␊ 6/177 ㏑[22m : 46 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]trailing [38;2;215;0;0m◀]0;/mnt/c/Users/migrie/dev/private/OpenConsole/README.md[25l[38;2;255;255;255m[48;2;18;18;18m[38;2;158;158;158m[48;2;48;48;48m[29;11H+0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m <[7;50H[?25h[25l[38;2;128;128;128m[48;2;28;28;28m[30;110H~@k[?25h[25l[38;2;175;0;0m[8;9H[[38;2;95;95;175mColorTool[38;2;175;0;0m]([38;2;0;175;175mhttps://github.com/Microsoft/Terminal/tree/master/src/tools/ColorTool[38;2;175;0;0m)[38;2;128;128;128m[22X[38;2;95;95;175m[9;9HSample projects[38;2;128;128;128m that show how to consume the Window[53X[10;9Hnsole APIs[94X[11;9H[104X[1m[38;2;215;95;0m
|
||||
Other related repositories include:[22m[38;2;128;128;128m[68X[38;2;95;95;175m[13;9HConsole API Documentation[38;2;128;128;128m[79X[14;9H[104X[1m[38;2;215;95;0m
|
||||
Build Status[22m[38;2;128;128;128m[92X[16;9H[104X
|
||||
ect|Build Status[88X[18;9H---[101X[19;9Hinal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[87X[20;9H[104X
|
||||
rTool|[98X[22;9H[104X
|
||||
[104X[1m[38;2;215;95;0m
|
||||
rminal & Console Overview[22m[38;2;128;128;128m[79X[25;9H[104X
|
||||
se take a few minutes to review the overview below before diving into the code:[25X[27;9H[104X[1m[38;2;215;95;0m
|
||||
indows Terminal[22m[38;2;128;128;128m[89X[38;2;175;215;0m[48;2;48;48;48m[29;9H▶[38;2;158;158;158m +0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m < [38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 3% [1m␊ 7/177 ㏑[22m : 46 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]tr[38;2;128;128;128m[48;2;28;28;28m[30;9Hmd" 177L, 11259C[88X[8;50H[?25h[25l[30;110H~@k[?25h[25l[38;2;78;78;78m[48;2;38;38;38m[8;1H 7 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mColorTool[38;2;128;128;128m[103X[38;2;78;78;78m[48;2;38;38;38m
|
||||
8 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;175;0;0m[[38;2;95;95;175mSample projects[38;2;175;0;0m]([38;2;0;175;175mhttps://github.com/Microsoft/Terminal/tree/master/samples[38;2;175;0;0m)[38;2;128;128;128m that show how to consume the Window[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28ms Console APIs[102X[38;2;78;78;78m[48;2;38;38;38m
|
||||
9 [38;2;28;28;28m[48;2;78;78;78m [38;2;128;128;128m[48;2;28;28;28m[114X[38;2;78;78;78m[48;2;38;38;38m
|
||||
10 [38;2;128;128;128m[48;2;28;28;28m####[1m[38;2;215;95;0m Other related repositories include:[22m[38;2;128;128;128m[76X[38;2;78;78;78m[48;2;38;38;38m
|
||||
11 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mConsole API Documentation[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
12 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
13 [38;2;128;128;128m[48;2;28;28;28m###[1m[38;2;215;95;0m Build Status[22m[38;2;128;128;128m[100X[38;2;78;78;78m[48;2;38;38;38m
|
||||
14 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
15 [38;2;128;128;128m[48;2;28;28;28mProject|Build Status[96X[38;2;78;78;78m[48;2;38;38;38m
|
||||
16 [38;2;128;128;128m[48;2;28;28;28m---|---[109X[38;2;78;78;78m[48;2;38;38;38m
|
||||
17 [38;2;128;128;128m[48;2;28;28;28mTerminal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[95X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
18 [38;2;128;128;128m[48;2;28;28;28mColorTool|[106X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
19 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
20 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Terminal & Console Overview[22m[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
21 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
22 [38;2;128;128;128m[48;2;28;28;28mPlease take a few minutes to review the overview below before diving into the code:[33X[38;2;78;78;78m[48;2;38;38;38m
|
||||
23 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
24 [38;2;128;128;128m[48;2;28;28;28m##[1m[38;2;215;95;0m Windows Terminal[22m[38;2;128;128;128m[97X[38;2;0;95;0m[48;2;175;215;0m
|
||||
[1mNORMAL[22m [38;2;175;215;0m[48;2;48;48;48m▶[38;2;158;158;158m +0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m < [38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 4% [1m␊ 8/177 ㏑[22m : 46 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]trailing [38;2;215;0;0m◀[38;2;128;128;128m[48;2;28;28;28m
|
||||
"README.md" 177L, 11259C[96X[9;50H[?25h[25l[30;110H~@k[?25h[25l[38;2;78;78;78m[48;2;38;38;38m[9;1H 8 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mSample projects[38;2;128;128;128m that show how to consume the Window[61X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28ms Console APIs[102X[38;2;78;78;78m[48;2;38;38;38m
|
||||
9 [38;2;28;28;28m[48;2;78;78;78m [38;2;128;128;128m[48;2;28;28;28m[114X[38;2;78;78;78m[48;2;38;38;38m
|
||||
10 [38;2;128;128;128m[48;2;28;28;28m####[1m[38;2;215;95;0m Other related repositories include:[22m[38;2;128;128;128m[76X[38;2;78;78;78m[48;2;38;38;38m
|
||||
11 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mConsole API Documentation[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
12 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
13 [38;2;128;128;128m[48;2;28;28;28m###[1m[38;2;215;95;0m Build Status[22m[38;2;128;128;128m[100X[38;2;78;78;78m[48;2;38;38;38m
|
||||
14 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
15 [38;2;128;128;128m[48;2;28;28;28mProject|Build Status[96X[38;2;78;78;78m[48;2;38;38;38m
|
||||
16 [38;2;128;128;128m[48;2;28;28;28m---|---[109X[38;2;78;78;78m[48;2;38;38;38m
|
||||
17 [38;2;128;128;128m[48;2;28;28;28mTerminal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[95X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
18 [38;2;128;128;128m[48;2;28;28;28mColorTool|[106X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
19 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
20 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Terminal & Console Overview[22m[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
21 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
22 [38;2;128;128;128m[48;2;28;28;28mPlease take a few minutes to review the overview below before diving into the code:[33X[38;2;78;78;78m[48;2;38;38;38m
|
||||
23 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
24 [38;2;128;128;128m[48;2;28;28;28m##[1m[38;2;215;95;0m Windows Terminal[22m[38;2;128;128;128m[97X[38;2;0;95;0m[48;2;175;215;0m
|
||||
[1mNORMAL[22m [38;2;175;215;0m[48;2;48;48;48m▶[38;2;158;158;158m +0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m < [38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 5% [1m␊ 9/177 ㏑[22m : 2 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]trailing [38;2;215;0;0m◀[38;2;128;128;128m[48;2;28;28;28m
|
||||
"README.md" 177L, 11259C[96X[11;6H[?25h[25l[30;110H~@k[?25h[25l[38;2;0;95;0m[48;2;175;215;0m[1m[29;89H10/177 ㏑[22m : 40 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]tr[38;2;128;128;128m[48;2;28;28;28m[30;89H[24X[12;44H[?25h[25l[30;110H~@k[?25h[25l[38;2;175;0;0m[13;9H[[38;2;95;95;175mConsole API Documentation[38;2;175;0;0m]([38;2;0;175;175mhttps://github.com/MicrosoftDocs/Console-Docs[38;2;175;0;0m)[38;2;128;128;128m[30X[14;9H[104X[1m[38;2;215;95;0m
|
||||
Build Status[22m[38;2;128;128;128m[92X[16;9H[104X
|
||||
ect|Build Status[88X[18;9H---[101X[19;9Hinal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[87X[20;9H[104X
|
||||
rTool|[98X[22;9H[104X
|
||||
[104X[1m[38;2;215;95;0m
|
||||
rminal & Console Overview[22m[38;2;128;128;128m[79X[25;9H[104X
|
||||
se take a few minutes to review the overview below before diving into the code:[25X[27;9H[104X[1m[38;2;215;95;0m
|
||||
indows Terminal[22m[38;2;128;128;128m[89X[38;2;175;215;0m[48;2;48;48;48m[29;9H▶[38;2;158;158;158m +0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m < [38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 6% [1m␊ 11/177 ㏑[22m : 46 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]tr[38;2;128;128;128m[48;2;28;28;28m[30;9Hmd" 177L, 11259C[88X[13;50H[?25h[25l[30;110H~@k[?25h[25l[38;2;95;95;175m[13;9HConsole API Documentation[38;2;128;128;128m[79X[14;9H[104X[1m[38;2;215;95;0m
|
||||
Build Status[22m[38;2;128;128;128m[92X[16;9H[104X
|
||||
ect|Build Status[88X[18;9H---[101X[19;9Hinal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[87X[20;9H[104X
|
||||
rTool|[98X[22;9H[104X
|
||||
[104X[1m[38;2;215;95;0m
|
||||
rminal & Console Overview[22m[38;2;128;128;128m[79X[25;9H[104X
|
||||
se take a few minutes to review the overview below before diving into the code:[25X[27;9H[104X[1m[38;2;215;95;0m
|
||||
indows Terminal[22m[38;2;128;128;128m[89X[38;2;175;215;0m[48;2;48;48;48m[29;9H▶[38;2;158;158;158m +0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m < [38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 6% [1m␊ 12/177 ㏑[22m : 1 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]tr[38;2;128;128;128m[48;2;28;28;28m[30;9Hmd" 177L, 11259C[88X[14;5H[?25h[25l[30;110H~@k[?25h[25l[38;2;0;95;0m[48;2;175;215;0m[29;83H7% [1m␊ 13/177 ㏑[22m : 16 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]tr[38;2;128;128;128m[48;2;28;28;28m[30;83H[30X[15;20H[?25h[25l[30;110H~@k[?25h[25l[38;2;0;95;0m[48;2;175;215;0m[1m[29;90H4/177 ㏑[22m : 1 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]tr[38;2;128;128;128m[48;2;28;28;28m[30;90H[23X[16;5H[?25h[25l[30;110H~@k[?25h[25l[38;2;0;95;0m[48;2;175;215;0m[29;83H8% [1m␊ 15/177 ㏑[22m : 20 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]tr[38;2;128;128;128m[48;2;28;28;28m[30;83H[30X[17;24H[?25h[25l[30;110H~@k[?25h[25l[38;2;0;95;0m[48;2;175;215;0m[29;83H9% [1m␊ 16/177 ㏑[22m : 7 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]tr[38;2;128;128;128m[48;2;28;28;28m[30;83H[30X[18;11H[?25h[25l[30;110H~@k[?25h[25l[38;2;175;0;0m[38;2;78;78;78m[48;2;38;38;38m[19;1H 17 [38;2;128;128;128m[48;2;28;28;28mTerminal|[38;2;175;0;0m[]([38;2;0;175;175mhtt[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;0;175;175m[48;2;28;28;28mps://dev.azure.com/ms/Terminal/_build?definitionId=136[38;2;175;0;0m)[38;2;128;128;128m[61X[38;2;78;78;78m[48;2;38;38;38m
|
||||
18 [38;2;128;128;128m[48;2;28;28;28mColorTool|[106X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
19 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
20 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Terminal & Console Overview[22m[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
21 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
22 [38;2;128;128;128m[48;2;28;28;28mPlease take a few minutes to review the overview below before diving into the code:[33X[38;2;78;78;78m[48;2;38;38;38m
|
||||
23 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
24 [38;2;128;128;128m[48;2;28;28;28m##[1m[38;2;215;95;0m Windows Terminal[22m[38;2;128;128;128m[97X[38;2;0;95;0m[48;2;175;215;0m
|
||||
[1mNORMAL[22m [38;2;175;215;0m[48;2;48;48;48m▶[38;2;158;158;158m +0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m < [38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 9% [1m␊ 17/177 ㏑[22m : 46 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]trailing [38;2;215;0;0m◀[38;2;128;128;128m[48;2;28;28;28m
|
||||
"README.md" 177L, 11259C[96X[19;50H[?25h[25l[30;110H~@k[?25h[25l[38;2;175;0;0m[38;2;78;78;78m[48;2;38;38;38m[19;1H 17 [38;2;128;128;128m[48;2;28;28;28mTerminal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[95X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
18 [38;2;128;128;128m[48;2;28;28;28mColorTool|[38;2;175;0;0m[38;2;128;128;128m[103X[38;2;78;78;78m[48;2;38;38;38m
|
||||
19 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
20 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Terminal & Console Overview[22m[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
21 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
22 [38;2;128;128;128m[48;2;28;28;28mPlease take a few minutes to review the overview below before diving into the code:[33X[38;2;78;78;78m[48;2;38;38;38m
|
||||
23 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
24 [38;2;128;128;128m[48;2;28;28;28m##[1m[38;2;215;95;0m Windows Terminal[22m[38;2;128;128;128m[97X[38;2;0;95;0m[48;2;175;215;0m
|
||||
[1mNORMAL[22m [38;2;175;215;0m[48;2;48;48;48m▶[38;2;158;158;158m +0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m < [38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 10% [1m␊ 18/177 ㏑[22m : 46 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]trailing [38;2;215;0;0m◀[38;2;128;128;128m[48;2;28;28;28m
|
||||
"README.md" 177L, 11259C[96X[21;50H[?25h[25l[30;110H~@k[?25h[25l[38;2;78;78;78m[48;2;38;38;38m[21;1H 18 [38;2;128;128;128m[48;2;28;28;28mColorTool|[106X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
19 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
20 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Terminal & Console Overview[22m[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
21 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
22 [38;2;128;128;128m[48;2;28;28;28mPlease take a few minutes to review the overview below before diving into the code:[33X[38;2;78;78;78m[48;2;38;38;38m
|
||||
23 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
24 [38;2;128;128;128m[48;2;28;28;28m##[1m[38;2;215;95;0m Windows Terminal[22m[38;2;128;128;128m[97X[38;2;0;95;0m[48;2;175;215;0m
|
||||
[1mNORMAL[22m [38;2;175;215;0m[48;2;48;48;48m▶[38;2;158;158;158m +0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m < [38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 10% [1m␊ 19/177 ㏑[22m : 1 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]trailing [38;2;215;0;0m◀[38;2;128;128;128m[48;2;28;28;28m
|
||||
"README.md" 177L, 11259C[96X[23;5H[?25h[25l[30;110H~@k[?25h[25l[38;2;0;95;0m[48;2;175;215;0m[29;83H1% [1m␊ 20/177 ㏑[22m : 29 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]tr[38;2;128;128;128m[48;2;28;28;28m[30;83H[30X[24;33H[?25h[25l[30;110H~@k[?25h[25l[38;2;0;95;0m[48;2;175;215;0m[1m[29;90H1/177 ㏑[22m : 1 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]tr[38;2;128;128;128m[48;2;28;28;28m[30;90H[23X[25;5H[?25h[25l[30;110H~@k[?25h[25l[38;2;0;95;0m[48;2;175;215;0m[38;2;78;78;78m[48;2;38;38;38m[2;1H 2 [38;2;128;128;128m[48;2;28;28;28m####[1m[38;2;215;95;0m This repository contains the source code for:[22m[38;2;128;128;128m[66X[38;2;78;78;78m[48;2;38;38;38m
|
||||
3 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
4 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m Windows Terminal[96X[38;2;78;78;78m[48;2;38;38;38m
|
||||
5 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m The Windows console host ([38;2;0;175;175mconhost.exe[38;2;128;128;128m)[74X[38;2;78;78;78m[48;2;38;38;38m
|
||||
6 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m Components shared between the two projects[70X[38;2;78;78;78m[48;2;38;38;38m
|
||||
7 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mColorTool[38;2;128;128;128m[103X[38;2;78;78;78m[48;2;38;38;38m
|
||||
8 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mSample projects[38;2;128;128;128m that show how to consume the Window[61X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28ms Console APIs[102X[38;2;78;78;78m[48;2;38;38;38m
|
||||
9 [38;2;28;28;28m[48;2;78;78;78m [38;2;128;128;128m[48;2;28;28;28m[114X[38;2;78;78;78m[48;2;38;38;38m
|
||||
10 [38;2;128;128;128m[48;2;28;28;28m####[1m[38;2;215;95;0m Other related repositories include:[22m[38;2;128;128;128m[76X[38;2;78;78;78m[48;2;38;38;38m
|
||||
11 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mConsole API Documentation[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
12 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
13 [38;2;128;128;128m[48;2;28;28;28m###[1m[38;2;215;95;0m Build Status[22m[38;2;128;128;128m[100X[38;2;78;78;78m[48;2;38;38;38m
|
||||
14 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
15 [38;2;128;128;128m[48;2;28;28;28mProject|Build Status[96X[38;2;78;78;78m[48;2;38;38;38m
|
||||
16 [38;2;128;128;128m[48;2;28;28;28m---|---[109X[38;2;78;78;78m[48;2;38;38;38m
|
||||
17 [38;2;128;128;128m[48;2;28;28;28mTerminal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[95X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
18 [38;2;128;128;128m[48;2;28;28;28mColorTool|[106X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
19 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
20 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Terminal & Console Overview[22m[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
21 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
22 [38;2;128;128;128m[48;2;28;28;28mPlease take a few minutes to review the overview below before diving into the code:[33X[38;2;78;78;78m[48;2;38;38;38m
|
||||
23 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
24 [38;2;128;128;128m[48;2;28;28;28m##[1m[38;2;215;95;0m Windows Terminal[22m[38;2;128;128;128m[97X[38;2;78;78;78m[48;2;38;38;38m
|
||||
25 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;0;95;0m[48;2;175;215;0m
|
||||
[1mNORMAL[22m [38;2;175;215;0m[48;2;48;48;48m▶[38;2;158;158;158m +0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m < [38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 12% [1m␊ 22/177 ㏑[22m : 46 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]trailing [38;2;215;0;0m◀[38;2;128;128;128m[48;2;28;28;28m
|
||||
[120X[25;50H[?25h[25l[30;110H~@k[?25h[25l[38;2;0;95;0m[48;2;175;215;0m[38;2;78;78;78m[48;2;38;38;38m[2;1H 5 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m The Windows console host ([38;2;0;175;175mconhost.exe[38;2;128;128;128m)[74X[38;2;78;78;78m[48;2;38;38;38m
|
||||
6 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m Components shared between the two projects[70X[38;2;78;78;78m[48;2;38;38;38m
|
||||
7 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mColorTool[38;2;128;128;128m[103X[38;2;78;78;78m[48;2;38;38;38m
|
||||
8 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mSample projects[38;2;128;128;128m that show how to consume the Window[61X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28ms Console APIs[102X[38;2;78;78;78m[48;2;38;38;38m
|
||||
9 [38;2;28;28;28m[48;2;78;78;78m [38;2;128;128;128m[48;2;28;28;28m[114X[38;2;78;78;78m[48;2;38;38;38m
|
||||
10 [38;2;128;128;128m[48;2;28;28;28m####[1m[38;2;215;95;0m Other related repositories include:[22m[38;2;128;128;128m[76X[38;2;78;78;78m[48;2;38;38;38m
|
||||
11 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mConsole API Documentation[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
12 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
13 [38;2;128;128;128m[48;2;28;28;28m###[1m[38;2;215;95;0m Build Status[22m[38;2;128;128;128m[100X[38;2;78;78;78m[48;2;38;38;38m
|
||||
14 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
15 [38;2;128;128;128m[48;2;28;28;28mProject|Build Status[96X[38;2;78;78;78m[48;2;38;38;38m
|
||||
16 [38;2;128;128;128m[48;2;28;28;28m---|---[109X[38;2;78;78;78m[48;2;38;38;38m
|
||||
17 [38;2;128;128;128m[48;2;28;28;28mTerminal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[95X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
18 [38;2;128;128;128m[48;2;28;28;28mColorTool|[106X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
19 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
20 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Terminal & Console Overview[22m[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
21 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
22 [38;2;128;128;128m[48;2;28;28;28mPlease take a few minutes to review the overview below before diving into the code:[33X[38;2;78;78;78m[48;2;38;38;38m
|
||||
23 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
24 [38;2;128;128;128m[48;2;28;28;28m##[1m[38;2;215;95;0m Windows Terminal[22m[38;2;128;128;128m[97X[38;2;78;78;78m[48;2;38;38;38m
|
||||
25 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
26 [38;2;128;128;128m[48;2;28;28;28mWindows Terminal is a new, modern, feature-rich, productive terminal application for command-line users. It includes[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m many of the features most frequently requested by the Windows command-line community including support for tabs, ri[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28mch text, globalization, configurability, theming & styling, and more.[47X[38;2;0;95;0m[48;2;175;215;0m
|
||||
[1mNORMAL[22m [38;2;175;215;0m[48;2;48;48;48m▶[38;2;158;158;158m +0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m < [38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 12% [1m␊ 23/177 ㏑[22m : 1 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]trailing [38;2;215;0;0m◀[38;2;128;128;128m[48;2;28;28;28m
|
||||
[120X[23;5H[?25h[25l[30;110H~@k[?25h[25l[38;2;0;95;0m[48;2;175;215;0m[29;83H3% [1m␊ 24/177 ㏑[22m : 19 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [9]tr[38;2;128;128;128m[48;2;28;28;28m[30;83H[30X[24;23H[?25h[25l[38;2;8;8;8m[48;2;215;95;0m[38;2;48;48;48m[48;2;18;18;18m[29;55H◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 13% [1m␊ 24/177 ㏑[22m : 19 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [64[24;23H[?25h[25l[38;2;128;128;128m[48;2;28;28;28m[30;110H~@k[?25h[25l[38;2;0;95;0m[48;2;175;215;0m[38;2;78;78;78m[48;2;38;38;38m[2;1H 1 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Welcome\! [22m[38;2;128;128;128m[104X[38;2;78;78;78m[48;2;38;38;38m
|
||||
2 [38;2;128;128;128m[48;2;28;28;28m####[1m[38;2;215;95;0m This repository contains the source code for:[22m[38;2;128;128;128m[66X[38;2;78;78;78m[48;2;38;38;38m
|
||||
3 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
4 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m Windows Terminal[96X[38;2;78;78;78m[48;2;38;38;38m
|
||||
5 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m The Windows console host ([38;2;0;175;175mconhost.exe[38;2;128;128;128m)[74X[38;2;78;78;78m[48;2;38;38;38m
|
||||
6 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m Components shared between the two projects[70X[38;2;78;78;78m[48;2;38;38;38m
|
||||
7 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mColorTool[38;2;128;128;128m[103X[38;2;78;78;78m[48;2;38;38;38m
|
||||
8 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mSample projects[38;2;128;128;128m that show how to consume the Window[61X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28ms Console APIs[102X[38;2;78;78;78m[48;2;38;38;38m
|
||||
9 [38;2;28;28;28m[48;2;78;78;78m [38;2;128;128;128m[48;2;28;28;28m[114X[38;2;78;78;78m[48;2;38;38;38m
|
||||
10 [38;2;128;128;128m[48;2;28;28;28m####[1m[38;2;215;95;0m Other related repositories include:[22m[38;2;128;128;128m[76X[38;2;78;78;78m[48;2;38;38;38m
|
||||
11 [38;2;0;135;255m[48;2;28;28;28m *[38;2;128;128;128m [38;2;95;95;175mConsole API Documentation[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
12 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
13 [38;2;128;128;128m[48;2;28;28;28m###[1m[38;2;215;95;0m Build Status[22m[38;2;128;128;128m[100X[38;2;78;78;78m[48;2;38;38;38m
|
||||
14 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
15 [38;2;128;128;128m[48;2;28;28;28mProject|Build Status[96X[38;2;78;78;78m[48;2;38;38;38m
|
||||
16 [38;2;128;128;128m[48;2;28;28;28m---|---[109X[38;2;78;78;78m[48;2;38;38;38m
|
||||
17 [38;2;128;128;128m[48;2;28;28;28mTerminal|[38;2;95;95;175mBuild Status[38;2;128;128;128m[95X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
18 [38;2;128;128;128m[48;2;28;28;28mColorTool|[106X[38;2;78;78;78m[48;2;38;38;38m
|
||||
[38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
19 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
20 [38;2;128;128;128m[48;2;28;28;28m#[1m[38;2;215;95;0m Terminal & Console Overview[22m[38;2;128;128;128m[87X[38;2;78;78;78m[48;2;38;38;38m
|
||||
21 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
22 [38;2;128;128;128m[48;2;28;28;28mPlease take a few minutes to review the overview below before diving into the code:[33X[38;2;78;78;78m[48;2;38;38;38m
|
||||
23 [38;2;128;128;128m[48;2;28;28;28m[116X[38;2;78;78;78m[48;2;38;38;38m
|
||||
24 [38;2;128;128;128m[48;2;28;28;28m##[1m[38;2;215;95;0m Windows Terminal[22m[38;2;128;128;128m[97X[38;2;0;95;0m[48;2;175;215;0m
|
||||
[1mNORMAL[22m [38;2;175;215;0m[48;2;48;48;48m▶[38;2;158;158;158m +0 ~0 -0 ⎇ dev/migrie/f/passthrough-2019 [38;2;48;48;48m[48;2;18;18;18m▶[38;2;255;255;255m <[38;2;48;48;48m◀[38;2;158;158;158m[48;2;48;48;48m [unix] [38;2;175;215;0m◀[38;2;0;95;0m[48;2;175;215;0m 1,397 words « 3% [1m␊ 6/177 ㏑[22m : 3 [38;2;215;95;0m◀[38;2;8;8;8m[48;2;215;95;0m Ξ [64]trailing [38;2;215;0;0m◀[38;2;128;128;128m[48;2;28;28;28m
|
||||
[120X[7;7H[?25h[25l[30;110H^[[7;7H[?25h[25l[30;110H [7;7H[?25h[25l[?2004h[30;1H:[109X[?25hq
|
||||
[?2004l]0;[?2004l[120X[120C[25l[23;0;0t[m[HMicrosoft Windows [Version 10.0.18936.1001][77X
|
||||
(c) 2019 Microsoft Corporation. All rights reserved.[68X
|
||||
[120X[30m[107m
|
||||
[12:00:25.93][97m[46m>c:\Users\migrie\dev\private\OpenConsole[36m[49m>[m[66X[35m
|
||||
[1][m [43m[dev/migrie/f/passthrough-2019][m [94mmigrie[m@[32mMIGRIE-SURFBOOK[m>wsl.exe[54X[92m
|
||||
zadjii@migrie-surfbook[m:[94m/mnt/c/Users/migrie/dev/private/OpenConsole[m$ vi README.md [39X[92m
|
||||
zadjii@migrie-surfbook[m:[94m/mnt/c/Users/migrie/dev/private/OpenConsole[m$ [52X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
[120X
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -260,6 +260,24 @@
|
||||
<PRIResource Include="Resources\en-US\Resources.resw" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" />
|
||||
<!--
|
||||
Microsoft.UI.Xaml contains some <Content> resource files that need to be included in our package.
|
||||
For some reason, they're not rolled up through dependent projects; if they were, their paths would
|
||||
be wrong.
|
||||
|
||||
WAP Packaging projects don't actually support nuget package references, so we added one manually.
|
||||
|
||||
This does mean that version changes to Microsoft.UI.Xaml must be manually reflected
|
||||
here.
|
||||
-->
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.2.190611001-prerelease\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.2.190611001-prerelease\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.2.190611001-prerelease\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.2.190611001-prerelease\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
<!-- End workaround -->
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WindowsTerminal\WindowsTerminal.vcxproj" />
|
||||
<ProjectReference Include="..\..\host\exe\Host.EXE.vcxproj" />
|
||||
|
||||
@@ -61,13 +61,26 @@ namespace winrt::TerminalApp::implementation
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void App::Create()
|
||||
void App::Create(uint64_t hWnd)
|
||||
{
|
||||
// Assert that we've already loaded our settings. We have to do
|
||||
// this as a MTA, before the app is Create()'d
|
||||
WINRT_ASSERT(_loadedInitialSettings);
|
||||
TraceLoggingRegister(g_hTerminalAppProvider);
|
||||
_Create(hWnd);
|
||||
}
|
||||
|
||||
App::~App()
|
||||
{
|
||||
TraceLoggingUnregister(g_hTerminalAppProvider);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Create all of the initial UI elements of the Terminal app.
|
||||
// * Initializes the first terminal control, using the default profile,
|
||||
// and adds it to our list of tabs.
|
||||
void App::_Create(uint64_t parentHwnd)
|
||||
{
|
||||
/* !!! TODO
|
||||
This is not the correct way to host a XAML page. This exists today because we valued
|
||||
getting a .xaml over tearing out all of the terminal logic and splitting it across App
|
||||
@@ -79,21 +92,15 @@ namespace winrt::TerminalApp::implementation
|
||||
_root = terminalPage.as<winrt::Windows::UI::Xaml::Controls::Control>();
|
||||
_tabContent = terminalPage->TabContent();
|
||||
_tabRow = terminalPage->TabRow();
|
||||
_tabView = _tabRow.TabView();
|
||||
_newTabButton = _tabRow.NewTabButton();
|
||||
_tabView = terminalPage->TabView();
|
||||
_newTabButton = terminalPage->NewTabButton();
|
||||
|
||||
if (_settings->GlobalSettings().GetShowTabsInTitlebar())
|
||||
_minMaxCloseControl = terminalPage->MinMaxCloseControl();
|
||||
_minMaxCloseControl.ParentWindowHandle(parentHwnd);
|
||||
|
||||
if (!_settings->GlobalSettings().GetShowTabsInTitlebar())
|
||||
{
|
||||
// Remove the TabView from the page. We'll hang on to it, we need to
|
||||
// put it in the titlebar.
|
||||
uint32_t index = 0;
|
||||
if (terminalPage->Root().Children().IndexOf(_tabRow, index))
|
||||
{
|
||||
terminalPage->Root().Children().RemoveAt(index);
|
||||
}
|
||||
|
||||
// Inform the host that our titlebar content has changed.
|
||||
_setTitleBarContentHandlers(*this, _tabRow);
|
||||
_minMaxCloseControl.Visibility(Visibility::Collapsed);
|
||||
}
|
||||
|
||||
// Event Bindings (Early)
|
||||
@@ -111,14 +118,6 @@ namespace winrt::TerminalApp::implementation
|
||||
_tabContent.SizeChanged({ this, &App::_OnContentSizeChanged });
|
||||
}
|
||||
|
||||
App::~App()
|
||||
{
|
||||
if (g_hTerminalAppProvider)
|
||||
{
|
||||
TraceLoggingUnregister(g_hTerminalAppProvider);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Show a ContentDialog with a single button to dismiss. Uses the
|
||||
// FrameworkElements provided as the title and content of this dialog, and
|
||||
@@ -457,6 +456,16 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::Windows::System::Launcher::LaunchUriAsync({ feedbackUriValue });
|
||||
}
|
||||
|
||||
Windows::UI::Xaml::Controls::Border App::GetDragBar() noexcept
|
||||
{
|
||||
if (_minMaxCloseControl)
|
||||
{
|
||||
return _minMaxCloseControl.DragBar();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called when the about button is clicked. See _ShowAboutDialog for more info.
|
||||
// Arguments:
|
||||
@@ -484,7 +493,6 @@ namespace winrt::TerminalApp::implementation
|
||||
bindings.NewTab([this]() { _OpenNewTab(std::nullopt); });
|
||||
bindings.DuplicateTab([this]() { _DuplicateTabViewItem(); });
|
||||
bindings.CloseTab([this]() { _CloseFocusedTab(); });
|
||||
bindings.ClosePane([this]() { _CloseFocusedPane(); });
|
||||
bindings.NewTabWithProfile([this](const auto index) { _OpenNewTab({ index }); });
|
||||
bindings.ScrollUp([this]() { _Scroll(-1); });
|
||||
bindings.ScrollDown([this]() { _Scroll(1); });
|
||||
@@ -497,7 +505,6 @@ namespace winrt::TerminalApp::implementation
|
||||
bindings.SwitchToTab([this](const auto index) { _SelectTab({ index }); });
|
||||
bindings.OpenSettings([this]() { _OpenSettings(); });
|
||||
bindings.ResizePane([this](const auto direction) { _ResizePane(direction); });
|
||||
bindings.MoveFocus([this](const auto direction) { _MoveFocus(direction); });
|
||||
bindings.CopyText([this](const auto trimWhitespace) { _CopyText(trimWhitespace); });
|
||||
bindings.PasteText([this]() { _PasteText(); });
|
||||
}
|
||||
@@ -734,16 +741,13 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Update the current theme of the application. This will trigger our
|
||||
// RequestedThemeChanged event, to have our host change the theme of the
|
||||
// root of the application.
|
||||
// - Update the current theme of the application. This will manually update
|
||||
// all of the elements in our UI to match the given theme.
|
||||
// Arguments:
|
||||
// - newTheme: The ElementTheme to apply to our elements.
|
||||
void App::_ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme)
|
||||
{
|
||||
_root.RequestedTheme(newTheme);
|
||||
// Propagate the event to the host layer, so it can update its own UI
|
||||
_requestedThemeChangedHandlers(*this, newTheme);
|
||||
}
|
||||
|
||||
UIElement App::GetRoot() noexcept
|
||||
@@ -907,16 +911,20 @@ namespace winrt::TerminalApp::implementation
|
||||
// currently displayed, it will be shown.
|
||||
// Arguments:
|
||||
// - settings: the TerminalSettings object to use to create the TerminalControl with.
|
||||
void App::_CreateNewTabFromSettings(GUID profileGuid, TerminalSettings settings)
|
||||
void App::_CreateNewTabFromSettings(GUID profileGuid, TerminalSettings settings, std::optional<uint64_t> serverHandle)
|
||||
{
|
||||
// Initialize the new tab
|
||||
|
||||
TerminalConnection::ITerminalConnection connection = nullptr;
|
||||
// Create a Conhost connection based on the values in our settings object.
|
||||
auto connection = TerminalConnection::ConhostConnection(settings.Commandline(),
|
||||
settings.StartingDirectory(),
|
||||
30,
|
||||
80,
|
||||
winrt::guid());
|
||||
if (!serverHandle)
|
||||
{
|
||||
connection = TerminalConnection::ConhostConnection(settings.Commandline(), settings.StartingDirectory(), 30, 80, winrt::guid());
|
||||
}
|
||||
else
|
||||
{
|
||||
connection = TerminalConnection::ConhostConnection(serverHandle.value(), 30, 80, winrt::guid());
|
||||
}
|
||||
|
||||
TermControl term{ settings, connection };
|
||||
|
||||
@@ -985,17 +993,6 @@ namespace winrt::TerminalApp::implementation
|
||||
_RemoveTabViewItem(focusedTab->GetTabViewItem());
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Close the currently focused pane. If the pane is the last pane in the
|
||||
// tab, the tab will also be closed. This will happen when we handle the
|
||||
// tab's Closed event.
|
||||
void App::_CloseFocusedPane()
|
||||
{
|
||||
int focusedTabIndex = _GetFocusedTabIndex();
|
||||
std::shared_ptr<Tab> focusedTab{ _tabs[focusedTabIndex] };
|
||||
focusedTab->ClosePane();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Move the viewport of the terminal of the currently focused tab up or
|
||||
// down a number of lines. Negative values of `delta` will move the
|
||||
@@ -1039,20 +1036,6 @@ namespace winrt::TerminalApp::implementation
|
||||
_tabs[focusedTabIndex]->ResizePane(direction);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Attempt to move focus between panes, as to focus the child on
|
||||
// the other side of the separator. See Pane::NavigateFocus for details.
|
||||
// - Moves the focus of the currently focused tab.
|
||||
// Arguments:
|
||||
// - direction: The direction to move the focus in.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void App::_MoveFocus(const Direction& direction)
|
||||
{
|
||||
const auto focusedTabIndex = _GetFocusedTabIndex();
|
||||
_tabs[focusedTabIndex]->NavigateFocus(direction);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Copy text from the focused terminal to the Windows Clipboard
|
||||
// Arguments:
|
||||
@@ -1183,6 +1166,33 @@ namespace winrt::TerminalApp::implementation
|
||||
return { L"Windows Terminal" };
|
||||
}
|
||||
|
||||
void App::IncomingConnection(uint64_t serverHandle)
|
||||
{
|
||||
_root.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [this, serverHandle]() {
|
||||
// Getting Guid for default profile
|
||||
const auto globalSettings = _settings->GlobalSettings();
|
||||
auto profileGuid = globalSettings.GetDefaultProfile();
|
||||
TerminalSettings settings = _settings->MakeSettings(profileGuid);
|
||||
|
||||
_CreateNewTabFromSettings(profileGuid, settings, serverHandle);
|
||||
});
|
||||
}
|
||||
|
||||
void App::IncomingConnection(hstring cmdline, hstring workingDir)
|
||||
{
|
||||
_root.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [this, cmdline, workingDir]() {
|
||||
// Getting Guid for default profile
|
||||
const auto globalSettings = _settings->GlobalSettings();
|
||||
auto profileGuid = globalSettings.GetDefaultProfile();
|
||||
TerminalSettings settings = _settings->MakeSettings(profileGuid);
|
||||
|
||||
settings.Commandline(cmdline);
|
||||
settings.StartingDirectory(workingDir);
|
||||
|
||||
_CreateNewTabFromSettings(profileGuid, settings);
|
||||
});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Additional responses to clicking on a TabView's item. Currently, just remove tab with middle click
|
||||
// Arguments:
|
||||
@@ -1233,7 +1243,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (focusedTabIndex >= _tabs.size())
|
||||
{
|
||||
focusedTabIndex = static_cast<int>(_tabs.size()) - 1;
|
||||
focusedTabIndex = _tabs.size() - 1;
|
||||
}
|
||||
|
||||
if (focusedTabIndex < 0)
|
||||
@@ -1328,11 +1338,7 @@ namespace winrt::TerminalApp::implementation
|
||||
const auto controlSettings = _settings->MakeSettings(realGuid);
|
||||
|
||||
// Create a Conhost connection based on the values in our settings object.
|
||||
auto controlConnection = TerminalConnection::ConhostConnection(controlSettings.Commandline(),
|
||||
controlSettings.StartingDirectory(),
|
||||
30,
|
||||
80,
|
||||
winrt::guid());
|
||||
TerminalConnection::ITerminalConnection controlConnection = TerminalConnection::ConhostConnection(controlSettings.Commandline(), controlSettings.StartingDirectory(), 30, 80, winrt::guid());
|
||||
|
||||
TermControl newControl{ controlSettings, controlConnection };
|
||||
|
||||
@@ -1433,6 +1439,4 @@ namespace winrt::TerminalApp::implementation
|
||||
// These macros will define them both for you.
|
||||
DEFINE_EVENT(App, TitleChanged, _titleChangeHandlers, TerminalControl::TitleChangedEventArgs);
|
||||
DEFINE_EVENT(App, LastTabClosed, _lastTabClosedHandlers, winrt::TerminalApp::LastTabClosedEventArgs);
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(App, SetTitleBarContent, _setTitleBarContentHandlers, TerminalApp::App, winrt::Windows::UI::Xaml::UIElement);
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(App, RequestedThemeChanged, _requestedThemeChangedHandlers, TerminalApp::App, winrt::Windows::UI::Xaml::ElementTheme);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,10 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
Windows::UI::Xaml::UIElement GetRoot() noexcept;
|
||||
|
||||
void Create();
|
||||
// Gets the current dragglable area in the non client region of the top level window
|
||||
Windows::UI::Xaml::Controls::Border GetDragBar() noexcept;
|
||||
|
||||
void Create(uint64_t hParentWnd);
|
||||
void LoadSettings();
|
||||
|
||||
Windows::Foundation::Point GetLaunchDimensions(uint32_t dpi);
|
||||
@@ -37,11 +40,12 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
hstring GetTitle();
|
||||
|
||||
void IncomingConnection(uint64_t serverHandle);
|
||||
void IncomingConnection(hstring cmdline, hstring workingDir);
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
DECLARE_EVENT(TitleChanged, _titleChangeHandlers, winrt::Microsoft::Terminal::TerminalControl::TitleChangedEventArgs);
|
||||
DECLARE_EVENT(LastTabClosed, _lastTabClosedHandlers, winrt::TerminalApp::LastTabClosedEventArgs);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTitleBarContent, _setTitleBarContentHandlers, TerminalApp::App, winrt::Windows::UI::Xaml::UIElement);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(RequestedThemeChanged, _requestedThemeChangedHandlers, TerminalApp::App, winrt::Windows::UI::Xaml::ElementTheme);
|
||||
|
||||
private:
|
||||
// If you add controls here, but forget to null them either here or in
|
||||
@@ -52,9 +56,10 @@ namespace winrt::TerminalApp::implementation
|
||||
// (which is a root when the tabs are in the titlebar.)
|
||||
Windows::UI::Xaml::Controls::Control _root{ nullptr };
|
||||
Microsoft::UI::Xaml::Controls::TabView _tabView{ nullptr };
|
||||
TerminalApp::TabRowControl _tabRow{ nullptr };
|
||||
Windows::UI::Xaml::Controls::Grid _tabRow{ nullptr };
|
||||
Windows::UI::Xaml::Controls::Grid _tabContent{ nullptr };
|
||||
Windows::UI::Xaml::Controls::SplitButton _newTabButton{ nullptr };
|
||||
winrt::TerminalApp::MinMaxCloseControl _minMaxCloseControl{ nullptr };
|
||||
|
||||
std::vector<std::shared_ptr<Tab>> _tabs;
|
||||
|
||||
@@ -69,6 +74,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
std::atomic<bool> _settingsReloadQueued{ false };
|
||||
|
||||
void _Create(uint64_t parentHWnd);
|
||||
void _CreateNewTabFlyout();
|
||||
|
||||
fire_and_forget _ShowDialog(const winrt::Windows::Foundation::IInspectable& titleElement,
|
||||
@@ -97,12 +103,11 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void _RegisterTerminalEvents(Microsoft::Terminal::TerminalControl::TermControl term, std::shared_ptr<Tab> hostingTab);
|
||||
|
||||
void _CreateNewTabFromSettings(GUID profileGuid, winrt::Microsoft::Terminal::Settings::TerminalSettings settings);
|
||||
void _CreateNewTabFromSettings(GUID profileGuid, winrt::Microsoft::Terminal::Settings::TerminalSettings settings, std::optional<uint64_t> serverHandle = std::nullopt);
|
||||
|
||||
void _OpenNewTab(std::optional<int> profileIndex);
|
||||
void _DuplicateTabViewItem();
|
||||
void _CloseFocusedTab();
|
||||
void _CloseFocusedPane();
|
||||
void _SelectNextTab(const bool bMoveRight);
|
||||
void _SelectTab(const int tabIndex);
|
||||
|
||||
@@ -120,7 +125,6 @@ namespace winrt::TerminalApp::implementation
|
||||
// MSFT:20641986: Add keybindings for New Window
|
||||
void _ScrollPage(int delta);
|
||||
void _ResizePane(const Direction& direction);
|
||||
void _MoveFocus(const Direction& direction);
|
||||
|
||||
void _OnLoaded(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
||||
void _OnTabSelectionChanged(const IInspectable& sender, const Windows::UI::Xaml::Controls::SelectionChangedEventArgs& eventArgs);
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
namespace TerminalApp
|
||||
{
|
||||
delegate void LastTabClosedEventArgs();
|
||||
[default_interface] runtimeclass App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
|
||||
[default_interface]
|
||||
runtimeclass App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
|
||||
{
|
||||
App();
|
||||
|
||||
@@ -15,20 +16,22 @@ namespace TerminalApp
|
||||
// then it might look like TermApp just failed to activate, which will
|
||||
// cause you to chase down the rabbit hole of "why is TermApp not
|
||||
// registered?" when it definitely is.
|
||||
void Create();
|
||||
void Create(UInt64 hParentWnd);
|
||||
|
||||
void LoadSettings();
|
||||
|
||||
Windows.UI.Xaml.UIElement GetRoot();
|
||||
Windows.UI.Xaml.Controls.Border GetDragBar{ get; };
|
||||
|
||||
Windows.Foundation.Point GetLaunchDimensions(UInt32 dpi);
|
||||
Boolean GetShowTabsInTitlebar();
|
||||
|
||||
event Microsoft.Terminal.TerminalControl.TitleChangedEventArgs TitleChanged;
|
||||
event LastTabClosedEventArgs LastTabClosed;
|
||||
event Windows.Foundation.TypedEventHandler<App, Windows.UI.Xaml.UIElement> SetTitleBarContent;
|
||||
event Windows.Foundation.TypedEventHandler<App, Windows.UI.Xaml.ElementTheme> RequestedThemeChanged;
|
||||
|
||||
String GetTitle();
|
||||
|
||||
void IncomingConnection(UInt64 serverHandle);
|
||||
void IncomingConnection(String cmdline, String workingDir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,9 +102,6 @@ namespace winrt::TerminalApp::implementation
|
||||
case ShortcutAction::CloseTab:
|
||||
_CloseTabHandlers();
|
||||
return true;
|
||||
case ShortcutAction::ClosePane:
|
||||
_ClosePaneHandlers();
|
||||
return true;
|
||||
|
||||
case ShortcutAction::ScrollUp:
|
||||
_ScrollUpHandlers();
|
||||
@@ -172,18 +169,7 @@ namespace winrt::TerminalApp::implementation
|
||||
case ShortcutAction::ResizePaneDown:
|
||||
_ResizePaneHandlers(Direction::Down);
|
||||
return true;
|
||||
case ShortcutAction::MoveFocusLeft:
|
||||
_MoveFocusHandlers(Direction::Left);
|
||||
return true;
|
||||
case ShortcutAction::MoveFocusRight:
|
||||
_MoveFocusHandlers(Direction::Right);
|
||||
return true;
|
||||
case ShortcutAction::MoveFocusUp:
|
||||
_MoveFocusHandlers(Direction::Up);
|
||||
return true;
|
||||
case ShortcutAction::MoveFocusDown:
|
||||
_MoveFocusHandlers(Direction::Down);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -252,7 +238,6 @@ namespace winrt::TerminalApp::implementation
|
||||
DEFINE_EVENT(AppKeyBindings, NewWindow, _NewWindowHandlers, TerminalApp::NewWindowEventArgs);
|
||||
DEFINE_EVENT(AppKeyBindings, CloseWindow, _CloseWindowHandlers, TerminalApp::CloseWindowEventArgs);
|
||||
DEFINE_EVENT(AppKeyBindings, CloseTab, _CloseTabHandlers, TerminalApp::CloseTabEventArgs);
|
||||
DEFINE_EVENT(AppKeyBindings, ClosePane, _ClosePaneHandlers, TerminalApp::ClosePaneEventArgs);
|
||||
DEFINE_EVENT(AppKeyBindings, SwitchToTab, _SwitchToTabHandlers, TerminalApp::SwitchToTabEventArgs);
|
||||
DEFINE_EVENT(AppKeyBindings, NextTab, _NextTabHandlers, TerminalApp::NextTabEventArgs);
|
||||
DEFINE_EVENT(AppKeyBindings, PrevTab, _PrevTabHandlers, TerminalApp::PrevTabEventArgs);
|
||||
@@ -266,6 +251,5 @@ namespace winrt::TerminalApp::implementation
|
||||
DEFINE_EVENT(AppKeyBindings, ScrollDownPage, _ScrollDownPageHandlers, TerminalApp::ScrollDownPageEventArgs);
|
||||
DEFINE_EVENT(AppKeyBindings, OpenSettings, _OpenSettingsHandlers, TerminalApp::OpenSettingsEventArgs);
|
||||
DEFINE_EVENT(AppKeyBindings, ResizePane, _ResizePaneHandlers, TerminalApp::ResizePaneEventArgs);
|
||||
DEFINE_EVENT(AppKeyBindings, MoveFocus, _MoveFocusHandlers, TerminalApp::MoveFocusEventArgs);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ namespace winrt::TerminalApp::implementation
|
||||
DECLARE_EVENT(NewWindow, _NewWindowHandlers, TerminalApp::NewWindowEventArgs);
|
||||
DECLARE_EVENT(CloseWindow, _CloseWindowHandlers, TerminalApp::CloseWindowEventArgs);
|
||||
DECLARE_EVENT(CloseTab, _CloseTabHandlers, TerminalApp::CloseTabEventArgs);
|
||||
DECLARE_EVENT(ClosePane, _ClosePaneHandlers, TerminalApp::ClosePaneEventArgs);
|
||||
DECLARE_EVENT(SwitchToTab, _SwitchToTabHandlers, TerminalApp::SwitchToTabEventArgs);
|
||||
DECLARE_EVENT(NextTab, _NextTabHandlers, TerminalApp::NextTabEventArgs);
|
||||
DECLARE_EVENT(PrevTab, _PrevTabHandlers, TerminalApp::PrevTabEventArgs);
|
||||
@@ -62,7 +61,6 @@ namespace winrt::TerminalApp::implementation
|
||||
DECLARE_EVENT(ScrollDownPage, _ScrollDownPageHandlers, TerminalApp::ScrollDownPageEventArgs);
|
||||
DECLARE_EVENT(OpenSettings, _OpenSettingsHandlers, TerminalApp::OpenSettingsEventArgs);
|
||||
DECLARE_EVENT(ResizePane, _ResizePaneHandlers, TerminalApp::ResizePaneEventArgs);
|
||||
DECLARE_EVENT(MoveFocus, _MoveFocusHandlers, TerminalApp::MoveFocusEventArgs);
|
||||
// clang-format on
|
||||
|
||||
private:
|
||||
|
||||
@@ -30,7 +30,6 @@ namespace TerminalApp
|
||||
NewWindow,
|
||||
CloseWindow,
|
||||
CloseTab,
|
||||
ClosePane,
|
||||
NextTab,
|
||||
PrevTab,
|
||||
SplitVertical,
|
||||
@@ -54,10 +53,6 @@ namespace TerminalApp
|
||||
ResizePaneRight,
|
||||
ResizePaneUp,
|
||||
ResizePaneDown,
|
||||
MoveFocusLeft,
|
||||
MoveFocusRight,
|
||||
MoveFocusUp,
|
||||
MoveFocusDown,
|
||||
OpenSettings
|
||||
};
|
||||
|
||||
@@ -69,7 +64,6 @@ namespace TerminalApp
|
||||
delegate void NewWindowEventArgs();
|
||||
delegate void CloseWindowEventArgs();
|
||||
delegate void CloseTabEventArgs();
|
||||
delegate void ClosePaneEventArgs();
|
||||
delegate void NextTabEventArgs();
|
||||
delegate void PrevTabEventArgs();
|
||||
delegate void SplitVerticalEventArgs();
|
||||
@@ -83,9 +77,9 @@ namespace TerminalApp
|
||||
delegate void ScrollDownPageEventArgs();
|
||||
delegate void OpenSettingsEventArgs();
|
||||
delegate void ResizePaneEventArgs(Direction direction);
|
||||
delegate void MoveFocusEventArgs(Direction direction);
|
||||
|
||||
[default_interface] runtimeclass AppKeyBindings : Microsoft.Terminal.Settings.IKeyBindings
|
||||
[default_interface]
|
||||
runtimeclass AppKeyBindings : Microsoft.Terminal.Settings.IKeyBindings
|
||||
{
|
||||
AppKeyBindings();
|
||||
|
||||
@@ -100,7 +94,6 @@ namespace TerminalApp
|
||||
event NewWindowEventArgs NewWindow;
|
||||
event CloseWindowEventArgs CloseWindow;
|
||||
event CloseTabEventArgs CloseTab;
|
||||
event ClosePaneEventArgs ClosePane;
|
||||
event SwitchToTabEventArgs SwitchToTab;
|
||||
event NextTabEventArgs NextTab;
|
||||
event PrevTabEventArgs PrevTab;
|
||||
@@ -114,6 +107,5 @@ namespace TerminalApp
|
||||
event ScrollDownPageEventArgs ScrollDownPage;
|
||||
event OpenSettingsEventArgs OpenSettings;
|
||||
event ResizePaneEventArgs ResizePane;
|
||||
event MoveFocusEventArgs MoveFocus;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ static constexpr std::string_view NewTabWithProfile8Key{ "newTabProfile8" };
|
||||
static constexpr std::string_view NewWindowKey{ "newWindow" };
|
||||
static constexpr std::string_view CloseWindowKey{ "closeWindow" };
|
||||
static constexpr std::string_view CloseTabKey{ "closeTab" };
|
||||
static constexpr std::string_view ClosePaneKey{ "closePane" };
|
||||
static constexpr std::string_view SwitchtoTabKey{ "switchToTab" };
|
||||
static constexpr std::string_view NextTabKey{ "nextTab" };
|
||||
static constexpr std::string_view PrevTabKey{ "prevTab" };
|
||||
@@ -56,10 +55,6 @@ static constexpr std::string_view ResizePaneLeftKey{ "resizePaneLeft" };
|
||||
static constexpr std::string_view ResizePaneRightKey{ "resizePaneRight" };
|
||||
static constexpr std::string_view ResizePaneUpKey{ "resizePaneUp" };
|
||||
static constexpr std::string_view ResizePaneDownKey{ "resizePaneDown" };
|
||||
static constexpr std::string_view MoveFocusLeftKey{ "moveFocusLeft" };
|
||||
static constexpr std::string_view MoveFocusRightKey{ "moveFocusRight" };
|
||||
static constexpr std::string_view MoveFocusUpKey{ "moveFocusUp" };
|
||||
static constexpr std::string_view MoveFocusDownKey{ "moveFocusDown" };
|
||||
|
||||
// Specifically use a map here over an unordered_map. We want to be able to
|
||||
// iterate over these entries in-order when we're serializing the keybindings.
|
||||
@@ -87,7 +82,6 @@ static const std::map<std::string_view, ShortcutAction, std::less<>> commandName
|
||||
{ NewWindowKey, ShortcutAction::NewWindow },
|
||||
{ CloseWindowKey, ShortcutAction::CloseWindow },
|
||||
{ CloseTabKey, ShortcutAction::CloseTab },
|
||||
{ ClosePaneKey, ShortcutAction::ClosePane },
|
||||
{ NextTabKey, ShortcutAction::NextTab },
|
||||
{ PrevTabKey, ShortcutAction::PrevTab },
|
||||
{ IncreaseFontSizeKey, ShortcutAction::IncreaseFontSize },
|
||||
@@ -111,10 +105,6 @@ static const std::map<std::string_view, ShortcutAction, std::less<>> commandName
|
||||
{ ResizePaneRightKey, ShortcutAction::ResizePaneRight },
|
||||
{ ResizePaneUpKey, ShortcutAction::ResizePaneUp },
|
||||
{ ResizePaneDownKey, ShortcutAction::ResizePaneDown },
|
||||
{ MoveFocusLeftKey, ShortcutAction::MoveFocusLeft },
|
||||
{ MoveFocusRightKey, ShortcutAction::MoveFocusRight },
|
||||
{ MoveFocusUpKey, ShortcutAction::MoveFocusUp },
|
||||
{ MoveFocusDownKey, ShortcutAction::MoveFocusDown },
|
||||
{ OpenSettingsKey, ShortcutAction::OpenSettings },
|
||||
};
|
||||
|
||||
|
||||
@@ -287,8 +287,8 @@ void CascadiaSettings::_CreateDefaultKeybindings()
|
||||
KeyChord{ KeyModifiers::Ctrl | KeyModifiers::Shift,
|
||||
static_cast<int>('D') });
|
||||
|
||||
keyBindings.SetKeyBinding(ShortcutAction::ClosePane,
|
||||
KeyChord{ KeyModifiers::Ctrl | KeyModifiers::Shift,
|
||||
keyBindings.SetKeyBinding(ShortcutAction::CloseTab,
|
||||
KeyChord{ KeyModifiers::Ctrl,
|
||||
static_cast<int>('W') });
|
||||
|
||||
keyBindings.SetKeyBinding(ShortcutAction::CopyText,
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
//
|
||||
//
|
||||
// MinMaxCloseControl.xaml.cpp
|
||||
// Implementation of the MinMaxCloseControl class
|
||||
//
|
||||
@@ -10,7 +8,6 @@
|
||||
#include "MinMaxCloseControl.h"
|
||||
|
||||
#include "MinMaxCloseControl.g.cpp"
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
@@ -19,37 +16,59 @@ namespace winrt::TerminalApp::implementation
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
void MinMaxCloseControl::Maximize()
|
||||
uint64_t MinMaxCloseControl::ParentWindowHandle() const
|
||||
{
|
||||
VisualStateManager::GoToState(MaximizeButton(), L"WindowStateMaximized", false);
|
||||
return reinterpret_cast<uint64_t>(_window);
|
||||
}
|
||||
|
||||
void MinMaxCloseControl::RestoreDown()
|
||||
void MinMaxCloseControl::ParentWindowHandle(uint64_t handle)
|
||||
{
|
||||
VisualStateManager::GoToState(MaximizeButton(), L"WindowStateNormal", false);
|
||||
_window = reinterpret_cast<HWND>(handle);
|
||||
}
|
||||
|
||||
// These event handlers simply forward each buttons click events up to the
|
||||
// events we've exposed.
|
||||
void MinMaxCloseControl::_MinimizeClick(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
RoutedEventArgs const& e)
|
||||
void MinMaxCloseControl::_OnMaximize(byte flag)
|
||||
{
|
||||
_minimizeClickHandlers(*this, e);
|
||||
if (_window)
|
||||
{
|
||||
POINT point1 = {};
|
||||
::GetCursorPos(&point1);
|
||||
const LPARAM lParam = MAKELPARAM(point1.x, point1.y);
|
||||
WINDOWPLACEMENT placement = { sizeof(placement) };
|
||||
::GetWindowPlacement(_window, &placement);
|
||||
if (placement.showCmd == SW_SHOWNORMAL)
|
||||
{
|
||||
winrt::Windows::UI::Xaml::VisualStateManager::GoToState(this->Maximize(), L"WindowStateMaximized", false);
|
||||
::PostMessage(_window, WM_SYSCOMMAND, SC_MAXIMIZE | flag, lParam);
|
||||
}
|
||||
else if (placement.showCmd == SW_SHOWMAXIMIZED)
|
||||
{
|
||||
winrt::Windows::UI::Xaml::VisualStateManager::GoToState(this->Maximize(), L"WindowStateNormal", false);
|
||||
::PostMessage(_window, WM_SYSCOMMAND, SC_RESTORE | flag, lParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MinMaxCloseControl::_MaximizeClick(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
RoutedEventArgs const& e)
|
||||
void MinMaxCloseControl::Maximize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e)
|
||||
{
|
||||
_maximizeClickHandlers(*this, e);
|
||||
}
|
||||
void MinMaxCloseControl::_CloseClick(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
RoutedEventArgs const& e)
|
||||
{
|
||||
_closeClickHandlers(*this, e);
|
||||
_OnMaximize(HTMAXBUTTON);
|
||||
}
|
||||
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(MinMaxCloseControl, MinimizeClick, _minimizeClickHandlers, TerminalApp::MinMaxCloseControl, RoutedEventArgs);
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(MinMaxCloseControl, MaximizeClick, _maximizeClickHandlers, TerminalApp::MinMaxCloseControl, RoutedEventArgs);
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(MinMaxCloseControl, CloseClick, _closeClickHandlers, TerminalApp::MinMaxCloseControl, RoutedEventArgs);
|
||||
void MinMaxCloseControl::DragBar_DoubleTapped(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs const& e)
|
||||
{
|
||||
_OnMaximize(HTCAPTION);
|
||||
}
|
||||
|
||||
void MinMaxCloseControl::Minimize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e)
|
||||
{
|
||||
if (_window)
|
||||
{
|
||||
::PostMessage(_window, WM_SYSCOMMAND, SC_MINIMIZE | HTMINBUTTON, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void MinMaxCloseControl::Close_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e)
|
||||
{
|
||||
::PostQuitMessage(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
//
|
||||
//
|
||||
// Declaration of the MainUserControl class.
|
||||
//
|
||||
|
||||
@@ -10,7 +8,6 @@
|
||||
#include "winrt/Windows.UI.Xaml.Markup.h"
|
||||
#include "winrt/Windows.UI.Xaml.Interop.h"
|
||||
#include "MinMaxCloseControl.g.h"
|
||||
#include "../../cascadia/inc/cppwinrt_utils.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
@@ -18,19 +15,17 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
MinMaxCloseControl();
|
||||
|
||||
void Maximize();
|
||||
void RestoreDown();
|
||||
void Minimize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
void Maximize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
void Close_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
void DragBar_DoubleTapped(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs const& e);
|
||||
|
||||
void _MinimizeClick(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
void _MaximizeClick(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
void _CloseClick(winrt::Windows::Foundation::IInspectable const& sender,
|
||||
winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
uint64_t ParentWindowHandle() const;
|
||||
void ParentWindowHandle(uint64_t handle);
|
||||
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(MinimizeClick, _minimizeClickHandlers, TerminalApp::MinMaxCloseControl, winrt::Windows::UI::Xaml::RoutedEventArgs);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(MaximizeClick, _maximizeClickHandlers, TerminalApp::MinMaxCloseControl, winrt::Windows::UI::Xaml::RoutedEventArgs);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(CloseClick, _closeClickHandlers, TerminalApp::MinMaxCloseControl, winrt::Windows::UI::Xaml::RoutedEventArgs);
|
||||
private:
|
||||
void _OnMaximize(byte flag);
|
||||
HWND _window{ nullptr }; // non-owning handle; should not be freed in the dtor.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace TerminalApp
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass MinMaxCloseControl : Windows.UI.Xaml.Controls.StackPanel
|
||||
[default_interface]
|
||||
runtimeclass MinMaxCloseControl : Windows.UI.Xaml.Controls.StackPanel
|
||||
{
|
||||
MinMaxCloseControl();
|
||||
|
||||
void Maximize();
|
||||
void RestoreDown();
|
||||
Windows.UI.Xaml.Controls.Grid Content{ get; };
|
||||
Windows.UI.Xaml.Controls.Border DragBar{ get; };
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<MinMaxCloseControl, Windows.UI.Xaml.RoutedEventArgs> MinimizeClick;
|
||||
event Windows.Foundation.TypedEventHandler<MinMaxCloseControl, Windows.UI.Xaml.RoutedEventArgs> MaximizeClick;
|
||||
event Windows.Foundation.TypedEventHandler<MinMaxCloseControl, Windows.UI.Xaml.RoutedEventArgs> CloseClick;
|
||||
UInt64 ParentWindowHandle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information. -->
|
||||
<StackPanel
|
||||
<StackPanel
|
||||
x:Class="TerminalApp.MinMaxCloseControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
@@ -131,7 +129,13 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
</ResourceDictionary>
|
||||
</StackPanel.Resources>
|
||||
|
||||
<Button Height="36.0" MinWidth="45.0" Width="45.0" x:Name="MinimizeButton" Style="{StaticResource CaptionButton}" Click="_MinimizeClick"
|
||||
<Grid x:Name="Content"></Grid>
|
||||
<Border Height="36.0"
|
||||
MinWidth="160.0"
|
||||
x:Name="DragBar"
|
||||
Background="{ThemeResource SystemChromeLowColor}"
|
||||
DoubleTapped="DragBar_DoubleTapped"/>
|
||||
<Button Height="36.0" Width="45.0" x:Name="Minimize" Style="{StaticResource CaptionButton}" Click="Minimize_Click"
|
||||
AutomationProperties.Name="Minimize">
|
||||
<Button.Resources>
|
||||
<ResourceDictionary>
|
||||
@@ -139,7 +143,7 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
</ResourceDictionary>
|
||||
</Button.Resources>
|
||||
</Button>
|
||||
<Button Height="36.0" MinWidth="45.0" Width="45.0" x:Name="MaximizeButton" Style="{StaticResource CaptionButton}" Click="_MaximizeClick"
|
||||
<Button Height="36.0" Width="45.0" x:Name="Maximize" Style="{StaticResource CaptionButton}" Click="Maximize_Click"
|
||||
AutomationProperties.Name="Maximize">
|
||||
<Button.Resources>
|
||||
<ResourceDictionary>
|
||||
@@ -148,7 +152,7 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
</ResourceDictionary>
|
||||
</Button.Resources>
|
||||
</Button>
|
||||
<Button Height="36.0" MinWidth="45.0" Width="45.0" x:Name="CloseButton" Style="{StaticResource CaptionButton}" Click="_CloseClick"
|
||||
<Button Height="36.0" Width="45.0" x:Name="Close" Style="{StaticResource CaptionButton}" Click="Close_Click"
|
||||
AutomationProperties.Name="Close">
|
||||
<Button.Resources>
|
||||
<ResourceDictionary>
|
||||
|
||||
@@ -187,95 +187,6 @@ bool Pane::ResizePane(const Direction& direction)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Attempts to handle moving focus to one of our children. If our split
|
||||
// direction isn't appropriate for the move direction, then we'll return
|
||||
// false, to try and let our parent handle the move. If our child we'd move
|
||||
// focus to is already focused, we'll also return false, to again let our
|
||||
// parent try and handle the focus movement.
|
||||
// Arguments:
|
||||
// - direction: The direction to move the focus in.
|
||||
// Return Value:
|
||||
// - true if we handled this focus move request.
|
||||
bool Pane::_NavigateFocus(const Direction& direction)
|
||||
{
|
||||
if (!DirectionMatchesSplit(direction, _splitState))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool focusSecond = (direction == Direction::Right) || (direction == Direction::Down);
|
||||
|
||||
const auto newlyFocusedChild = focusSecond ? _secondChild : _firstChild;
|
||||
|
||||
// If the child we want to move focus to is _already_ focused, return false,
|
||||
// to try and let our parent figure it out.
|
||||
if (newlyFocusedChild->WasLastFocused())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Transfer focus to our child, and update the focus of our tree.
|
||||
newlyFocusedChild->_FocusFirstChild();
|
||||
UpdateFocus();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Attempts to move focus to one of our children. If we have a focused child,
|
||||
// we'll try to move the focus in the direction requested.
|
||||
// - If there isn't a pane that exists as a child of this pane in the correct
|
||||
// direction, we'll return false. This will indicate to our parent that they
|
||||
// should try and move the focus themselves. In this way, the focus can move
|
||||
// up and down the tree to the correct pane.
|
||||
// - This method is _very_ similar to ResizePane. Both are trying to find the
|
||||
// right separator to move (focus) in a direction.
|
||||
// Arguments:
|
||||
// - direction: The direction to move the focus in.
|
||||
// Return Value:
|
||||
// - true if we or a child handled this focus move request.
|
||||
bool Pane::NavigateFocus(const Direction& direction)
|
||||
{
|
||||
// If we're a leaf, do nothing. We can't possibly have a descendant with a
|
||||
// separator the correct direction.
|
||||
if (_IsLeaf())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if either our first or second child is the currently focused leaf.
|
||||
// If it is, and the requested move direction matches our separator, then
|
||||
// we're the pane that needs to handle this focus move.
|
||||
const bool firstIsFocused = _firstChild->_IsLeaf() && _firstChild->_lastFocused;
|
||||
const bool secondIsFocused = _secondChild->_IsLeaf() && _secondChild->_lastFocused;
|
||||
if (firstIsFocused || secondIsFocused)
|
||||
{
|
||||
return _NavigateFocus(direction);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If neither of our children were the focused leaf, then recurse into
|
||||
// our children and see if they can handle the focus move.
|
||||
// For each child, if it has a focused descendant, try having that child
|
||||
// handle the focus move.
|
||||
// If the child wasn't able to handle the focus move, it's possible that
|
||||
// there were no descendants with a separator the correct direction. If
|
||||
// our separator _is_ the correct direction, then we should be the pane
|
||||
// to move focus into our other child. Otherwise, just return false, as
|
||||
// we couldn't handle it either.
|
||||
if ((!_firstChild->_IsLeaf()) && _firstChild->_HasFocusedChild())
|
||||
{
|
||||
return _firstChild->NavigateFocus(direction) || _NavigateFocus(direction);
|
||||
}
|
||||
else if ((!_secondChild->_IsLeaf()) && _secondChild->_HasFocusedChild())
|
||||
{
|
||||
return _secondChild->NavigateFocus(direction) || _NavigateFocus(direction);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called when our attached control is closed. Triggers listeners to our close
|
||||
// event, if we're a leaf pane.
|
||||
@@ -308,18 +219,6 @@ void Pane::_ControlClosedHandler()
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Fire our Closed event to tell our parent that we should be removed.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Pane::Close()
|
||||
{
|
||||
// Fire our Closed event to tell our parent that we should be removed.
|
||||
_closedHandlers();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the root UIElement of this pane. There may be a single TermControl as a
|
||||
// child, or an entire tree of grids and panes as children of this element.
|
||||
|
||||
@@ -47,13 +47,10 @@ public:
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::TerminalSettings& settings, const GUID& profile);
|
||||
void ResizeContent(const winrt::Windows::Foundation::Size& newSize);
|
||||
bool ResizePane(const winrt::TerminalApp::Direction& direction);
|
||||
bool NavigateFocus(const winrt::TerminalApp::Direction& direction);
|
||||
|
||||
void SplitHorizontal(const GUID& profile, const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
|
||||
void SplitVertical(const GUID& profile, const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
|
||||
|
||||
void Close();
|
||||
|
||||
DECLARE_EVENT(Closed, _closedHandlers, winrt::Microsoft::Terminal::TerminalControl::ConnectionClosedEventArgs);
|
||||
|
||||
private:
|
||||
@@ -83,9 +80,7 @@ private:
|
||||
void _CreateRowColDefinitions(const winrt::Windows::Foundation::Size& rootSize);
|
||||
void _CreateSplitContent();
|
||||
void _ApplySplitDefinitions();
|
||||
|
||||
bool _Resize(const winrt::TerminalApp::Direction& direction);
|
||||
bool _NavigateFocus(const winrt::TerminalApp::Direction& direction);
|
||||
|
||||
void _CloseChild(const bool closeFirst);
|
||||
|
||||
|
||||
@@ -237,30 +237,4 @@ void Tab::ResizePane(const winrt::TerminalApp::Direction& direction)
|
||||
_rootPane->ResizePane(direction);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Attempt to move focus between panes, as to focus the child on
|
||||
// the other side of the separator. See Pane::NavigateFocus for details.
|
||||
// Arguments:
|
||||
// - direction: The direction to move the focus in.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Tab::NavigateFocus(const winrt::TerminalApp::Direction& direction)
|
||||
{
|
||||
_rootPane->NavigateFocus(direction);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Closes the currently focused pane in this tab. If it's the last pane in
|
||||
// this tab, our Closed event will be fired (at a later time) for anyone
|
||||
// registered as a handler of our close event.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Tab::ClosePane()
|
||||
{
|
||||
auto focused = _rootPane->GetFocusedPane();
|
||||
focused->Close();
|
||||
}
|
||||
|
||||
DEFINE_EVENT(Tab, Closed, _closedHandlers, ConnectionClosedEventArgs);
|
||||
|
||||
@@ -25,14 +25,11 @@ public:
|
||||
void UpdateFocus();
|
||||
void ResizeContent(const winrt::Windows::Foundation::Size& newSize);
|
||||
void ResizePane(const winrt::TerminalApp::Direction& direction);
|
||||
void NavigateFocus(const winrt::TerminalApp::Direction& direction);
|
||||
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::TerminalSettings& settings, const GUID& profile);
|
||||
winrt::hstring GetFocusedTitle() const;
|
||||
void SetTabText(const winrt::hstring& text);
|
||||
|
||||
void ClosePane();
|
||||
|
||||
DECLARE_EVENT(Closed, _closedHandlers, winrt::Microsoft::Terminal::TerminalControl::ConnectionClosedEventArgs);
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "TabRowControl.h"
|
||||
|
||||
#include "TabRowControl.g.cpp"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace Windows::UI::Xaml;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
TabRowControl::TabRowControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Bound in the Xaml editor to the [+] button.
|
||||
// Arguments:
|
||||
// <unused>
|
||||
void TabRowControl::OnNewTabButtonClick(IInspectable const&, Controls::SplitButtonClickEventArgs const&)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "winrt/Microsoft.UI.Xaml.Controls.h"
|
||||
|
||||
#include "TabRowControl.g.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct TabRowControl : TabRowControlT<TabRowControl>
|
||||
{
|
||||
TabRowControl();
|
||||
|
||||
void OnNewTabButtonClick(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Controls::SplitButtonClickEventArgs const& args);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
struct TabRowControl : TabRowControlT<TabRowControl, implementation::TabRowControl>
|
||||
{
|
||||
};
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass TabRowControl : Windows.UI.Xaml.Controls.Grid
|
||||
{
|
||||
TabRowControl();
|
||||
Windows.UI.Xaml.Controls.SplitButton NewTabButton { get; };
|
||||
Microsoft.UI.Xaml.Controls.TabView TabView { get; };
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information. -->
|
||||
<Grid
|
||||
x:Class="TerminalApp.TabRowControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:TerminalApp"
|
||||
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<mux:TabView x:Name="TabView" VerticalAlignment="Bottom">
|
||||
|
||||
<mux:TabView.RightCustomContent>
|
||||
<SplitButton
|
||||
x:Name="NewTabButton"
|
||||
Click="OnNewTabButtonClick"
|
||||
Background="{ThemeResource SystemChromeLowColor}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Left">
|
||||
<Viewbox MaxHeight="15"
|
||||
MaxWidth="15">
|
||||
<SymbolIcon Symbol="Add" />
|
||||
</Viewbox>
|
||||
</SplitButton>
|
||||
</mux:TabView.RightCustomContent>
|
||||
|
||||
</mux:TabView>
|
||||
|
||||
</Grid>
|
||||
@@ -30,8 +30,6 @@
|
||||
<ClInclude Include="TerminalPage.h" />
|
||||
<ClInclude Include="MinMaxCloseControl.h" />
|
||||
<ClInclude Include="AppKeyBindings.h" />
|
||||
<ClInclude Include="TitlebarControl.h" />
|
||||
<ClInclude Include="TabRowControl.h" />
|
||||
<ClInclude Include="App.h" />
|
||||
</ItemGroup>
|
||||
<!-- ========================= Cpp Files ======================== -->
|
||||
@@ -105,32 +103,4 @@
|
||||
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<!--
|
||||
This is a terrible, terrible rule. There exists a bug in Visual Studio 2019 16.2 and 16.3 previews
|
||||
where ResolveAssemblyReferences will try and fail to parse a .lib when it produces a .winmd.
|
||||
To fix that, we have to _temporarily_ replace the %(Implementation) on any winmd-producing
|
||||
static library references with the empty string so as to make ResolveAssemblyReferences
|
||||
not try to read it.
|
||||
|
||||
Upstream problem report:
|
||||
https://developercommunity.visualstudio.com/content/problem/629524/static-library-reference-causes-there-was-a-proble.html
|
||||
-->
|
||||
<Target Name="_RemoveTerminalAppLibImplementationFromReference" BeforeTargets="ResolveAssemblyReferences">
|
||||
<ItemGroup>
|
||||
<_TerminalAppLibProjectReference Include="@(_ResolvedProjectReferencePaths)" Condition="'%(Filename)' == 'TerminalApp'" />
|
||||
<_ResolvedProjectReferencePaths Remove="@(_TerminalAppLibProjectReference)" />
|
||||
<_ResolvedProjectReferencePaths Include="@(_TerminalAppLibProjectReference)">
|
||||
<Implementation />
|
||||
</_ResolvedProjectReferencePaths>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_RestoreTerminalAppLibImplementationFromReference" AfterTargets="ResolveAssemblyReferences">
|
||||
<ItemGroup>
|
||||
<_ResolvedProjectReferencePaths Remove="@(_TerminalAppLibProjectReference)" />
|
||||
<_ResolvedProjectReferencePaths Include="@(_TerminalAppLibProjectReference)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<!-- End "terrible, terrible rule" -->
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -15,4 +15,13 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Bound in the Xaml editor to the [+] button.
|
||||
// Arguments:
|
||||
// - sender
|
||||
// - event arguments
|
||||
void TerminalPage::OnNewTabButtonClick(IInspectable const&, Controls::SplitButtonClickEventArgs const&)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace winrt::TerminalApp::implementation
|
||||
struct TerminalPage : TerminalPageT<TerminalPage>
|
||||
{
|
||||
TerminalPage();
|
||||
|
||||
void OnNewTabButtonClick(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Controls::SplitButtonClickEventArgs const& args);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass TerminalPage : Windows.UI.Xaml.Controls.Page
|
||||
[default_interface]
|
||||
runtimeclass TerminalPage : Windows.UI.Xaml.Controls.Page
|
||||
{
|
||||
TerminalPage();
|
||||
}
|
||||
|
||||
@@ -10,13 +10,39 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid x:Name="Root" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<local:TabRowControl x:Name="TabRow" Grid.Row="0" />
|
||||
<Grid x:Name="TabRow" Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<mux:TabView x:Name="TabView" Grid.Column="0" />
|
||||
|
||||
<SplitButton
|
||||
x:Name="NewTabButton"
|
||||
Grid.Column="1"
|
||||
Click="OnNewTabButtonClick"
|
||||
Background="{ThemeResource SystemChromeLowColor}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Left">
|
||||
<Viewbox MaxHeight="15"
|
||||
MaxWidth="15">
|
||||
<SymbolIcon Symbol="Add" />
|
||||
</Viewbox>
|
||||
</SplitButton>
|
||||
|
||||
<local:MinMaxCloseControl
|
||||
x:Name="MinMaxCloseControl"
|
||||
Grid.Column="3"
|
||||
HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
|
||||
<Grid x:Name="TabContent" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
|
||||
</Grid>
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
//
|
||||
// TitlebarControl.xaml.cpp
|
||||
// Implementation of the TitlebarControl class
|
||||
//
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "TitlebarControl.h"
|
||||
|
||||
#include "TitlebarControl.g.cpp"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
TitlebarControl::TitlebarControl(uint64_t handle) :
|
||||
_window{ reinterpret_cast<HWND>(handle) }
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Register our event handlers on the MMC buttons.
|
||||
MinMaxCloseControl().MinimizeClick({ this, &TitlebarControl::Minimize_Click });
|
||||
MinMaxCloseControl().MaximizeClick({ this, &TitlebarControl::Maximize_Click });
|
||||
MinMaxCloseControl().CloseClick({ this, &TitlebarControl::Close_Click });
|
||||
}
|
||||
|
||||
Windows::UI::Xaml::UIElement TitlebarControl::Content()
|
||||
{
|
||||
return ContentRoot().Children().Size() > 0 ? ContentRoot().Children().GetAt(0) : nullptr;
|
||||
}
|
||||
|
||||
void TitlebarControl::Content(Windows::UI::Xaml::UIElement content)
|
||||
{
|
||||
ContentRoot().Children().Clear();
|
||||
ContentRoot().Children().Append(content);
|
||||
}
|
||||
|
||||
void TitlebarControl::Root_SizeChanged(const IInspectable& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e)
|
||||
{
|
||||
const auto windowWidth = ActualWidth();
|
||||
const auto minMaxCloseWidth = MinMaxCloseControl().ActualWidth();
|
||||
const auto dragBarMinWidth = DragBar().MinWidth();
|
||||
const auto maxWidth = windowWidth - minMaxCloseWidth - dragBarMinWidth;
|
||||
ContentRoot().MaxWidth(maxWidth);
|
||||
}
|
||||
|
||||
void TitlebarControl::_OnMaximizeOrRestore(byte flag)
|
||||
{
|
||||
POINT point1 = {};
|
||||
::GetCursorPos(&point1);
|
||||
const LPARAM lParam = MAKELPARAM(point1.x, point1.y);
|
||||
WINDOWPLACEMENT placement = { sizeof(placement) };
|
||||
::GetWindowPlacement(_window, &placement);
|
||||
if (placement.showCmd == SW_SHOWNORMAL)
|
||||
{
|
||||
MinMaxCloseControl().Maximize();
|
||||
::PostMessage(_window, WM_SYSCOMMAND, SC_MAXIMIZE | flag, lParam);
|
||||
}
|
||||
else if (placement.showCmd == SW_SHOWMAXIMIZED)
|
||||
{
|
||||
MinMaxCloseControl().RestoreDown();
|
||||
::PostMessage(_window, WM_SYSCOMMAND, SC_RESTORE | flag, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
void TitlebarControl::Maximize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e)
|
||||
{
|
||||
_OnMaximizeOrRestore(HTMAXBUTTON);
|
||||
}
|
||||
|
||||
void TitlebarControl::DragBar_DoubleTapped(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs const& e)
|
||||
{
|
||||
_OnMaximizeOrRestore(HTCAPTION);
|
||||
}
|
||||
|
||||
void TitlebarControl::Minimize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e)
|
||||
{
|
||||
if (_window)
|
||||
{
|
||||
::PostMessage(_window, WM_SYSCOMMAND, SC_MINIMIZE | HTMINBUTTON, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void TitlebarControl::Close_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e)
|
||||
{
|
||||
::PostQuitMessage(0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
//
|
||||
// Declaration of the MainUserControl class.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "winrt/Windows.UI.Xaml.h"
|
||||
#include "winrt/Windows.UI.Xaml.Markup.h"
|
||||
#include "winrt/Windows.UI.Xaml.Interop.h"
|
||||
#include "TitlebarControl.g.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct TitlebarControl : TitlebarControlT<TitlebarControl>
|
||||
{
|
||||
TitlebarControl(uint64_t handle);
|
||||
|
||||
Windows::UI::Xaml::UIElement Content();
|
||||
void Content(Windows::UI::Xaml::UIElement content);
|
||||
|
||||
void Root_SizeChanged(const IInspectable& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e);
|
||||
|
||||
void Minimize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
void Maximize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
void Close_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
void DragBar_DoubleTapped(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs const& e);
|
||||
|
||||
private:
|
||||
void _OnMaximizeOrRestore(byte flag);
|
||||
HWND _window{ nullptr }; // non-owning handle; should not be freed in the dtor.
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
struct TitlebarControl : TitlebarControlT<TitlebarControl, implementation::TitlebarControl>
|
||||
{
|
||||
};
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass TitlebarControl : Windows.UI.Xaml.Controls.Grid
|
||||
{
|
||||
TitlebarControl(UInt64 parentWindowHandle);
|
||||
|
||||
Windows.UI.Xaml.UIElement Content;
|
||||
Windows.UI.Xaml.Controls.Border DragBar { get; };
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information. -->
|
||||
<Grid
|
||||
x:Class="TerminalApp.TitlebarControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:TerminalApp"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
x:Name="Root"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Top"
|
||||
SizeChanged="Root_SizeChanged"
|
||||
d:DesignHeight="36"
|
||||
Background="{ThemeResource SystemChromeLowColor}"
|
||||
d:DesignWidth="400">
|
||||
|
||||
<!-- TODO:GH#1988
|
||||
This xaml should probably be a template thing, where the background is a
|
||||
resource that the app hosting this control can override. Then, it App.xaml,
|
||||
we'd make sure to set the resource for our background to the appropriate
|
||||
color. SystemControlForegroundAccentBrush also works nicely, to use the
|
||||
accent color. (which is GH#1963)-->
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid x:Name="ContentRoot" Grid.Column="0" />
|
||||
|
||||
<Border
|
||||
x:Name="DragBar"
|
||||
Grid.Column="1"
|
||||
MinWidth="45.0"
|
||||
DoubleTapped="DragBar_DoubleTapped"/>
|
||||
|
||||
<local:MinMaxCloseControl
|
||||
Grid.Column="2"
|
||||
x:Name="MinMaxCloseControl"
|
||||
HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
|
||||
@@ -35,12 +35,6 @@
|
||||
<Page Include="../TerminalPage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="../TitlebarControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="../TabRowControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- ========================= Headers ======================== -->
|
||||
@@ -53,12 +47,6 @@
|
||||
<DependentUpon>../TerminalPage.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="../TitlebarControl.h">
|
||||
<DependentUpon>../TitlebarControl.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="../TabRowControl.h">
|
||||
<DependentUpon>../TabRowControl.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="../Tab.h" />
|
||||
<ClInclude Include="../Pane.h" />
|
||||
<ClInclude Include="../ColorScheme.h" />
|
||||
@@ -84,12 +72,6 @@
|
||||
<DependentUpon>../TerminalPage.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="../TitlebarControl.cpp">
|
||||
<DependentUpon>../TitlebarControl.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="../TabRowControl.cpp">
|
||||
<DependentUpon>../TabRowControl.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="../Tab.cpp" />
|
||||
<ClCompile Include="../Pane.cpp" />
|
||||
<ClCompile Include="../ColorScheme.cpp" />
|
||||
@@ -134,14 +116,6 @@
|
||||
<DependentUpon>../TerminalPage.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="../TitlebarControl.idl">
|
||||
<DependentUpon>../TitlebarControl.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="../TabRowControl.idl">
|
||||
<DependentUpon>../TabRowControl.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- ========================= Misc Files ======================== -->
|
||||
@@ -258,7 +232,7 @@
|
||||
<Implementation>Microsoft.UI.Xaml.dll</Implementation>
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
<Private>true</Private>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
<ReferenceCopyLocalPaths Include="$(_MUXRoot)runtimes\win10-$(Native-Platform)\native\Microsoft.UI.Xaml.dll" />
|
||||
<ReferenceCopyLocalPaths Include="$(_MUXRoot)runtimes\win10-$(Native-Platform)\native\Microsoft.UI.Xaml.pri" />
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <conpty-universal.h>
|
||||
#include "../../types/inc/Utils.hpp"
|
||||
#include "../../types/inc/UTF8OutPipeReader.hpp"
|
||||
|
||||
using namespace ::Microsoft::Console;
|
||||
|
||||
@@ -38,6 +37,23 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
}
|
||||
}
|
||||
|
||||
ConhostConnection::ConhostConnection(const uint64_t server,
|
||||
const uint32_t initialRows,
|
||||
const uint32_t initialCols,
|
||||
const guid& initialGuid) :
|
||||
_initialRows{ initialRows },
|
||||
_initialCols{ initialCols },
|
||||
_commandline{},
|
||||
_startingDirectory{},
|
||||
_guid{ initialGuid },
|
||||
_hServer{ reinterpret_cast<HANDLE>(server) }
|
||||
{
|
||||
if (_guid == guid{})
|
||||
{
|
||||
_guid = Utils::CreateGuid();
|
||||
}
|
||||
}
|
||||
|
||||
winrt::guid ConhostConnection::Guid() const noexcept
|
||||
{
|
||||
return _guid;
|
||||
@@ -72,6 +88,12 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
startingDirectory = _startingDirectory;
|
||||
}
|
||||
|
||||
std::optional<HANDLE> server;
|
||||
if (_hServer)
|
||||
{
|
||||
server = _hServer.get();
|
||||
}
|
||||
|
||||
EnvironmentVariableMapW extraEnvVars;
|
||||
{
|
||||
// Convert connection Guid to string and ignore the enclosing '{}'.
|
||||
@@ -89,6 +111,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
startingDirectory,
|
||||
static_cast<short>(_initialCols),
|
||||
static_cast<short>(_initialRows),
|
||||
server,
|
||||
&_inPipe,
|
||||
&_outPipe,
|
||||
&_signalPipe,
|
||||
@@ -190,37 +213,39 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
|
||||
DWORD ConhostConnection::_OutputThread()
|
||||
{
|
||||
UTF8OutPipeReader pipeReader{ _outPipe.get() };
|
||||
std::string_view strView{};
|
||||
|
||||
// process the data of the output pipe in a loop
|
||||
const size_t bufferSize = 4096;
|
||||
BYTE buffer[bufferSize];
|
||||
DWORD dwRead;
|
||||
while (true)
|
||||
{
|
||||
HRESULT result = pipeReader.Read(strView);
|
||||
if (FAILED(result) || result == S_FALSE)
|
||||
dwRead = 0;
|
||||
bool fSuccess = false;
|
||||
|
||||
fSuccess = !!ReadFile(_outPipe.get(), buffer, bufferSize, &dwRead, nullptr);
|
||||
if (!fSuccess)
|
||||
{
|
||||
if (_closing.load())
|
||||
{
|
||||
// This is okay, break out to kill the thread
|
||||
return 0;
|
||||
}
|
||||
|
||||
_disconnectHandlers();
|
||||
return (DWORD)-1;
|
||||
else
|
||||
{
|
||||
_disconnectHandlers();
|
||||
return (DWORD)-1;
|
||||
}
|
||||
}
|
||||
|
||||
if (strView.empty())
|
||||
if (dwRead == 0)
|
||||
{
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Convert buffer to hstring
|
||||
auto hstr{ winrt::to_hstring(strView) };
|
||||
char* pchStr = (char*)(buffer);
|
||||
std::string str{ pchStr, dwRead };
|
||||
auto hstr = winrt::to_hstring(str);
|
||||
|
||||
// Pass the output to our registered event handlers
|
||||
_outputHandlers(hstr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
struct ConhostConnection : ConhostConnectionT<ConhostConnection>
|
||||
{
|
||||
ConhostConnection(const hstring& cmdline, const hstring& startingDirectory, const uint32_t rows, const uint32_t cols, const guid& guid);
|
||||
ConhostConnection(const uint64_t server, const uint32_t rows, const uint32_t cols, const guid& guid);
|
||||
|
||||
winrt::event_token TerminalOutput(TerminalConnection::TerminalOutputEventArgs const& handler);
|
||||
void TerminalOutput(winrt::event_token const& token) noexcept;
|
||||
@@ -41,6 +42,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
wil::unique_handle _hOutputThread;
|
||||
wil::unique_process_information _piConhost;
|
||||
wil::unique_handle _hJob;
|
||||
wil::unique_handle _hServer;
|
||||
|
||||
static DWORD WINAPI StaticOutputThreadProc(LPVOID lpParameter);
|
||||
DWORD _OutputThread();
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace Microsoft.Terminal.TerminalConnection
|
||||
runtimeclass ConhostConnection : ITerminalConnection
|
||||
{
|
||||
ConhostConnection(String cmdline, String startingDirectory, UInt32 rows, UInt32 columns, Guid guid);
|
||||
ConhostConnection(UInt64 server, UInt32 rows, UInt32 columns, Guid guid);
|
||||
|
||||
Guid Guid { get; };
|
||||
};
|
||||
|
||||
@@ -606,9 +606,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
if (bindings)
|
||||
{
|
||||
KeyChord chord(
|
||||
modifiers.IsCtrlPressed(),
|
||||
modifiers.IsAltPressed(),
|
||||
modifiers.IsShiftPressed(),
|
||||
WI_IsAnyFlagSet(modifiers, CTRL_PRESSED),
|
||||
WI_IsAnyFlagSet(modifiers, ALT_PRESSED),
|
||||
WI_IsFlagSet(modifiers, SHIFT_PRESSED),
|
||||
vkey);
|
||||
handled = bindings.TryKeyChord(chord);
|
||||
}
|
||||
@@ -1473,8 +1473,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// find out which modifiers (ctrl, alt, shift) are pressed in events that
|
||||
// don't necessarily include that state.
|
||||
// Return Value:
|
||||
// - The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
|
||||
ControlKeyStates TermControl::_GetPressedModifierKeys() const
|
||||
// - The combined ControlKeyState flags as a bitfield.
|
||||
DWORD TermControl::_GetPressedModifierKeys() const
|
||||
{
|
||||
CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||
// DONT USE
|
||||
@@ -1488,28 +1488,24 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
struct KeyModifier
|
||||
{
|
||||
VirtualKey vkey;
|
||||
ControlKeyStates flags;
|
||||
DWORD flag;
|
||||
};
|
||||
|
||||
constexpr std::array<KeyModifier, 5> modifiers{ {
|
||||
{ VirtualKey::RightMenu, ControlKeyStates::RightAltPressed },
|
||||
{ VirtualKey::LeftMenu, ControlKeyStates::LeftAltPressed },
|
||||
{ VirtualKey::RightControl, ControlKeyStates::RightCtrlPressed },
|
||||
{ VirtualKey::LeftControl, ControlKeyStates::LeftCtrlPressed },
|
||||
{ VirtualKey::Shift, ControlKeyStates::ShiftPressed },
|
||||
{ VirtualKey::RightMenu, RIGHT_ALT_PRESSED },
|
||||
{ VirtualKey::LeftMenu, LEFT_ALT_PRESSED },
|
||||
{ VirtualKey::RightControl, RIGHT_CTRL_PRESSED },
|
||||
{ VirtualKey::LeftControl, LEFT_CTRL_PRESSED },
|
||||
{ VirtualKey::Shift, SHIFT_PRESSED },
|
||||
} };
|
||||
|
||||
ControlKeyStates flags;
|
||||
DWORD flags = 0;
|
||||
|
||||
for (const auto& mod : modifiers)
|
||||
{
|
||||
const auto state = window.GetKeyState(mod.vkey);
|
||||
const auto isDown = WI_IsFlagSet(state, CoreVirtualKeyStates::Down);
|
||||
|
||||
if (isDown)
|
||||
{
|
||||
flags |= mod.flags;
|
||||
}
|
||||
flags |= isDown ? mod.flag : 0;
|
||||
}
|
||||
|
||||
return flags;
|
||||
|
||||
@@ -122,6 +122,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
void _ApplyUISettings();
|
||||
void _InitializeBackgroundBrush();
|
||||
void _BackgroundColorChanged(const uint32_t color);
|
||||
void _ApplyConnectionSettings();
|
||||
void _InitializeTerminal();
|
||||
void _UpdateFont();
|
||||
void _KeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
|
||||
@@ -152,7 +153,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
void _ScrollbarUpdater(Windows::UI::Xaml::Controls::Primitives::ScrollBar scrollbar, const int viewTop, const int viewHeight, const int bufferSize);
|
||||
static Windows::UI::Xaml::Thickness _ParseThicknessFromPadding(const hstring padding);
|
||||
|
||||
::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() const;
|
||||
DWORD _GetPressedModifierKeys() const;
|
||||
|
||||
const COORD _GetTerminalPosition(winrt::Windows::Foundation::Point cursorPosition);
|
||||
const unsigned int _NumberOfClicks(winrt::Windows::Foundation::Point clickPos, Timestamp clickTime);
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Microsoft::Terminal::Core
|
||||
{
|
||||
class ControlKeyStates;
|
||||
}
|
||||
|
||||
constexpr Microsoft::Terminal::Core::ControlKeyStates operator|(Microsoft::Terminal::Core::ControlKeyStates lhs, Microsoft::Terminal::Core::ControlKeyStates rhs) noexcept;
|
||||
|
||||
// This class is functionally equivalent to PowerShell's System.Management.Automation.Host.ControlKeyStates enum:
|
||||
// https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.controlkeystates
|
||||
// It's flagging values are compatible to those used by the NT console subsystem (<um/wincon.h>),
|
||||
// as these are being used throughout older parts of this project.
|
||||
class Microsoft::Terminal::Core::ControlKeyStates
|
||||
{
|
||||
struct StaticValue
|
||||
{
|
||||
DWORD v;
|
||||
};
|
||||
|
||||
public:
|
||||
static constexpr StaticValue RightAltPressed{ RIGHT_ALT_PRESSED };
|
||||
static constexpr StaticValue LeftAltPressed{ LEFT_ALT_PRESSED };
|
||||
static constexpr StaticValue RightCtrlPressed{ RIGHT_CTRL_PRESSED };
|
||||
static constexpr StaticValue LeftCtrlPressed{ LEFT_CTRL_PRESSED };
|
||||
static constexpr StaticValue ShiftPressed{ SHIFT_PRESSED };
|
||||
static constexpr StaticValue NumlockOn{ NUMLOCK_ON };
|
||||
static constexpr StaticValue ScrolllockOn{ SCROLLLOCK_ON };
|
||||
static constexpr StaticValue CapslockOn{ CAPSLOCK_ON };
|
||||
static constexpr StaticValue EnhancedKey{ ENHANCED_KEY };
|
||||
|
||||
constexpr ControlKeyStates() noexcept :
|
||||
_value(0) {}
|
||||
|
||||
constexpr ControlKeyStates(StaticValue value) noexcept :
|
||||
_value(value.v) {}
|
||||
|
||||
explicit constexpr ControlKeyStates(DWORD value) noexcept :
|
||||
_value(value) {}
|
||||
|
||||
ControlKeyStates& operator|=(ControlKeyStates rhs) noexcept
|
||||
{
|
||||
_value |= rhs.Value();
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr DWORD Value() const noexcept
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
constexpr bool IsShiftPressed() const noexcept
|
||||
{
|
||||
return IsAnyFlagSet(ShiftPressed);
|
||||
}
|
||||
|
||||
constexpr bool IsAltPressed() const noexcept
|
||||
{
|
||||
return IsAnyFlagSet(RightAltPressed | LeftAltPressed);
|
||||
}
|
||||
|
||||
constexpr bool IsCtrlPressed() const noexcept
|
||||
{
|
||||
return IsAnyFlagSet(RightCtrlPressed | LeftCtrlPressed);
|
||||
}
|
||||
|
||||
constexpr bool IsAltGrPressed() const noexcept
|
||||
{
|
||||
return AreAllFlagsSet(RightAltPressed | LeftCtrlPressed);
|
||||
}
|
||||
|
||||
constexpr bool IsModifierPressed() const noexcept
|
||||
{
|
||||
return IsAnyFlagSet(RightAltPressed | LeftAltPressed | RightCtrlPressed | LeftCtrlPressed | ShiftPressed);
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr bool AreAllFlagsSet(ControlKeyStates mask) const noexcept
|
||||
{
|
||||
return (Value() & mask.Value()) == mask.Value();
|
||||
}
|
||||
|
||||
constexpr bool IsAnyFlagSet(ControlKeyStates mask) const noexcept
|
||||
{
|
||||
return (Value() & mask.Value()) != 0;
|
||||
}
|
||||
|
||||
DWORD _value;
|
||||
};
|
||||
|
||||
constexpr Microsoft::Terminal::Core::ControlKeyStates operator|(Microsoft::Terminal::Core::ControlKeyStates lhs, Microsoft::Terminal::Core::ControlKeyStates rhs) noexcept
|
||||
{
|
||||
return Microsoft::Terminal::Core::ControlKeyStates{ lhs.Value() | rhs.Value() };
|
||||
}
|
||||
|
||||
constexpr Microsoft::Terminal::Core::ControlKeyStates operator&(Microsoft::Terminal::Core::ControlKeyStates lhs, Microsoft::Terminal::Core::ControlKeyStates rhs) noexcept
|
||||
{
|
||||
return Microsoft::Terminal::Core::ControlKeyStates{ lhs.Value() & rhs.Value() };
|
||||
}
|
||||
|
||||
constexpr bool operator==(Microsoft::Terminal::Core::ControlKeyStates lhs, Microsoft::Terminal::Core::ControlKeyStates rhs) noexcept
|
||||
{
|
||||
return lhs.Value() == rhs.Value();
|
||||
}
|
||||
|
||||
constexpr bool operator!=(Microsoft::Terminal::Core::ControlKeyStates lhs, Microsoft::Terminal::Core::ControlKeyStates rhs) noexcept
|
||||
{
|
||||
return lhs.Value() != rhs.Value();
|
||||
}
|
||||
@@ -2,9 +2,6 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ControlKeyStates.hpp"
|
||||
|
||||
namespace Microsoft::Terminal::Core
|
||||
{
|
||||
class ITerminalInput
|
||||
@@ -12,7 +9,7 @@ namespace Microsoft::Terminal::Core
|
||||
public:
|
||||
virtual ~ITerminalInput() {}
|
||||
|
||||
virtual bool SendKeyEvent(const WORD vkey, const ControlKeyStates states) = 0;
|
||||
virtual bool SendKeyEvent(const WORD vkey, const DWORD modifiers) = 0;
|
||||
|
||||
// void SendMouseEvent(uint row, uint col, KeyModifiers modifiers);
|
||||
[[nodiscard]] virtual HRESULT UserResize(const COORD size) noexcept = 0;
|
||||
|
||||
@@ -197,11 +197,11 @@ void Terminal::Write(std::wstring_view stringView)
|
||||
// real character out of the event.
|
||||
// Arguments:
|
||||
// - vkey: The vkey of the key pressed.
|
||||
// - states: The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
|
||||
// - modifiers: The current ControlKeyState flags.
|
||||
// Return Value:
|
||||
// - true if we translated the key event, and it should not be processed any further.
|
||||
// - false if we did not translate the key, and it should be processed into a character.
|
||||
bool Terminal::SendKeyEvent(const WORD vkey, const ControlKeyStates states)
|
||||
bool Terminal::SendKeyEvent(const WORD vkey, const DWORD modifiers)
|
||||
{
|
||||
if (_snapOnInput && _scrollOffset != 0)
|
||||
{
|
||||
@@ -210,6 +210,8 @@ bool Terminal::SendKeyEvent(const WORD vkey, const ControlKeyStates states)
|
||||
_NotifyScrollEvent();
|
||||
}
|
||||
|
||||
KeyEvent keyEv{ true, 0, vkey, 0, UNICODE_NULL, modifiers };
|
||||
|
||||
// AltGr key combinations don't always contain any meaningful,
|
||||
// pretranslated unicode character during WM_KEYDOWN.
|
||||
// E.g. on a German keyboard AltGr+Q should result in a "@" character,
|
||||
@@ -217,58 +219,50 @@ bool Terminal::SendKeyEvent(const WORD vkey, const ControlKeyStates states)
|
||||
// By returning false though, we can abort handling this WM_KEYDOWN
|
||||
// event and let the WM_CHAR handler kick in, which will be
|
||||
// provided with an appropriate unicode character.
|
||||
if (states.IsAltGrPressed())
|
||||
if (keyEv.IsAltGrPressed())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto ctrlPressed = keyEv.IsCtrlPressed();
|
||||
const auto altPressed = keyEv.IsAltPressed();
|
||||
const auto shiftPressed = keyEv.IsShiftPressed();
|
||||
|
||||
// Alt key sequences _require_ the char to be in the keyevent. If alt is
|
||||
// pressed, manually get the character that's being typed, and put it in the
|
||||
// KeyEvent.
|
||||
// DON'T manually handle Alt+Space - the system will use this to bring up
|
||||
// the system menu for restore, min/maximimize, size, move, close
|
||||
wchar_t ch = UNICODE_NULL;
|
||||
if (states.IsAltPressed() && vkey != VK_SPACE)
|
||||
if (altPressed && vkey != VK_SPACE)
|
||||
{
|
||||
ch = static_cast<wchar_t>(LOWORD(MapVirtualKey(vkey, MAPVK_VK_TO_CHAR)));
|
||||
// MapVirtualKey will give us the capitalized version of the char.
|
||||
// However, if shift isn't pressed, we want to send the lowercase version.
|
||||
// (See GH#637)
|
||||
if (!states.IsShiftPressed())
|
||||
if (!shiftPressed)
|
||||
{
|
||||
ch = towlower(ch);
|
||||
}
|
||||
}
|
||||
|
||||
if (states.IsCtrlPressed())
|
||||
// Manually handle Ctrl+H. Ctrl+H should be handled as Backspace. To do this
|
||||
// correctly, the keyEvents's char needs to be set to Backspace.
|
||||
// 0x48 is the VKEY for 'H', which isn't named
|
||||
if (ctrlPressed && vkey == 0x48)
|
||||
{
|
||||
switch (vkey)
|
||||
{
|
||||
case 0x48:
|
||||
// Manually handle Ctrl+H. Ctrl+H should be handled as Backspace. To do this
|
||||
// correctly, the keyEvents's char needs to be set to Backspace.
|
||||
// 0x48 is the VKEY for 'H', which isn't named
|
||||
ch = UNICODE_BACKSPACE;
|
||||
break;
|
||||
case VK_SPACE:
|
||||
// Manually handle Ctrl+Space here. The terminalInput translator requires
|
||||
// the char to be set to Space for space handling to work correctly.
|
||||
ch = UNICODE_SPACE;
|
||||
break;
|
||||
}
|
||||
ch = UNICODE_BACKSPACE;
|
||||
}
|
||||
// Manually handle Ctrl+Space here. The terminalInput translator requires
|
||||
// the char to be set to Space for space handling to work correctly.
|
||||
if (ctrlPressed && vkey == VK_SPACE)
|
||||
{
|
||||
ch = UNICODE_SPACE;
|
||||
}
|
||||
|
||||
// Manually handle Escape here. If we let it fall through, it'll come
|
||||
// back up through the character handler. It's registered as a translation
|
||||
// in TerminalInput, so we'll let TerminalInput control it.
|
||||
if (vkey == VK_ESCAPE)
|
||||
{
|
||||
ch = UNICODE_ESC;
|
||||
}
|
||||
keyEv.SetCharData(ch);
|
||||
|
||||
const bool manuallyHandled = ch != UNICODE_NULL;
|
||||
|
||||
KeyEvent keyEv{ true, 0, vkey, 0, ch, states.Value() };
|
||||
const bool translated = _terminalInput->HandleKey(&keyEv);
|
||||
|
||||
return translated && manuallyHandled;
|
||||
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
|
||||
#pragma region ITerminalInput
|
||||
// These methods are defined in Terminal.cpp
|
||||
bool SendKeyEvent(const WORD vkey, const Microsoft::Terminal::Core::ControlKeyStates states) override;
|
||||
bool SendKeyEvent(const WORD vkey, const DWORD modifiers) override;
|
||||
[[nodiscard]] HRESULT UserResize(const COORD viewportSize) noexcept override;
|
||||
void UserScrollViewport(const int viewTop) override;
|
||||
int GetScrollOffset() override;
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\ControlKeyStates.hpp" />
|
||||
<ClInclude Include="..\TerminalDispatch.hpp" />
|
||||
<ClInclude Include="..\ITerminalApi.hpp" />
|
||||
<ClInclude Include="..\pch.h" />
|
||||
|
||||
@@ -48,12 +48,12 @@ namespace TerminalCoreUnitTests
|
||||
// Verify that Alt+a generates a lowercase a on the input
|
||||
expectedinput = L"\x1b"
|
||||
"a";
|
||||
VERIFY_IS_TRUE(term.SendKeyEvent(L'A', ControlKeyStates::LeftAltPressed));
|
||||
VERIFY_IS_TRUE(term.SendKeyEvent(L'A', LEFT_ALT_PRESSED));
|
||||
|
||||
// Verify that Alt+shift+a generates a uppercase a on the input
|
||||
expectedinput = L"\x1b"
|
||||
"A";
|
||||
VERIFY_IS_TRUE(term.SendKeyEvent(L'A', ControlKeyStates::LeftAltPressed | ControlKeyStates::ShiftPressed));
|
||||
VERIFY_IS_TRUE(term.SendKeyEvent(L'A', LEFT_ALT_PRESSED | SHIFT_PRESSED));
|
||||
}
|
||||
|
||||
void InputTest::AltSpace()
|
||||
@@ -61,6 +61,6 @@ namespace TerminalCoreUnitTests
|
||||
// Make sure we don't handle Alt+Space. The system will use this to
|
||||
// bring up the system menu for restore, min/maximimize, size, move,
|
||||
// close
|
||||
VERIFY_IS_FALSE(term.SendKeyEvent(L' ', ControlKeyStates::LeftAltPressed));
|
||||
VERIFY_IS_FALSE(term.SendKeyEvent(L' ', LEFT_ALT_PRESSED));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,27 +61,25 @@ AppHost::~AppHost()
|
||||
void AppHost::Initialize()
|
||||
{
|
||||
_window->Initialize();
|
||||
|
||||
if (_useNonClientArea)
|
||||
{
|
||||
// Register our callbar for when the app's non-client content changes.
|
||||
// This has to be done _before_ App::Create, as the app might set the
|
||||
// content in Create.
|
||||
_app.SetTitleBarContent({ this, &AppHost::_UpdateTitleBarContent });
|
||||
}
|
||||
_app.RequestedThemeChanged({ this, &AppHost::_UpdateTheme });
|
||||
|
||||
_app.Create();
|
||||
const auto handle = _window->GetHandle();
|
||||
_app.Create(reinterpret_cast<uint64_t>(handle));
|
||||
|
||||
_app.TitleChanged({ this, &AppHost::AppTitleChanged });
|
||||
_app.LastTabClosed({ this, &AppHost::LastTabClosed });
|
||||
|
||||
AppTitleChanged(_app.GetTitle());
|
||||
|
||||
// Set up the content of the application. If the app has a custom titlebar,
|
||||
// set that content as well.
|
||||
_window->SetContent(_app.GetRoot());
|
||||
_window->OnAppInitialized();
|
||||
_window->OnAppInitialized(_app);
|
||||
}
|
||||
|
||||
void AppHost::IncomingConnectionByHandle(HANDLE handle)
|
||||
{
|
||||
_app.IncomingConnection(reinterpret_cast<uint64_t>(handle));
|
||||
}
|
||||
|
||||
void AppHost::IncomingConnectionByLaunch(std::wstring_view cmdline, std::wstring_view workingDir)
|
||||
{
|
||||
_app.IncomingConnection(winrt::hstring(cmdline), winrt::hstring(workingDir));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -195,32 +193,3 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, const RECT proposedRect)
|
||||
// the originally proposed window size.
|
||||
LOG_LAST_ERROR_IF(!succeeded);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called when the app wants to set its titlebar content. We'll take the
|
||||
// UIElement and set the Content property of our Titlebar that element.
|
||||
// Arguments:
|
||||
// - sender: unused
|
||||
// - arg: the UIElement to use as the new Titlebar content.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void AppHost::_UpdateTitleBarContent(const winrt::TerminalApp::App&, const winrt::Windows::UI::Xaml::UIElement& arg)
|
||||
{
|
||||
if (_useNonClientArea)
|
||||
{
|
||||
(static_cast<NonClientIslandWindow*>(_window.get()))->SetTitlebarContent(arg);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called when the app wants to change its theme. We'll forward this to the
|
||||
// IslandWindow, so it can update the root UI element of the entire XAML tree.
|
||||
// Arguments:
|
||||
// - sender: unused
|
||||
// - arg: the ElementTheme to use as the new theme for the UI
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void AppHost::_UpdateTheme(const winrt::TerminalApp::App&, const winrt::Windows::UI::Xaml::ElementTheme& arg)
|
||||
{
|
||||
_window->UpdateTheme(arg);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ public:
|
||||
AppHost() noexcept;
|
||||
virtual ~AppHost();
|
||||
|
||||
void IncomingConnectionByHandle(HANDLE handle);
|
||||
void IncomingConnectionByLaunch(std::wstring_view cmdline, std::wstring_view workingDir);
|
||||
void AppTitleChanged(winrt::hstring newTitle);
|
||||
void LastTabClosed();
|
||||
void Initialize();
|
||||
@@ -25,8 +27,4 @@ private:
|
||||
winrt::TerminalApp::App _app;
|
||||
|
||||
void _HandleCreateWindow(const HWND hwnd, const RECT proposedRect);
|
||||
void _UpdateTitleBarContent(const winrt::TerminalApp::App& sender,
|
||||
const winrt::Windows::UI::Xaml::UIElement& arg);
|
||||
void _UpdateTheme(const winrt::TerminalApp::App&,
|
||||
const winrt::Windows::UI::Xaml::ElementTheme& arg);
|
||||
};
|
||||
|
||||
@@ -79,7 +79,7 @@ void IslandWindow::Close()
|
||||
|
||||
// Method Description:
|
||||
// - Set a callback to be called when we process a WM_CREATE message. This gives
|
||||
// the AppHost a chance to resize the window to the propoer size.
|
||||
// the AppHost a chance to resize the window to the proper size.
|
||||
// Arguments:
|
||||
// - pfn: a function to be called during the handling of WM_CREATE. It takes two
|
||||
// parameters:
|
||||
@@ -196,41 +196,22 @@ void IslandWindow::OnResize(const UINT width, const UINT height)
|
||||
// - Called when the window is minimized to the taskbar.
|
||||
void IslandWindow::OnMinimize()
|
||||
{
|
||||
// TODO GH#1989 Stop rendering island content when the app is minimized.
|
||||
// TODO MSFT#21315817 Stop rendering island content when the app is minimized.
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called when the window is restored from having been minimized.
|
||||
void IslandWindow::OnRestore()
|
||||
{
|
||||
// TODO GH#1989 Stop rendering island content when the app is minimized.
|
||||
// TODO MSFT#21315817 Stop rendering island content when the app is minimized.
|
||||
}
|
||||
|
||||
void IslandWindow::SetContent(winrt::Windows::UI::Xaml::UIElement content)
|
||||
void IslandWindow::OnAppInitialized(winrt::TerminalApp::App app)
|
||||
{
|
||||
_rootGrid.Children().Clear();
|
||||
_rootGrid.Children().Append(content);
|
||||
}
|
||||
_rootGrid.Children().Append(app.GetRoot());
|
||||
|
||||
void IslandWindow::OnAppInitialized()
|
||||
{
|
||||
// Do a quick resize to force the island to paint
|
||||
const auto size = GetPhysicalSize();
|
||||
OnSize(size.cx, size.cy);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called when the app wants to change its theme. We'll update the root UI
|
||||
// element of the entire XAML tree, so that all UI elements get the theme
|
||||
// applied.
|
||||
// Arguments:
|
||||
// - arg: the ElementTheme to use as the new theme for the UI
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void IslandWindow::UpdateTheme(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme)
|
||||
{
|
||||
_rootGrid.RequestedTheme(requestedTheme);
|
||||
// Invalidate the window rect, so that we'll repaint any elements we're
|
||||
// drawing ourselves to match the new theme
|
||||
::InvalidateRect(_window.get(), nullptr, false);
|
||||
}
|
||||
|
||||
@@ -20,15 +20,12 @@ public:
|
||||
void OnResize(const UINT width, const UINT height) override;
|
||||
void OnMinimize() override;
|
||||
void OnRestore() override;
|
||||
virtual void OnAppInitialized();
|
||||
virtual void SetContent(winrt::Windows::UI::Xaml::UIElement content);
|
||||
virtual void OnAppInitialized(winrt::TerminalApp::App app);
|
||||
|
||||
virtual void Initialize();
|
||||
void Initialize();
|
||||
|
||||
void SetCreateCallback(std::function<void(const HWND, const RECT)> pfn) noexcept;
|
||||
|
||||
void UpdateTheme(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme);
|
||||
|
||||
protected:
|
||||
void ForceResize()
|
||||
{
|
||||
|
||||
@@ -42,82 +42,17 @@ NonClientIslandWindow::~NonClientIslandWindow()
|
||||
// - <unused>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void NonClientIslandWindow::OnDragBarSizeChanged(winrt::Windows::Foundation::IInspectable /*sender*/,
|
||||
winrt::Windows::UI::Xaml::SizeChangedEventArgs /*eventArgs*/)
|
||||
void NonClientIslandWindow::OnDragBarSizeChanged(winrt::Windows::Foundation::IInspectable /*sender*/, winrt::Windows::UI::Xaml::SizeChangedEventArgs /*eventArgs*/)
|
||||
{
|
||||
_UpdateDragRegion();
|
||||
}
|
||||
|
||||
void NonClientIslandWindow::OnAppInitialized()
|
||||
void NonClientIslandWindow::OnAppInitialized(winrt::TerminalApp::App app)
|
||||
{
|
||||
IslandWindow::OnAppInitialized();
|
||||
}
|
||||
|
||||
void NonClientIslandWindow::Initialize()
|
||||
{
|
||||
IslandWindow::Initialize();
|
||||
|
||||
// Set up our grid of content. We'll use _rootGrid as our root element.
|
||||
// There will be two children of this grid - the TitlebarControl, and the
|
||||
// "client content"
|
||||
_rootGrid.Children().Clear();
|
||||
Controls::RowDefinition titlebarRow{};
|
||||
Controls::RowDefinition contentRow{};
|
||||
titlebarRow.Height(GridLengthHelper::Auto());
|
||||
|
||||
_rootGrid.RowDefinitions().Append(titlebarRow);
|
||||
_rootGrid.RowDefinitions().Append(contentRow);
|
||||
|
||||
// Create our titlebar control
|
||||
_titlebar = winrt::TerminalApp::TitlebarControl{ reinterpret_cast<uint64_t>(GetHandle()) };
|
||||
_dragBar = _titlebar.DragBar();
|
||||
|
||||
_dragBar = app.GetDragBar();
|
||||
_rootGrid.SizeChanged({ this, &NonClientIslandWindow::OnDragBarSizeChanged });
|
||||
|
||||
_rootGrid.Children().Append(_titlebar);
|
||||
|
||||
Controls::Grid::SetRow(_titlebar, 0);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Set the content of the "client area" of our window to the given content.
|
||||
// Arguments:
|
||||
// - content: the new UI element to use as the client content
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void NonClientIslandWindow::SetContent(winrt::Windows::UI::Xaml::UIElement content)
|
||||
{
|
||||
_clientContent = content;
|
||||
|
||||
_rootGrid.Children().Append(content);
|
||||
|
||||
// SetRow only works on FrameworkElement's, so cast it to a FWE before
|
||||
// calling. We know that our content is a Grid, so we don't need to worry
|
||||
// about this.
|
||||
const auto fwe = content.try_as<winrt::Windows::UI::Xaml::FrameworkElement>();
|
||||
if (fwe)
|
||||
{
|
||||
Controls::Grid::SetRow(fwe, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Set the content of the "titlebar area" of our window to the given content.
|
||||
// Arguments:
|
||||
// - content: the new UI element to use as the titlebar content
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void NonClientIslandWindow::SetTitlebarContent(winrt::Windows::UI::Xaml::UIElement content)
|
||||
{
|
||||
_titlebar.Content(content);
|
||||
|
||||
// When the size of the titlebar content changes, we want to make sure to
|
||||
// update the size of the drag region as well.
|
||||
const auto fwe = content.try_as<winrt::Windows::UI::Xaml::FrameworkElement>();
|
||||
if (fwe)
|
||||
{
|
||||
fwe.SizeChanged({ this, &NonClientIslandWindow::OnDragBarSizeChanged });
|
||||
}
|
||||
IslandWindow::OnAppInitialized(app);
|
||||
}
|
||||
|
||||
RECT NonClientIslandWindow::GetDragAreaRect() const noexcept
|
||||
@@ -126,12 +61,7 @@ RECT NonClientIslandWindow::GetDragAreaRect() const noexcept
|
||||
{
|
||||
const auto scale = GetCurrentDpiScale();
|
||||
const auto transform = _dragBar.TransformToVisual(_rootGrid);
|
||||
const auto logicalDragBarRect = winrt::Windows::Foundation::Rect{
|
||||
0.0f,
|
||||
0.0f,
|
||||
static_cast<float>(_dragBar.ActualWidth()),
|
||||
static_cast<float>(_dragBar.ActualHeight())
|
||||
};
|
||||
const auto logicalDragBarRect = winrt::Windows::Foundation::Rect{ 0.0f, 0.0f, static_cast<float>(_dragBar.ActualWidth()), static_cast<float>(_dragBar.ActualHeight()) };
|
||||
const auto clientDragBarRect = transform.TransformBounds(logicalDragBarRect);
|
||||
RECT dragBarRect = {
|
||||
static_cast<LONG>(clientDragBarRect.X * scale),
|
||||
@@ -188,14 +118,8 @@ void NonClientIslandWindow::OnSize(const UINT width, const UINT height)
|
||||
_rootGrid.Arrange(finalRect);
|
||||
}
|
||||
|
||||
// I'm not sure that HWND_BOTTOM does anything differnet than HWND_TOP for us.
|
||||
winrt::check_bool(SetWindowPos(_interopWindowHandle,
|
||||
HWND_BOTTOM,
|
||||
xPos,
|
||||
yPos,
|
||||
windowsWidth,
|
||||
windowsHeight,
|
||||
SWP_SHOWWINDOW));
|
||||
// I'm not sure that HWND_BOTTOM is any different than HWND_TOP for us.
|
||||
winrt::check_bool(SetWindowPos(_interopWindowHandle, HWND_BOTTOM, xPos, yPos, windowsWidth, windowsHeight, SWP_SHOWWINDOW));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -219,7 +143,6 @@ void NonClientIslandWindow::_UpdateDragRegion()
|
||||
const auto width = windowRect.right - windowRect.left;
|
||||
const auto height = windowRect.bottom - windowRect.top;
|
||||
|
||||
const auto scale = GetCurrentDpiScale();
|
||||
const auto dpi = ::GetDpiForWindow(_window.get());
|
||||
|
||||
const auto dragY = ::GetSystemMetricsForDpi(SM_CYDRAG, dpi);
|
||||
@@ -395,14 +318,11 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
|
||||
// First get the monitor pointer from either the active window or the default location (0,0,0,0)
|
||||
HMONITOR hMonitor = nullptr;
|
||||
|
||||
// NOTE: We must use the nearest monitor because sometimes the system moves
|
||||
// the window around into strange spots while performing snap and Win+D
|
||||
// operations. Those operations won't work correctly if we use
|
||||
// MONITOR_DEFAULTTOPRIMARY.
|
||||
// NOTE: We must use the nearest monitor because sometimes the system moves the window around into strange spots while performing snap and Win+D operations.
|
||||
// Those operations won't work correctly if we use MONITOR_DEFAULTTOPRIMARY.
|
||||
if (!EqualRect(&rc, &rcZero))
|
||||
{
|
||||
// For invalid window handles or when we were passed a non-zero
|
||||
// suggestion rectangle, get the monitor from the rect.
|
||||
// For invalid window handles or when we were passed a non-zero suggestion rectangle, get the monitor from the rect.
|
||||
hMonitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST);
|
||||
}
|
||||
else
|
||||
@@ -411,9 +331,8 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
|
||||
hMonitor = MonitorFromWindow(_window.get(), MONITOR_DEFAULTTONEAREST);
|
||||
}
|
||||
|
||||
// If for whatever reason there is no monitor, we're going to give back
|
||||
// whatever we got since we can't figure anything out. We won't adjust the
|
||||
// DPI either. That's OK. DPI doesn't make much sense with no display.
|
||||
// If for whatever reason there is no monitor, we're going to give back whatever we got since we can't figure anything out.
|
||||
// We won't adjust the DPI either. That's OK. DPI doesn't make much sense with no display.
|
||||
if (nullptr == hMonitor)
|
||||
{
|
||||
return rc;
|
||||
@@ -425,11 +344,9 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
|
||||
|
||||
GetMonitorInfoW(hMonitor, &MonitorInfo);
|
||||
|
||||
// We have to make a correction to the work area. If we actually consume the
|
||||
// entire work area (by maximizing the window). The window manager will
|
||||
// render the borders off-screen. We need to pad the work rectangle with the
|
||||
// border dimensions to represent the actual max outer edges of the window
|
||||
// rect.
|
||||
// We have to make a correction to the work area. If we actually consume the entire work area (by maximizing the window)
|
||||
// The window manager will render the borders off-screen.
|
||||
// We need to pad the work rectangle with the border dimensions to represent the actual max outer edges of the window rect.
|
||||
WINDOWINFO wi = { 0 };
|
||||
wi.cbSize = sizeof(WINDOWINFO);
|
||||
GetWindowInfo(_window.get(), &wi);
|
||||
@@ -547,8 +464,8 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
|
||||
const auto yPos = _isMaximized ? _maximizedMargins.cyTopHeight : dragY;
|
||||
|
||||
// Create brush for borders, titlebar color.
|
||||
const auto backgroundBrush = _titlebar.Background();
|
||||
const auto backgroundSolidBrush = backgroundBrush.as<Media::SolidColorBrush>();
|
||||
const auto backgroundBrush = _dragBar.Background();
|
||||
const auto backgroundSolidBrush = backgroundBrush.as<winrt::Windows::UI::Xaml::Media::SolidColorBrush>();
|
||||
const auto backgroundColor = backgroundSolidBrush.Color();
|
||||
const auto color = RGB(backgroundColor.R, backgroundColor.G, backgroundColor.B);
|
||||
_backgroundBrush = wil::unique_hbrush(CreateSolidBrush(color));
|
||||
@@ -558,16 +475,12 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
|
||||
const auto cx = windowRect.right - windowRect.left;
|
||||
const auto cy = windowRect.bottom - windowRect.top;
|
||||
|
||||
// Fill in ONLY the titlebar area. If we paint the _entirety_ of the
|
||||
// window rect here, the single pixel of the bottom border (set in
|
||||
// _UpdateFrameMargins) will be drawn, and blend with whatever the
|
||||
// border color is.
|
||||
RECT dragBarRect = GetDragAreaRect();
|
||||
const auto dragHeight = RECT_HEIGHT(&dragBarRect);
|
||||
dragBarRect.left = 0;
|
||||
dragBarRect.right = cx;
|
||||
dragBarRect.top = 0;
|
||||
dragBarRect.bottom = dragHeight + yPos;
|
||||
// Fill in the _entire_ titlebar area.
|
||||
RECT dragBarRect = {};
|
||||
dragBarRect.left = xPos;
|
||||
dragBarRect.right = xPos + cx;
|
||||
dragBarRect.top = yPos;
|
||||
dragBarRect.bottom = yPos + cy;
|
||||
::FillRect(hdc.get(), &dragBarRect, _backgroundBrush.get());
|
||||
|
||||
// Draw the top window border
|
||||
|
||||
@@ -36,16 +36,9 @@ public:
|
||||
|
||||
MARGINS GetFrameMargins() const noexcept;
|
||||
|
||||
void Initialize() override;
|
||||
|
||||
void OnAppInitialized() override;
|
||||
void SetContent(winrt::Windows::UI::Xaml::UIElement content) override;
|
||||
void SetTitlebarContent(winrt::Windows::UI::Xaml::UIElement content);
|
||||
void OnAppInitialized(winrt::TerminalApp::App app) override;
|
||||
|
||||
private:
|
||||
winrt::TerminalApp::TitlebarControl _titlebar{ nullptr };
|
||||
winrt::Windows::UI::Xaml::UIElement _clientContent{ nullptr };
|
||||
|
||||
wil::unique_hbrush _backgroundBrush;
|
||||
wil::unique_hrgn _dragBarRegion;
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -74,17 +72,46 @@
|
||||
</ItemGroup>
|
||||
<!-- Dependencies -->
|
||||
<ItemGroup>
|
||||
<!-- Even though we do have proper recursive dependencies, we want to keep some of these here
|
||||
so that the AppX Manifest contains their activatable classes. -->
|
||||
<!-- Manually include the .pri files from the app project as content files. -->
|
||||
<NativeReferenceFile Include="$(OpenConsoleDir)$(Platform)\$(Configuration)\TerminalAppLib\*.pri">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</NativeReferenceFile>
|
||||
<!-- Manually include the xbf files from the app project as content files -->
|
||||
<NativeReferenceFile Include="$(OpenConsoleDir)$(Platform)\$(Configuration)\TerminalAppLib\*.xbf">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</NativeReferenceFile>
|
||||
<!--
|
||||
the packaging project wont recurse through our dependencies, you have to
|
||||
make sure that if you add a cppwinrt dependency to any of these projects,
|
||||
you also update all the consumers
|
||||
-->
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettings\TerminalSettings.vcxproj" />
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\TerminalControl.vcxproj" />
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalConnection\TerminalConnection.vcxproj" />
|
||||
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalApp\TerminalApp.vcxproj" />
|
||||
|
||||
<!-- Don't add a ProjectReference to TerminalApp here. If you do, the
|
||||
packaging project will find the TerminalApp.pri from both the TerminalAppLib
|
||||
and TerminalApp project, and we only want this lib project's pri file. We'll
|
||||
manually add a reference to the TerminalApp winmd and dll below, because we
|
||||
still need those. -->
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- A small helper for paths to the compiled cppwinrt projects -->
|
||||
<_BinRoot Condition="'$(Platform)' != 'Win32'">$(OpenConsoleDir)$(Platform)\$(Configuration)\</_BinRoot>
|
||||
<_BinRoot Condition="'$(Platform)' == 'Win32'">$(OpenConsoleDir)$(Configuration)\</_BinRoot>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- Manually reference TerminalApp, since we can't use a ProjectReference. -->
|
||||
<Reference Include="TerminalApp">
|
||||
<HintPath>$(_BinRoot)\TerminalApp\TerminalApp.winmd</HintPath>
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
<Private>false</Private>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
</Reference>
|
||||
<ReferenceCopyLocalPaths Include="$(_BinRoot)\TerminalApp\TerminalApp.dll" />
|
||||
</ItemGroup>
|
||||
<!--
|
||||
This ItemGroup and the Globals PropertyGroup below it are required in order
|
||||
to enable F5 debugging for the unpackaged application
|
||||
@@ -100,7 +127,6 @@
|
||||
<!-- DON'T REDIRECT OUR OUTPUT -->
|
||||
<NoOutputRedirection>true</NoOutputRedirection>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.2.190611001-prerelease\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.2.190611001-prerelease\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
@@ -112,38 +138,9 @@
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.0-rc\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.0-rc\build\native\Microsoft.VCRTForwarders.140.targets'))" />
|
||||
</Target>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)src\common.build.post.props" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190521.3\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190521.3\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.0-rc\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.0-rc\build\native\Microsoft.VCRTForwarders.140.targets')" />
|
||||
|
||||
<!-- Override GetPackagingOutputs to roll up all our dependencies.
|
||||
This ensures that when the WAP packaging project asks what files go into
|
||||
the package, we tell it.
|
||||
This is a heavily stripped version of the one in Microsoft.*.AppxPackage.targets.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<_ContinueOnError Condition="'$(BuildingProject)' == 'true'">true</_ContinueOnError>
|
||||
<_ContinueOnError Condition="'$(BuildingProject)' != 'true'">false</_ContinueOnError>
|
||||
</PropertyGroup>
|
||||
<Target Name="GetPackagingOutputs" Returns="@(PackagingOutputs)">
|
||||
<MSBuild
|
||||
Projects="@(ProjectReferenceWithConfiguration)"
|
||||
Targets="GetPackagingOutputs"
|
||||
BuildInParallel="$(BuildInParallel)"
|
||||
Properties="%(ProjectReferenceWithConfiguration.SetConfiguration); %(ProjectReferenceWithConfiguration.SetPlatform)"
|
||||
Condition="'@(ProjectReferenceWithConfiguration)' != ''
|
||||
and '%(ProjectReferenceWithConfiguration.BuildReference)' == 'true'
|
||||
and '%(ProjectReferenceWithConfiguration.ReferenceOutputAssembly)' == 'true'"
|
||||
ContinueOnError="$(_ContinueOnError)">
|
||||
<Output TaskParameter="TargetOutputs" ItemName="_PackagingOutputsFromOtherProjects"/>
|
||||
</MSBuild>
|
||||
|
||||
<ItemGroup>
|
||||
<PackagingOutputs Include="@(_PackagingOutputsFromOtherProjects)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
30
src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj.filters
Normal file
30
src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj.filters
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="WindowsTerminal.manifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="AppHost.cpp" />
|
||||
<ClCompile Include="IslandWindow.cpp" />
|
||||
<ClCompile Include="NonClientIslandWindow.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="AppHost.h" />
|
||||
<ClInclude Include="BaseWindow.h" />
|
||||
<ClInclude Include="IslandWindow.h" />
|
||||
<ClInclude Include="NonClientIslandWindow.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="WindowsTerminal.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "pch.h"
|
||||
#include "AppHost.h"
|
||||
#include "..\..\types\Manager.h"
|
||||
#include "resource.h"
|
||||
|
||||
using namespace winrt;
|
||||
@@ -107,6 +108,16 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
|
||||
// provides an implementation of Windows.UI.Xaml.Application.
|
||||
AppHost host;
|
||||
|
||||
// Create a manager object for IPC.
|
||||
Manager manager;
|
||||
|
||||
// Create and register on connection callbacks from the manager into the application host.
|
||||
std::function<void(HANDLE)> onHandleConnection = std::bind(&AppHost::IncomingConnectionByHandle, &host, std::placeholders::_1);
|
||||
std::function<void(std::wstring_view, std::wstring_view)> onLaunchConnection = std::bind(&AppHost::IncomingConnectionByLaunch, &host, std::placeholders::_1, std::placeholders::_2);
|
||||
|
||||
Manager::s_RegisterOnConnection(onHandleConnection);
|
||||
Manager::s_RegisterOnConnection(onLaunchConnection);
|
||||
|
||||
// !!! LOAD BEARING !!!
|
||||
// This is _magic_. Do the initial loading of our settings *BEFORE* we
|
||||
// initialize our COM apartment type. This is because the Windows.Storage
|
||||
@@ -132,5 +143,8 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
|
||||
TranslateMessage(&message);
|
||||
DispatchMessage(&message);
|
||||
}
|
||||
|
||||
manager.NotifyExit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ const std::wstring_view ConsoleArguments::HEIGHT_ARG = L"--height";
|
||||
const std::wstring_view ConsoleArguments::INHERIT_CURSOR_ARG = L"--inheritcursor";
|
||||
const std::wstring_view ConsoleArguments::FEATURE_ARG = L"--feature";
|
||||
const std::wstring_view ConsoleArguments::FEATURE_PTY_ARG = L"pty";
|
||||
const std::wstring_view ConsoleArguments::FORCE_MANAGER_ARG = L"--manager";
|
||||
|
||||
std::wstring EscapeArgument(std::wstring_view ac)
|
||||
{
|
||||
@@ -102,7 +103,9 @@ ConsoleArguments::ConsoleArguments(const std::wstring& commandline,
|
||||
_vtOutHandle(hStdOut),
|
||||
_recievedEarlySizeChange{ false },
|
||||
_originalWidth{ -1 },
|
||||
_originalHeight{ -1 }
|
||||
_originalHeight{ -1 },
|
||||
_forceManager{ false },
|
||||
_workingDirectory{ wil::GetCurrentDirectoryW().get() }
|
||||
{
|
||||
_clientCommandline = L"";
|
||||
_vtMode = L"";
|
||||
@@ -285,7 +288,7 @@ void ConsoleArguments::s_ConsumeArg(_Inout_ std::vector<std::wstring>& args, _In
|
||||
// - S_OK if we could successfully parse the given text and store it in the handle value location.
|
||||
// - E_INVALIDARG if we couldn't parse the text as a valid hex-encoded handle number OR
|
||||
// if the handle value was already filled.
|
||||
[[nodiscard]] HRESULT ConsoleArguments::s_ParseHandleArg(const std::wstring& handleAsText, _Inout_ DWORD& handleAsVal)
|
||||
[[nodiscard]] HRESULT ConsoleArguments::s_ParseHandleArg(const std::wstring& handleAsText, _Inout_ HANDLE& handleAsVal)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
@@ -296,13 +299,15 @@ void ConsoleArguments::s_ConsumeArg(_Inout_ std::vector<std::wstring>& args, _In
|
||||
}
|
||||
else if (0 == handleAsVal)
|
||||
{
|
||||
handleAsVal = wcstoul(handleAsText.c_str(), nullptr /*endptr*/, 16 /*base*/);
|
||||
const auto handleAsUlong = wcstoul(handleAsText.c_str(), nullptr /*endptr*/, 16 /*base*/);
|
||||
|
||||
// If the handle didn't parse into a reasonable handle ID, invalid.
|
||||
if (handleAsVal == 0)
|
||||
if (handleAsUlong == 0)
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
|
||||
handleAsVal = UlongToHandle(handleAsUlong);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -467,6 +472,12 @@ void ConsoleArguments::s_ConsumeArg(_Inout_ std::vector<std::wstring>& args, _In
|
||||
{
|
||||
hr = s_HandleFeatureValue(args, i);
|
||||
}
|
||||
else if (arg == FORCE_MANAGER_ARG)
|
||||
{
|
||||
_forceManager = true;
|
||||
s_ConsumeArg(args, i);
|
||||
hr = S_OK;
|
||||
}
|
||||
else if (arg == HEADLESS_ARG)
|
||||
{
|
||||
_headless = true;
|
||||
@@ -552,62 +563,72 @@ bool ConsoleArguments::InConptyMode() const noexcept
|
||||
return IsValidHandle(_vtInHandle) || IsValidHandle(_vtOutHandle) || HasSignalHandle();
|
||||
}
|
||||
|
||||
bool ConsoleArguments::IsHeadless() const
|
||||
bool ConsoleArguments::IsHeadless() const noexcept
|
||||
{
|
||||
return _headless;
|
||||
}
|
||||
|
||||
bool ConsoleArguments::ShouldCreateServerHandle() const
|
||||
bool ConsoleArguments::ShouldCreateServerHandle() const noexcept
|
||||
{
|
||||
return _createServerHandle;
|
||||
}
|
||||
|
||||
HANDLE ConsoleArguments::GetServerHandle() const
|
||||
bool ConsoleArguments::ShouldSendToManager() const noexcept
|
||||
{
|
||||
return ULongToHandle(_serverHandle);
|
||||
return _forceManager;
|
||||
}
|
||||
|
||||
HANDLE ConsoleArguments::GetSignalHandle() const
|
||||
HANDLE ConsoleArguments::GetServerHandle() const noexcept
|
||||
{
|
||||
return ULongToHandle(_signalHandle);
|
||||
return _serverHandle;
|
||||
}
|
||||
|
||||
HANDLE ConsoleArguments::GetVtInHandle() const
|
||||
void ConsoleArguments::SetServerHandle(const HANDLE server) noexcept
|
||||
{
|
||||
_serverHandle = server;
|
||||
}
|
||||
|
||||
HANDLE ConsoleArguments::GetSignalHandle() const noexcept
|
||||
{
|
||||
return _signalHandle;
|
||||
}
|
||||
|
||||
HANDLE ConsoleArguments::GetVtInHandle() const noexcept
|
||||
{
|
||||
return _vtInHandle;
|
||||
}
|
||||
|
||||
HANDLE ConsoleArguments::GetVtOutHandle() const
|
||||
HANDLE ConsoleArguments::GetVtOutHandle() const noexcept
|
||||
{
|
||||
return _vtOutHandle;
|
||||
}
|
||||
|
||||
std::wstring ConsoleArguments::GetClientCommandline() const
|
||||
std::wstring_view ConsoleArguments::GetClientCommandline() const noexcept
|
||||
{
|
||||
return _clientCommandline;
|
||||
}
|
||||
|
||||
std::wstring ConsoleArguments::GetVtMode() const
|
||||
std::wstring ConsoleArguments::GetVtMode() const noexcept
|
||||
{
|
||||
return _vtMode;
|
||||
}
|
||||
|
||||
bool ConsoleArguments::GetForceV1() const
|
||||
bool ConsoleArguments::GetForceV1() const noexcept
|
||||
{
|
||||
return _forceV1;
|
||||
}
|
||||
|
||||
short ConsoleArguments::GetWidth() const
|
||||
short ConsoleArguments::GetWidth() const noexcept
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
short ConsoleArguments::GetHeight() const
|
||||
short ConsoleArguments::GetHeight() const noexcept
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
bool ConsoleArguments::GetInheritCursor() const
|
||||
bool ConsoleArguments::GetInheritCursor() const noexcept
|
||||
{
|
||||
return _inheritCursor;
|
||||
}
|
||||
|
||||
@@ -33,23 +33,26 @@ public:
|
||||
|
||||
bool HasVtHandles() const;
|
||||
bool InConptyMode() const noexcept;
|
||||
bool IsHeadless() const;
|
||||
bool ShouldCreateServerHandle() const;
|
||||
bool IsHeadless() const noexcept;
|
||||
bool ShouldCreateServerHandle() const noexcept;
|
||||
bool ShouldSendToManager() const noexcept;
|
||||
|
||||
HANDLE GetServerHandle() const;
|
||||
HANDLE GetVtInHandle() const;
|
||||
HANDLE GetVtOutHandle() const;
|
||||
HANDLE GetServerHandle() const noexcept;
|
||||
void SetServerHandle(const HANDLE server) noexcept;
|
||||
|
||||
HANDLE GetVtInHandle() const noexcept;
|
||||
HANDLE GetVtOutHandle() const noexcept;
|
||||
|
||||
bool HasSignalHandle() const;
|
||||
HANDLE GetSignalHandle() const;
|
||||
HANDLE GetSignalHandle() const noexcept;
|
||||
|
||||
std::wstring GetClientCommandline() const;
|
||||
std::wstring GetVtMode() const;
|
||||
bool GetForceV1() const;
|
||||
std::wstring_view GetClientCommandline() const noexcept;
|
||||
std::wstring GetVtMode() const noexcept;
|
||||
bool GetForceV1() const noexcept;
|
||||
|
||||
short GetWidth() const;
|
||||
short GetHeight() const;
|
||||
bool GetInheritCursor() const;
|
||||
short GetWidth() const noexcept;
|
||||
short GetHeight() const noexcept;
|
||||
bool GetInheritCursor() const noexcept;
|
||||
|
||||
void SetExpectedSize(COORD dimensions) noexcept;
|
||||
|
||||
@@ -66,6 +69,7 @@ public:
|
||||
static const std::wstring_view INHERIT_CURSOR_ARG;
|
||||
static const std::wstring_view FEATURE_ARG;
|
||||
static const std::wstring_view FEATURE_PTY_ARG;
|
||||
static const std::wstring_view FORCE_MANAGER_ARG;
|
||||
|
||||
private:
|
||||
#ifdef UNIT_TESTING
|
||||
@@ -107,6 +111,8 @@ private:
|
||||
|
||||
std::wstring _clientCommandline;
|
||||
|
||||
std::wstring _workingDirectory;
|
||||
|
||||
HANDLE _vtInHandle;
|
||||
|
||||
HANDLE _vtOutHandle;
|
||||
@@ -119,9 +125,10 @@ private:
|
||||
short _width;
|
||||
short _height;
|
||||
|
||||
bool _forceManager;
|
||||
bool _createServerHandle;
|
||||
DWORD _serverHandle;
|
||||
DWORD _signalHandle;
|
||||
HANDLE _serverHandle;
|
||||
HANDLE _signalHandle;
|
||||
bool _inheritCursor;
|
||||
|
||||
bool _recievedEarlySizeChange;
|
||||
@@ -144,7 +151,7 @@ private:
|
||||
_Inout_ size_t& index);
|
||||
|
||||
[[nodiscard]] static HRESULT s_ParseHandleArg(const std::wstring& handleAsText,
|
||||
_Inout_ DWORD& handleAsVal);
|
||||
_Inout_ HANDLE& handle);
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class ConsoleArgumentsTests;
|
||||
|
||||
@@ -77,28 +77,7 @@ VtInputThread::VtInputThread(_In_ wil::unique_hfile hPipe,
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
if (gci.GetVtIo()->IsInPassthroughMode())
|
||||
{
|
||||
try
|
||||
{
|
||||
std::deque<std::unique_ptr<IInputEvent>> inputEvents;
|
||||
for (size_t i = 0; i < cchSequence; i++)
|
||||
{
|
||||
inputEvents.push_back(std::make_unique<KeyEvent>(true, 1ui16, 0ui16, 0ui16, pwsSequence[i], 0));
|
||||
}
|
||||
gci.GetActiveInputBuffer()->Write(inputEvents);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_HR(wil::ResultFromCaughtException());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_pInputStateMachine->ProcessString(pwsSequence.get(), cchSequence);
|
||||
}
|
||||
_pInputStateMachine->ProcessString(pwsSequence.get(), cchSequence);
|
||||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
|
||||
@@ -70,14 +70,14 @@ VtIo::VtIo() :
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT VtIo::Initialize(const ConsoleArguments* const pArgs)
|
||||
[[nodiscard]] HRESULT VtIo::Initialize(const ConsoleArguments args)
|
||||
{
|
||||
_lookingForCursorPosition = pArgs->GetInheritCursor();
|
||||
_lookingForCursorPosition = args.GetInheritCursor();
|
||||
|
||||
// If we were already given VT handles, set up the VT IO engine to use those.
|
||||
if (pArgs->InConptyMode())
|
||||
if (args.InConptyMode())
|
||||
{
|
||||
return _Initialize(pArgs->GetVtInHandle(), pArgs->GetVtOutHandle(), pArgs->GetVtMode(), pArgs->GetSignalHandle());
|
||||
return _Initialize(args.GetVtInHandle(), args.GetVtOutHandle(), args.GetVtMode(), args.GetSignalHandle());
|
||||
}
|
||||
// Didn't need to initialize if we didn't have VT stuff. It's still OK, but report we did nothing.
|
||||
else
|
||||
@@ -397,18 +397,3 @@ void VtIo::_ShutdownIfNeeded()
|
||||
ServiceLocator::RundownAndExit(ERROR_BROKEN_PIPE);
|
||||
}
|
||||
}
|
||||
|
||||
void VtIo::SetPassthroughMode(const bool enable)
|
||||
{
|
||||
_pVtRenderEngine->SetPassthroughMode(enable);
|
||||
}
|
||||
bool VtIo::IsInPassthroughMode()
|
||||
{
|
||||
return _pVtRenderEngine->IsInPassthroughMode();
|
||||
}
|
||||
void VtIo::PassthroughString(std::wstring_view view)
|
||||
{
|
||||
std::wstring wstr{ view };
|
||||
// LOG_IF_FAILED(_pVtRenderEngine->WriteTerminalW(wstr));
|
||||
_pVtRenderEngine->PassthroughString(wstr);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
VtIo();
|
||||
virtual ~VtIo() override = default;
|
||||
|
||||
[[nodiscard]] HRESULT Initialize(const ConsoleArguments* const pArgs);
|
||||
[[nodiscard]] HRESULT Initialize(const ConsoleArguments args);
|
||||
|
||||
[[nodiscard]] HRESULT CreateAndStartSignalThread() noexcept;
|
||||
[[nodiscard]] HRESULT CreateIoHandlers() noexcept;
|
||||
@@ -36,10 +36,6 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
void CloseInput() override;
|
||||
void CloseOutput() override;
|
||||
|
||||
void SetPassthroughMode(const bool enable);
|
||||
void PassthroughString(std::wstring_view view);
|
||||
bool IsInPassthroughMode();
|
||||
|
||||
private:
|
||||
// After CreateIoHandlers is called, these will be invalid.
|
||||
wil::unique_hfile _hInput;
|
||||
|
||||
@@ -941,17 +941,6 @@ using Microsoft::Console::VirtualTerminal::StateMachine;
|
||||
const DWORD dwFlags,
|
||||
_Inout_opt_ PSHORT const psScrollY)
|
||||
{
|
||||
CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
if (gci.IsInVtIoMode() && gci.GetVtIo()->IsInPassthroughMode())
|
||||
// if (WI_IsFlagSet(screenInfo.OutputMode, ENABLE_PASSTHROUGH_MODE))
|
||||
{
|
||||
const size_t BufferSize = *pcb;
|
||||
const size_t cch = BufferSize / sizeof(WCHAR);
|
||||
gci.GetVtIo()->PassthroughString({ pwchRealUnicode, cch });
|
||||
// *pcb += BufferSize;
|
||||
// return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!WI_IsFlagSet(screenInfo.OutputMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING) ||
|
||||
!WI_IsFlagSet(screenInfo.OutputMode, ENABLE_PROCESSED_OUTPUT))
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "srvinit.h"
|
||||
#include "..\server\Entrypoints.h"
|
||||
#include "..\interactivity\inc\ServiceLocator.hpp"
|
||||
#include "..\types\Manager.h"
|
||||
|
||||
// Define TraceLogging provider
|
||||
TRACELOGGING_DEFINE_PROVIDER(
|
||||
@@ -195,7 +196,7 @@ int CALLBACK wWinMain(
|
||||
{
|
||||
if (args.ShouldCreateServerHandle())
|
||||
{
|
||||
hr = Entrypoints::StartConsoleForCmdLine(args.GetClientCommandline().c_str(), &args);
|
||||
hr = Entrypoints::StartConsoleForCmdLine(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -203,7 +204,7 @@ int CALLBACK wWinMain(
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = Entrypoints::StartConsoleForServerHandle(args.GetServerHandle(), &args);
|
||||
hr = Entrypoints::StartConsoleForServerHandle(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define VALID_TEXT_ATTRIBUTES (FG_ATTRS | BG_ATTRS | META_ATTRS)
|
||||
|
||||
#define INPUT_MODES (ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_VIRTUAL_TERMINAL_INPUT)
|
||||
#define OUTPUT_MODES (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN | ENABLE_LVB_GRID_WORLDWIDE | ENABLE_PASSTHROUGH_MODE)
|
||||
#define OUTPUT_MODES (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN | ENABLE_LVB_GRID_WORLDWIDE)
|
||||
#define PRIVATE_MODES (ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE | ENABLE_AUTO_POSITION | ENABLE_EXTENDED_FLAGS)
|
||||
|
||||
using namespace Microsoft::Console::Types;
|
||||
@@ -394,14 +394,7 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
|
||||
|
||||
SCREEN_INFORMATION& screenInfo = context.GetActiveBuffer();
|
||||
const DWORD dwOldMode = screenInfo.OutputMode;
|
||||
DWORD preprocessNewMode = mode;
|
||||
|
||||
if (!gci.IsInVtIoMode() &&
|
||||
(WI_IsFlagSet(preprocessNewMode, ENABLE_PASSTHROUGH_MODE)))
|
||||
{
|
||||
WI_ClearFlag(preprocessNewMode, ENABLE_PASSTHROUGH_MODE);
|
||||
}
|
||||
const DWORD dwNewMode = preprocessNewMode;
|
||||
const DWORD dwNewMode = mode;
|
||||
|
||||
screenInfo.OutputMode = dwNewMode;
|
||||
|
||||
@@ -420,31 +413,6 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
|
||||
screenInfo.SetDefaultVtTabStops();
|
||||
}
|
||||
|
||||
if (gci.IsInVtIoMode())
|
||||
{
|
||||
// if we're moving from passthrough on->off
|
||||
if (WI_IsFlagClear(dwNewMode, ENABLE_PASSTHROUGH_MODE) &&
|
||||
WI_IsFlagSet(dwOldMode, ENABLE_PASSTHROUGH_MODE))
|
||||
{
|
||||
gci.GetVtIo()->SetPassthroughMode(false);
|
||||
// Trigger a redaw all, to sync us back up.
|
||||
ServiceLocator::LocateGlobals().pRender->TriggerRedrawAll();
|
||||
}
|
||||
// if we're moving from passthrough off->on
|
||||
else if (WI_IsFlagSet(dwNewMode, ENABLE_PASSTHROUGH_MODE) &&
|
||||
WI_IsFlagClear(dwOldMode, ENABLE_PASSTHROUGH_MODE))
|
||||
{
|
||||
// DebugBreak();
|
||||
// Trigger a frame NOW, to flush any state since the last frame
|
||||
RECT dummy{ 0 };
|
||||
// ServiceLocator::LocateGlobals().pRender->TriggerSystemRedraw(&dummy);
|
||||
// ServiceLocator::LocateGlobals().pRender->WaitForPaintCompletion(1000);
|
||||
LOG_IF_FAILED(ServiceLocator::LocateGlobals().pRender->PaintFrame());
|
||||
gci.GetVtIo()->SetPassthroughMode(true);
|
||||
ServiceLocator::LocateGlobals().pRender->WaitForPaintCompletion(1000);
|
||||
}
|
||||
}
|
||||
|
||||
gci.SetVirtTermLevel(WI_IsFlagSet(dwNewMode, ENABLE_VIRTUAL_TERMINAL_PROCESSING) ? 1 : 0);
|
||||
gci.SetAutomaticReturnOnNewline(WI_IsFlagSet(screenInfo.OutputMode, DISABLE_NEWLINE_AUTO_RETURN) ? false : true);
|
||||
gci.SetGridRenderingAllowedWorldwide(WI_IsFlagSet(screenInfo.OutputMode, ENABLE_LVB_GRID_WORLDWIDE));
|
||||
|
||||
@@ -71,9 +71,6 @@ Revision History:
|
||||
#define CONSOLE_SUSPENDED (CONSOLE_OUTPUT_SUSPENDED)
|
||||
// clang-format on
|
||||
|
||||
// ENABLE_LVB_GRID_WORLDWIDE is 0x0010
|
||||
#define ENABLE_PASSTHROUGH_MODE 0x0020
|
||||
|
||||
class COOKED_READ_DATA;
|
||||
class CommandHistory;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "renderFontDefaults.hpp"
|
||||
|
||||
#include "ApiRoutines.h"
|
||||
#include "ConsoleArguments.hpp"
|
||||
|
||||
#include "../types/inc/GlyphWidth.hpp"
|
||||
|
||||
@@ -31,15 +32,15 @@ using namespace Microsoft::Console::Render;
|
||||
const UINT CONSOLE_EVENT_FAILURE_ID = 21790;
|
||||
const UINT CONSOLE_LPC_PORT_FAILURE_ID = 21791;
|
||||
|
||||
[[nodiscard]] HRESULT ConsoleServerInitialization(_In_ HANDLE Server, const ConsoleArguments* const args)
|
||||
[[nodiscard]] HRESULT ConsoleServerInitialization(const ConsoleArguments& args)
|
||||
{
|
||||
Globals& Globals = ServiceLocator::LocateGlobals();
|
||||
|
||||
try
|
||||
{
|
||||
Globals.pDeviceComm = new DeviceComm(Server);
|
||||
Globals.pDeviceComm = new DeviceComm(args.GetServerHandle());
|
||||
|
||||
Globals.launchArgs = *args;
|
||||
Globals.launchArgs = args;
|
||||
|
||||
Globals.uiOEMCP = GetOEMCP();
|
||||
Globals.uiWindowsCP = GetACP();
|
||||
@@ -245,10 +246,10 @@ void ConsoleCheckDebug()
|
||||
#endif
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT ConsoleCreateIoThreadLegacy(_In_ HANDLE Server, const ConsoleArguments* const args)
|
||||
[[nodiscard]] HRESULT ConsoleCreateIoThreadLegacy(const ConsoleArguments& args)
|
||||
{
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
RETURN_IF_FAILED(ConsoleServerInitialization(Server, args));
|
||||
RETURN_IF_FAILED(ConsoleServerInitialization(args));
|
||||
RETURN_IF_FAILED(g.hConsoleInputInitEvent.create(wil::EventOptions::None));
|
||||
|
||||
// Set up and tell the driver about the input available event.
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <deque>
|
||||
#include <future>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
@@ -201,6 +201,7 @@ bool SignalResizeWindow(const HANDLE hSignal,
|
||||
// - startingDirectory: The directory to start the process in
|
||||
// - w: The initial width of the pty, in characters
|
||||
// - h: The initial height of the pty, in characters
|
||||
// - hServer: An optional handle to a server connection handle already established for this PTY.
|
||||
// - hInput: A handle to the pipe for writing input to the pty.
|
||||
// - hOutput: A handle to the pipe for reading the output of the pty.
|
||||
// - hSignal: A handle to the pipe for writing signal messages to the pty.
|
||||
@@ -216,6 +217,7 @@ bool SignalResizeWindow(const HANDLE hSignal,
|
||||
std::optional<std::wstring> startingDirectory,
|
||||
const unsigned short w,
|
||||
const unsigned short h,
|
||||
std::optional<HANDLE> const hServer,
|
||||
HANDLE* const hInput,
|
||||
HANDLE* const hOutput,
|
||||
HANDLE* const hSignal,
|
||||
@@ -254,6 +256,11 @@ bool SignalResizeWindow(const HANDLE hSignal,
|
||||
SetHandleInformation(outPipeConhostSide, HANDLE_FLAG_INHERIT, 1);
|
||||
SetHandleInformation(signalPipeConhostSide, HANDLE_FLAG_INHERIT, 1);
|
||||
|
||||
if (hServer.has_value())
|
||||
{
|
||||
SetHandleInformation(hServer.value(), HANDLE_FLAG_INHERIT, 1);
|
||||
}
|
||||
|
||||
std::wstring conhostCmdline = L"conhost.exe";
|
||||
conhostCmdline += L" --headless";
|
||||
std::wstringstream ss;
|
||||
@@ -264,9 +271,19 @@ bool SignalResizeWindow(const HANDLE hSignal,
|
||||
}
|
||||
|
||||
ss << L" --signal 0x" << std::hex << HandleToUlong(signalPipeConhostSide);
|
||||
|
||||
if (hServer.has_value())
|
||||
{
|
||||
ss << L" --server 0x" << std::hex << HandleToUlong(hServer.value());
|
||||
}
|
||||
|
||||
conhostCmdline += ss.str();
|
||||
conhostCmdline += L" -- ";
|
||||
conhostCmdline += cmdline;
|
||||
|
||||
if (!hServer.has_value())
|
||||
{
|
||||
conhostCmdline += L" -- ";
|
||||
conhostCmdline += cmdline;
|
||||
}
|
||||
|
||||
STARTUPINFO si = { 0 };
|
||||
si.cb = sizeof(STARTUPINFOW);
|
||||
|
||||
@@ -27,7 +27,6 @@ Author(s):
|
||||
|
||||
// UNICODE_NULL is a Windows macro definition
|
||||
const wchar_t UNICODE_BACKSPACE = 0x8;
|
||||
const wchar_t UNICODE_ESC = 0x1b;
|
||||
const wchar_t UNICODE_DEL = 0x7f;
|
||||
// NOTE: This isn't actually a backspace. It's a graphical block. But
|
||||
// I believe it's emitted by one of our ANSI/OEM --> Unicode conversions.
|
||||
|
||||
@@ -507,11 +507,6 @@ void Renderer::WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs)
|
||||
_pThread->WaitForPaintCompletionAndDisable(dwTimeoutMs);
|
||||
}
|
||||
|
||||
void Renderer::WaitForPaintCompletion(const DWORD dwTimeoutMs)
|
||||
{
|
||||
_pThread->WaitForPaintCompletion(dwTimeoutMs);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Paint helper to fill in the background color of the invalid area within the frame.
|
||||
// Arguments:
|
||||
|
||||
@@ -73,7 +73,6 @@ namespace Microsoft::Console::Render
|
||||
|
||||
void EnablePainting() override;
|
||||
void WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs) override;
|
||||
void WaitForPaintCompletion(const DWORD dwTimeoutMs) override;
|
||||
|
||||
void AddRenderEngine(_In_ IRenderEngine* const pEngine) override;
|
||||
|
||||
|
||||
@@ -242,8 +242,3 @@ void RenderThread::WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs)
|
||||
ResetEvent(_hPaintEnabledEvent);
|
||||
WaitForSingleObject(_hPaintCompletedEvent, dwTimeoutMs);
|
||||
}
|
||||
|
||||
void RenderThread::WaitForPaintCompletion(const DWORD dwTimeoutMs)
|
||||
{
|
||||
WaitForSingleObject(_hPaintCompletedEvent, dwTimeoutMs);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace Microsoft::Console::Render
|
||||
|
||||
void EnablePainting() override;
|
||||
void WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs) override;
|
||||
void WaitForPaintCompletion(const DWORD dwTimeoutMs) override;
|
||||
|
||||
private:
|
||||
static DWORD WINAPI s_ThreadProc(_In_ LPVOID lpParameter);
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace Microsoft::Console::Render
|
||||
virtual void NotifyPaint() = 0;
|
||||
virtual void EnablePainting() = 0;
|
||||
virtual void WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs) = 0;
|
||||
virtual void WaitForPaintCompletion(const DWORD dwTimeoutMs) = 0;
|
||||
};
|
||||
|
||||
inline Microsoft::Console::Render::IRenderThread::~IRenderThread(){};
|
||||
|
||||
@@ -54,7 +54,6 @@ namespace Microsoft::Console::Render
|
||||
|
||||
virtual void EnablePainting() = 0;
|
||||
virtual void WaitForPaintCompletionAndDisable(const DWORD dwTimeoutMs) = 0;
|
||||
virtual void WaitForPaintCompletion(const DWORD dwTimeoutMs) = 0;
|
||||
|
||||
virtual void AddRenderEngine(_In_ IRenderEngine* const pEngine) = 0;
|
||||
};
|
||||
|
||||
@@ -40,11 +40,7 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
|
||||
// the pipe.
|
||||
[[nodiscard]] HRESULT XtermEngine::StartPaint() noexcept
|
||||
{
|
||||
const auto hr = VtEngine::StartPaint();
|
||||
if (hr == S_FALSE)
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
RETURN_IF_FAILED(VtEngine::StartPaint());
|
||||
|
||||
_trace.TraceLastText(_lastText);
|
||||
|
||||
|
||||
@@ -24,10 +24,6 @@ using namespace Microsoft::Console::Types;
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
if (_passthroughMode)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// If there's nothing to do, quick return
|
||||
bool somethingToDo = _fInvalidRectUsed ||
|
||||
|
||||
@@ -417,19 +417,3 @@ HRESULT VtEngine::RequestCursor() noexcept
|
||||
RETURN_IF_FAILED(_Flush());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void VtEngine::SetPassthroughMode(const bool enable)
|
||||
{
|
||||
_passthroughMode = enable;
|
||||
}
|
||||
|
||||
void VtEngine::PassthroughString(const std::wstring& wstr)
|
||||
{
|
||||
LOG_IF_FAILED(WriteTerminalW(wstr));
|
||||
LOG_IF_FAILED(_Flush());
|
||||
}
|
||||
|
||||
bool VtEngine::IsInPassthroughMode()
|
||||
{
|
||||
return _passthroughMode;
|
||||
}
|
||||
|
||||
@@ -95,10 +95,6 @@ namespace Microsoft::Console::Render
|
||||
|
||||
void SetTerminalOwner(Microsoft::Console::ITerminalOwner* const terminalOwner);
|
||||
|
||||
void SetPassthroughMode(const bool enable);
|
||||
void PassthroughString(const std::wstring& wstr);
|
||||
bool IsInPassthroughMode();
|
||||
|
||||
protected:
|
||||
wil::unique_hfile _hFile;
|
||||
std::string _buffer;
|
||||
@@ -137,8 +133,6 @@ namespace Microsoft::Console::Render
|
||||
|
||||
Microsoft::Console::VirtualTerminal::RenderTracing _trace;
|
||||
|
||||
bool _passthroughMode{ false };
|
||||
|
||||
[[nodiscard]] HRESULT _Write(std::string_view const str) noexcept;
|
||||
[[nodiscard]] HRESULT _WriteFormattedString(const std::string* const pFormat, ...) noexcept;
|
||||
[[nodiscard]] HRESULT _Flush() noexcept;
|
||||
|
||||
@@ -9,10 +9,21 @@
|
||||
|
||||
#include "winbasep.h"
|
||||
|
||||
[[nodiscard]] HRESULT Entrypoints::StartConsoleForServerHandle(const HANDLE ServerHandle,
|
||||
const ConsoleArguments* const args)
|
||||
#include "..\types\Manager.h"
|
||||
#include "..\host\ConsoleArguments.hpp"
|
||||
|
||||
[[nodiscard]] HRESULT Entrypoints::StartConsoleForServerHandle(const ConsoleArguments& args)
|
||||
{
|
||||
return ConsoleCreateIoThreadLegacy(ServerHandle, args);
|
||||
if (args.ShouldSendToManager())
|
||||
{
|
||||
if (Manager::s_TrySendToManager(args.GetServerHandle()))
|
||||
{
|
||||
SleepEx(INFINITE, FALSE);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return ConsoleCreateIoThreadLegacy(args);
|
||||
}
|
||||
|
||||
// this function has unreachable code due to its unusual lifetime. We
|
||||
@@ -20,9 +31,17 @@
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4702)
|
||||
|
||||
[[nodiscard]] HRESULT Entrypoints::StartConsoleForCmdLine(_In_ PCWSTR pwszCmdLine,
|
||||
const ConsoleArguments* const args)
|
||||
[[nodiscard]] HRESULT Entrypoints::StartConsoleForCmdLine(ConsoleArguments& args)
|
||||
{
|
||||
if (args.ShouldSendToManager())
|
||||
{
|
||||
if (Manager::s_TrySendToManager(args.GetClientCommandline(), L"C:\\windows\\system32"))
|
||||
{
|
||||
SleepEx(INFINITE, FALSE);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a scope because we're going to exit thread if everything goes well.
|
||||
// This scope will ensure all C++ objects and smart pointers get a chance to destruct before ExitThread is called.
|
||||
{
|
||||
@@ -39,7 +58,8 @@
|
||||
L"\\Reference",
|
||||
FALSE));
|
||||
|
||||
RETURN_IF_NTSTATUS_FAILED(Entrypoints::StartConsoleForServerHandle(ServerHandle.get(), args));
|
||||
args.SetServerHandle(ServerHandle.get());
|
||||
RETURN_IF_NTSTATUS_FAILED(Entrypoints::StartConsoleForServerHandle(args));
|
||||
|
||||
// If we get to here, we have transferred ownership of the server handle to the console, so release it.
|
||||
// Keep a copy of the value so we can open the client handles even though we're no longer the owner.
|
||||
@@ -143,6 +163,8 @@
|
||||
NULL));
|
||||
|
||||
// We have to copy the command line string we're given because CreateProcessW has to be called with mutable data.
|
||||
PCWSTR pwszCmdLine = args.GetClientCommandline().data();
|
||||
|
||||
if (wcslen(pwszCmdLine) == 0)
|
||||
{
|
||||
// If they didn't give us one, just launch cmd.exe.
|
||||
|
||||
@@ -20,6 +20,6 @@ class ConsoleArguments;
|
||||
|
||||
namespace Entrypoints
|
||||
{
|
||||
[[nodiscard]] HRESULT StartConsoleForServerHandle(const HANDLE ServerHandle, const ConsoleArguments* const args);
|
||||
[[nodiscard]] HRESULT StartConsoleForCmdLine(_In_ PCWSTR pwszCmdLine, const ConsoleArguments* const args);
|
||||
[[nodiscard]] HRESULT StartConsoleForServerHandle(const ConsoleArguments& args);
|
||||
[[nodiscard]] HRESULT StartConsoleForCmdLine(ConsoleArguments& args);
|
||||
};
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
|
||||
class ConsoleArguments;
|
||||
|
||||
[[nodiscard]] HRESULT ConsoleCreateIoThreadLegacy(_In_ HANDLE Server, const ConsoleArguments* const args);
|
||||
[[nodiscard]] HRESULT ConsoleCreateIoThreadLegacy(const ConsoleArguments& args);
|
||||
|
||||
@@ -2,178 +2,9 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include <windows.h>
|
||||
#include <wil\Common.h>
|
||||
#include <wil\result.h>
|
||||
#include <wil\resource.h>
|
||||
#include <wil\wistd_functional.h>
|
||||
#include <wil\wistd_memory.h>
|
||||
#include <stdlib.h> /* srand, rand */
|
||||
#include <time.h> /* time */
|
||||
#include <conio.h>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <assert.h>
|
||||
|
||||
#define ENABLE_PASSTHROUGH_MODE 0x0020
|
||||
|
||||
std::string csi(std::string seq)
|
||||
{
|
||||
std::string fullSeq = "\x1b[";
|
||||
fullSeq += seq;
|
||||
return fullSeq;
|
||||
}
|
||||
|
||||
std::string osc(std::string seq)
|
||||
{
|
||||
std::string fullSeq = "\x1b]";
|
||||
fullSeq += seq;
|
||||
fullSeq += "\x7";
|
||||
return fullSeq;
|
||||
}
|
||||
|
||||
void testOutput()
|
||||
{
|
||||
wprintf(L"Attempting to start passthrough mode...\n");
|
||||
auto hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
DWORD dwMode = 0;
|
||||
THROW_LAST_ERROR_IF(!GetConsoleMode(hOut, &dwMode));
|
||||
|
||||
wprintf(L"Original Mode: 0x%x\n", dwMode);
|
||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
dwMode |= DISABLE_NEWLINE_AUTO_RETURN;
|
||||
dwMode |= ENABLE_PASSTHROUGH_MODE;
|
||||
|
||||
wprintf(L"Requested Mode: 0x%x\n", dwMode);
|
||||
THROW_LAST_ERROR_IF(!SetConsoleMode(hOut, dwMode));
|
||||
|
||||
DWORD roundtripMode = 0;
|
||||
THROW_LAST_ERROR_IF(!GetConsoleMode(hOut, &roundtripMode));
|
||||
wprintf(L"Rountripped Mode: 0x%x\n", dwMode);
|
||||
|
||||
if (roundtripMode != dwMode)
|
||||
{
|
||||
wprintf(L"Mode did not rountrip\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
wprintf(L"Mode rountripped successfully\n");
|
||||
}
|
||||
|
||||
wprintf(L"Press a key to continue\n");
|
||||
_getch();
|
||||
|
||||
wprintf(L"We're going to write some VT straight to the terminal\n");
|
||||
|
||||
printf(csi("31m").c_str());
|
||||
printf(osc("0;Title:foo").c_str());
|
||||
wprintf(L"Press a key to continue\n");
|
||||
_getch();
|
||||
|
||||
printf(csi("0m").c_str());
|
||||
wprintf(L"Time for something more complicated...\n");
|
||||
Sleep(500);
|
||||
printf(csi("2;1H").c_str());
|
||||
printf(csi("44m").c_str());
|
||||
printf(csi("K").c_str());
|
||||
Sleep(500);
|
||||
|
||||
printf(csi("9;1H").c_str());
|
||||
printf(csi("46m").c_str());
|
||||
printf(csi("K").c_str());
|
||||
Sleep(500);
|
||||
|
||||
printf(csi("3;8r").c_str());
|
||||
printf(csi("3;1H").c_str());
|
||||
printf(csi("0m").c_str());
|
||||
Sleep(500);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
wprintf(L"Print in the margins %d\n", i);
|
||||
Sleep(500);
|
||||
}
|
||||
|
||||
printf(csi("r").c_str());
|
||||
wprintf(L"Press a key to continue\n");
|
||||
_getch();
|
||||
}
|
||||
|
||||
void launchChild(int argc, WCHAR* argv[])
|
||||
{
|
||||
auto hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
auto hIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||
|
||||
DWORD dwMode = 0;
|
||||
THROW_LAST_ERROR_IF(!GetConsoleMode(hOut, &dwMode));
|
||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
dwMode |= DISABLE_NEWLINE_AUTO_RETURN;
|
||||
dwMode |= ENABLE_PASSTHROUGH_MODE;
|
||||
THROW_LAST_ERROR_IF(!SetConsoleMode(hOut, dwMode));
|
||||
|
||||
DWORD dwInMode = 0;
|
||||
GetConsoleMode(hIn, &dwInMode);
|
||||
dwInMode = ENABLE_VIRTUAL_TERMINAL_INPUT;
|
||||
SetConsoleMode(hIn, dwInMode);
|
||||
|
||||
std::wstring commandline = L"";
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
commandline += (argv[i]);
|
||||
commandline += (L" ");
|
||||
}
|
||||
|
||||
std::unique_ptr<wchar_t[]> mutableCommandline = std::make_unique<wchar_t[]>(commandline.length() + 1);
|
||||
THROW_IF_NULL_ALLOC(mutableCommandline);
|
||||
|
||||
HRESULT hr = StringCchCopy(mutableCommandline.get(), commandline.length() + 1, commandline.c_str());
|
||||
THROW_IF_FAILED(hr);
|
||||
|
||||
STARTUPINFO si = { 0 };
|
||||
si.cb = sizeof(STARTUPINFOW);
|
||||
PROCESS_INFORMATION _piClient;
|
||||
|
||||
bool fSuccess = !!CreateProcessW(
|
||||
nullptr,
|
||||
mutableCommandline.get(),
|
||||
nullptr, // lpProcessAttributes
|
||||
nullptr, // lpThreadAttributes
|
||||
true, // bInheritHandles
|
||||
false, // dwCreationFlags
|
||||
nullptr, // lpEnvironment
|
||||
nullptr, // lpCurrentDirectory
|
||||
&si, // lpStartupInfo
|
||||
&_piClient // lpProcessInformation
|
||||
);
|
||||
THROW_LAST_ERROR_IF(!fSuccess);
|
||||
|
||||
// Sleep(10000);
|
||||
WaitForSingleObject(_piClient.hProcess, INFINITE);
|
||||
}
|
||||
|
||||
// This wmain exists for help in writing scratch programs while debugging.
|
||||
int __cdecl wmain(int argc, WCHAR* argv[])
|
||||
int __cdecl wmain(int /*argc*/, WCHAR* /*argv[]*/)
|
||||
{
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
wprintf(argv[i]);
|
||||
wprintf(L" ");
|
||||
}
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
std::wstring arg1 = argv[1];
|
||||
if (arg1 == L"--test")
|
||||
{
|
||||
testOutput();
|
||||
}
|
||||
else if (arg1 == L"--")
|
||||
{
|
||||
launchChild(argc - 2, &argv[2]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
357
src/types/Manager.cpp
Normal file
357
src/types/Manager.cpp
Normal file
@@ -0,0 +1,357 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "precomp.h"
|
||||
#include "Manager.h"
|
||||
|
||||
static constexpr std::wstring_view MUTEX_NAME = L"Local\\WindowsTerminalManager";
|
||||
static constexpr std::wstring_view PIPE_NAME = L"\\\\.\\pipe\\WindowsTerminalManagerPipe";
|
||||
static constexpr DWORD PIPE_BUFFER_SIZE = 4096;
|
||||
|
||||
Manager::Manager() :
|
||||
_mutex(),
|
||||
_pipe(),
|
||||
_exit(),
|
||||
_theServer(false)
|
||||
{
|
||||
// Create exit event.
|
||||
_exit.create();
|
||||
|
||||
// Try to open the mutex.
|
||||
if (!_mutex.try_open(MUTEX_NAME.data()))
|
||||
{
|
||||
// If we can't open it, create one because no one else did.
|
||||
_mutex.create(MUTEX_NAME.data());
|
||||
_theServer = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it could just be opened, we're not the server.
|
||||
_theServer = false;
|
||||
}
|
||||
|
||||
// If we're the server, establish communication listener and thread
|
||||
if (_theServer)
|
||||
{
|
||||
_becomeServer();
|
||||
}
|
||||
// If we're not the server, find out who it is so we can get notified when they leave and become the server.
|
||||
else
|
||||
{
|
||||
ManagerMessageQuery query;
|
||||
query.size = sizeof(query);
|
||||
query.type = ManagerMessageTypes::GetManagerPid;
|
||||
|
||||
const auto reply = _ask(query);
|
||||
|
||||
_waitToBecomeServer = std::async(std::launch::async, [reply, this] {
|
||||
|
||||
wil::unique_handle managerProcess(OpenProcess(SYNCHRONIZE, FALSE, reply.reply.getPid.id));
|
||||
THROW_LAST_ERROR_IF_NULL(managerProcess.get());
|
||||
|
||||
WaitForSingleObject(managerProcess.get(), INFINITE);
|
||||
_becomeServer();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Manager::NotifyExit()
|
||||
{
|
||||
_exit.SetEvent();
|
||||
}
|
||||
|
||||
bool Manager::s_TrySendToManager(const HANDLE server)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get PID from remote process.
|
||||
ManagerMessageQuery query;
|
||||
query.size = sizeof(query);
|
||||
query.type = ManagerMessageTypes::GetManagerPid;
|
||||
|
||||
auto reply = _ask(query);
|
||||
const auto processId = reply.reply.getPid.id;
|
||||
|
||||
// Open for handle duping.
|
||||
wil::unique_handle otherProcess(OpenProcess(PROCESS_DUP_HANDLE, FALSE, processId));
|
||||
THROW_LAST_ERROR_IF_NULL(otherProcess.get());
|
||||
|
||||
// Send handle into that process.
|
||||
HANDLE targetHandle;
|
||||
THROW_IF_WIN32_BOOL_FALSE(DuplicateHandle(GetCurrentProcess(), server,
|
||||
otherProcess.get(), &targetHandle,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS));
|
||||
|
||||
// Tell remote process about new handle ID
|
||||
query.size = sizeof(query);
|
||||
query.type = ManagerMessageTypes::SendConnection;
|
||||
query.query.sendConn.handle = targetHandle;
|
||||
|
||||
reply = _ask(query);
|
||||
|
||||
return reply.reply.sendConn.ok;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Manager::s_TrySendToManager(const std::wstring_view cmdline,
|
||||
const std::wstring_view workingDir)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Figure out how much data we actually need to send with the variable length strings
|
||||
size_t size = sizeof(ManagerMessageQuery) + 1;
|
||||
size += 2*(cmdline.size() + 1);
|
||||
size += 2*(workingDir.size() + 1);
|
||||
|
||||
// Make a big buffer to hold it all contiguously
|
||||
const auto buffer = std::make_unique<byte[]>(size);
|
||||
|
||||
// Make pointers to fill up each piece of data
|
||||
const auto query = reinterpret_cast<ManagerMessageQuery*>(buffer.get());
|
||||
const auto cmdPayload = reinterpret_cast<PWCHAR>(buffer.get() + sizeof(ManagerMessageQuery) + 1);
|
||||
const auto workingPayload = reinterpret_cast<PWCHAR>(buffer.get() + sizeof(ManagerMessageQuery) + 1 + (cmdline.size() + 1) * 2);
|
||||
|
||||
// Tell the remote process the command line and working directory
|
||||
query->size = gsl::narrow<DWORD>(size);
|
||||
query->type = ManagerMessageTypes::SendCmdAndWorking;
|
||||
query->query.sendCmdAndWorking.cmd = gsl::narrow<DWORD>(cmdline.size());
|
||||
query->query.sendCmdAndWorking.working = gsl::narrow<DWORD>(workingDir.size());
|
||||
|
||||
THROW_IF_FAILED(StringCchCopyW(cmdPayload, cmdline.size() + 1, cmdline.data()));
|
||||
THROW_IF_FAILED(StringCchCopyW(workingPayload, workingDir.size() + 1, workingDir.data()));
|
||||
|
||||
const auto reply = _ask(*query);
|
||||
|
||||
return reply.reply.sendConn.ok;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::_becomeServer()
|
||||
{
|
||||
// lock?
|
||||
|
||||
// test if pipe exists?
|
||||
|
||||
_theServer = true;
|
||||
|
||||
// enter loop to make server connections
|
||||
_serverWork = std::async(std::launch::async, [this] {
|
||||
_serverLoop();
|
||||
});
|
||||
}
|
||||
|
||||
void Manager::_serverLoop()
|
||||
{
|
||||
wil::unique_event newClient;
|
||||
newClient.create(wil::EventOptions::ManualReset);
|
||||
|
||||
bool keepGoing = true;
|
||||
while (keepGoing)
|
||||
{
|
||||
OVERLAPPED overlap = { 0 };
|
||||
overlap.hEvent = newClient.get();
|
||||
|
||||
wil::unique_handle pipe(CreateNamedPipeW(PIPE_NAME.data(),
|
||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT | PIPE_ACCEPT_REMOTE_CLIENTS,
|
||||
PIPE_UNLIMITED_INSTANCES,
|
||||
PIPE_BUFFER_SIZE,
|
||||
PIPE_BUFFER_SIZE,
|
||||
0,
|
||||
nullptr)); // replace with actual security descriptor?
|
||||
|
||||
THROW_LAST_ERROR_IF(pipe.get() == INVALID_HANDLE_VALUE);
|
||||
|
||||
if (!ConnectNamedPipe(pipe.get(), &overlap))
|
||||
{
|
||||
// IO pending and Pipe Connected are OK error codes. Go into the wait.
|
||||
const auto gle = GetLastError();
|
||||
if (gle != ERROR_IO_PENDING && gle != ERROR_PIPE_CONNECTED)
|
||||
{
|
||||
THROW_LAST_ERROR();
|
||||
}
|
||||
}
|
||||
|
||||
std::array<HANDLE, 2> waitOn;
|
||||
waitOn.at(0) = _exit.get();
|
||||
waitOn.at(1) = newClient.get();
|
||||
const auto ret = WaitForMultipleObjects(gsl::narrow<DWORD>(waitOn.size()), waitOn.data(), FALSE, INFINITE);
|
||||
|
||||
if (ret == WAIT_OBJECT_0)
|
||||
{
|
||||
keepGoing = false;
|
||||
continue;
|
||||
}
|
||||
else if (ret == WAIT_OBJECT_0 + 1)
|
||||
{
|
||||
const auto loosePipeHandle = pipe.release();
|
||||
auto future = std::async(std::launch::async, [this, loosePipeHandle] {
|
||||
_perClientLoop(wil::unique_handle(loosePipeHandle));
|
||||
});
|
||||
_perClientWork.push_back(std::move(future));
|
||||
}
|
||||
else if (ret == WAIT_FAILED)
|
||||
{
|
||||
THROW_LAST_ERROR();
|
||||
}
|
||||
else
|
||||
{
|
||||
THROW_WIN32(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::_perClientLoop(wil::unique_handle pipe)
|
||||
{
|
||||
/*bool keepGoing = true;
|
||||
while (keepGoing)*/
|
||||
{
|
||||
ManagerMessageQuery query;
|
||||
DWORD bytesRead = 0;
|
||||
SetLastError(S_OK);
|
||||
const auto result = ReadFile(pipe.get(),
|
||||
&query,
|
||||
sizeof(query),
|
||||
&bytesRead,
|
||||
nullptr);
|
||||
|
||||
// False is OK if it's ERROR_MORE_DATA.
|
||||
const auto gle = GetLastError();
|
||||
THROW_LAST_ERROR_IF(!result && gle != ERROR_MORE_DATA);
|
||||
|
||||
std::unique_ptr<byte[]> buffer;
|
||||
if (gle == ERROR_MORE_DATA)
|
||||
{
|
||||
const auto remainingBytes = query.size - gsl::narrow<DWORD>(sizeof(query));
|
||||
buffer = std::make_unique<byte[]>(remainingBytes);
|
||||
|
||||
bytesRead = 0;
|
||||
THROW_IF_WIN32_BOOL_FALSE(ReadFile(pipe.get(),
|
||||
buffer.get(),
|
||||
remainingBytes,
|
||||
&bytesRead,
|
||||
nullptr));
|
||||
}
|
||||
|
||||
ManagerMessageReply reply;
|
||||
switch (query.type)
|
||||
{
|
||||
case ManagerMessageTypes::GetManagerPid:
|
||||
reply = _getPid(query);
|
||||
break;
|
||||
case ManagerMessageTypes::SendConnection:
|
||||
reply = _sendConnection(query);
|
||||
break;
|
||||
case ManagerMessageTypes::SendCmdAndWorking:
|
||||
reply = _sendCmdAndWorking(query, buffer);
|
||||
break;
|
||||
default:
|
||||
THROW_HR(E_NOTIMPL);
|
||||
}
|
||||
|
||||
DWORD bytesWritten = 0;
|
||||
THROW_IF_WIN32_BOOL_FALSE(WriteFile(pipe.get(),
|
||||
&reply,
|
||||
sizeof(reply),
|
||||
&bytesWritten,
|
||||
nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
Manager::ManagerMessageReply Manager::_ask(Manager::ManagerMessageQuery& query)
|
||||
{
|
||||
ManagerMessageReply reply;
|
||||
|
||||
DWORD bytesRead = 0;
|
||||
THROW_IF_WIN32_BOOL_FALSE(CallNamedPipeW(PIPE_NAME.data(),
|
||||
&query,
|
||||
query.size,
|
||||
&reply,
|
||||
sizeof(reply),
|
||||
&bytesRead,
|
||||
NMPWAIT_WAIT_FOREVER));
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
Manager::ManagerMessageReply Manager::_getPid(ManagerMessageQuery /*query*/)
|
||||
{
|
||||
ManagerMessageReply reply;
|
||||
|
||||
reply.type = ManagerMessageTypes::GetManagerPid;
|
||||
reply.reply.getPid.id = GetCurrentProcessId();
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
static std::vector<std::function<void(HANDLE)>> s_onHandleConnection;
|
||||
|
||||
void Manager::s_RegisterOnConnection(std::function<void(HANDLE)> func)
|
||||
{
|
||||
s_onHandleConnection.push_back(func);
|
||||
}
|
||||
|
||||
Manager::ManagerMessageReply Manager::_sendConnection(ManagerMessageQuery query)
|
||||
{
|
||||
const auto serverHandle = query.query.sendConn.handle;
|
||||
|
||||
// create new conhost connection...
|
||||
for (const auto& func : s_onHandleConnection)
|
||||
{
|
||||
func(serverHandle);
|
||||
}
|
||||
|
||||
ManagerMessageReply reply;
|
||||
|
||||
reply.type = ManagerMessageTypes::SendConnection;
|
||||
reply.reply.sendConn.ok = true;
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
static std::vector<std::function<void(std::wstring_view, std::wstring_view)>> s_onLaunchConnection;
|
||||
|
||||
void Manager::s_RegisterOnConnection(std::function<void(std::wstring_view, std::wstring_view)> func)
|
||||
{
|
||||
s_onLaunchConnection.push_back(func);
|
||||
}
|
||||
|
||||
Manager::ManagerMessageReply Manager::_sendCmdAndWorking(ManagerMessageQuery query, std::unique_ptr<BYTE[]>& buffer)
|
||||
{
|
||||
const auto cmd = query.query.sendCmdAndWorking.cmd;
|
||||
const auto work = query.query.sendCmdAndWorking.working;
|
||||
|
||||
std::wstring_view cmdline(reinterpret_cast<wchar_t*>(buffer.get() + 1), cmd);
|
||||
std::wstring_view workingDir(reinterpret_cast<wchar_t*>(buffer.get() + 1 + (cmd + 1) * 2), work);
|
||||
|
||||
// create new conhost connection...
|
||||
for (const auto& func : s_onLaunchConnection)
|
||||
{
|
||||
func(cmdline, workingDir);
|
||||
}
|
||||
|
||||
ManagerMessageReply reply;
|
||||
|
||||
reply.type = ManagerMessageTypes::SendCmdAndWorking;
|
||||
reply.reply.sendCmdAndWorking.ok = true;
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
84
src/types/Manager.h
Normal file
84
src/types/Manager.h
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
class Manager final
|
||||
{
|
||||
public:
|
||||
Manager();
|
||||
virtual ~Manager();
|
||||
|
||||
void NotifyExit();
|
||||
|
||||
static void s_RegisterOnConnection(std::function<void(HANDLE)> func);
|
||||
static void s_RegisterOnConnection(std::function<void(std::wstring_view, std::wstring_view)> func);
|
||||
static bool s_TrySendToManager(const HANDLE server);
|
||||
static bool s_TrySendToManager(const std::wstring_view cmdline,
|
||||
const std::wstring_view workingDir);
|
||||
|
||||
Manager(const Manager&) = delete;
|
||||
Manager(Manager&&) = delete;
|
||||
Manager& operator=(const Manager&) = delete;
|
||||
Manager& operator=(Manager&&) = delete;
|
||||
private:
|
||||
wil::unique_mutex _mutex;
|
||||
wil::unique_event _exit;
|
||||
wil::unique_handle _pipe;
|
||||
bool _theServer;
|
||||
std::future<void> _waitToBecomeServer;
|
||||
std::future<void> _serverWork;
|
||||
std::vector<std::future<void>> _perClientWork;
|
||||
|
||||
enum class ManagerMessageTypes
|
||||
{
|
||||
GetManagerPid,
|
||||
SendConnection,
|
||||
SendCmdAndWorking
|
||||
};
|
||||
|
||||
struct ManagerMessageQuery
|
||||
{
|
||||
DWORD size;
|
||||
ManagerMessageTypes type;
|
||||
union
|
||||
{
|
||||
struct SendConnection
|
||||
{
|
||||
HANDLE handle;
|
||||
} sendConn;
|
||||
struct SendCmdAndWorking
|
||||
{
|
||||
DWORD cmd;
|
||||
DWORD working;
|
||||
} sendCmdAndWorking;
|
||||
} query;
|
||||
};
|
||||
|
||||
struct ManagerMessageReply
|
||||
{
|
||||
ManagerMessageTypes type;
|
||||
union
|
||||
{
|
||||
struct GetManagerPid
|
||||
{
|
||||
DWORD id;
|
||||
} getPid;
|
||||
struct SendConnection
|
||||
{
|
||||
bool ok;
|
||||
} sendConn;
|
||||
struct SendCmdAndWorking
|
||||
{
|
||||
bool ok;
|
||||
} sendCmdAndWorking;
|
||||
} reply;
|
||||
};
|
||||
|
||||
static ManagerMessageReply _ask(ManagerMessageQuery& query);
|
||||
static ManagerMessageReply _getPid(ManagerMessageQuery query);
|
||||
static ManagerMessageReply _sendConnection(ManagerMessageQuery query);
|
||||
static ManagerMessageReply _sendCmdAndWorking(ManagerMessageQuery query, std::unique_ptr<byte[]>& buffer);
|
||||
|
||||
void _becomeServer();
|
||||
void _serverLoop();
|
||||
void _perClientLoop(wil::unique_handle pipe);
|
||||
};
|
||||
@@ -1,98 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "precomp.h"
|
||||
#include "inc/Utf8OutPipeReader.hpp"
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
UTF8OutPipeReader::UTF8OutPipeReader(HANDLE outPipe) :
|
||||
_outPipe{ outPipe }
|
||||
{
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// Populates a string_view with *complete* UTF-8 codepoints read from the pipe.
|
||||
// If it receives an incomplete codepoint, it will cache it until it can be completed.
|
||||
// Note: This method trusts that the other end will, in fact, send complete codepoints.
|
||||
// Arguments:
|
||||
// - strView: on return, populated with successfully-read codepoints.
|
||||
// Return Value:
|
||||
// An HRESULT indicating whether the read was successful. For the purposes of this
|
||||
// method, a closed pipe is considered a successful (but false!) read. All other errors
|
||||
// are translated into an appropriate status code.
|
||||
// S_OK for a successful read
|
||||
// S_FALSE for a read on a closed pipe
|
||||
// E_* (anything) for a failed read
|
||||
[[nodiscard]] HRESULT UTF8OutPipeReader::Read(_Out_ std::string_view& strView)
|
||||
{
|
||||
DWORD dwRead{};
|
||||
bool fSuccess{};
|
||||
|
||||
// in case of early escaping
|
||||
*_buffer = 0;
|
||||
strView = std::string_view{ reinterpret_cast<char*>(_buffer), 0 };
|
||||
|
||||
// copy UTF-8 code units that were remaining from the previously read chunk (if any)
|
||||
if (_dwPartialsLen != 0)
|
||||
{
|
||||
std::move(_utf8Partials, _utf8Partials + _dwPartialsLen, _buffer);
|
||||
}
|
||||
|
||||
// try to read data
|
||||
fSuccess = !!ReadFile(_outPipe, &_buffer[_dwPartialsLen], std::extent<decltype(_buffer)>::value - _dwPartialsLen, &dwRead, nullptr);
|
||||
|
||||
dwRead += _dwPartialsLen;
|
||||
_dwPartialsLen = 0;
|
||||
|
||||
if (!fSuccess) // reading failed (we must check this first, because dwRead will also be 0.)
|
||||
{
|
||||
auto lastError = GetLastError();
|
||||
if (lastError == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
// This is a successful, but detectable, exit.
|
||||
// There is a chance that we put some partials into the buffer. Since
|
||||
// the pipe has closed, they're just invalid now. They're not worth
|
||||
// reporting.
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
return HRESULT_FROM_WIN32(lastError);
|
||||
}
|
||||
|
||||
if (dwRead == 0) // quit if no data has been read and no cached data was left over
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
const BYTE* const endPtr{ _buffer + dwRead };
|
||||
const BYTE* backIter{ endPtr - 1 };
|
||||
// If the last byte in the buffer was a byte belonging to a UTF-8 multi-byte character
|
||||
if ((*backIter & _Utf8BitMasks::MaskAsciiByte) > _Utf8BitMasks::IsAsciiByte)
|
||||
{
|
||||
// Check only up to 3 last bytes, if no Lead Byte was found then the byte before must be the Lead Byte and no partials are in the buffer
|
||||
for (DWORD dwSequenceLen{ 1UL }, stop{ dwRead < 4UL ? dwRead : 4UL }; dwSequenceLen < stop; ++dwSequenceLen, --backIter)
|
||||
{
|
||||
// If Lead Byte found
|
||||
if ((*backIter & _Utf8BitMasks::MaskContinuationByte) > _Utf8BitMasks::IsContinuationByte)
|
||||
{
|
||||
// If the Lead Byte indicates that the last bytes in the buffer is a partial UTF-8 code point then cache them:
|
||||
// Use the bitmask at index `dwSequenceLen`. Compare the result with the operand having the same index. If they
|
||||
// are not equal then the sequence has to be cached because it is a partial code point. Otherwise the
|
||||
// sequence is a complete UTF-8 code point and the whole buffer is ready for the conversion to hstring.
|
||||
if ((*backIter & _cmpMasks[dwSequenceLen]) != _cmpOperands[dwSequenceLen])
|
||||
{
|
||||
std::move(backIter, endPtr, _utf8Partials);
|
||||
dwRead -= dwSequenceLen;
|
||||
_dwPartialsLen = dwSequenceLen;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// give back a view of the part of the buffer that contains complete code points only
|
||||
strView = std::string_view{ reinterpret_cast<char*>(_buffer), dwRead };
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- UTF8OutPipeReader.hpp
|
||||
|
||||
Abstract:
|
||||
- This reads a UTF-8 stream and gives back a buffer that contains complete code points only
|
||||
- Partial UTF-8 code points at the end of the buffer read are cached and prepended to the next chunk read
|
||||
|
||||
Author(s):
|
||||
- Steffen Illhardt (german-one) 12-July-2019
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <wil\common.h>
|
||||
#include <wil\resource.h>
|
||||
#include <string_view>
|
||||
|
||||
class UTF8OutPipeReader final
|
||||
{
|
||||
public:
|
||||
UTF8OutPipeReader(HANDLE outPipe);
|
||||
[[nodiscard]] HRESULT Read(_Out_ std::string_view& strView);
|
||||
|
||||
private:
|
||||
enum _Utf8BitMasks : BYTE
|
||||
{
|
||||
IsAsciiByte = 0b0'0000000, // Any byte representing an ASCII character has the MSB set to 0
|
||||
MaskAsciiByte = 0b1'0000000, // Bit mask to be used in a bitwise AND operation to find out whether or not a byte match the IsAsciiByte pattern
|
||||
IsContinuationByte = 0b10'000000, // Continuation bytes of any UTF-8 non-ASCII character have the MSB set to 1 and the adjacent bit set to 0
|
||||
MaskContinuationByte = 0b11'000000, // Bit mask to be used in a bitwise AND operation to find out whether or not a byte match the IsContinuationByte pattern
|
||||
IsLeadByteTwoByteSequence = 0b110'00000, // A lead byte that indicates a UTF-8 non-ASCII character consisting of two bytes has the two highest bits set to 1 and the adjacent bit set to 0
|
||||
MaskLeadByteTwoByteSequence = 0b111'00000, // Bit mask to be used in a bitwise AND operation to find out whether or not a lead byte match the IsLeadByteTwoByteSequence pattern
|
||||
IsLeadByteThreeByteSequence = 0b1110'0000, // A lead byte that indicates a UTF-8 non-ASCII character consisting of three bytes has the three highest bits set to 1 and the adjacent bit set to 0
|
||||
MaskLeadByteThreeByteSequence = 0b1111'0000, // Bit mask to be used in a bitwise AND operation to find out whether or not a lead byte match the IsLeadByteThreeByteSequence pattern
|
||||
IsLeadByteFourByteSequence = 0b11110'000, // A lead byte that indicates a UTF-8 non-ASCII character consisting of four bytes has the four highest bits set to 1 and the adjacent bit set to 0
|
||||
MaskLeadByteFourByteSequence = 0b11111'000 // Bit mask to be used in a bitwise AND operation to find out whether or not a lead byte match the IsLeadByteFourByteSequence pattern
|
||||
};
|
||||
|
||||
// array of bitmasks
|
||||
constexpr const static BYTE _cmpMasks[]{
|
||||
0, // unused
|
||||
_Utf8BitMasks::MaskContinuationByte,
|
||||
_Utf8BitMasks::MaskLeadByteTwoByteSequence,
|
||||
_Utf8BitMasks::MaskLeadByteThreeByteSequence,
|
||||
};
|
||||
|
||||
// array of values for the comparisons
|
||||
constexpr const static BYTE _cmpOperands[]{
|
||||
0, // unused
|
||||
_Utf8BitMasks::IsAsciiByte, // intentionally conflicts with MaskContinuationByte
|
||||
_Utf8BitMasks::IsLeadByteTwoByteSequence,
|
||||
_Utf8BitMasks::IsLeadByteThreeByteSequence,
|
||||
};
|
||||
|
||||
HANDLE _outPipe; // non-owning reference to a pipe.
|
||||
BYTE _buffer[4096]{ 0 }; // buffer for the chunk read
|
||||
BYTE _utf8Partials[4]{ 0 }; // buffer for code units of a partial UTF-8 code point that have to be cached
|
||||
DWORD _dwPartialsLen{}; // number of cached UTF-8 code units
|
||||
};
|
||||
@@ -5,6 +5,7 @@
|
||||
<ClCompile Include="..\CodepointWidthDetector.cpp" />
|
||||
<ClCompile Include="..\convert.cpp" />
|
||||
<ClCompile Include="..\GlyphWidth.cpp" />
|
||||
<ClCompile Include="..\Manager.cpp" />
|
||||
<ClCompile Include="..\MouseEvent.cpp" />
|
||||
<ClCompile Include="..\FocusEvent.cpp" />
|
||||
<ClCompile Include="..\IInputEvent.cpp" />
|
||||
@@ -12,7 +13,6 @@
|
||||
<ClCompile Include="..\MenuEvent.cpp" />
|
||||
<ClCompile Include="..\ModifierKeyState.cpp" />
|
||||
<ClCompile Include="..\Utf16Parser.cpp" />
|
||||
<ClCompile Include="..\UTF8OutPipeReader.cpp" />
|
||||
<ClCompile Include="..\Viewport.cpp" />
|
||||
<ClCompile Include="..\WindowBufferSizeEvent.cpp" />
|
||||
<ClCompile Include="..\precomp.cpp">
|
||||
@@ -25,9 +25,9 @@
|
||||
<ClInclude Include="..\inc\convert.hpp" />
|
||||
<ClInclude Include="..\inc\GlyphWidth.hpp" />
|
||||
<ClInclude Include="..\inc\IInputEvent.hpp" />
|
||||
<ClInclude Include="..\inc\UTF8OutPipeReader.hpp" />
|
||||
<ClInclude Include="..\inc\Viewport.hpp" />
|
||||
<ClInclude Include="..\inc\Utf16Parser.hpp" />
|
||||
<ClInclude Include="..\Manager.h" />
|
||||
<ClInclude Include="..\precomp.h" />
|
||||
<ClInclude Include="..\utils.hpp" />
|
||||
</ItemGroup>
|
||||
@@ -41,4 +41,4 @@
|
||||
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
|
||||
<Import Project="$(SolutionDir)src\common.build.lib.props" />
|
||||
<Import Project="$(SolutionDir)src\common.build.post.props" />
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -57,7 +57,7 @@
|
||||
<ClCompile Include="..\utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\UTF8OutPipeReader.cpp">
|
||||
<ClCompile Include="..\Manager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
@@ -86,7 +86,7 @@
|
||||
<ClInclude Include="..\utils.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\UTF8OutPipeReader.hpp">
|
||||
<ClInclude Include="..\Manager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -33,6 +33,7 @@ SOURCES= \
|
||||
..\FocusEvent.cpp \
|
||||
..\GlyphWidth.cpp \
|
||||
..\KeyEvent.cpp \
|
||||
..\Manager.cpp \
|
||||
..\MenuEvent.cpp \
|
||||
..\ModifierKeyState.cpp \
|
||||
..\MouseEvent.cpp \
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(SolutionDir)src\common.build.pre.props" />
|
||||
<ItemGroup>
|
||||
<ClCompile Include="UTF8OutPipeReaderTests.cpp" />
|
||||
<ClCompile Include="UtilsTests.cpp" />
|
||||
<ClCompile Include="UuidTests.cpp" />
|
||||
<ClCompile Include="..\precomp.cpp">
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "precomp.h"
|
||||
#include "WexTestClass.h"
|
||||
#include "..\..\inc\consoletaeftemplates.hpp"
|
||||
|
||||
#include "..\inc\UTF8OutPipeReader.hpp"
|
||||
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
|
||||
using namespace WEX::Common;
|
||||
using namespace WEX::Logging;
|
||||
using namespace WEX::TestExecution;
|
||||
|
||||
class UTF8OutPipeReaderTests
|
||||
{
|
||||
TEST_CLASS(UTF8OutPipeReaderTests);
|
||||
|
||||
TEST_METHOD(TestUtf8MergePartials)
|
||||
{
|
||||
// The test uses the character 'GOTHIC LETTER HWAIR' (U+10348) as an example
|
||||
// Its UTF-8 representation consists of four bytes:
|
||||
// 1 2 3 4
|
||||
// 0xF0 0x90 0x8D 0x88
|
||||
//
|
||||
// For the test a std::string is filled with 4104 '.' characters to make sure it exceeds the
|
||||
// buffer size of 4096 bytes in UTF8OutPipeReader.
|
||||
//
|
||||
// This figure shows how the string is getting changed for the 7 sub-tests. The digits 1 to 4
|
||||
// represent the four bytes of the 'Hwair' letter. The vertical bar represents the buffer boundary.
|
||||
// Test 1: [more points] . . S 1 2 3 4 T|U V W X Y Z . .
|
||||
// Test 2: [more points] . . S T 1 2 3 4|U V W X Y Z . .
|
||||
// Test 3: [more points] . . S T U 1 2 3|4 V W X Y Z . .
|
||||
// Test 4: [more points] . . S T U V 1 2|3 4 W X Y Z . .
|
||||
// Test 5: [more points] . . S T U V W 1|2 3 4 X Y Z . .
|
||||
// Test 6: [more points] . . S T U V W X|1 2 3 4 Y Z . .
|
||||
// Test 7: [more points] . . S T U V W X|Y 1 2 3 4 Z . .
|
||||
//
|
||||
// Tests 1, 6, and 7 prove proper ASCII handling.
|
||||
// Test 2 leaves all four bytes of 'Hwair' in the first chunk.
|
||||
// Test 3, 4, and 5 move the partials from the end of the first chunk to the begin of the
|
||||
// second chunk.
|
||||
//
|
||||
// At the beginning of a test the whole string is converted into a winrt::hstring for reference.
|
||||
// During the test a second hstring is concatenated out of the chunks that we get from
|
||||
// UTF8OutPipeReader::Read. Each chunk is separately converted to hstring in order to make
|
||||
// sure it would be corrupted if we get UTF-8 partials.
|
||||
// The test is positive if both hstrings are equal.
|
||||
|
||||
const size_t bufferSize{ 4096 }; // NOTE: This has to match the buffer size in UTF8OutPipeReader!
|
||||
std::string utf8TestString(bufferSize + 8, '.'); // create a test string with the required size
|
||||
|
||||
// Test 1:
|
||||
// ||
|
||||
utf8TestString.replace(bufferSize - 6, 12, "S\xF0\x90\x8D\x88TUVWXYZ");
|
||||
VERIFY_SUCCEEDED(RunTest(utf8TestString));
|
||||
|
||||
// Test 2:
|
||||
// | |
|
||||
utf8TestString.replace(bufferSize - 6, 12, "ST\xF0\x90\x8D\x88UVWXYZ");
|
||||
VERIFY_SUCCEEDED(RunTest(utf8TestString));
|
||||
|
||||
// Test 3:
|
||||
// | |
|
||||
utf8TestString.replace(bufferSize - 6, 12, "STU\xF0\x90\x8D\x88VWXYZ");
|
||||
VERIFY_SUCCEEDED(RunTest(utf8TestString));
|
||||
|
||||
// Test 4:
|
||||
// | |
|
||||
utf8TestString.replace(bufferSize - 6, 12, "STUV\xF0\x90\x8D\x88WXYZ");
|
||||
VERIFY_SUCCEEDED(RunTest(utf8TestString));
|
||||
|
||||
// Test 5:
|
||||
// | |
|
||||
utf8TestString.replace(bufferSize - 6, 12, "STUVW\xF0\x90\x8D\x88XYZ");
|
||||
VERIFY_SUCCEEDED(RunTest(utf8TestString));
|
||||
|
||||
// Test 6:
|
||||
// | |
|
||||
utf8TestString.replace(bufferSize - 6, 12, "STUVWX\xF0\x90\x8D\x88YZ");
|
||||
VERIFY_SUCCEEDED(RunTest(utf8TestString));
|
||||
|
||||
// Test 7:
|
||||
// ||
|
||||
utf8TestString.replace(bufferSize - 6, 12, "STUVWXY\xF0\x90\x8D\x88Z");
|
||||
VERIFY_SUCCEEDED(RunTest(utf8TestString));
|
||||
}
|
||||
|
||||
struct ThreadData
|
||||
{
|
||||
wil::unique_hfile& inPipe;
|
||||
std::string& utf8TestString;
|
||||
};
|
||||
|
||||
// Thread function which writes the UTF-8 data to the pipe.
|
||||
static DWORD WINAPI WritePipeThread(LPVOID threadArg)
|
||||
{
|
||||
ThreadData* pThreadData{ reinterpret_cast<ThreadData*>(threadArg) };
|
||||
DWORD length{};
|
||||
|
||||
WriteFile(pThreadData->inPipe.get(), pThreadData->utf8TestString.c_str(), static_cast<DWORD>(pThreadData->utf8TestString.size()), &length, nullptr);
|
||||
pThreadData->inPipe.reset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Performs the sub-tests.
|
||||
HRESULT RunTest(std::string& utf8TestString)
|
||||
{
|
||||
std::string_view strView{}; // contains the chunk that we get from UTF8OutPipeReader::Read
|
||||
const winrt::hstring utf16Expected{ winrt::to_hstring(utf8TestString) }; // contains the whole string converted to UTF-16
|
||||
winrt::hstring utf16Actual{}; // will be concatenated from the converted chunks
|
||||
|
||||
wil::unique_hfile outPipe{};
|
||||
wil::unique_hfile inPipe{};
|
||||
|
||||
SECURITY_ATTRIBUTES sa{ sizeof(SECURITY_ATTRIBUTES) };
|
||||
CreatePipe(&outPipe, &inPipe, &sa, 0); // create the pipe handles
|
||||
|
||||
UTF8OutPipeReader reader{ outPipe.get() };
|
||||
|
||||
ThreadData data{ inPipe, utf8TestString };
|
||||
|
||||
wil::unique_handle threadHandle{ CreateThread(nullptr, 0, WritePipeThread, &data, 0, nullptr) }; // create a thread that writes to the pipe
|
||||
RETURN_HR_IF_NULL(E_FAIL, threadHandle.get());
|
||||
|
||||
// process the chunks that we get from UTF8OutPipeReader::Read
|
||||
while (true)
|
||||
{
|
||||
// get a chunk of UTF-8 data
|
||||
THROW_IF_FAILED(reader.Read(strView));
|
||||
|
||||
if (strView.empty())
|
||||
{
|
||||
// this is okay, no data left in the pipe
|
||||
break;
|
||||
}
|
||||
|
||||
// convert the chunk to hstring and append it to the resulting hstring
|
||||
utf16Actual = utf16Actual + winrt::to_hstring(strView);
|
||||
}
|
||||
|
||||
WaitForSingleObject(threadHandle.get(), 2000);
|
||||
|
||||
// the test passed if both hstrings are equal
|
||||
if (utf16Actual == utf16Expected)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
};
|
||||
@@ -187,7 +187,7 @@ function Invoke-OpenConsoleTests()
|
||||
}
|
||||
$OpenConsolePath = "$env:OpenConsoleroot\bin\$OpenConsolePlatform\$Configuration\OpenConsole.exe"
|
||||
$RunTePath = "$env:OpenConsoleRoot\tools\runte.cmd"
|
||||
$TaefExePath = "$env:OpenConsoleRoot\packages\Taef.Redist.Wlk.10.38.190610001-uapadmin\build\Binaries\$Platform\te.exe"
|
||||
$TaefExePath = "$env:OpenConsoleRoot\packages\Taef.Redist.Wlk.10.30.180808002\build\binaries\$Platform\te.exe"
|
||||
$BinDir = "$env:OpenConsoleRoot\bin\$OpenConsolePlatform\$Configuration"
|
||||
[xml]$TestConfig = Get-Content "$env:OpenConsoleRoot\tools\tests.xml"
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
@echo off
|
||||
|
||||
"%msbuild%" Openconsole.sln /t:Conhost\Host_EXE /m /p:Configuration=Debug /p:Platform=%ARCH%
|
||||
|
||||
:eof
|
||||
@@ -104,7 +104,7 @@ shift
|
||||
goto :ARGS_LOOP
|
||||
|
||||
:POST_ARGS_LOOP
|
||||
set TAEF=%OPENCON%\packages\Taef.Redist.Wlk.10.38.190610001-uapadmin\build\Binaries\%ARCH%\TE.exe
|
||||
set TAEF=%OPENCON%\packages\Taef.Redist.Wlk.10.30.180808002\build\binaries\%ARCH%\TE.exe
|
||||
rem Set this envvar so setup won't repeat itself
|
||||
set OpenConBuild=true
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
@echo off
|
||||
|
||||
rem openvt - launch the vtterm binary
|
||||
rem Runs the VtPipeTerm.exe binary generated by the build in the debug directory.
|
||||
rem Passes any args along.
|
||||
|
||||
setlocal
|
||||
set _last_build=%OPENCON%\bin\%ARCH%\%_LAST_BUILD_CONF%
|
||||
|
||||
if not exist %_last_build%\scratch.exe (
|
||||
echo Could not locate the scratch.exe in %_last_build%. Double check that it has been built and try again.
|
||||
goto :eof
|
||||
)
|
||||
|
||||
set _r=%random%
|
||||
set copy_dir=OpenConsole\%_r%
|
||||
rem Generate a unique name, so that we can debug multiple revisions of the binary at the same time if needed.
|
||||
|
||||
(xcopy /Y %_last_build%\OpenConsole.exe %TEMP%\%copy_dir%\conhost.exe*) > nul
|
||||
(xcopy /Y %_last_build%\console.dll %TEMP%\%copy_dir%\console.dll*) > nul
|
||||
(xcopy /Y %_last_build%\scratch.exe %TEMP%\%copy_dir%\scratch.exe*) > nul
|
||||
|
||||
echo Launching %TEMP%\%copy_dir%\scratch.exe...
|
||||
%TEMP%\%copy_dir%\scratch.exe %*
|
||||
Reference in New Issue
Block a user