diff --git a/Scratch.sln b/Scratch.sln
new file mode 100644
index 000000000..ac6caf341
--- /dev/null
+++ b/Scratch.sln
@@ -0,0 +1,221 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31205.134
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Package", "scratch\ScratchIslandApp\Package\Package.wapproj", "{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleAppLib", "scratch\ScratchIslandApp\SampleApp\SampleAppLib.vcxproj", "{A4394404-37F7-41C1-802B-49788D3720E3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleApp", "scratch\ScratchIslandApp\SampleApp\dll\SampleApp.vcxproj", "{26C51792-41A3-4FE0-AB5E-8B69D557BF91}"
+ ProjectSection(ProjectDependencies) = postProject
+ {A4394404-37F7-41C1-802B-49788D3720E3} = {A4394404-37F7-41C1-802B-49788D3720E3}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowExe", "scratch\ScratchIslandApp\WindowExe\WindowExe.vcxproj", "{B4427499-9FDE-4208-B456-5BC580637633}"
+ ProjectSection(ProjectDependencies) = postProject
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91} = {26C51792-41A3-4FE0-AB5E-8B69D557BF91}
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common Props", "Common Props", "{53DD5520-E64C-4C06-B472-7CE62CA539C9}"
+ ProjectSection(SolutionItems) = preProject
+ src\common.build.post.props = src\common.build.post.props
+ src\common.build.pre.props = src\common.build.pre.props
+ src\common.build.tests.props = src\common.build.tests.props
+ common.openconsole.props = common.openconsole.props
+ src\cppwinrt.build.post.props = src\cppwinrt.build.post.props
+ src\cppwinrt.build.pre.props = src\cppwinrt.build.pre.props
+ src\wap-common.build.post.props = src\wap-common.build.post.props
+ src\wap-common.build.pre.props = src\wap-common.build.pre.props
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmt", "src\dep\fmt\fmt.vcxproj", "{6BAE5851-50D5-4934-8D5E-30361A8A40F3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Types", "src\types\lib\types.vcxproj", "{18D09A24-8240-42D6-8CB6-236EEE820263}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dependencies", "dependencies", "{75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ AuditMode|ARM64 = AuditMode|ARM64
+ AuditMode|x64 = AuditMode|x64
+ AuditMode|x86 = AuditMode|x86
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Fuzzing|ARM64 = Fuzzing|ARM64
+ Fuzzing|x64 = Fuzzing|x64
+ Fuzzing|x86 = Fuzzing|x86
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.ActiveCfg = Debug|ARM64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.Build.0 = Debug|ARM64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.Deploy.0 = Debug|ARM64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.ActiveCfg = Debug|x64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.Build.0 = Debug|x64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.Deploy.0 = Debug|x64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.ActiveCfg = Debug|x86
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.Build.0 = Debug|x86
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.Deploy.0 = Debug|x86
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.Build.0 = Debug|ARM64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.ActiveCfg = Debug|x64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.Build.0 = Debug|x64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.Deploy.0 = Debug|x64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.ActiveCfg = Debug|x86
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.Build.0 = Debug|x86
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.Deploy.0 = Debug|x86
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.ActiveCfg = Debug|ARM64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.Build.0 = Debug|ARM64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.Deploy.0 = Debug|ARM64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.ActiveCfg = Debug|x64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.Build.0 = Debug|x64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.Deploy.0 = Debug|x64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.ActiveCfg = Debug|x86
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.Build.0 = Debug|x86
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.Deploy.0 = Debug|x86
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.ActiveCfg = Release|ARM64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.Build.0 = Release|ARM64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.Deploy.0 = Release|ARM64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.ActiveCfg = Release|x64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.Build.0 = Release|x64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.Deploy.0 = Release|x64
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.ActiveCfg = Release|x86
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.Build.0 = Release|x86
+ {CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.Deploy.0 = Release|x86
+ {A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x64.ActiveCfg = AuditMode|x64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x64.Build.0 = AuditMode|x64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x86.ActiveCfg = AuditMode|Win32
+ {A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x86.Build.0 = AuditMode|Win32
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Debug|ARM64.Build.0 = Debug|ARM64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x64.ActiveCfg = Debug|x64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x64.Build.0 = Debug|x64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x86.ActiveCfg = Debug|Win32
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x86.Build.0 = Debug|Win32
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x64.Build.0 = Fuzzing|x64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x86.Build.0 = Fuzzing|Win32
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Release|ARM64.ActiveCfg = Release|ARM64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Release|ARM64.Build.0 = Release|ARM64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Release|x64.ActiveCfg = Release|x64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Release|x64.Build.0 = Release|x64
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Release|x86.ActiveCfg = Release|Win32
+ {A4394404-37F7-41C1-802B-49788D3720E3}.Release|x86.Build.0 = Release|Win32
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x64.ActiveCfg = AuditMode|x64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x64.Build.0 = AuditMode|x64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x86.ActiveCfg = AuditMode|Win32
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x86.Build.0 = AuditMode|Win32
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|ARM64.Build.0 = Debug|ARM64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x64.ActiveCfg = Debug|x64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x64.Build.0 = Debug|x64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x86.ActiveCfg = Debug|Win32
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x86.Build.0 = Debug|Win32
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x64.Build.0 = Fuzzing|x64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x86.Build.0 = Fuzzing|Win32
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|ARM64.ActiveCfg = Release|ARM64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|ARM64.Build.0 = Release|ARM64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x64.ActiveCfg = Release|x64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x64.Build.0 = Release|x64
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x86.ActiveCfg = Release|Win32
+ {26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x86.Build.0 = Release|Win32
+ {B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
+ {B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
+ {B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x64.ActiveCfg = AuditMode|x64
+ {B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x64.Build.0 = AuditMode|x64
+ {B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x86.ActiveCfg = AuditMode|Win32
+ {B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x86.Build.0 = AuditMode|Win32
+ {B4427499-9FDE-4208-B456-5BC580637633}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {B4427499-9FDE-4208-B456-5BC580637633}.Debug|ARM64.Build.0 = Debug|ARM64
+ {B4427499-9FDE-4208-B456-5BC580637633}.Debug|x64.ActiveCfg = Debug|x64
+ {B4427499-9FDE-4208-B456-5BC580637633}.Debug|x64.Build.0 = Debug|x64
+ {B4427499-9FDE-4208-B456-5BC580637633}.Debug|x86.ActiveCfg = Debug|Win32
+ {B4427499-9FDE-4208-B456-5BC580637633}.Debug|x86.Build.0 = Debug|Win32
+ {B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
+ {B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
+ {B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
+ {B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x64.Build.0 = Fuzzing|x64
+ {B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
+ {B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x86.Build.0 = Fuzzing|Win32
+ {B4427499-9FDE-4208-B456-5BC580637633}.Release|ARM64.ActiveCfg = Release|ARM64
+ {B4427499-9FDE-4208-B456-5BC580637633}.Release|ARM64.Build.0 = Release|ARM64
+ {B4427499-9FDE-4208-B456-5BC580637633}.Release|x64.ActiveCfg = Release|x64
+ {B4427499-9FDE-4208-B456-5BC580637633}.Release|x64.Build.0 = Release|x64
+ {B4427499-9FDE-4208-B456-5BC580637633}.Release|x86.ActiveCfg = Release|Win32
+ {B4427499-9FDE-4208-B456-5BC580637633}.Release|x86.Build.0 = Release|Win32
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x64.ActiveCfg = AuditMode|x64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x64.Build.0 = AuditMode|x64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x86.ActiveCfg = AuditMode|Win32
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x86.Build.0 = AuditMode|Win32
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM64.Build.0 = Debug|ARM64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.ActiveCfg = Debug|x64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.Build.0 = Debug|x64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.ActiveCfg = Debug|Win32
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.Build.0 = Debug|Win32
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.Build.0 = Fuzzing|x64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x86.Build.0 = Fuzzing|Win32
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.ActiveCfg = Release|ARM64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.Build.0 = Release|ARM64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.ActiveCfg = Release|x64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.Build.0 = Release|x64
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.ActiveCfg = Release|Win32
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.Build.0 = Release|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x64.ActiveCfg = AuditMode|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x64.Build.0 = AuditMode|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x86.ActiveCfg = AuditMode|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x86.Build.0 = AuditMode|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|ARM64.Build.0 = Debug|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.ActiveCfg = Debug|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.Build.0 = Debug|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.ActiveCfg = Debug|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.Build.0 = Debug|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x64.Build.0 = Fuzzing|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x86.Build.0 = Fuzzing|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.ActiveCfg = Release|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.Build.0 = Release|ARM64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x64.ActiveCfg = Release|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x64.Build.0 = Release|x64
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x86.ActiveCfg = Release|Win32
+ {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {6BAE5851-50D5-4934-8D5E-30361A8A40F3} = {75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}
+ {18D09A24-8240-42D6-8CB6-236EEE820263} = {75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {05EAE315-9188-4D7B-B889-7D5F480A8915}
+ EndGlobalSection
+EndGlobal
diff --git a/consolegit2gitfilters.json b/consolegit2gitfilters.json
index 5a760692b..5f5d0eb26 100644
--- a/consolegit2gitfilters.json
+++ b/consolegit2gitfilters.json
@@ -23,6 +23,8 @@
"/doc/cascadia/",
"/doc/user-docs/",
"/src/tools/MonarchPeasantSample/",
+ "/scratch/",
+ "Scratch.sln",
],
"SuffixFilters": [
".dbb",
diff --git a/scratch/ScratchIslandApp/Package/Package.appxmanifest b/scratch/ScratchIslandApp/Package/Package.appxmanifest
new file mode 100644
index 000000000..dcd54adca
--- /dev/null
+++ b/scratch/ScratchIslandApp/Package/Package.appxmanifest
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+ Sample App
+ A Lone Developer
+ Images\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/scratch/ScratchIslandApp/Package/Package.wapproj b/scratch/ScratchIslandApp/Package/Package.wapproj
new file mode 100644
index 000000000..262719541
--- /dev/null
+++ b/scratch/ScratchIslandApp/Package/Package.wapproj
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+ false
+ false
+
+
+ cf31505e-3bae-4c0a-81d7-f1eb279f40bb
+ ..\WindowExe\WindowExe.vcxproj
+ NativeOnly
+
+
+ false
+ Never
+
+
+ true
+ False
+ Package_TemporaryKey.pfx
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd
+ $(OpenConsoleCommonOutDir)TerminalConnection\TerminalConnection.dll
+ true
+ true
+ true
+
+
+ $(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd
+ $(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.dll
+ true
+ true
+ true
+
+
+
+
+
+
+
+ <_TemporaryFilteredWapProjOutput Include="@(_FilteredNonWapProjProjectOutput)" />
+ <_FilteredNonWapProjProjectOutput Remove="@(_TemporaryFilteredWapProjOutput)" />
+ <_FilteredNonWapProjProjectOutput Include="@(_TemporaryFilteredWapProjOutput)">
+
+
+
+
+
+
+
+
+
+ <_GenerateProjectPriFileDependsOn Condition="$(MSBuildVersion) < '16.3.0'">OpenConsoleLiftDesktopBridgePriFiles;$(_GenerateProjectPriFileDependsOn)
+
+
+
+ <_PriFile Include="@(_NonWapProjProjectOutput)" Condition="'%(Extension)' == '.pri'" />
+
+
+
+
+
+
+
+ $([MSBuild]::Unescape('$(WapProjBeforeGenerateAppxManifestDependsOn.Replace('_RemoveAllNonWapUWPItems', '_OpenConsoleRemoveAllNonWapUWPItems'))'))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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}.
+
+
+
+
+
+
+
+
+
diff --git a/scratch/ScratchIslandApp/Package/Resources/Resources.resw b/scratch/ScratchIslandApp/Package/Resources/Resources.resw
new file mode 100644
index 000000000..872f430e7
--- /dev/null
+++ b/scratch/ScratchIslandApp/Package/Resources/Resources.resw
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Scratch XAML Island App
+
+
+ Scratch App
+
+
diff --git a/scratch/ScratchIslandApp/Package/Resources/en-US/Resources.resw b/scratch/ScratchIslandApp/Package/Resources/en-US/Resources.resw
new file mode 100644
index 000000000..4ffee428e
--- /dev/null
+++ b/scratch/ScratchIslandApp/Package/Resources/en-US/Resources.resw
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ A scratch app for XAML Islands tests
+
+
diff --git a/scratch/ScratchIslandApp/SampleApp/App.base.h b/scratch/ScratchIslandApp/SampleApp/App.base.h
new file mode 100644
index 000000000..d6da79f1b
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/App.base.h
@@ -0,0 +1,40 @@
+#pragma once
+
+namespace winrt::SampleApp::implementation
+{
+ template
+ struct App_baseWithProvider : public App_base
+ {
+ using IXamlType = ::winrt::Windows::UI::Xaml::Markup::IXamlType;
+
+ IXamlType GetXamlType(::winrt::Windows::UI::Xaml::Interop::TypeName const& type)
+ {
+ return AppProvider()->GetXamlType(type);
+ }
+
+ IXamlType GetXamlType(::winrt::hstring const& fullName)
+ {
+ return AppProvider()->GetXamlType(fullName);
+ }
+
+ ::winrt::com_array<::winrt::Windows::UI::Xaml::Markup::XmlnsDefinition> GetXmlnsDefinitions()
+ {
+ return AppProvider()->GetXmlnsDefinitions();
+ }
+
+ private:
+ bool _contentLoaded{ false };
+ std::shared_ptr _appProvider;
+ std::shared_ptr AppProvider()
+ {
+ if (!_appProvider)
+ {
+ _appProvider = std::make_shared();
+ }
+ return _appProvider;
+ }
+ };
+
+ template
+ using AppT2 = App_baseWithProvider;
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/App.cpp b/scratch/ScratchIslandApp/SampleApp/App.cpp
new file mode 100644
index 000000000..5a2ae523f
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/App.cpp
@@ -0,0 +1,65 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+#include "App.h"
+#include "App.g.cpp"
+
+using namespace winrt;
+using namespace winrt::Windows::ApplicationModel::Activation;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Controls;
+using namespace winrt::Windows::UI::Xaml::Navigation;
+
+namespace winrt::SampleApp::implementation
+{
+ App::App()
+ {
+ // This is the same trick that Initialize() is about to use to figure out whether we're coming
+ // from a UWP context or from a Win32 context
+ // See https://github.com/windows-toolkit/Microsoft.Toolkit.Win32/blob/52611c57d89554f357f281d0c79036426a7d9257/Microsoft.Toolkit.Win32.UI.XamlApplication/XamlApplication.cpp#L42
+ const auto dispatcherQueue = ::winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
+ if (dispatcherQueue)
+ {
+ _isUwp = true;
+ }
+
+ Initialize();
+
+ // Disable XAML's automatic backplating of text when in High Contrast
+ // mode: we want full control of and responsibility for the foreground
+ // and background colors that we draw in XAML.
+ HighContrastAdjustment(::winrt::Windows::UI::Xaml::ApplicationHighContrastAdjustment::None);
+ }
+
+ SampleAppLogic App::Logic()
+ {
+ static SampleAppLogic logic;
+ return logic;
+ }
+
+ ///
+ /// Invoked when the application is launched normally by the end user. Other entry points
+ /// will be used such as when the application is launched to open a specific file.
+ ///
+ /// Details about the launch request and process.
+ void App::OnLaunched(LaunchActivatedEventArgs const& /*e*/)
+ {
+ // if this is a UWP... it means its our problem to hook up the content to the window here.
+ if (_isUwp)
+ {
+ auto content = Window::Current().Content();
+ if (content == nullptr)
+ {
+ auto logic = Logic();
+ logic.Create();
+
+ auto page = logic.GetRoot().as();
+
+ Window::Current().Content(page);
+ Window::Current().Activate();
+ }
+ }
+ }
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/App.h b/scratch/ScratchIslandApp/SampleApp/App.h
new file mode 100644
index 000000000..fb6235d75
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/App.h
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#pragma once
+
+#include "App.g.h"
+#include "App.base.h"
+
+namespace winrt::SampleApp::implementation
+{
+ struct App : AppT2
+ {
+ public:
+ App();
+ void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const&);
+
+ SampleApp::SampleAppLogic Logic();
+
+ private:
+ bool _isUwp = false;
+ };
+}
+
+namespace winrt::SampleApp::factory_implementation
+{
+ struct App : AppT
+ {
+ };
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/App.idl b/scratch/ScratchIslandApp/SampleApp/App.idl
new file mode 100644
index 000000000..e51a73332
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/App.idl
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+import "SampleAppLogic.idl";
+
+namespace SampleApp
+{
+ // ADD ARBITRARY APP LOGIC TO SampleAppLogic.idl, NOT HERE.
+ // This is for XAML platform setup only.
+ [default_interface] runtimeclass App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
+ {
+ App();
+
+ SampleAppLogic Logic { get; };
+ }
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/App.xaml b/scratch/ScratchIslandApp/SampleApp/App.xaml
new file mode 100644
index 000000000..c6a2328f4
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/App.xaml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 8,0,8,0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/scratch/ScratchIslandApp/SampleApp/MyPage.cpp b/scratch/ScratchIslandApp/SampleApp/MyPage.cpp
new file mode 100644
index 000000000..d4af3d80e
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/MyPage.cpp
@@ -0,0 +1,54 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+#include "MyPage.h"
+#include
+#include "MyPage.g.cpp"
+#include "..\..\..\src\cascadia\UnitTests_Control\MockControlSettings.h"
+
+using namespace std::chrono_literals;
+using namespace winrt::Microsoft::Terminal;
+
+namespace winrt
+{
+ namespace MUX = Microsoft::UI::Xaml;
+ namespace WUX = Windows::UI::Xaml;
+ using IInspectable = Windows::Foundation::IInspectable;
+}
+
+namespace winrt::SampleApp::implementation
+{
+ MyPage::MyPage()
+ {
+ InitializeComponent();
+ }
+
+ void MyPage::Create()
+ {
+ TerminalConnection::EchoConnection conn{};
+ auto settings = winrt::make_self();
+
+ Control::TermControl control{ *settings, conn };
+
+ InProcContent().Children().Append(control);
+
+ // Once the control loads (and not before that), write some text for debugging:
+ control.Initialized([conn](auto&&, auto&&) {
+ conn.WriteInput(L"This TermControl is hosted in-proc...");
+ });
+ }
+
+ // Method Description:
+ // - Gets the title of the currently focused terminal control. If there
+ // isn't a control selected for any reason, returns "Windows Terminal"
+ // Arguments:
+ // -
+ // Return Value:
+ // - the title of the focused control if there is one, else "Windows Terminal"
+ hstring MyPage::Title()
+ {
+ return { L"Sample Application" };
+ }
+
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/MyPage.h b/scratch/ScratchIslandApp/SampleApp/MyPage.h
new file mode 100644
index 000000000..c16c02bb3
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/MyPage.h
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#pragma once
+
+#include "MyPage.g.h"
+#include "../../../src/cascadia/inc/cppwinrt_utils.h"
+
+namespace winrt::SampleApp::implementation
+{
+ struct MyPage : MyPageT
+ {
+ public:
+ MyPage();
+
+ void Create();
+
+ hstring Title();
+
+ private:
+ friend struct MyPageT; // for Xaml to bind events
+ };
+}
+
+namespace winrt::SampleApp::factory_implementation
+{
+ BASIC_FACTORY(MyPage);
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/MyPage.idl b/scratch/ScratchIslandApp/SampleApp/MyPage.idl
new file mode 100644
index 000000000..d3d0645b5
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/MyPage.idl
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+namespace SampleApp
+{
+ [default_interface] runtimeclass MyPage : Windows.UI.Xaml.Controls.Page
+ {
+ MyPage();
+ }
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/MyPage.xaml b/scratch/ScratchIslandApp/SampleApp/MyPage.xaml
new file mode 100644
index 000000000..f6e129ee7
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/MyPage.xaml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/scratch/ScratchIslandApp/SampleApp/MySettings.cpp b/scratch/ScratchIslandApp/SampleApp/MySettings.cpp
new file mode 100644
index 000000000..c042a34e7
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/MySettings.cpp
@@ -0,0 +1,11 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+
+#include "MySettings.h"
+#include "MySettings.g.cpp"
+
+namespace winrt::SampleApp::implementation
+{
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/MySettings.h b/scratch/ScratchIslandApp/SampleApp/MySettings.h
new file mode 100644
index 000000000..170c9b540
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/MySettings.h
@@ -0,0 +1,97 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+--*/
+#pragma once
+#include "../../inc/cppwinrt_utils.h"
+#include
+#include
+#include "MySettings.g.h"
+
+namespace winrt::SampleApp::implementation
+{
+ struct MySettings : MySettingsT
+ {
+ public:
+ MySettings() = default;
+
+ // --------------------------- Core Settings ---------------------------
+ // All of these settings are defined in ICoreSettings.
+
+ WINRT_PROPERTY(til::color, DefaultForeground, DEFAULT_FOREGROUND);
+ WINRT_PROPERTY(til::color, DefaultBackground, DEFAULT_BACKGROUND);
+ WINRT_PROPERTY(til::color, SelectionBackground, DEFAULT_FOREGROUND);
+ WINRT_PROPERTY(int32_t, HistorySize, DEFAULT_HISTORY_SIZE);
+ WINRT_PROPERTY(int32_t, InitialRows, 30);
+ WINRT_PROPERTY(int32_t, InitialCols, 80);
+
+ WINRT_PROPERTY(bool, SnapOnInput, true);
+ WINRT_PROPERTY(bool, AltGrAliasing, true);
+ WINRT_PROPERTY(til::color, CursorColor, DEFAULT_CURSOR_COLOR);
+ WINRT_PROPERTY(winrt::Microsoft::Terminal::Core::CursorStyle, CursorShape, winrt::Microsoft::Terminal::Core::CursorStyle::Vintage);
+ WINRT_PROPERTY(uint32_t, CursorHeight, DEFAULT_CURSOR_HEIGHT);
+ WINRT_PROPERTY(winrt::hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS);
+ WINRT_PROPERTY(bool, CopyOnSelect, false);
+ WINRT_PROPERTY(bool, InputServiceWarning, true);
+ WINRT_PROPERTY(bool, FocusFollowMouse, false);
+
+ WINRT_PROPERTY(winrt::Windows::Foundation::IReference, TabColor, nullptr);
+
+ WINRT_PROPERTY(winrt::Windows::Foundation::IReference, StartingTabColor, nullptr);
+
+ winrt::Microsoft::Terminal::Core::ICoreAppearance UnfocusedAppearance() { return {}; };
+
+ WINRT_PROPERTY(bool, TrimBlockSelection, false);
+ // ------------------------ End of Core Settings -----------------------
+
+ WINRT_PROPERTY(winrt::hstring, ProfileName);
+ WINRT_PROPERTY(bool, UseAcrylic, false);
+ WINRT_PROPERTY(double, TintOpacity, 0.5);
+ WINRT_PROPERTY(winrt::hstring, Padding, DEFAULT_PADDING);
+ WINRT_PROPERTY(winrt::hstring, FontFace, L"Consolas");
+ WINRT_PROPERTY(int32_t, FontSize, DEFAULT_FONT_SIZE);
+
+ WINRT_PROPERTY(winrt::Windows::UI::Text::FontWeight, FontWeight);
+
+ WINRT_PROPERTY(winrt::hstring, BackgroundImage);
+ WINRT_PROPERTY(double, BackgroundImageOpacity, 1.0);
+
+ WINRT_PROPERTY(winrt::Windows::UI::Xaml::Media::Stretch, BackgroundImageStretchMode, winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill);
+ WINRT_PROPERTY(winrt::Windows::UI::Xaml::HorizontalAlignment, BackgroundImageHorizontalAlignment, winrt::Windows::UI::Xaml::HorizontalAlignment::Center);
+ WINRT_PROPERTY(winrt::Windows::UI::Xaml::VerticalAlignment, BackgroundImageVerticalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment::Center);
+
+ WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::IKeyBindings, KeyBindings, nullptr);
+
+ WINRT_PROPERTY(winrt::hstring, Commandline);
+ WINRT_PROPERTY(winrt::hstring, StartingDirectory);
+ WINRT_PROPERTY(winrt::hstring, StartingTitle);
+ WINRT_PROPERTY(bool, SuppressApplicationTitle);
+ WINRT_PROPERTY(winrt::hstring, EnvironmentVariables);
+
+ WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::ScrollbarState, ScrollState, winrt::Microsoft::Terminal::Control::ScrollbarState::Visible);
+
+ WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale);
+
+ WINRT_PROPERTY(bool, RetroTerminalEffect, false);
+ WINRT_PROPERTY(bool, ForceFullRepaintRendering, false);
+ WINRT_PROPERTY(bool, SoftwareRendering, false);
+ WINRT_PROPERTY(bool, ForceVTInput, false);
+
+ WINRT_PROPERTY(winrt::hstring, PixelShaderPath);
+
+ WINRT_PROPERTY(bool, DetectURLs, true);
+
+ private:
+ std::array _ColorTable;
+
+ public:
+ winrt::Microsoft::Terminal::Core::Color GetColorTableEntry(int32_t index) noexcept { return _ColorTable.at(index); }
+ std::array ColorTable() { return _ColorTable; }
+ void ColorTable(std::array /*colors*/) {}
+ };
+}
+
+namespace winrt::SampleApp::factory_implementation
+{
+ BASIC_FACTORY(MySettings);
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/MySettings.idl b/scratch/ScratchIslandApp/SampleApp/MySettings.idl
new file mode 100644
index 000000000..42422b21a
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/MySettings.idl
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+namespace SampleApp
+{
+ [default_interface] runtimeclass MySettings : Microsoft.Terminal.Core.ICoreSettings,
+ Microsoft.Terminal.Control.IControlSettings,
+ Microsoft.Terminal.Core.ICoreAppearance,
+ Microsoft.Terminal.Control.IControlAppearance
+
+ {
+ MySettings();
+ }
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/Resources/en-US/Resources.resw b/scratch/ScratchIslandApp/SampleApp/Resources/en-US/Resources.resw
new file mode 100644
index 000000000..f4af46df5
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/Resources/en-US/Resources.resw
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
diff --git a/scratch/ScratchIslandApp/SampleApp/SampleAppLib.vcxproj b/scratch/ScratchIslandApp/SampleApp/SampleAppLib.vcxproj
new file mode 100644
index 000000000..c16d6be6f
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/SampleAppLib.vcxproj
@@ -0,0 +1,181 @@
+
+
+
+ {a4394404-37f7-41c1-802b-49788d3720e3}
+ Win32Proj
+ SampleApp
+ SampleAppLib
+ SampleAppLib
+ StaticLibrary
+ Console
+ true
+
+ false
+ nested
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+ MyPage.xaml
+ Code
+
+
+ App.xaml
+
+
+ SampleAppLogic.idl
+
+
+
+
+
+
+
+ MyPage.xaml
+ Code
+
+
+ Create
+
+
+ App.xaml
+
+
+ SampleAppLogic.idl
+
+
+
+
+
+
+
+
+ App.xaml
+
+
+
+
+ MyPage.xaml
+ Code
+
+
+
+
+
+
+
+
+
+
+
+ Warning
+
+
+
+
+
+ $(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd
+ true
+ false
+ false
+
+
+ $(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd
+ true
+ false
+ false
+
+
+ $(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd
+ true
+ false
+ false
+
+
+
+
+
+ pch.h
+ ..;%(AdditionalIncludeDirectories);
+
+ 4702;%(DisableSpecificWarnings)
+
+
+ $(OpenConsoleCommonOutDir)\ConTypes.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+ 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}.
+
+
+
+
+
+
+
+ <_GenerateProjectPriFileDependsOn>OpenConsolePlaceAppXbfAtRootOfResourceTree;$(_GenerateProjectPriFileDependsOn)
+
+
+
+ <_RelocatedAppXamlData Include="@(PackagingOutputs)" Condition="'%(Filename)' == 'App' and ('%(Extension)' == '.xaml' or '%(Extension)' == '.xbf')" />
+
+
+ %(Filename)%(Extension)
+
+
+
+
+
+
diff --git a/scratch/ScratchIslandApp/SampleApp/SampleAppLogic.cpp b/scratch/ScratchIslandApp/SampleApp/SampleAppLogic.cpp
new file mode 100644
index 000000000..4498f70df
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/SampleAppLogic.cpp
@@ -0,0 +1,84 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+#include "SampleAppLogic.h"
+#include "SampleAppLogic.g.cpp"
+
+#include
+
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Controls;
+using namespace winrt::Windows::UI::Core;
+using namespace winrt::Windows::System;
+
+namespace winrt
+{
+ namespace MUX = Microsoft::UI::Xaml;
+ using IInspectable = Windows::Foundation::IInspectable;
+}
+
+namespace winrt::SampleApp::implementation
+{
+ // Function Description:
+ // - Get the SampleAppLogic for the current active Xaml application, or null if there isn't one.
+ // Return value:
+ // - A pointer (bare) to the SampleAppLogic, or nullptr. The app logic outlives all other objects,
+ // unless the application is in a terrible way, so this is "safe."
+ SampleAppLogic* SampleAppLogic::Current() noexcept
+ try
+ {
+ if (auto currentXamlApp{ winrt::Windows::UI::Xaml::Application::Current().try_as() })
+ {
+ if (auto SampleAppLogicPointer{ winrt::get_self(currentXamlApp.Logic()) })
+ {
+ return SampleAppLogicPointer;
+ }
+ }
+ return nullptr;
+ }
+ catch (...)
+ {
+ LOG_CAUGHT_EXCEPTION();
+ return nullptr;
+ }
+
+ SampleAppLogic::SampleAppLogic()
+ {
+ // For your own sanity, it's better to do setup outside the ctor.
+ // If you do any setup in the ctor that ends up throwing an exception,
+ // then it might look like App just failed to activate, which will
+ // cause you to chase down the rabbit hole of "why is App not
+ // registered?" when it definitely is.
+
+ // The MyPage has to be constructed during our construction, to
+ // make sure that there's a terminal page for callers of
+ // SetTitleBarContent
+ _root = winrt::make_self();
+ }
+
+ // Method Description:
+ // - Build the UI for the terminal app. Before this method is called, it
+ // should not be assumed that the SampleApp is usable. The Settings
+ // should be loaded before this is called, either with LoadSettings or
+ // GetLaunchDimensions (which will call LoadSettings)
+ // Arguments:
+ // -
+ // Return Value:
+ // -
+ void SampleAppLogic::Create()
+ {
+ _root->Create();
+ }
+
+ UIElement SampleAppLogic::GetRoot() noexcept
+ {
+ return _root.as();
+ }
+
+ hstring SampleAppLogic::Title()
+ {
+ return _root->Title();
+ }
+
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/SampleAppLogic.h b/scratch/ScratchIslandApp/SampleApp/SampleAppLogic.h
new file mode 100644
index 000000000..8b8642a8e
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/SampleAppLogic.h
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#pragma once
+
+#include "SampleAppLogic.g.h"
+#include "MyPage.h"
+#include "../../../src/cascadia/inc/cppwinrt_utils.h"
+
+namespace winrt::SampleApp::implementation
+{
+ struct SampleAppLogic : SampleAppLogicT
+ {
+ public:
+ static SampleAppLogic* Current() noexcept;
+
+ SampleAppLogic();
+ ~SampleAppLogic() = default;
+
+ void Create();
+
+ Windows::UI::Xaml::UIElement GetRoot() noexcept;
+
+ winrt::hstring Title();
+
+ private:
+ // If you add controls here, but forget to null them either here or in
+ // the ctor, you're going to have a bad time. It'll mysteriously fail to
+ // activate the SampleAppLogic.
+ // ALSO: If you add any UIElements as roots here, make sure they're
+ // updated in _ApplyTheme. The root currently is _root.
+ winrt::com_ptr _root{ nullptr };
+ };
+}
+
+namespace winrt::SampleApp::factory_implementation
+{
+ struct SampleAppLogic : SampleAppLogicT
+ {
+ };
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/SampleAppLogic.idl b/scratch/ScratchIslandApp/SampleApp/SampleAppLogic.idl
new file mode 100644
index 000000000..9b7d49e1a
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/SampleAppLogic.idl
@@ -0,0 +1,19 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+
+namespace SampleApp
+{
+
+ [default_interface] runtimeclass SampleAppLogic
+ {
+ SampleAppLogic();
+
+ void Create();
+
+ Windows.UI.Xaml.UIElement GetRoot();
+
+ String Title { get; };
+
+ }
+}
diff --git a/scratch/ScratchIslandApp/SampleApp/dll/SampleApp.def b/scratch/ScratchIslandApp/SampleApp/dll/SampleApp.def
new file mode 100644
index 000000000..8c1a02932
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/dll/SampleApp.def
@@ -0,0 +1,3 @@
+EXPORTS
+DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
+DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
diff --git a/scratch/ScratchIslandApp/SampleApp/dll/SampleApp.vcxproj b/scratch/ScratchIslandApp/SampleApp/dll/SampleApp.vcxproj
new file mode 100644
index 000000000..1b1961fac
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/dll/SampleApp.vcxproj
@@ -0,0 +1,101 @@
+
+
+
+ {26c51792-41a3-4fe0-ab5e-8b69d557bf91}
+ SampleApp
+ SampleApp
+
+
+ DynamicLibrary
+ Console
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+
+
+
+ $(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd
+ true
+ false
+ false
+
+
+ $(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd
+ true
+ false
+ false
+
+
+ $(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd
+ true
+ false
+ false
+
+
+
+
+
+
+
+
+ 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}.
+
+
+
+
+
+
+
+ $(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories);
+
+
+ WindowsApp.lib;%(AdditionalDependencies)
+
+ /INCLUDE:_DllMain@12 %(AdditionalOptions)
+ /INCLUDE:DllMain %(AdditionalOptions)
+
+
+
+
diff --git a/scratch/ScratchIslandApp/SampleApp/dll/pch.cpp b/scratch/ScratchIslandApp/SampleApp/dll/pch.cpp
new file mode 100644
index 000000000..3c27d44d5
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/dll/pch.cpp
@@ -0,0 +1,4 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
diff --git a/scratch/ScratchIslandApp/SampleApp/dll/pch.h b/scratch/ScratchIslandApp/SampleApp/dll/pch.h
new file mode 100644
index 000000000..76004c88f
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/dll/pch.h
@@ -0,0 +1,12 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+//
+// pch.h
+// Header for platform projection include files
+//
+
+#pragma once
+
+// This file can be empty - the pch.h in SampleApp/lib does the heavy lifting
+// of including all the headers we need. As this project is just a dll wrapper,
+// we don't actually need anything in here.
diff --git a/scratch/ScratchIslandApp/SampleApp/init.cpp b/scratch/ScratchIslandApp/SampleApp/init.cpp
new file mode 100644
index 000000000..1c169d9d9
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/init.cpp
@@ -0,0 +1,13 @@
+// Copyright (c) Microsoft Corporation
+// Licensed under the MIT license.
+
+#include "pch.h"
+#include
+#include
+
+BOOL WINAPI DllMain(HINSTANCE /*hInstDll*/, DWORD /*reason*/, LPVOID /*reserved*/)
+{
+ return TRUE;
+}
+
+UTILS_DEFINE_LIBRARY_RESOURCE_SCOPE(L"SampleApp/Resources")
diff --git a/scratch/ScratchIslandApp/SampleApp/packages.config b/scratch/ScratchIslandApp/SampleApp/packages.config
new file mode 100644
index 000000000..a6c68340a
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/scratch/ScratchIslandApp/SampleApp/pch.cpp b/scratch/ScratchIslandApp/SampleApp/pch.cpp
new file mode 100644
index 000000000..3c27d44d5
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/pch.cpp
@@ -0,0 +1,4 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
diff --git a/scratch/ScratchIslandApp/SampleApp/pch.h b/scratch/ScratchIslandApp/SampleApp/pch.h
new file mode 100644
index 000000000..fd9d893f9
--- /dev/null
+++ b/scratch/ScratchIslandApp/SampleApp/pch.h
@@ -0,0 +1,71 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+//
+// pch.h
+// Header for platform projection include files
+//
+
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN
+#define NOMCX
+#define NOHELP
+#define NOCOMM
+
+// Manually include til after we include Windows.Foundation to give it winrt superpowers
+#define BLOCK_TIL
+#include
+// This is inexplicable, but for whatever reason, cppwinrt conflicts with the
+// SDK definition of this function, so the only fix is to undef it.
+// from WinBase.h
+// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime
+#ifdef GetCurrentTime
+#undef GetCurrentTime
+#endif
+
+#include
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "winrt/Windows.UI.Xaml.Markup.h"
+#include "winrt/Windows.UI.ViewManagement.h"
+
+#include
+#include
+#include
+#include
+
+#include
+
+// Including TraceLogging essentials for the binary
+#include
+#include
+TRACELOGGING_DECLARE_PROVIDER(g_hSampleAppProvider);
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+// Manually include til after we include Windows.Foundation to give it winrt superpowers
+#include "til.h"
diff --git a/scratch/ScratchIslandApp/WindowExe/SampleAppHost.cpp b/scratch/ScratchIslandApp/WindowExe/SampleAppHost.cpp
new file mode 100644
index 000000000..2d3afefc5
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/SampleAppHost.cpp
@@ -0,0 +1,78 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+#include "SampleAppHost.h"
+#include "../types/inc/Viewport.hpp"
+#include "../types/inc/utils.hpp"
+#include "../types/inc/User32Utils.hpp"
+#include "resource.h"
+
+using namespace winrt::Windows::UI;
+using namespace winrt::Windows::UI::Composition;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Hosting;
+using namespace winrt::Windows::Foundation::Numerics;
+using namespace ::Microsoft::Console;
+using namespace ::Microsoft::Console::Types;
+
+SampleAppHost::SampleAppHost() noexcept :
+ _app{},
+ _logic{ nullptr }, // don't make one, we're going to take a ref on app's
+ _window{ nullptr }
+{
+ _logic = _app.Logic(); // get a ref to app's logic
+
+ _window = std::make_unique();
+ _window->MakeWindow();
+}
+
+SampleAppHost::~SampleAppHost()
+{
+ // destruction order is important for proper teardown here
+ _window = nullptr;
+ _app.Close();
+ _app = nullptr;
+}
+// Method Description:
+// - Initializes the XAML island, creates the terminal app, and sets the
+// island's content to that of the terminal app's content. Also registers some
+// callbacks with TermApp.
+// !!! IMPORTANT!!!
+// This must be called *AFTER* WindowsXamlManager::InitializeForCurrentThread.
+// If it isn't, then we won't be able to create the XAML island.
+// Arguments:
+// -
+// Return Value:
+// -
+void SampleAppHost::Initialize()
+{
+ _window->Initialize();
+
+ _logic.Create();
+
+ _window->UpdateTitle(_logic.Title());
+
+ // Set up the content of the application. If the app has a custom titlebar,
+ // set that content as well.
+ _window->SetContent(_logic.GetRoot());
+
+ _window->OnAppInitialized();
+
+ // THIS IS A HACK
+ //
+ // We've got a weird crash that happens terribly inconsistently, only in
+ // Debug mode. Apparently, there's some weird ref-counting magic that goes
+ // on during teardown, and our Application doesn't get closed quite right,
+ // which can cause us to crash into the debugger. This of course, only
+ // happens on exit, and happens somewhere in the XamlHost.dll code.
+ //
+ // Crazily, if we _manually leak the Application_ here, then the crash
+ // doesn't happen. This doesn't matter, because we really want the
+ // Application to live for _the entire lifetime of the process_, so the only
+ // time when this object would actually need to get cleaned up is _during
+ // exit_. So we can safely leak this Application object, and have it just
+ // get cleaned up normally when our process exits.
+ ::winrt::SampleApp::App a{ _app };
+ ::winrt::detach_abi(a);
+}
diff --git a/scratch/ScratchIslandApp/WindowExe/SampleAppHost.h b/scratch/ScratchIslandApp/WindowExe/SampleAppHost.h
new file mode 100644
index 000000000..226f90a4b
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/SampleAppHost.h
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+
+#include "SampleIslandWindow.h"
+
+class SampleAppHost
+{
+public:
+ SampleAppHost() noexcept;
+ virtual ~SampleAppHost();
+
+ void Initialize();
+
+private:
+ std::unique_ptr _window;
+ winrt::SampleApp::App _app;
+ winrt::SampleApp::SampleAppLogic _logic;
+};
diff --git a/scratch/ScratchIslandApp/WindowExe/SampleBaseWindow.h b/scratch/ScratchIslandApp/WindowExe/SampleBaseWindow.h
new file mode 100644
index 000000000..5c25452b3
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/SampleBaseWindow.h
@@ -0,0 +1,228 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#pragma once
+
+// Custom window messages
+#define CM_UPDATE_TITLE (WM_USER)
+
+#include
+
+template
+class BaseWindow
+{
+public:
+ virtual ~BaseWindow() = 0;
+ static T* GetThisFromHandle(HWND const window) noexcept
+ {
+ return reinterpret_cast(GetWindowLongPtr(window, GWLP_USERDATA));
+ }
+
+ [[nodiscard]] static LRESULT __stdcall WndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
+ {
+ WINRT_ASSERT(window);
+
+ if (WM_NCCREATE == message)
+ {
+ auto cs = reinterpret_cast(lparam);
+ T* that = static_cast(cs->lpCreateParams);
+ WINRT_ASSERT(that);
+ WINRT_ASSERT(!that->_window);
+ that->_window = wil::unique_hwnd(window);
+
+ return that->_OnNcCreate(wparam, lparam);
+ }
+ else if (T* that = GetThisFromHandle(window))
+ {
+ return that->MessageHandler(message, wparam, lparam);
+ }
+
+ return DefWindowProc(window, message, wparam, lparam);
+ }
+
+ [[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
+ {
+ switch (message)
+ {
+ case WM_DPICHANGED:
+ {
+ return HandleDpiChange(_window.get(), wparam, lparam);
+ }
+
+ case WM_DESTROY:
+ {
+ PostQuitMessage(0);
+ return 0;
+ }
+
+ case WM_SIZE:
+ {
+ UINT width = LOWORD(lparam);
+ UINT height = HIWORD(lparam);
+
+ switch (wparam)
+ {
+ case SIZE_MAXIMIZED:
+ [[fallthrough]];
+ case SIZE_RESTORED:
+ if (_minimized)
+ {
+ _minimized = false;
+ OnRestore();
+ }
+
+ // We always need to fire the resize event, even when we're transitioning from minimized.
+ // We might be transitioning directly from minimized to maximized, and we'll need
+ // to trigger any size-related content changes.
+ OnResize(width, height);
+ break;
+ case SIZE_MINIMIZED:
+ if (!_minimized)
+ {
+ _minimized = true;
+ OnMinimize();
+ }
+ break;
+ default:
+ // do nothing.
+ break;
+ }
+ break;
+ }
+ case CM_UPDATE_TITLE:
+ {
+ SetWindowTextW(_window.get(), _title.c_str());
+ break;
+ }
+ }
+
+ return DefWindowProc(_window.get(), message, wparam, lparam);
+ }
+
+ // DPI Change handler. on WM_DPICHANGE resize the window
+ [[nodiscard]] LRESULT HandleDpiChange(const HWND hWnd, const WPARAM wParam, const LPARAM lParam)
+ {
+ _inDpiChange = true;
+ const HWND hWndStatic = GetWindow(hWnd, GW_CHILD);
+ if (hWndStatic != nullptr)
+ {
+ const UINT uDpi = HIWORD(wParam);
+
+ // Resize the window
+ auto lprcNewScale = reinterpret_cast(lParam);
+
+ SetWindowPos(hWnd, nullptr, lprcNewScale->left, lprcNewScale->top, lprcNewScale->right - lprcNewScale->left, lprcNewScale->bottom - lprcNewScale->top, SWP_NOZORDER | SWP_NOACTIVATE);
+
+ _currentDpi = uDpi;
+ }
+ _inDpiChange = false;
+ return 0;
+ }
+
+ virtual void OnResize(const UINT width, const UINT height) = 0;
+ virtual void OnMinimize() = 0;
+ virtual void OnRestore() = 0;
+
+ RECT GetWindowRect() const noexcept
+ {
+ RECT rc = { 0 };
+ ::GetWindowRect(_window.get(), &rc);
+ return rc;
+ }
+
+ HWND GetHandle() const noexcept
+ {
+ return _window.get();
+ }
+
+ float GetCurrentDpiScale() const noexcept
+ {
+ const auto dpi = ::GetDpiForWindow(_window.get());
+ const auto scale = static_cast(dpi) / static_cast(USER_DEFAULT_SCREEN_DPI);
+ return scale;
+ }
+
+ // Gets the physical size of the client area of the HWND in _window
+ SIZE GetPhysicalSize() const noexcept
+ {
+ RECT rect = {};
+ GetClientRect(_window.get(), &rect);
+ const auto windowsWidth = rect.right - rect.left;
+ const auto windowsHeight = rect.bottom - rect.top;
+ return SIZE{ windowsWidth, windowsHeight };
+ }
+
+ // Gets the logical (in DIPs) size of a physical size specified by the parameter physicalSize
+ // Remarks:
+ // XAML coordinate system is always in Display Independent Pixels (a.k.a DIPs or Logical). However Win32 GDI (because of legacy reasons)
+ // in DPI mode "Per-Monitor and Per-Monitor (V2) DPI Awareness" is always in physical pixels.
+ // The formula to transform is:
+ // logical = (physical / dpi) + 0.5 // 0.5 is to ensure that we pixel snap correctly at the edges, this is necessary with odd DPIs like 1.25, 1.5, 1, .75
+ // See also:
+ // https://docs.microsoft.com/en-us/windows/desktop/LearnWin32/dpi-and-device-independent-pixels
+ // https://docs.microsoft.com/en-us/windows/desktop/hidpi/high-dpi-desktop-application-development-on-windows#per-monitor-and-per-monitor-v2-dpi-awareness
+ winrt::Windows::Foundation::Size GetLogicalSize(const SIZE physicalSize) const noexcept
+ {
+ const auto scale = GetCurrentDpiScale();
+ // 0.5 is to ensure that we pixel snap correctly at the edges, this is necessary with odd DPIs like 1.25, 1.5, 1, .75
+ const auto logicalWidth = (physicalSize.cx / scale) + 0.5f;
+ const auto logicalHeight = (physicalSize.cy / scale) + 0.5f;
+ return winrt::Windows::Foundation::Size(logicalWidth, logicalHeight);
+ }
+
+ winrt::Windows::Foundation::Size GetLogicalSize() const noexcept
+ {
+ return GetLogicalSize(GetPhysicalSize());
+ }
+
+ // Method Description:
+ // - Sends a message to our message loop to update the title of the window.
+ // Arguments:
+ // - newTitle: a string to use as the new title of the window.
+ // Return Value:
+ // -
+ void UpdateTitle(std::wstring_view newTitle)
+ {
+ _title = newTitle;
+ PostMessageW(_window.get(), CM_UPDATE_TITLE, 0, reinterpret_cast(nullptr));
+ }
+
+ // Method Description:
+ // Reset the current dpi of the window. This method is only called after we change the
+ // initial launch position. This makes sure the dpi is consistent with the monitor on which
+ // the window will launch
+ void RefreshCurrentDPI()
+ {
+ _currentDpi = GetDpiForWindow(_window.get());
+ }
+
+protected:
+ using base_type = BaseWindow;
+ wil::unique_hwnd _window;
+
+ unsigned int _currentDpi = 0;
+ bool _inDpiChange = false;
+
+ std::wstring _title = L"";
+
+ bool _minimized = false;
+
+ // Method Description:
+ // - This method is called when the window receives the WM_NCCREATE message.
+ // Return Value:
+ // - The value returned from the window proc.
+ virtual [[nodiscard]] LRESULT _OnNcCreate(WPARAM wParam, LPARAM lParam) noexcept
+ {
+ SetWindowLongPtr(_window.get(), GWLP_USERDATA, reinterpret_cast(this));
+
+ EnableNonClientDpiScaling(_window.get());
+ _currentDpi = GetDpiForWindow(_window.get());
+
+ return DefWindowProc(_window.get(), WM_NCCREATE, wParam, lParam);
+ };
+};
+
+template
+inline BaseWindow::~BaseWindow()
+{
+}
diff --git a/scratch/ScratchIslandApp/WindowExe/SampleIslandWindow.cpp b/scratch/ScratchIslandApp/WindowExe/SampleIslandWindow.cpp
new file mode 100644
index 000000000..1c5cf10d0
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/SampleIslandWindow.cpp
@@ -0,0 +1,220 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+#include "SampleIslandWindow.h"
+#include "../types/inc/Viewport.hpp"
+#include "resource.h"
+#include "icon.h"
+
+extern "C" IMAGE_DOS_HEADER __ImageBase;
+
+using namespace winrt::Windows::UI;
+using namespace winrt::Windows::UI::Composition;
+using namespace winrt::Windows::UI::Xaml;
+using namespace winrt::Windows::UI::Xaml::Hosting;
+using namespace winrt::Windows::Foundation::Numerics;
+using namespace ::Microsoft::Console::Types;
+
+#define XAML_HOSTING_WINDOW_CLASS_NAME L"SCRATCH_HOSTING_WINDOW_CLASS"
+
+SampleIslandWindow::SampleIslandWindow() noexcept :
+ _interopWindowHandle{ nullptr },
+ _rootGrid{ nullptr },
+ _source{ nullptr }
+{
+}
+
+SampleIslandWindow::~SampleIslandWindow()
+{
+ _source.Close();
+}
+
+// Method Description:
+// - Create the actual window that we'll use for the application.
+// Arguments:
+// -
+// Return Value:
+// -
+void SampleIslandWindow::MakeWindow() noexcept
+{
+ WNDCLASS wc{};
+ wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ wc.hInstance = reinterpret_cast(&__ImageBase);
+ wc.lpszClassName = XAML_HOSTING_WINDOW_CLASS_NAME;
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = WndProc;
+ wc.hIcon = LoadIconW(wc.hInstance, MAKEINTRESOURCEW(IDI_APPICON));
+ RegisterClass(&wc);
+ WINRT_ASSERT(!_window);
+
+ // Create the window with the default size here - During the creation of the
+ // window, the system will give us a chance to set its size in WM_CREATE.
+ // WM_CREATE will be handled synchronously, before CreateWindow returns.
+ WINRT_VERIFY(CreateWindowEx(0,
+ wc.lpszClassName,
+ L"ScratchApp",
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ nullptr,
+ nullptr,
+ wc.hInstance,
+ this));
+
+ WINRT_ASSERT(_window);
+}
+
+// Method Description:
+// - Called when no tab is remaining to close the window.
+// Arguments:
+// -
+// Return Value:
+// -
+void SampleIslandWindow::Close()
+{
+ PostQuitMessage(0);
+}
+
+// Method Description:
+// - Handles a WM_CREATE message. Calls our create callback, if one's been set.
+// Arguments:
+// - wParam: unused
+// - lParam: the lParam of a WM_CREATE, which is a pointer to a CREATESTRUCTW
+// Return Value:
+// -
+void SampleIslandWindow::_HandleCreateWindow(const WPARAM, const LPARAM lParam) noexcept
+{
+ // Get proposed window rect from create structure
+ CREATESTRUCTW* pcs = reinterpret_cast(lParam);
+ RECT rc;
+ rc.left = pcs->x;
+ rc.top = pcs->y;
+ rc.right = rc.left + pcs->cx;
+ rc.bottom = rc.top + pcs->cy;
+
+ ShowWindow(_window.get(), SW_SHOW);
+
+ UpdateWindow(_window.get());
+
+ UpdateWindowIconForActiveMetrics(_window.get());
+}
+
+void SampleIslandWindow::Initialize()
+{
+ const bool initialized = (_interopWindowHandle != nullptr);
+
+ _source = DesktopWindowXamlSource{};
+
+ auto interop = _source.as();
+ winrt::check_hresult(interop->AttachToWindow(_window.get()));
+
+ // stash the child interop handle so we can resize it when the main hwnd is resized
+ interop->get_WindowHandle(&_interopWindowHandle);
+
+ _rootGrid = winrt::Windows::UI::Xaml::Controls::Grid();
+ _source.Content(_rootGrid);
+}
+
+void SampleIslandWindow::OnSize(const UINT width, const UINT height)
+{
+ // update the interop window size
+ SetWindowPos(_interopWindowHandle, nullptr, 0, 0, width, height, SWP_SHOWWINDOW | SWP_NOACTIVATE);
+
+ if (_rootGrid)
+ {
+ const auto size = GetLogicalSize();
+ _rootGrid.Width(size.Width);
+ _rootGrid.Height(size.Height);
+ }
+}
+
+[[nodiscard]] LRESULT SampleIslandWindow::MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept
+{
+ switch (message)
+ {
+ case WM_CREATE:
+ {
+ _HandleCreateWindow(wparam, lparam);
+ return 0;
+ }
+ case WM_SETFOCUS:
+ {
+ if (_interopWindowHandle != nullptr)
+ {
+ // send focus to the child window
+ SetFocus(_interopWindowHandle);
+ return 0;
+ }
+ break;
+ }
+ case WM_MENUCHAR:
+ {
+ // GH#891: return this LRESULT here to prevent the app from making a
+ // bell when alt+key is pressed. A menu is active and the user presses a
+ // key that does not correspond to any mnemonic or accelerator key,
+ return MAKELRESULT(0, MNC_CLOSE);
+ }
+ case WM_THEMECHANGED:
+ UpdateWindowIconForActiveMetrics(_window.get());
+ return 0;
+ }
+
+ return base_type::MessageHandler(message, wparam, lparam);
+}
+
+// Method Description:
+// - Called when the window has been resized (or maximized)
+// Arguments:
+// - width: the new width of the window _in pixels_
+// - height: the new height of the window _in pixels_
+void SampleIslandWindow::OnResize(const UINT width, const UINT height)
+{
+ if (_interopWindowHandle)
+ {
+ OnSize(width, height);
+ }
+}
+
+// Method Description:
+// - Called when the window is minimized to the taskbar.
+void SampleIslandWindow::OnMinimize()
+{
+}
+
+// Method Description:
+// - Called when the window is restored from having been minimized.
+void SampleIslandWindow::OnRestore()
+{
+}
+
+void SampleIslandWindow::SetContent(winrt::Windows::UI::Xaml::UIElement content)
+{
+ _rootGrid.Children().Clear();
+ _rootGrid.Children().Append(content);
+}
+
+void SampleIslandWindow::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:
+// -
+void SampleIslandWindow::OnApplicationThemeChanged(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);
+}
diff --git a/scratch/ScratchIslandApp/WindowExe/SampleIslandWindow.h b/scratch/ScratchIslandApp/WindowExe/SampleIslandWindow.h
new file mode 100644
index 000000000..14a62f13c
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/SampleIslandWindow.h
@@ -0,0 +1,45 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+#include "SampleBaseWindow.h"
+#include "../../../src/cascadia/inc/cppwinrt_utils.h"
+
+class SampleIslandWindow :
+ public BaseWindow
+{
+public:
+ SampleIslandWindow() noexcept;
+ virtual ~SampleIslandWindow() override;
+
+ virtual void MakeWindow() noexcept;
+ void Close();
+
+ virtual void OnSize(const UINT width, const UINT height);
+
+ [[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override;
+ 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 OnApplicationThemeChanged(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme);
+
+ virtual void Initialize();
+
+protected:
+ void ForceResize()
+ {
+ // Do a quick resize to force the island to paint
+ const auto size = GetPhysicalSize();
+ OnSize(size.cx, size.cy);
+ }
+
+ HWND _interopWindowHandle;
+
+ winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource _source;
+
+ winrt::Windows::UI::Xaml::Controls::Grid _rootGrid;
+
+ void _HandleCreateWindow(const WPARAM wParam, const LPARAM lParam) noexcept;
+};
diff --git a/scratch/ScratchIslandApp/WindowExe/SampleMain.cpp b/scratch/ScratchIslandApp/WindowExe/SampleMain.cpp
new file mode 100644
index 000000000..4c09f262c
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/SampleMain.cpp
@@ -0,0 +1,122 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+#include "SampleAppHost.h"
+#include "resource.h"
+#include "../types/inc/User32Utils.hpp"
+#include
+
+using namespace winrt;
+using namespace winrt::Windows::UI;
+using namespace winrt::Windows::UI::Composition;
+using namespace winrt::Windows::UI::Xaml::Hosting;
+using namespace winrt::Windows::Foundation::Numerics;
+
+// Routine Description:
+// - Takes an image architecture and locates a string resource that maps to that architecture.
+// Arguments:
+// - imageArchitecture - An IMAGE_FILE_MACHINE architecture enum value
+// - See https://docs.microsoft.com/en-us/windows/win32/sysinfo/image-file-machine-constants
+// Return Value:
+// - A string value representing the human-readable name of this architecture.
+static std::wstring ImageArchitectureToString(USHORT imageArchitecture)
+{
+ // clang-format off
+ const auto id = imageArchitecture == IMAGE_FILE_MACHINE_I386 ? IDS_X86_ARCHITECTURE :
+ imageArchitecture == IMAGE_FILE_MACHINE_AMD64 ? IDS_AMD64_ARCHITECTURE :
+ imageArchitecture == IMAGE_FILE_MACHINE_ARM64 ? IDS_ARM64_ARCHITECTURE :
+ imageArchitecture == IMAGE_FILE_MACHINE_ARM ? IDS_ARM_ARCHITECTURE :
+ IDS_UNKNOWN_ARCHITECTURE;
+ // clang-format on
+
+ return GetStringResource(id);
+}
+
+// Routine Description:
+// - Blocks the user from launching the application with a message box dialog and early exit
+// if the process architecture doesn't match the system platform native architecture.
+// - This is because the conhost.exe must match the condrv.sys on the system and the PTY
+// infrastructure that powers everything won't work if we have a mismatch.
+// Arguments:
+// -
+// Return Value:
+// -
+static void EnsureNativeArchitecture()
+{
+ USHORT processMachine{};
+ USHORT nativeMachine{};
+ THROW_IF_WIN32_BOOL_FALSE(IsWow64Process2(GetCurrentProcess(), &processMachine, &nativeMachine));
+ if (processMachine != IMAGE_FILE_MACHINE_UNKNOWN && processMachine != nativeMachine)
+ {
+ const auto formatPattern = GetStringResource(IDS_ERROR_ARCHITECTURE_FORMAT);
+
+ const auto nativeArchitecture = ImageArchitectureToString(nativeMachine);
+ const auto processArchitecture = ImageArchitectureToString(processMachine);
+
+ auto buffer{ wil::str_printf(formatPattern.data(), nativeArchitecture.data(), processArchitecture.data()) };
+
+ MessageBoxW(nullptr,
+ buffer.data(),
+ GetStringResource(IDS_ERROR_DIALOG_TITLE).data(),
+ MB_OK | MB_ICONERROR);
+
+ ExitProcess(0);
+ }
+}
+
+static bool _messageIsF7Keypress(const MSG& message)
+{
+ return (message.message == WM_KEYDOWN || message.message == WM_SYSKEYDOWN) && message.wParam == VK_F7;
+}
+static bool _messageIsAltKeyup(const MSG& message)
+{
+ return (message.message == WM_KEYUP || message.message == WM_SYSKEYUP) && message.wParam == VK_MENU;
+}
+
+int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
+{
+ // If Terminal is spawned by a shortcut that requests that it run in a new process group
+ // while attached to a console session, that request is nonsense. That request will, however,
+ // cause WT to start with Ctrl-C disabled. This wouldn't matter, because it's a Windows-subsystem
+ // application. Unfortunately, that state is heritable. In short, if you start WT using cmd in
+ // a weird way, ^C stops working _inside_ the terminal. Mad.
+ SetConsoleCtrlHandler(NULL, FALSE);
+
+ // Block the user from starting if they launched the incorrect architecture version of the project.
+ // This should only be applicable to developer versions. The package installation process
+ // should choose and install the correct one from the bundle.
+ EnsureNativeArchitecture();
+
+ // Make sure to call this so we get WM_POINTER messages.
+ EnableMouseInPointer(true);
+
+ // !!! LOAD BEARING !!!
+ // We must initialize the main thread as a single-threaded apartment before
+ // constructing any Xaml objects. Failing to do so will cause some issues
+ // in accessibility somewhere down the line when a UIAutomation object will
+ // be queried on the wrong thread at the wrong time.
+ // We used to initialize as STA only _after_ initializing the application
+ // host, which loaded the settings. The settings needed to be loaded in MTA
+ // because we were using the Windows.Storage APIs. Since we're no longer
+ // doing that, we can safely init as STA before any WinRT dispatches.
+ winrt::init_apartment(winrt::apartment_type::single_threaded);
+
+ // Create the SampleAppHost object, which will create both the window and the
+ // Terminal App. This MUST BE constructed before the Xaml manager as TermApp
+ // provides an implementation of Windows.UI.Xaml.Application.
+ SampleAppHost host;
+
+ // Initialize the xaml content. This must be called AFTER the
+ // WindowsXamlManager is initialized.
+ host.Initialize();
+
+ MSG message;
+
+ while (GetMessage(&message, nullptr, 0, 0))
+ {
+ TranslateMessage(&message);
+ DispatchMessage(&message);
+ }
+ return 0;
+}
diff --git a/scratch/ScratchIslandApp/WindowExe/WindowExe.def b/scratch/ScratchIslandApp/WindowExe/WindowExe.def
new file mode 100644
index 000000000..5f282702b
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/WindowExe.def
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/scratch/ScratchIslandApp/WindowExe/WindowExe.manifest b/scratch/ScratchIslandApp/WindowExe/WindowExe.manifest
new file mode 100644
index 000000000..9d91e543d
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/WindowExe.manifest
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PerMonitorV2
+ true
+
+
+
diff --git a/scratch/ScratchIslandApp/WindowExe/WindowExe.rc b/scratch/ScratchIslandApp/WindowExe/WindowExe.rc
new file mode 100644
index 000000000..b11a8c88d
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/WindowExe.rc
@@ -0,0 +1,97 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+
+IDI_APPICON ICON "..\\..\\..\\res\\terminal.ico"
+IDI_APPICON_HC_BLACK ICON "..\\..\\..\\res\\terminal\\images\\terminal_contrast-black.ico"
+IDI_APPICON_HC_WHITE ICON "..\\..\\..\\res\\terminal\\images\\terminal_contrast-white.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_ERROR_DIALOG_TITLE "Error"
+ IDS_HELP_DIALOG_TITLE "Help"
+ IDS_ERROR_ARCHITECTURE_FORMAT
+ "This sample is designed to run on your system's native architecture (%s).\nYou are currently using the %s version.\n\nPlease use the version of this sample that matches your system's native architecture."
+ IDS_X86_ARCHITECTURE "i386"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_AMD64_ARCHITECTURE "AMD64"
+ IDS_ARM64_ARCHITECTURE "ARM64"
+ IDS_ARM_ARCHITECTURE "ARM"
+ IDS_UNKNOWN_ARCHITECTURE "Unknown"
+END
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/scratch/ScratchIslandApp/WindowExe/WindowExe.vcxproj b/scratch/ScratchIslandApp/WindowExe/WindowExe.vcxproj
new file mode 100644
index 000000000..edd372c2f
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/WindowExe.vcxproj
@@ -0,0 +1,220 @@
+
+
+
+
+
+ {b4427499-9fde-4208-b456-5bc580637633}
+ Win32Proj
+ WindowExe
+ WindowExe
+ WindowExe
+ Application
+ false
+ Windows Store
+ true
+ false
+ Windows
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+ $(OpenConsoleDir)\src\inc;$(OpenConsoleDir)\dep;$(OpenConsoleDir)\dep\Console;$(OpenConsoleDir)\dep\Win32K;$(OpenConsoleDir)\dep\gsl\include;%(AdditionalIncludeDirectories);
+
+
+ %(AdditionalDependencies)
+
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(OpenConsoleCommonOutDir)TerminalCore\Microsoft.Terminal.Core.winmd
+ true
+ true
+ true
+
+
+ $(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd
+ $(OpenConsoleCommonOutDir)TerminalConnection\TerminalConnection.dll
+ true
+ true
+ true
+
+
+ $(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.winmd
+ $(OpenConsoleCommonOutDir)Microsoft.Terminal.Control\Microsoft.Terminal.Control.dll
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+ WindowsLocalDebugger
+
+
+
+
+
+
+
+
+
+ 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}.
+
+
+
+
+
+
+
+
+
+ <_ContinueOnError Condition="'$(BuildingProject)' == 'true'">true
+ <_ContinueOnError Condition="'$(BuildingProject)' != 'true'">false
+
+
+
+
+
+
+
+
+
+
+
+
+ x86
+ $(Platform)
+
+
+
+
+ <_OpenConsoleVCLibToCopy Include="$(VCToolsRedistInstallDir)\$(ReasonablePlatform)\Microsoft.VC142.CRT\*.dll" />
+
+
+ $(ProjectName)
+ BuiltProjectOutputGroup
+ %(Filename)%(Extension)
+
+
+
+
+
+
+
+
+ <_TerminalConnectionDlls Include="$(OpenConsoleCommonOutDir)\TerminalConnection\*.dll" />
+
+
+ $(ProjectName)
+ BuiltProjectOutputGroup
+ %(Filename)%(Extension)
+
+
+
+
+
+
+ <_WindowsTerminalExe Include="$(OpenConsoleCommonOutDir)\WindowsTerminal\*.exe" />
+
+
+ $(ProjectName)
+ BuiltProjectOutputGroup
+ %(Filename)%(Extension)
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/scratch/ScratchIslandApp/WindowExe/icon.cpp b/scratch/ScratchIslandApp/WindowExe/icon.cpp
new file mode 100644
index 000000000..ca194de06
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/icon.cpp
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
+#include "resource.h"
+
+static int _GetActiveAppIconResource()
+{
+ auto iconResource{ IDI_APPICON };
+
+ HIGHCONTRASTW hcInfo{};
+ hcInfo.cbSize = sizeof(hcInfo);
+
+ if (SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(hcInfo), &hcInfo, 0))
+ {
+ if (WI_IsFlagSet(hcInfo.dwFlags, HCF_HIGHCONTRASTON))
+ {
+ iconResource = IDI_APPICON_HC_BLACK;
+
+ if (0x00FFFFFF == GetSysColor(COLOR_WINDOW)) // white window color == white high contrast
+ {
+ iconResource = IDI_APPICON_HC_WHITE;
+ }
+ }
+ }
+
+ return iconResource;
+}
+
+void UpdateWindowIconForActiveMetrics(HWND window)
+{
+ auto iconResource{ MAKEINTRESOURCEW(_GetActiveAppIconResource()) };
+
+ // These handles are loaded with LR_SHARED, so they are safe to "leak".
+ HANDLE smallIcon{ LoadImageW(wil::GetModuleInstanceHandle(), iconResource, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED) };
+ LOG_LAST_ERROR_IF_NULL(smallIcon);
+
+ HANDLE largeIcon{ LoadImageW(wil::GetModuleInstanceHandle(), iconResource, IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_SHARED) };
+ LOG_LAST_ERROR_IF_NULL(largeIcon);
+
+ if (smallIcon)
+ {
+ SendMessageW(window, WM_SETICON, ICON_SMALL, reinterpret_cast(smallIcon));
+ }
+ if (largeIcon)
+ {
+ SendMessageW(window, WM_SETICON, ICON_BIG, reinterpret_cast(largeIcon));
+ }
+}
diff --git a/scratch/ScratchIslandApp/WindowExe/icon.h b/scratch/ScratchIslandApp/WindowExe/icon.h
new file mode 100644
index 000000000..5e418fc28
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/icon.h
@@ -0,0 +1,6 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#pragma once
+
+void UpdateWindowIconForActiveMetrics(HWND window);
diff --git a/scratch/ScratchIslandApp/WindowExe/packages.config b/scratch/ScratchIslandApp/WindowExe/packages.config
new file mode 100644
index 000000000..409baff13
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/scratch/ScratchIslandApp/WindowExe/pch.cpp b/scratch/ScratchIslandApp/WindowExe/pch.cpp
new file mode 100644
index 000000000..398a99f66
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/pch.cpp
@@ -0,0 +1,4 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+#include "pch.h"
diff --git a/scratch/ScratchIslandApp/WindowExe/pch.h b/scratch/ScratchIslandApp/WindowExe/pch.h
new file mode 100644
index 000000000..de08907f8
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/pch.h
@@ -0,0 +1,82 @@
+/*++
+Copyright (c) Microsoft Corporation
+Licensed under the MIT license.
+
+Module Name:
+- pch.h
+
+Abstract:
+- Contains external headers to include in the precompile phase of console build process.
+- Avoid including internal project headers. Instead include them only in the classes that need them (helps with test project building).
+--*/
+
+#pragma once
+
+// Ignore checked iterators warning from VC compiler.
+#define _SCL_SECURE_NO_WARNINGS
+
+// Block minwindef.h min/max macros to prevent conflict
+#define NOMINMAX
+
+#define WIN32_LEAN_AND_MEAN
+#define NOMCX
+#define NOHELP
+#define NOCOMM
+
+#include
+
+#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Manually include til after we include Windows.Foundation to give it winrt superpowers
+#define BLOCK_TIL
+#include "../inc/LibraryIncludes.h"
+
+// This is inexplicable, but for whatever reason, cppwinrt conflicts with the
+// SDK definition of this function, so the only fix is to undef it.
+// from WinBase.h
+// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime
+#ifdef GetCurrentTime
+#undef GetCurrentTime
+#endif
+
+#include
+
+// Needed just for XamlIslands to work at all:
+#include
+#include
+#include
+#include
+
+// Additional headers for various xaml features. We need:
+// * Core so we can resume_foreground with CoreDispatcher
+// * Controls for grid
+// * Media for ScaleTransform
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+// Including TraceLogging essentials for the binary
+#include
+#include
+TRACELOGGING_DECLARE_PROVIDER(g_hWindowsTerminalProvider);
+#include
+#include
+
+// For commandline argument processing
+#include
+#include
+#include
+#include "til.h"
diff --git a/scratch/ScratchIslandApp/WindowExe/resource.h b/scratch/ScratchIslandApp/WindowExe/resource.h
new file mode 100644
index 000000000..7e2918600
--- /dev/null
+++ b/scratch/ScratchIslandApp/WindowExe/resource.h
@@ -0,0 +1,27 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by WindowsTerminal.rc
+//
+#define IDI_APPICON 101
+#define IDI_APPICON_HC_BLACK 102
+#define IDI_APPICON_HC_WHITE 103
+
+#define IDS_ERROR_DIALOG_TITLE 105
+#define IDS_HELP_DIALOG_TITLE 106
+#define IDS_ERROR_ARCHITECTURE_FORMAT 110
+#define IDS_X86_ARCHITECTURE 111
+#define IDS_AMD64_ARCHITECTURE 112
+#define IDS_ARM64_ARCHITECTURE 113
+#define IDS_ARM_ARCHITECTURE 114
+#define IDS_UNKNOWN_ARCHITECTURE 115
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif