Compare commits

..

26 Commits

Author SHA1 Message Date
Dustin L. Howett
d1e080cf63 Migrate spelling-0.0.21 changes from main 2021-01-05 11:17:53 -06:00
Dustin L. Howett
6711e4398c Migrate spelling-0.0.19 changes from main 2021-01-05 11:17:53 -06:00
Mike Griese
4a536a39e7 This is going to turn into a disaster.
We still need to reference MUX
    to get mdmerge happy, but we can't roll that up without rolling up the DLL
    and now we'll get duplicate types in WT.vcxproj. GAH. We'll need to have
    Remoting accept a callback to say "I encountered a commandline, someone,
    deal with it?", then have apphost register for that callback. So the flow
    is monarch->AppHost->AppLogic
2021-01-05 11:17:53 -06:00
Mike Griese
d4dbd530e9 change the namespace 2021-01-05 08:55:40 -06:00
Mike Griese
b3601ab8d3 some project cleanup 2021-01-05 08:43:51 -06:00
Mike Griese
ca6a5fb537 Move the commandline args to their own project, so Remoting can reference them too 2021-01-05 08:26:16 -06:00
Mike Griese
c08889585b last commit before the holidays 2020-12-18 15:21:53 -06:00
Mike Griese
5939636182 Oh yea actually remove the thing 2020-12-18 12:48:23 -06:00
Mike Griese
f978a9c52c it's hard to believe he's gone / were it so easy 2020-12-18 12:45:29 -06:00
Mike Griese
e1402d834f This seems to work to create a thread listening for the monarch, and safely tear it down. It _seems_ like it. 2020-12-18 09:29:45 -06:00
Mike Griese
e101efd11d pr nits 2020-12-18 07:12:12 -06:00
Mike Griese
d08e65ce03 _final_ final cleanup for review 2020-12-17 14:33:50 -06:00
Mike Griese
b4fe1bffbf Final cleanup for review 2020-12-17 14:26:06 -06:00
Mike Griese
0103331987 cleanup Peasant for review 2020-12-17 12:49:27 -06:00
Mike Griese
9c6eac4e86 Clean up a lot for review 2020-12-17 12:39:59 -06:00
Mike Griese
a3faed6b7d finish renaming this test 2020-12-17 11:15:57 -06:00
Mike Griese
0579b2417b LocalTests_Remoting -> UnitTests_Remoting 2020-12-17 11:10:09 -06:00
Mike Griese
590b9ff0c7 this macro makes me feel dirty 2020-12-17 11:01:52 -06:00
Mike Griese
03bfc6e8a9 This works as a unittest, but not a local test. That's batty 2020-12-17 10:50:48 -06:00
Mike Griese
5cabcfb452 add a note to future me 2020-12-17 07:43:46 -06:00
Mike Griese
9a41647ffe HOLY SHIT I GOT THE COMANDLINE TO EXECUTE IN THE CURRENT WINDOW!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2020-12-17 07:24:16 -06:00
Mike Griese
27ace16652 whoop, we pass the commandline from the peasant, to the monarch, and then back! 2020-12-16 16:31:51 -06:00
Mike Griese
36539cfa47 This won't work, but I'm committing this becaus I finally got it to compile a String[] 2020-12-16 16:03:23 -06:00
Mike Griese
5a9cdc8b0b Shockingly, this works, it works elevated, and it works unpackaged 2020-12-16 09:51:24 -06:00
Mike Griese
1f52d35833 Yank all the M/P files, this builds?! 2020-12-16 08:08:55 -06:00
Mike Griese
3bef7bbb38 Get all the projects created and hooked up to the sln 2020-12-16 07:59:52 -06:00
135 changed files with 2862 additions and 1559 deletions

View File

@@ -171,18 +171,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControl", "src\casc
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminal", "src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj", "{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}"
ProjectSection(ProjectDependencies) = postProject
{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}
{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}
{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}
{CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}
{CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746}
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalApp", "src\cascadia\TerminalApp\dll\TerminalApp.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}"
ProjectSection(ProjectDependencies) = postProject
{CA5CAD1A-9A12-429C-B551-8562EC954746} = {CA5CAD1A-9A12-429C-B551-8562EC954746}
{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}
{CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076}
{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}
{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}
{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}
EndProjectSection
@@ -231,11 +232,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_TerminalApp", "sr
{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAppLib", "src\cascadia\TerminalApp\TerminalAppLib.vcxproj", "{CA5CAD1A-9A12-429C-B551-8562EC954746}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommandlineArgs", "src\cascadia\CommandlineArgs\CommandlineArgs.vcxproj", "{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}"
ProjectSection(ProjectDependencies) = postProject
{CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076}
{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAppLib", "src\cascadia\TerminalApp\TerminalAppLib.vcxproj", "{CA5CAD1A-9A12-429C-B551-8562EC954746}"
ProjectSection(ProjectDependencies) = postProject
{CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076}
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA} = {2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}
{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}
{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_TerminalApp", "src\cascadia\LocalTests_TerminalApp\TerminalApp.LocalTests.vcxproj", "{CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}"
@@ -341,6 +349,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_SettingsModel",
{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Remoting.Lib", "src\cascadia\Remoting\Microsoft.Terminal.RemotingLib.vcxproj", "{43CE4CE5-0010-4B99-9569-672670D26E26}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Remoting", "src\cascadia\Remoting\dll\Microsoft.Terminal.Remoting.vcxproj", "{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}"
ProjectSection(ProjectDependencies) = postProject
{43CE4CE5-0010-4B99-9569-672670D26E26} = {43CE4CE5-0010-4B99-9569-672670D26E26}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_Remoting", "src\cascadia\UnitTests_Remoting\Remoting.UnitTests.vcxproj", "{68A10CD3-AA64-465B-AF5F-ED4E9700543C}"
ProjectSection(ProjectDependencies) = postProject
{43CE4CE5-0010-4B99-9569-672670D26E26} = {43CE4CE5-0010-4B99-9569-672670D26E26}
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AuditMode|Any CPU = AuditMode|Any CPU
@@ -1593,6 +1614,30 @@ Global
{CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Release|x64.Build.0 = Release|x64
{CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Release|x86.ActiveCfg = Release|Win32
{CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Release|x86.Build.0 = Release|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|x64.ActiveCfg = AuditMode|x64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|Any CPU.ActiveCfg = Debug|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|ARM64.ActiveCfg = Debug|ARM64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|ARM64.Build.0 = Debug|ARM64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|x64.ActiveCfg = Debug|x64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|x64.Build.0 = Debug|x64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|x86.ActiveCfg = Debug|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Debug|x86.Build.0 = Debug|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|Any CPU.ActiveCfg = Release|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|ARM64.ActiveCfg = Release|ARM64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|ARM64.Build.0 = Release|ARM64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|x64.ActiveCfg = Release|x64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|x64.Build.0 = Release|x64
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|x86.ActiveCfg = Release|Win32
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA}.Release|x86.Build.0 = Release|Win32
{CA5CAD1A-9A12-429C-B551-8562EC954746}.AuditMode|Any CPU.ActiveCfg = Debug|Win32
{CA5CAD1A-9A12-429C-B551-8562EC954746}.AuditMode|ARM64.ActiveCfg = Release|ARM64
{CA5CAD1A-9A12-429C-B551-8562EC954746}.AuditMode|DotNet_x64Test.ActiveCfg = Debug|Win32
@@ -2137,6 +2182,84 @@ Global
{CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Release|x64.Build.0 = Release|x64
{CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Release|x86.ActiveCfg = Release|Win32
{CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Release|x86.Build.0 = Release|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|x64.ActiveCfg = Release|x64
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|x86.Build.0 = AuditMode|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|Any CPU.ActiveCfg = Debug|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|ARM64.ActiveCfg = Debug|ARM64
{43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|ARM64.Build.0 = Debug|ARM64
{43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|x64.ActiveCfg = Debug|x64
{43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|x64.Build.0 = Debug|x64
{43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|x86.ActiveCfg = Debug|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|x86.Build.0 = Debug|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.Release|Any CPU.ActiveCfg = Release|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.Release|ARM64.ActiveCfg = Release|ARM64
{43CE4CE5-0010-4B99-9569-672670D26E26}.Release|ARM64.Build.0 = Release|ARM64
{43CE4CE5-0010-4B99-9569-672670D26E26}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.Release|x64.ActiveCfg = Release|x64
{43CE4CE5-0010-4B99-9569-672670D26E26}.Release|x64.Build.0 = Release|x64
{43CE4CE5-0010-4B99-9569-672670D26E26}.Release|x86.ActiveCfg = Release|Win32
{43CE4CE5-0010-4B99-9569-672670D26E26}.Release|x86.Build.0 = Release|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.AuditMode|x64.ActiveCfg = Release|x64
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.AuditMode|x86.Build.0 = AuditMode|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Debug|Any CPU.ActiveCfg = Debug|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Debug|ARM64.ActiveCfg = Debug|ARM64
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Debug|ARM64.Build.0 = Debug|ARM64
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Debug|x64.ActiveCfg = Debug|x64
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Debug|x64.Build.0 = Debug|x64
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Debug|x86.ActiveCfg = Debug|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Debug|x86.Build.0 = Debug|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Release|Any CPU.ActiveCfg = Release|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Release|ARM64.ActiveCfg = Release|ARM64
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Release|ARM64.Build.0 = Release|ARM64
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Release|x64.ActiveCfg = Release|x64
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Release|x64.Build.0 = Release|x64
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Release|x86.ActiveCfg = Release|Win32
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Release|x86.Build.0 = Release|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.AuditMode|x64.ActiveCfg = AuditMode|x64
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.AuditMode|x86.Build.0 = AuditMode|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Debug|Any CPU.ActiveCfg = Debug|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Debug|ARM64.ActiveCfg = Debug|ARM64
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Debug|ARM64.Build.0 = Debug|ARM64
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Debug|x64.ActiveCfg = Debug|x64
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Debug|x64.Build.0 = Debug|x64
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Debug|x86.ActiveCfg = Debug|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Debug|x86.Build.0 = Debug|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|Any CPU.ActiveCfg = Release|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|ARM64.ActiveCfg = Release|ARM64
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|ARM64.Build.0 = Release|ARM64
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x64.ActiveCfg = Release|x64
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x64.Build.0 = Release|x64
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x86.ActiveCfg = Release|Win32
{68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2197,6 +2320,7 @@ Global
{84848BFA-931D-42CE-9ADF-01EE54DE7890} = {59840756-302F-44DF-AA47-441A9D673202}
{376FE273-6B84-4EB5-8B30-8DE9D21B022C} = {59840756-302F-44DF-AA47-441A9D673202}
{CA5CAD1A-9333-4D05-B12A-1905CBF112F9} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
{2658E9B0-BD84-48B7-BB5E-3D18F4DF07BA} = {59840756-302F-44DF-AA47-441A9D673202}
{CA5CAD1A-9A12-429C-B551-8562EC954746} = {59840756-302F-44DF-AA47-441A9D673202}
{CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
{48D21369-3D7B-4431-9967-24E81292CF63} = {05500DEF-2294-41E3-AF9A-24E580B82836}
@@ -2221,6 +2345,9 @@ Global
{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {59840756-302F-44DF-AA47-441A9D673202}
{CA5CAD1A-082C-4476-9F33-94B339494076} = {59840756-302F-44DF-AA47-441A9D673202}
{CA5CAD1A-9B68-456A-B13E-C8218070DC42} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
{43CE4CE5-0010-4B99-9569-672670D26E26} = {59840756-302F-44DF-AA47-441A9D673202}
{27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {59840756-302F-44DF-AA47-441A9D673202}
{68A10CD3-AA64-465B-AF5F-ED4E9700543C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}

View File

@@ -18,7 +18,7 @@ FOR %%A IN (TestHostApp.exe,te.exe,te.processhost.exe,conhost.exe,OpenConsole.ex
echo %TIME%
:: kill dhandler, which is a tool designed to handle unexpected windows appearing. But since our tests are
:: kill dhandler, which is a tool designed to handle unexpected windows appearing. But since our tests are
:: expected to show UI we don't want it running.
taskkill -f -im dhandler.exe
@@ -28,7 +28,7 @@ echo %TIME%
powershell -ExecutionPolicy Bypass .\InstallTestAppDependencies.ps1
echo %TIME%
set testBinaryCandidates=TerminalApp.LocalTests.dll Conhost.UIA.Tests.dll
set testBinaryCandidates=TerminalApp.LocalTests.dll SettingsModel.LocalTests.dll Conhost.UIA.Tests.dll
set testBinaries=
for %%B in (%testBinaryCandidates%) do (
if exist %%B (
@@ -103,4 +103,4 @@ copy /y *_subresults.json %HELIX_WORKITEM_UPLOAD_ROOT%
type testResults.xml
echo %TIME%
echo %TIME%

View File

@@ -5,14 +5,14 @@ parameters:
testSuite: ''
# If a Pipeline runs this template more than once, this parameter should be unique per build flavor to differentiate the
# the different test runs:
helixType: 'test/devtest'
helixType: 'test/devtest'
artifactName: 'drop'
maxParallel: 4
rerunPassesRequiredToAvoidFailure: 5
taefQuery: ''
# if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline:
useBuildOutputFromPipeline: $(System.DefinitionId)
matrix:
matrix:
# Release_x86:
# buildPlatform: 'x86'
# buildConfiguration: 'release'
@@ -39,13 +39,13 @@ jobs:
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\taef.redist.wlk.10.57.200731005-develop\build\Binaries\$(buildPlatform)
helixCommonArgs: '/binaryLogger:$(Build.SourcesDirectory)/${{parameters.name}}.$(buildPlatform).$(buildConfiguration).binlog /p:HelixBuild=$(Build.BuildId).$(buildPlatform).$(buildConfiguration) /p:Platform=$(buildPlatform) /p:Configuration=$(buildConfiguration) /p:HelixType=${{parameters.helixType}} /p:TestSuite=${{parameters.testSuite}} /p:ProjFilesPath=$(Build.ArtifactStagingDirectory) /p:rerunPassesRequiredToAvoidFailure=${{parameters.rerunPassesRequiredToAvoidFailure}}'
steps:
- task: CmdLine@1
displayName: 'Display build machine environment variables'
inputs:
filename: 'set'
- task: NuGetToolInstaller@0
displayName: 'Use NuGet 5.2.0'
inputs:
@@ -59,23 +59,23 @@ jobs:
nugetConfigPath: nuget.config
restoreDirectory: packages
- task: DownloadBuildArtifacts@0
- task: DownloadBuildArtifacts@0
condition:
and(succeeded(),eq(variables['useBuildOutputFromBuildId'],''))
inputs:
artifactName: ${{ parameters.artifactName }}
inputs:
artifactName: ${{ parameters.artifactName }}
downloadPath: '$(artifactsDir)'
- task: DownloadBuildArtifacts@0
- task: DownloadBuildArtifacts@0
condition:
and(succeeded(),ne(variables['useBuildOutputFromBuildId'],''))
inputs:
inputs:
buildType: specific
buildVersionToDownload: specific
project: $(System.TeamProjectId)
pipeline: ${{ parameters.useBuildOutputFromPipeline }}
buildId: $(useBuildOutputFromBuildId)
artifactName: ${{ parameters.artifactName }}
artifactName: ${{ parameters.artifactName }}
downloadPath: '$(artifactsDir)'
- task: CmdLine@1
@@ -90,7 +90,7 @@ jobs:
targetType: filePath
filePath: build\Helix\PrepareHelixPayload.ps1
arguments: -Platform '$(buildPlatform)' -Configuration '$(buildConfiguration)' -ArtifactName '${{ parameters.artifactName }}'
- task: CmdLine@1
displayName: 'Display Helix payload contents'
inputs:
@@ -104,7 +104,16 @@ jobs:
outputProjFileName: 'RunTestsInHelix-TerminalAppLocalTests.proj'
testSuite: '${{ parameters.testSuite }}'
taefQuery: ${{ parameters.taefQuery }}
- template: helix-createprojfile-steps.yml
parameters:
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\SettingsModel.LocalTests.dll'
outputProjFileName: 'RunTestsInHelix-SettingsModelLocalTests.proj'
testSuite: '${{ parameters.testSuite }}'
taefQuery: ${{ parameters.taefQuery }}
- template: helix-createprojfile-steps.yml
parameters:
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
@@ -118,7 +127,7 @@ jobs:
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)
artifactName: ${{ parameters.artifactName }}
- task: DotNetCoreCLI@2
displayName: 'Run tests in Helix (open queues)'
env:

View File

@@ -11,7 +11,7 @@
- Yes, the large majority of the `DEFINE_PROPERTYKEY` defs are the same, it's only the last byte of the guid that changes
2. Add matching fields to Settings.hpp
- Add getters, setters, the whole drill.
- add getters, setters, the whole drill.
3. Add to the propsheet
- We need to add it to *reading and writing* the registry from the propsheet, and *reading* the link from the propsheet. Yes, that's weird, but the propsheet is smart enough to re-use ShortcutSerialization::s_SetLinkValues, but not smart enough to do the same with RegistrySerialization.

View File

@@ -48,17 +48,3 @@ Invoke-OpenConsoleTests
```
`Invoke-OpenConsoleTests` supports a number of options, which you can enumerate by running `Invoke-OpenConsoleTests -?`.
### Debugging Tests
If you want to debug a test, you can do so by using the TAEF /waitForDebugger flag, such as:
runut *Tests.dll /name:TextBufferTests::TestInsertCharacter /waitForDebugger
Replace the test name with the one you want to debug. Then, TAEF will begin executing the test and output something like this:
TAEF: Waiting for debugger - PID <some PID> @ IP <some IP address>
You can then attach to that PID in your debugger of choice. In Visual Studio, you can use Debug -> Attach To Process, or you could use WinDbg or whatever you want.
Once the debugger attaches, the test will execute and your breakpoints will be hit.

View File

@@ -11,16 +11,10 @@
// - attr - the default text attribute
// Return Value:
// - constructed object
ATTR_ROW::ATTR_ROW(const UINT cchRowWidth, const TextAttribute attr) noexcept
// Note: will throw exception if unable to allocate memory for text attribute storage
ATTR_ROW::ATTR_ROW(const UINT cchRowWidth, const TextAttribute attr)
{
try
{
_list.emplace_back(TextAttributeRun(cchRowWidth, attr));
}
catch (...)
{
FAIL_FAST_CAUGHT_EXCEPTION();
}
_list.push_back(TextAttributeRun(cchRowWidth, attr));
_cchRowWidth = cchRowWidth;
}
@@ -31,7 +25,7 @@ ATTR_ROW::ATTR_ROW(const UINT cchRowWidth, const TextAttribute attr) noexcept
void ATTR_ROW::Reset(const TextAttribute attr)
{
_list.clear();
_list.emplace_back(TextAttributeRun(_cchRowWidth, attr));
_list.push_back(TextAttributeRun(_cchRowWidth, attr));
}
// Routine Description:
@@ -185,14 +179,14 @@ size_t ATTR_ROW::FindAttrIndex(const size_t index, size_t* const pApplies) const
// - Finds the hyperlink IDs present in this row and returns them
// Return value:
// - An unordered set containing the hyperlink IDs present in this row
std::vector<uint16_t> ATTR_ROW::GetHyperlinks()
std::unordered_set<uint16_t> ATTR_ROW::GetHyperlinks()
{
std::vector<uint16_t> ids;
std::unordered_set<uint16_t> ids;
for (const auto& run : _list)
{
if (run.GetAttributes().IsHyperlink())
{
ids.emplace_back(run.GetAttributes().GetHyperlinkId());
ids.emplace(run.GetAttributes().GetHyperlinkId());
}
}
return ids;
@@ -408,7 +402,7 @@ void ATTR_ROW::ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAtt
// The original run was 3 long. The insertion run was 1 long. We need 1 more for the
// fact that an existing piece of the run was split in half (to hold the latter half).
const size_t cNewRun = _list.size() + newAttrs.size() + 1;
decltype(_list) newRun;
std::vector<TextAttributeRun> newRun;
newRun.reserve(cNewRun);
// We will start analyzing from the beginning of our existing run.
@@ -601,7 +595,8 @@ std::vector<TextAttributeRun> ATTR_ROW::PackAttrs(const std::vector<TextAttribut
{
if (runs.empty() || runs.back().GetAttributes() != attr)
{
runs.emplace_back(TextAttributeRun(1, attr));
const TextAttributeRun run(1, attr);
runs.push_back(run);
}
else
{

View File

@@ -28,16 +28,7 @@ class ATTR_ROW final
public:
using const_iterator = typename AttrRowIterator;
ATTR_ROW(const UINT cchRowWidth, const TextAttribute attr)
noexcept;
~ATTR_ROW() = default;
ATTR_ROW(const ATTR_ROW&) = default;
ATTR_ROW& operator=(const ATTR_ROW&) = default;
ATTR_ROW(ATTR_ROW&&)
noexcept = default;
ATTR_ROW& operator=(ATTR_ROW&&) noexcept = default;
ATTR_ROW(const UINT cchRowWidth, const TextAttribute attr);
void Reset(const TextAttribute attr);
@@ -50,7 +41,7 @@ public:
size_t FindAttrIndex(const size_t index,
size_t* const pApplies) const;
std::vector<uint16_t> GetHyperlinks();
std::unordered_set<uint16_t> GetHyperlinks();
bool SetAttrToEnd(const UINT iStart, const TextAttribute attr);
void ReplaceAttrs(const TextAttribute& toBeReplacedAttr, const TextAttribute& replaceWith) noexcept;
@@ -74,7 +65,7 @@ public:
friend class AttrRowIterator;
private:
boost::container::small_vector<TextAttributeRun, 1> _list;
std::vector<TextAttributeRun> _list;
size_t _cchRowWidth;
#ifdef UNIT_TESTING

View File

@@ -39,6 +39,19 @@ bool AttrRowIterator::operator!=(const AttrRowIterator& it) const noexcept
return !(*this == it);
}
AttrRowIterator& AttrRowIterator::operator++() noexcept
{
_increment(1);
return *this;
}
AttrRowIterator AttrRowIterator::operator++(int) noexcept
{
auto copy = *this;
_increment(1);
return copy;
}
AttrRowIterator& AttrRowIterator::operator+=(const ptrdiff_t& movement)
{
if (!_exceeded)
@@ -61,6 +74,19 @@ AttrRowIterator& AttrRowIterator::operator-=(const ptrdiff_t& movement)
return this->operator+=(-movement);
}
AttrRowIterator& AttrRowIterator::operator--() noexcept
{
_decrement(1);
return *this;
}
AttrRowIterator AttrRowIterator::operator--(int) noexcept
{
auto copy = *this;
_decrement(1);
return copy;
}
const TextAttribute* AttrRowIterator::operator->() const
{
THROW_HR_IF(E_BOUNDS, _exceeded);

View File

@@ -38,38 +38,20 @@ public:
bool operator==(const AttrRowIterator& it) const noexcept;
bool operator!=(const AttrRowIterator& it) const noexcept;
AttrRowIterator& operator++() noexcept
{
_increment(1);
return *this;
}
AttrRowIterator operator++(int) noexcept
{
auto copy = *this;
_increment(1);
return copy;
}
AttrRowIterator& operator++() noexcept;
AttrRowIterator operator++(int) noexcept;
AttrRowIterator& operator+=(const ptrdiff_t& movement);
AttrRowIterator& operator-=(const ptrdiff_t& movement);
AttrRowIterator& operator--() noexcept
{
_decrement(1);
return *this;
}
AttrRowIterator operator--(int) noexcept
{
auto copy = *this;
_decrement(1);
return copy;
}
AttrRowIterator& operator--() noexcept;
AttrRowIterator operator--(int) noexcept;
const TextAttribute* operator->() const;
const TextAttribute& operator*() const;
private:
boost::container::small_vector_base<TextAttributeRun>::const_iterator _run;
std::vector<TextAttributeRun>::const_iterator _run;
const ATTR_ROW* _pAttrRow;
size_t _currentAttributeIndex; // index of TextAttribute within the current TextAttributeRun
bool _exceeded;

View File

@@ -15,16 +15,13 @@
// Return Value:
// - instantiated object
// Note: will through if unable to allocate char/attribute buffers
#pragma warning(push)
#pragma warning(disable : 26447) // small_vector's constructor says it can throw but it should not given how we use it. This suppresses this error for the AuditMode build.
CharRow::CharRow(size_t rowWidth, ROW* const pParent) noexcept :
CharRow::CharRow(size_t rowWidth, ROW* const pParent) :
_wrapForced{ false },
_doubleBytePadded{ false },
_data(rowWidth, value_type()),
_pParent{ FAIL_FAST_IF_NULL(pParent) }
{
}
#pragma warning(pop)
// Routine Description:
// - Sets the wrap status for the current row
@@ -144,7 +141,7 @@ typename CharRow::const_iterator CharRow::cend() const noexcept
// - The calculated left boundary of the internal string.
size_t CharRow::MeasureLeft() const noexcept
{
const_iterator it = _data.cbegin();
std::vector<value_type>::const_iterator it = _data.cbegin();
while (it != _data.cend() && it->IsSpace())
{
++it;
@@ -158,9 +155,9 @@ size_t CharRow::MeasureLeft() const noexcept
// - <none>
// Return Value:
// - The calculated right boundary of the internal string.
size_t CharRow::MeasureRight() const
size_t CharRow::MeasureRight() const noexcept
{
const_reverse_iterator it = _data.crbegin();
std::vector<value_type>::const_reverse_iterator it = _data.crbegin();
while (it != _data.crend() && it->IsSpace())
{
++it;

View File

@@ -49,12 +49,11 @@ class CharRow final
public:
using glyph_type = typename wchar_t;
using value_type = typename CharRowCell;
using iterator = typename boost::container::small_vector_base<value_type>::iterator;
using const_iterator = typename boost::container::small_vector_base<value_type>::const_iterator;
using const_reverse_iterator = typename boost::container::small_vector_base<value_type>::const_reverse_iterator;
using iterator = typename std::vector<value_type>::iterator;
using const_iterator = typename std::vector<value_type>::const_iterator;
using reference = typename CharRowCellReference;
CharRow(size_t rowWidth, ROW* const pParent) noexcept;
CharRow(size_t rowWidth, ROW* const pParent);
void SetWrapForced(const bool wrap) noexcept;
bool WasWrapForced() const noexcept;
@@ -64,7 +63,7 @@ public:
void Reset() noexcept;
[[nodiscard]] HRESULT Resize(const size_t newSize) noexcept;
size_t MeasureLeft() const noexcept;
size_t MeasureRight() const;
size_t MeasureRight() const noexcept;
void ClearCell(const size_t column);
bool ContainsText() const noexcept;
const DbcsAttribute& DbcsAttrAt(const size_t column) const;
@@ -102,7 +101,7 @@ protected:
bool _doubleBytePadded;
// storage for glyph data and dbcs attributes
boost::container::small_vector<value_type, 120> _data;
std::vector<value_type> _data;
// ROW that this CharRow belongs to
ROW* _pParent;

View File

@@ -8,6 +8,18 @@
// default glyph value, used for resetting the character data portion of a cell
static constexpr wchar_t DefaultValue = UNICODE_SPACE;
CharRowCell::CharRowCell() noexcept :
_wch{ DefaultValue },
_attr{}
{
}
CharRowCell::CharRowCell(const wchar_t wch, const DbcsAttribute attr) noexcept :
_wch{ wch },
_attr{ attr }
{
}
// Routine Description:
// - "erases" the glyph. really sets it back to the default "empty" value
void CharRowCell::EraseChars() noexcept

View File

@@ -17,7 +17,6 @@ Author(s):
#pragma once
#include "DbcsAttribute.hpp"
#include "unicode.hpp"
#if (defined(_M_IX86) || defined(_M_AMD64))
// currently CharRowCell's fields use 3 bytes of memory, leaving the 4th byte in unused. this leads
@@ -28,13 +27,8 @@ Author(s):
class CharRowCell final
{
public:
CharRowCell() noexcept = default;
CharRowCell(const wchar_t wch, const DbcsAttribute attr) noexcept
:
_wch(wch),
_attr(attr)
{
}
CharRowCell() noexcept;
CharRowCell(const wchar_t wch, const DbcsAttribute attr) noexcept;
void EraseChars() noexcept;
void Reset() noexcept;
@@ -50,8 +44,8 @@ public:
friend constexpr bool operator==(const CharRowCell& a, const CharRowCell& b) noexcept;
private:
wchar_t _wch{ UNICODE_SPACE };
DbcsAttribute _attr{};
wchar_t _wch;
DbcsAttribute _attr;
};
#if (defined(_M_IX86) || defined(_M_AMD64))

View File

@@ -32,8 +32,8 @@ public:
}
~CharRowCellReference() = default;
CharRowCellReference(const CharRowCellReference&) noexcept = default;
CharRowCellReference(CharRowCellReference&&) noexcept = default;
CharRowCellReference(const CharRowCellReference&) = default;
CharRowCellReference(CharRowCellReference&&) = default;
void operator=(const CharRowCellReference&) = delete;
void operator=(CharRowCellReference&&) = delete;

View File

@@ -16,15 +16,50 @@
// - pParent - the text buffer that this row belongs to
// Return Value:
// - constructed object
ROW::ROW(const SHORT rowId, const unsigned short rowWidth, const TextAttribute fillAttribute, TextBuffer* const pParent) noexcept :
ROW::ROW(const SHORT rowId, const short rowWidth, const TextAttribute fillAttribute, TextBuffer* const pParent) :
_id{ rowId },
_rowWidth{ rowWidth },
_charRow{ rowWidth, this },
_attrRow{ rowWidth, fillAttribute },
_rowWidth{ gsl::narrow<size_t>(rowWidth) },
_charRow{ gsl::narrow<size_t>(rowWidth), this },
_attrRow{ gsl::narrow<UINT>(rowWidth), fillAttribute },
_pParent{ pParent }
{
}
size_t ROW::size() const noexcept
{
return _rowWidth;
}
const CharRow& ROW::GetCharRow() const noexcept
{
return _charRow;
}
CharRow& ROW::GetCharRow() noexcept
{
return _charRow;
}
const ATTR_ROW& ROW::GetAttrRow() const noexcept
{
return _attrRow;
}
ATTR_ROW& ROW::GetAttrRow() noexcept
{
return _attrRow;
}
SHORT ROW::GetId() const noexcept
{
return _id;
}
void ROW::SetId(const SHORT id) noexcept
{
_id = id;
}
// Routine Description:
// - Sets all properties of the ROW to default values
// Arguments:
@@ -52,7 +87,7 @@ bool ROW::Reset(const TextAttribute Attr)
// - width - the new width, in cells
// Return Value:
// - S_OK if successful, otherwise relevant error
[[nodiscard]] HRESULT ROW::Resize(const unsigned short width)
[[nodiscard]] HRESULT ROW::Resize(const size_t width)
{
RETURN_IF_FAILED(_charRow.Resize(width));
try
@@ -78,6 +113,25 @@ void ROW::ClearColumn(const size_t column)
_charRow.ClearCell(column);
}
// Routine Description:
// - gets the text of the row as it would be shown on the screen
// Return Value:
// - wstring containing text for the row
std::wstring ROW::GetText() const
{
return _charRow.GetText();
}
RowCellIterator ROW::AsCellIter(const size_t startIndex) const
{
return AsCellIter(startIndex, size() - startIndex);
}
RowCellIterator ROW::AsCellIter(const size_t startIndex, const size_t count) const
{
return RowCellIterator(*this, startIndex, count);
}
UnicodeStorage& ROW::GetUnicodeStorage() noexcept
{
return _pParent->GetUnicodeStorage();

View File

@@ -32,28 +32,27 @@ class TextBuffer;
class ROW final
{
public:
ROW(const SHORT rowId, const unsigned short rowWidth, const TextAttribute fillAttribute, TextBuffer* const pParent)
noexcept;
ROW(const SHORT rowId, const short rowWidth, const TextAttribute fillAttribute, TextBuffer* const pParent);
size_t size() const noexcept { return _rowWidth; }
size_t size() const noexcept;
const CharRow& GetCharRow() const noexcept { return _charRow; }
CharRow& GetCharRow() noexcept { return _charRow; }
const CharRow& GetCharRow() const noexcept;
CharRow& GetCharRow() noexcept;
const ATTR_ROW& GetAttrRow() const noexcept { return _attrRow; }
ATTR_ROW& GetAttrRow() noexcept { return _attrRow; }
const ATTR_ROW& GetAttrRow() const noexcept;
ATTR_ROW& GetAttrRow() noexcept;
SHORT GetId() const noexcept { return _id; }
void SetId(const SHORT id) noexcept { _id = id; }
SHORT GetId() const noexcept;
void SetId(const SHORT id) noexcept;
bool Reset(const TextAttribute Attr);
[[nodiscard]] HRESULT Resize(const unsigned short width);
[[nodiscard]] HRESULT Resize(const size_t width);
void ClearColumn(const size_t column);
std::wstring GetText() const { return _charRow.GetText(); }
std::wstring GetText() const;
RowCellIterator AsCellIter(const size_t startIndex) const { return AsCellIter(startIndex, size() - startIndex); }
RowCellIterator AsCellIter(const size_t startIndex, const size_t count) const { return RowCellIterator(*this, startIndex, count); }
RowCellIterator AsCellIter(const size_t startIndex) const;
RowCellIterator AsCellIter(const size_t startIndex, const size_t count) const;
UnicodeStorage& GetUnicodeStorage() noexcept;
const UnicodeStorage& GetUnicodeStorage() const noexcept;
@@ -70,7 +69,7 @@ private:
CharRow _charRow;
ATTR_ROW _attrRow;
SHORT _id;
unsigned short _rowWidth;
size_t _rowWidth;
TextBuffer* _pParent; // non ownership pointer
};

View File

@@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "TextAttributeRun.hpp"
TextAttributeRun::TextAttributeRun() noexcept :
_cchLength(0)
{
SetAttributes(TextAttribute(0));
}
TextAttributeRun::TextAttributeRun(const size_t cchLength, const TextAttribute attr) noexcept :
_cchLength(cchLength)
{
SetAttributes(attr);
}
size_t TextAttributeRun::GetLength() const noexcept
{
return _cchLength;
}
void TextAttributeRun::SetLength(const size_t cchLength) noexcept
{
_cchLength = cchLength;
}
void TextAttributeRun::IncrementLength() noexcept
{
_cchLength++;
}
void TextAttributeRun::DecrementLength() noexcept
{
_cchLength--;
}
const TextAttribute& TextAttributeRun::GetAttributes() const noexcept
{
return _attributes;
}
void TextAttributeRun::SetAttributes(const TextAttribute textAttribute) noexcept
{
_attributes = textAttribute;
}

View File

@@ -25,24 +25,20 @@ Revision History:
class TextAttributeRun final
{
public:
TextAttributeRun() = default;
TextAttributeRun(const size_t cchLength, const TextAttribute attr) noexcept :
_cchLength(gsl::narrow<unsigned int>(cchLength))
{
SetAttributes(attr);
}
TextAttributeRun() noexcept;
TextAttributeRun(const size_t cchLength, const TextAttribute attr) noexcept;
size_t GetLength() const noexcept { return _cchLength; }
void SetLength(const size_t cchLength) noexcept { _cchLength = gsl::narrow<unsigned int>(cchLength); }
void IncrementLength() noexcept { _cchLength++; }
void DecrementLength() noexcept { _cchLength--; }
size_t GetLength() const noexcept;
void SetLength(const size_t cchLength) noexcept;
void IncrementLength() noexcept;
void DecrementLength() noexcept;
const TextAttribute& GetAttributes() const noexcept { return _attributes; }
void SetAttributes(const TextAttribute textAttribute) noexcept { _attributes = textAttribute; }
const TextAttribute& GetAttributes() const noexcept;
void SetAttributes(const TextAttribute textAttribute) noexcept;
private:
unsigned int _cchLength{ 0 };
TextAttribute _attributes{ 0 };
size_t _cchLength;
TextAttribute _attributes;
#ifdef UNIT_TESTING
friend class AttrRowTests;

View File

@@ -6,7 +6,7 @@
<RootNamespace>bufferout</RootNamespace>
<ProjectName>BufferOut</ProjectName>
<TargetName>ConBufferOut</TargetName>
<ConfigurationType>StaticLibrary</ConfigurationType>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(SolutionDir)src\common.build.pre.props" />
<ItemGroup>
@@ -22,6 +22,7 @@
<ClCompile Include="..\search.cpp" />
<ClCompile Include="..\TextColor.cpp" />
<ClCompile Include="..\TextAttribute.cpp" />
<ClCompile Include="..\TextAttributeRun.cpp" />
<ClCompile Include="..\textBuffer.cpp" />
<ClCompile Include="..\textBufferCellIterator.cpp" />
<ClCompile Include="..\textBufferTextIterator.cpp" />
@@ -60,4 +61,4 @@
</ItemGroup>
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.post.props" />
</Project>
</Project>

View File

@@ -40,6 +40,7 @@ SOURCES= \
..\RowCellIterator.cpp \
..\TextColor.cpp \
..\TextAttribute.cpp \
..\TextAttributeRun.cpp \
..\textBuffer.cpp \
..\textBufferCellIterator.cpp \
..\textBufferTextIterator.cpp \

View File

@@ -42,7 +42,6 @@ TextBuffer::TextBuffer(const COORD screenBufferSize,
_currentPatternId{ 0 }
{
// initialize ROWs
_storage.reserve(static_cast<size_t>(screenBufferSize.Y));
for (size_t i = 0; i < static_cast<size_t>(screenBufferSize.Y); ++i)
{
_storage.emplace_back(static_cast<SHORT>(i), screenBufferSize.X, _currentAttributes, this);
@@ -838,10 +837,11 @@ void TextBuffer::Reset()
const SHORT TopRowIndex = (GetFirstRowIndex() + TopRow) % currentSize.Y;
// rotate rows until the top row is at index 0
for (int i = 0; i < TopRowIndex; i++)
const ROW& newTopRow = _storage.at(TopRowIndex);
while (&newTopRow != &_storage.front())
{
_storage.emplace_back(std::move(_storage.front()));
_storage.erase(_storage.begin());
_storage.push_back(std::move(_storage.front()));
_storage.pop_front();
}
_SetFirstRowIndex(0);
@@ -1230,15 +1230,9 @@ void TextBuffer::_PruneHyperlinks()
// If the buffer does not contain the same reference, we can remove that hyperlink from our map
// This way, obsolete hyperlink references are cleared from our hyperlink map instead of hanging around
// Get all the hyperlink references in the row we're erasing
const auto hyperlinks = _storage.at(_firstRow).GetAttrRow().GetHyperlinks();
if (!hyperlinks.empty())
auto firstRowRefs = _storage.at(_firstRow).GetAttrRow().GetHyperlinks();
if (!firstRowRefs.empty())
{
// Move to unordered set so we can use hashed lookup of IDs instead of linear search.
// Only make it an unordered set now because set always heap allocates but vector
// doesn't when the set is empty (saving an allocation in the common case of no links.)
std::unordered_set<uint16_t> firstRowRefs{ hyperlinks.cbegin(), hyperlinks.cend() };
const auto total = TotalRowCount();
// Loop through all the rows in the buffer except the first row -
// we have found all hyperlink references in the first row and put them in refs,
@@ -1260,12 +1254,12 @@ void TextBuffer::_PruneHyperlinks()
break;
}
}
}
// Now delete obsolete references from our map
for (auto hyperlinkReference : firstRowRefs)
{
RemoveHyperlinkFromMap(hyperlinkReference);
}
// Now delete obsolete references from our map
for (auto hyperlinkReference : firstRowRefs)
{
RemoveHyperlinkFromMap(hyperlinkReference);
}
}
@@ -2416,7 +2410,7 @@ PointTree TextBuffer::GetPatterns(const size_t firstRow, const size_t lastRow) c
// all the text into one string and find the patterns in that string
for (auto i = firstRow; i <= lastRow; ++i)
{
auto& row = GetRowByOffset(i);
auto row = GetRowByOffset(i);
concatAll += row.GetCharRow().GetText();
}

View File

@@ -49,8 +49,6 @@ filling in the last row, and updating the screen.
#pragma once
#include <vector>
#include "cursor.h"
#include "Row.hpp"
#include "TextAttribute.hpp"
@@ -192,7 +190,7 @@ public:
private:
void _UpdateSize();
Microsoft::Console::Types::Viewport _size;
std::vector<ROW> _storage;
std::deque<ROW> _storage;
Cursor _cursor;
SHORT _firstRow; // indexes top row (not necessarily 0)

View File

@@ -2,14 +2,12 @@
// Licensed under the MIT license.
#include "pch.h"
#include "AppLogic.h"
#include "AppCommandlineArgs.h"
#include "../types/inc/utils.hpp"
#include <LibraryResources.h>
using namespace winrt::TerminalApp;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace TerminalApp;
using namespace CommandlineArgs;
// Either a ; at the start of a line, or a ; preceded by any non-\ char.
const std::wregex AppCommandlineArgs::_commandDelimiterRegex{ LR"(^;|[^\\];)" };
@@ -687,7 +685,7 @@ std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchMode> AppComman
// - 0 if the commandline was successfully parsed
int AppCommandlineArgs::ParseArgs(winrt::array_view<const winrt::hstring>& args)
{
auto commands = ::TerminalApp::AppCommandlineArgs::BuildCommands(args);
auto commands = ::CommandlineArgs::AppCommandlineArgs::BuildCommands(args);
for (auto& cmdBlob : commands)
{

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license.
#pragma once
#include <CLI11/CLI11.hpp>
#include "Commandline.h"
#ifdef UNIT_TESTING
@@ -12,12 +13,12 @@ namespace TerminalAppLocalTests
};
#endif
namespace TerminalApp
namespace CommandlineArgs
{
class AppCommandlineArgs;
};
class TerminalApp::AppCommandlineArgs final
class CommandlineArgs::AppCommandlineArgs final
{
public:
static constexpr std::string_view NixHelpFlag{ "-?" };

View File

@@ -4,7 +4,7 @@
#include "pch.h"
#include "Commandline.h"
using namespace TerminalApp;
using namespace CommandlineArgs;
size_t Commandline::Argc() const
{

View File

@@ -23,12 +23,12 @@ namespace TerminalAppLocalTests
{
class CommandlineTest;
};
namespace TerminalApp
namespace CommandlineArgs
{
class Commandline;
};
class TerminalApp::Commandline
class CommandlineArgs::Commandline
{
public:
static constexpr std::wstring_view Delimiter{ L";" };

View File

@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{2658e9b0-bd84-48b7-bb5e-3d18f4df07ba}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Microsoft.Terminal.CommandlineArgs</RootNamespace>
<ProjectName>CommandlineArgs</ProjectName>
<TargetName>CommandlineArgs</TargetName>
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
<ConfigurationType>StaticLibrary</ConfigurationType>
<SubSystem>Console</SubSystem>
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<ItemDefinitionGroup>
<ClCompile>
<!-- For CLI11: It uses dynamic_cast to cast types around, which depends
on being compiled with RTTI (/GR). -->
<RuntimeTypeInfo>true</RuntimeTypeInfo>
</ClCompile>
</ItemDefinitionGroup>
<!-- ========================= Headers ======================== -->
<ItemGroup>
<ClInclude Include="AppCommandlineArgs.h" />
<ClInclude Include="Commandline.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
<ClCompile Include="AppCommandlineArgs.cpp" />
<ClCompile Include="Commandline.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
</ItemGroup>
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>
<!--
the packaging project won't 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\types\lib\types.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WinRTUtils\WinRTUtils.vcxproj">
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<!-- For whatever reason, we can't include the TerminalControl and
TerminalSettings projects' winmds via project references. So we'll have to
manually include the winmds as References below -->
</ItemGroup>
<PropertyGroup>
<!-- This is a hack to get the ARM64 CI build working. See
https://github.com/Microsoft/msbuild/issues/3746 - it looks like MsBuild
just has a bug in it.-->
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>Warning</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
<ItemGroup>
<!-- Manually add references to each of our dependent winmds. Mark them as
private=false and CopyLocalSatelliteAssemblies=false, so that we don't
propagate them upwards (which can make referencing this project result in
duplicate type definitions)-->
<!-- Despite this lib only _really_ depending on the settings model, we need
to reference Connection, Control, and MUX here, because they have types that
TSM depends on, and the midl compiler will be mad if it can't find them. -->
<Reference Include="Microsoft.Terminal.TerminalConnection">
<HintPath>$(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.TerminalControl">
<HintPath>$(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.TerminalControl.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.Settings.Model">
<HintPath>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Settings.Model\Microsoft.Terminal.Settings.Model.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
</ItemGroup>
<!-- ====================== Compiler & Linker Flags ===================== -->
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<!-- Manually disable unreachable code warning, because jconcpp has a ton of that. -->
<DisableSpecificWarnings>4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>WindowsApp.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<!-- ========================= Globals ======================== -->
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\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('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>
<!-- <Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" /> -->
</Project>

View File

@@ -0,0 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"

View File

@@ -0,0 +1,53 @@
// 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 <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 <wil/cppwinrt.h>
#include <unknwn.h>
#include <hstring.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
// You might think "we're not doing any UI in this lib", and you'd be right.
// However, we need this for Windows.UI.Color
#include <winrt/windows.ui.h>
// Including TraceLogging essentials for the binary
#include <TraceLoggingProvider.h>
#include <winmeta.h>
TRACELOGGING_DECLARE_PROVIDER(g_hTerminalAppProvider);
#include <telemetry/ProjectTelemetry.h>
#include <TraceLoggingActivity.h>
#include <shellapi.h>
#include <shobjidl_core.h>
#include <winrt/Microsoft.Terminal.Settings.Model.h>
#include <CLI11/CLI11.hpp>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h"

View File

@@ -0,0 +1,25 @@
#include "pch.h"
#include "CommandlineArgs.h"
#include "CommandlineArgs.g.cpp"
using namespace winrt;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Windows::Foundation;
namespace winrt::Microsoft::Terminal::Remoting::implementation
{
// LOAD BEARING CODE
// If you try to move this into the header, you will experience P A I N
// It must be defined after CommandlineArgs.g.cpp, otherwise the compiler
// will give you just the most impossible template errors to try and
// decipher.
void CommandlineArgs::Args(winrt::array_view<const winrt::hstring> const& value)
{
_args = { value.begin(), value.end() };
}
winrt::com_array<winrt::hstring> CommandlineArgs::Args()
{
return winrt::com_array<winrt::hstring>{ _args.begin(), _args.end() };
}
}

View File

@@ -0,0 +1,39 @@
#pragma once
#include "CommandlineArgs.g.h"
#include "../cascadia/inc/cppwinrt_utils.h"
namespace winrt::Microsoft::Terminal::Remoting::implementation
{
struct CommandlineArgs : public CommandlineArgsT<CommandlineArgs>
{
public:
CommandlineArgs() :
_args{},
_cwd{ L"" }
{
}
CommandlineArgs(const winrt::array_view<const winrt::hstring>& args,
winrt::hstring currentDirectory) :
_args{ args.begin(), args.end() },
_cwd{ currentDirectory }
{
}
winrt::hstring CurrentDirectory() { return _cwd; };
void Args(winrt::array_view<const winrt::hstring> const& value);
winrt::com_array<winrt::hstring> Args();
private:
winrt::com_array<winrt::hstring> _args;
winrt::hstring _cwd;
};
}
namespace winrt::Microsoft::Terminal::Remoting::factory_implementation
{
BASIC_FACTORY(CommandlineArgs);
}

View File

@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{43ce4ce5-0010-4b99-9569-672670d26e26}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<ProjectName>Microsoft.Terminal.Remoting.Lib</ProjectName>
<RootNamespace>Microsoft.Terminal.Remoting</RootNamespace>
<TargetName>Microsoft.Terminal.Remoting.Lib</TargetName>
<WindowsTargetPlatformMinVersion>10.0.17763.0</WindowsTargetPlatformMinVersion>
<ConfigurationType>StaticLibrary</ConfigurationType>
<SubSystem>Console</SubSystem>
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<ItemDefinitionGroup>
<ClCompile>
<!-- For CLI11: It uses dynamic_cast to cast types around, which depends
on being compiled with RTTI (/GR). We need this in this project, because
we're including the CLI11 header via the CommandlineArgs project. -->
<RuntimeTypeInfo>true</RuntimeTypeInfo>
</ClCompile>
</ItemDefinitionGroup>
<!-- ========================= Headers ======================== -->
<ItemGroup>
<ClInclude Include="Monarch.h">
<DependentUpon>Monarch.idl</DependentUpon>
</ClInclude>
<ClInclude Include="pch.h" />
<ClInclude Include="MonarchFactory.h" />
<ClInclude Include="Peasant.h">
<DependentUpon>Peasant.idl</DependentUpon>
</ClInclude>
<ClInclude Include="WindowManager.h">
<DependentUpon>WindowManager.idl</DependentUpon>
</ClInclude>
<ClInclude Include="CommandlineArgs.h">
<DependentUpon>Peasant.idl</DependentUpon>
</ClInclude>
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
<ClCompile Include="Monarch.cpp">
<DependentUpon>Monarch.idl</DependentUpon>
</ClCompile>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Peasant.cpp">
<DependentUpon>Peasant.idl</DependentUpon>
</ClCompile>
<ClCompile Include="WindowManager.cpp">
<DependentUpon>WindowManager.idl</DependentUpon>
</ClCompile>
<ClCompile Include="CommandlineArgs.cpp">
<DependentUpon>Peasant.idl</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
<Midl Include="Monarch.idl" />
<Midl Include="Peasant.idl" />
<Midl Include="WindowManager.idl" />
</ItemGroup>
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
<PRIResource Include="Resources\en-US\Resources.resw" />
<OCResourceDirectory Include="Resources" />
<None Include="packages.config" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>
<!--
the packaging project won't 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\types\lib\types.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WinRTUtils\WinRTUtils.vcxproj">
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\CommandlineArgs\CommandlineArgs.vcxproj" >
<Private>true</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
<!-- Make sure to set ReferenceOutputAssembly=false, or we'll try and
MDMERGE with MUX from the CommandlineArgs output, and get duplicate type
errors everywhere. -->
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<!-- This is going to turn into a disaster. We still need to reference MUX
to get mdmerge happy, but we can't roll that up without rolling up the DLL
and now we'll get duplicate types in WT.vcxproj. GAH. We'll need to have
Remoting accept a callback to say "I encountered a commandline, someone,
deal with it?", then have apphost register for that callback. So the flow
is monarch->AppHost->AppLogic -->
</ProjectReference>
<!-- For whatever reason, we can't include the TerminalControl and
TerminalSettings projects' winmds via project references. So we'll have to
manually include the winmds as References below -->
<Reference Include="Microsoft.Terminal.TerminalConnection">
<HintPath>$(OpenConsoleCommonOutDir)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.TerminalControl">
<HintPath>$(OpenConsoleCommonOutDir)TerminalControl\Microsoft.Terminal.TerminalControl.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
<Reference Include="Microsoft.Terminal.Settings.Model">
<HintPath>$(OpenConsoleCommonOutDir)Microsoft.Terminal.Settings.Model\Microsoft.Terminal.Settings.Model.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</Reference>
</ItemGroup>
<!-- ====================== Compiler & Linker Flags ===================== -->
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<AdditionalDependencies>WindowsApp.lib;user32.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Reference>
<Private>false</Private>
</Reference>
</ItemDefinitionGroup>
<!-- ========================= Globals ======================== -->
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project>

View File

@@ -0,0 +1,149 @@
#include "pch.h"
#include "Monarch.h"
#include "CommandlineArgs.h"
#include "../CommandlineArgs/AppCommandlineArgs.h"
#include "Monarch.g.cpp"
#include "../../types/inc/utils.hpp"
using namespace winrt;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Windows::Foundation;
using namespace ::Microsoft::Console;
namespace winrt::Microsoft::Terminal::Remoting::implementation
{
Monarch::Monarch() :
_ourPID{ GetCurrentProcessId() }
{
}
// This is a private constructor to be used in unit tests, where we don't
// want each Monarch to necessarily use the current PID.
Monarch::Monarch(const uint64_t testPID) :
_ourPID{ testPID }
{
}
Monarch::~Monarch()
{
}
uint64_t Monarch::GetPID()
{
return _ourPID;
}
// Method Description:
// - Add the given peasant to the list of peasants we're tracking. This Peasant may have already been assigned an ID. If it hasn't, then give it an ID.
// Arguments:
// - peasant: the new Peasant to track.
// Return Value:
// - the ID assigned to the peasant.
uint64_t Monarch::AddPeasant(Remoting::IPeasant peasant)
{
// TODO:projects/5 This is terrible. There's gotta be a better way
// of finding the first opening in a non-consecutive map of int->object
auto providedID = peasant.GetID();
if (providedID == 0)
{
// Peasant doesn't currently have an ID. Assign it a new one.
peasant.AssignID(_nextPeasantID++);
}
else
{
// Peasant already had an ID (from an older monarch). Leave that one
// be. Make sure that the next peasant's ID is higher than it.
_nextPeasantID = providedID >= _nextPeasantID ? providedID + 1 : _nextPeasantID;
}
auto newPeasantsId = peasant.GetID();
_peasants[newPeasantsId] = peasant;
// Add an event listener to the peasant's WindowActivated event.
peasant.WindowActivated({ this, &Monarch::_peasantWindowActivated });
return newPeasantsId;
}
// Method Description:
// - Event handler for the Peasant::WindowActivated event. Used as an
// opportunity for us to update our internal stack of the "most recent
// window".
// Arguments:
// - sender: the Peasant that raised this event. This might be out-of-proc!
// Return Value:
// - <none>
void Monarch::_peasantWindowActivated(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& /*args*/)
{
// TODO:projects/5 Pass the desktop and timestamp of when the window was
// activated in `args`.
if (auto peasant{ sender.try_as<Remoting::Peasant>() })
{
auto theirID = peasant.GetID();
_setMostRecentPeasant(theirID);
}
}
// Method Description:
// - Lookup a peasant by its ID.
// Arguments:
// - peasantID: The ID Of the peasant to find
// Return Value:
// - the peasant if it exists in our map, otherwise null
Remoting::IPeasant Monarch::_getPeasant(uint64_t peasantID)
{
try
{
auto peasantSearch = _peasants.find(peasantID);
auto maybeThePeasant = peasantSearch == _peasants.end() ? nullptr : peasantSearch->second;
if (maybeThePeasant)
{
maybeThePeasant.GetPID();
}
return maybeThePeasant;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
// Remove the peasant from the list of peasants
_peasants.erase(peasantID);
return nullptr;
}
}
void Monarch::_setMostRecentPeasant(const uint64_t peasantID)
{
// TODO:projects/5 Use a heap/priority queue per-desktop to track which
// peasant was the most recent per-desktop. When we want to get the most
// recent of all desktops (WindowingBehavior::UseExisting), then use the
// most recent of all desktops.
_mostRecentPeasant = peasantID;
}
// Method Description:
// - Try to handle a commandline from a new WT invocation. We might need to
// hand the commandline to an existing window, or we might need to tell
// the caller that they need to become a new window to handle it themselves.
// Arguments:
// - <none>
// Return Value:
// - <none>
bool Monarch::ProposeCommandline(const Remoting::CommandlineArgs& /*args*/)
{
// TODO:projects/5
// The branch dev/migrie/f/remote-commandlines has a more complete
// version of this function, with a naive implementation. For now, we
// always want to create a new window, so we'll just return true. This
// will tell the caller that we didn't handle the commandline, and they
// should open a new window to deal with it themselves.
CommandlineArgs::AppCommandlineArgs argParser;
return true;
}
}

View File

@@ -0,0 +1,62 @@
#pragma once
#include "Monarch.g.h"
#include "Peasant.h"
#include "../cascadia/inc/cppwinrt_utils.h"
// {06171993-7eb1-4f3e-85f5-8bdd7386cce3}
constexpr GUID Monarch_clsid{
0x06171993,
0x7eb1,
0x4f3e,
{ 0x85, 0xf5, 0x8b, 0xdd, 0x73, 0x86, 0xcc, 0xe3 }
};
enum class WindowingBehavior : uint64_t
{
UseNew = 0,
UseExisting = 1,
};
namespace RemotingUnitTests
{
class RemotingTests;
};
namespace winrt::Microsoft::Terminal::Remoting::implementation
{
struct Monarch : public MonarchT<Monarch>
{
Monarch();
~Monarch();
uint64_t GetPID();
uint64_t AddPeasant(winrt::Microsoft::Terminal::Remoting::IPeasant peasant);
bool ProposeCommandline(const winrt::Microsoft::Terminal::Remoting::CommandlineArgs& args);
private:
Monarch(const uint64_t testPID);
uint64_t _ourPID;
uint64_t _nextPeasantID{ 1 };
uint64_t _thisPeasantID{ 0 };
uint64_t _mostRecentPeasant{ 0 };
WindowingBehavior _windowingBehavior{ WindowingBehavior::UseNew };
std::unordered_map<uint64_t, winrt::Microsoft::Terminal::Remoting::IPeasant> _peasants;
winrt::Microsoft::Terminal::Remoting::IPeasant _getPeasant(uint64_t peasantID);
void _setMostRecentPeasant(const uint64_t peasantID);
void _peasantWindowActivated(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args);
friend class RemotingUnitTests::RemotingTests;
};
}
namespace winrt::Microsoft::Terminal::Remoting::factory_implementation
{
BASIC_FACTORY(Monarch);
}

View File

@@ -0,0 +1,12 @@
import "Peasant.idl";
namespace Microsoft.Terminal.Remoting
{
[default_interface] runtimeclass Monarch {
Monarch();
UInt64 GetPID();
UInt64 AddPeasant(IPeasant peasant);
Boolean ProposeCommandline(CommandlineArgs args);
};
}

View File

@@ -0,0 +1,49 @@
#include "pch.h"
#include "Monarch.h"
// This seems like a hack, but it works.
//
// This class factory works so that there's only ever one instance of a Monarch
// per-process. Once the first monarch is created, we'll stash it in g_weak.
// Future callers who try to instantiate a Monarch will get the one that's
// already been made.
//
// I'm sure there's a better way to do this with WRL, but I'm not familiar
// enough with WRL to know for sure.
winrt::weak_ref<winrt::Microsoft::Terminal::Remoting::implementation::Monarch> g_weak{ nullptr };
struct MonarchFactory : winrt::implements<MonarchFactory, ::IClassFactory>
{
MonarchFactory() = default;
HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept
{
*result = nullptr;
if (outer)
{
return CLASS_E_NOAGGREGATION;
}
if (!g_weak)
{
// Create a new Monarch instance
auto strong = winrt::make_self<winrt::Microsoft::Terminal::Remoting::implementation::Monarch>();
g_weak = (*strong).get_weak();
return strong.as(iid, result);
}
else
{
// We already instantiated one Monarch, let's just return that one!
auto strong = g_weak.get();
return strong.as(iid, result);
}
}
HRESULT __stdcall LockServer(BOOL) noexcept
{
return S_OK;
}
};

View File

@@ -0,0 +1,63 @@
#include "pch.h"
#include "Peasant.h"
#include "CommandlineArgs.h"
#include "Peasant.g.cpp"
#include "../../types/inc/utils.hpp"
using namespace winrt;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Windows::Foundation;
using namespace ::Microsoft::Console;
namespace winrt::Microsoft::Terminal::Remoting::implementation
{
Peasant::Peasant() :
_ourPID{ GetCurrentProcessId() }
{
}
// This is a private constructor to be used in unit tests, where we don't
// want each Peasant to necessarily use the current PID.
Peasant::Peasant(const uint64_t testPID) :
_ourPID{ testPID }
{
}
void Peasant::AssignID(uint64_t id)
{
_id = id;
}
uint64_t Peasant::GetID()
{
return _id;
}
uint64_t Peasant::GetPID()
{
return _ourPID;
}
bool Peasant::ExecuteCommandline(const Remoting::CommandlineArgs& args)
{
// If this is the first set of args we were ever told about, stash them
// away. We'll need to get at them later, when we setup the startup
// actions for the window.
if (_initialArgs == nullptr)
{
_initialArgs = args;
}
// Raise an event with these args. The AppHost will listen for this
// event to know when to take these args and dispatch them to a
// currently-running window.
_ExecuteCommandlineRequestedHandlers(*this, args);
return true;
}
Remoting::CommandlineArgs Peasant::InitialArgs()
{
return _initialArgs;
}
}

View File

@@ -0,0 +1,41 @@
#pragma once
#include "Peasant.g.h"
#include "../cascadia/inc/cppwinrt_utils.h"
namespace RemotingUnitTests
{
class RemotingTests;
};
namespace winrt::Microsoft::Terminal::Remoting::implementation
{
struct Peasant : public PeasantT<Peasant>
{
Peasant();
void AssignID(uint64_t id);
uint64_t GetID();
uint64_t GetPID();
bool ExecuteCommandline(const winrt::Microsoft::Terminal::Remoting::CommandlineArgs& args);
winrt::Microsoft::Terminal::Remoting::CommandlineArgs InitialArgs();
TYPED_EVENT(WindowActivated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(ExecuteCommandlineRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::CommandlineArgs);
private:
Peasant(const uint64_t testPID);
uint64_t _ourPID;
uint64_t _id{ 0 };
winrt::Microsoft::Terminal::Remoting::CommandlineArgs _initialArgs{ nullptr };
friend class RemotingUnitTests::RemotingTests;
};
}
namespace winrt::Microsoft::Terminal::Remoting::factory_implementation
{
BASIC_FACTORY(Peasant);
}

View File

@@ -0,0 +1,31 @@
namespace Microsoft.Terminal.Remoting
{
runtimeclass CommandlineArgs
{
CommandlineArgs();
CommandlineArgs(String[] args, String cwd);
String[] Args { get; set; };
String CurrentDirectory();
};
interface IPeasant
{
CommandlineArgs InitialArgs { get; };
void AssignID(UInt64 id);
UInt64 GetID();
UInt64 GetPID();
Boolean ExecuteCommandline(CommandlineArgs args);
event Windows.Foundation.TypedEventHandler<Object, Object> WindowActivated;
event Windows.Foundation.TypedEventHandler<Object, CommandlineArgs> ExecuteCommandlineRequested;
};
[default_interface] runtimeclass Peasant : IPeasant
{
Peasant();
};
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,213 @@
#include "pch.h"
#include "WindowManager.h"
#include "MonarchFactory.h"
#include "CommandlineArgs.h"
#include "WindowManager.g.cpp"
#include "../../types/inc/utils.hpp"
using namespace winrt;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Windows::Foundation;
using namespace ::Microsoft::Console;
namespace winrt::Microsoft::Terminal::Remoting::implementation
{
WindowManager::WindowManager()
{
_monarchWaitInterrupt.create();
// Register with COM as a server for the Monarch class
_registerAsMonarch();
// Instantiate an instance of the Monarch. This may or may not be in-proc!
_createMonarchAndCallbacks();
}
WindowManager::~WindowManager()
{
// IMPORTANT! Tear down the registration as soon as we exit. If we're not a
// real peasant window (the monarch passed our commandline to someone else),
// then the monarch dies, we don't want our registration becoming the active
// monarch!
CoRevokeClassObject(_registrationHostClass);
_registrationHostClass = 0;
_monarchWaitInterrupt.SetEvent();
if (_electionThread.joinable())
{
_electionThread.join();
}
}
void WindowManager::ProposeCommandline(const Remoting::CommandlineArgs& args)
{
const bool isKing = _areWeTheKing();
// If we're the king, we _definitely_ want to process the arguments, we were
// launched with them!
//
// Otherwise, the King will tell us if we should make a new window
_shouldCreateWindow = isKing ||
_monarch.ProposeCommandline(args);
if (_shouldCreateWindow)
{
// If we should create a new window, then instantiate our Peasant
// instance, and tell that peasant to handle that commandline.
_createOurPeasant();
// TODO:MG Spawn a thread to wait on the monarch, and handle the election
if (!isKing)
{
_createPeasantThread();
}
_peasant.ExecuteCommandline(args);
}
// Otherwise, we'll do _nothing_.
}
bool WindowManager::ShouldCreateWindow()
{
return _shouldCreateWindow;
}
void WindowManager::_registerAsMonarch()
{
winrt::check_hresult(CoRegisterClassObject(Monarch_clsid,
winrt::make<::MonarchFactory>().get(),
CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE,
&_registrationHostClass));
}
void WindowManager::_createMonarch()
{
// Heads up! This only works because we're using
// "metadata-based-marshalling" for our WinRT types. THat means the OS is
// using the .winmd file we generate to figure out the proxy/stub
// definitions for our types automatically. This only works in the following
// cases:
//
// * If we're running unpackaged: the .winmd must be a sibling of the .exe
// * If we're running packaged: the .winmd must be in the package root
_monarch = create_instance<Remoting::Monarch>(Monarch_clsid,
CLSCTX_LOCAL_SERVER);
}
void WindowManager::_createMonarchAndCallbacks()
{
_createMonarch();
const auto isKing = _areWeTheKing();
if (!isKing)
{
return;
}
// Here, we're the king!
// Wait, don't. Let's just have the monarch try/catch any accesses to
// peasants. If the peasant dies, then it can't get the peasant's
// anything. In that case, _remove it_.
}
bool WindowManager::_areWeTheKing()
{
auto kingPID = _monarch.GetPID();
auto ourPID = GetCurrentProcessId();
return (ourPID == kingPID);
}
Remoting::IPeasant WindowManager::_createOurPeasant()
{
auto p = winrt::make_self<Remoting::implementation::Peasant>();
_peasant = *p;
_monarch.AddPeasant(_peasant);
return _peasant;
}
bool WindowManager::_electionNight2020()
{
_createMonarchAndCallbacks();
// Tell the new monarch who we are. We might be that monarch!
_monarch.AddPeasant(_peasant);
if (_areWeTheKing())
{
return true;
}
return false;
}
void WindowManager::_createPeasantThread()
{
// If we catch an exception trying to get at the monarch ever, we can
// set the _monarchWaitInterrupt, and use that to trigger a new
// election. Though, we wouldn't be able to retry the function that
// caused the exception in the first place...
_electionThread = std::thread([this] {
_waitOnMonarchThread();
});
}
void WindowManager::_waitOnMonarchThread()
{
HANDLE waits[2];
waits[1] = _monarchWaitInterrupt.get();
bool exitRequested = false;
while (!exitRequested)
{
wil::unique_handle hMonarch{ OpenProcess(PROCESS_ALL_ACCESS,
FALSE,
static_cast<DWORD>(_monarch.GetPID())) };
// TODO:MG If we fail to open the monarch, then they don't exist
// anymore! Go straight to an election.
//
// TODO:MG At any point in all this, the current monarch might die.
// We go straight to a new election, right? Worst case, eventually,
// we'll become the new monarch.
//
// if (hMonarch.get() == nullptr)
// {
// const auto gle = GetLastError();
// return false;
// }
waits[0] = hMonarch.get();
auto waitResult = WaitForMultipleObjects(2, waits, FALSE, INFINITE);
switch (waitResult)
{
case WAIT_OBJECT_0 + 0: // waits[0] was signaled
// Connect to the new monarch, which might be us!
// If we become the monarch, then we'll return true and exit this thread.
exitRequested = _electionNight2020();
break;
case WAIT_OBJECT_0 + 1: // waits[1] was signaled
exitRequested = true;
break;
case WAIT_TIMEOUT:
printf("Wait timed out. This should be impossible.\n");
exitRequested = true;
break;
// Return value is invalid.
default:
{
auto gle = GetLastError();
printf("WaitForMultipleObjects returned: %d\n", waitResult);
printf("Wait error: %d\n", gle);
ExitProcess(0);
}
}
}
}
Remoting::Peasant WindowManager::CurrentWindow()
{
return _peasant;
}
}

View File

@@ -0,0 +1,45 @@
#pragma once
#include "WindowManager.g.h"
#include "Peasant.h"
#include "Monarch.h"
#include "../cascadia/inc/cppwinrt_utils.h"
namespace winrt::Microsoft::Terminal::Remoting::implementation
{
struct WindowManager final : public WindowManagerT<WindowManager>
{
WindowManager();
~WindowManager();
void ProposeCommandline(const winrt::Microsoft::Terminal::Remoting::CommandlineArgs& args);
bool ShouldCreateWindow();
winrt::Microsoft::Terminal::Remoting::Peasant CurrentWindow();
private:
bool _shouldCreateWindow{ false };
DWORD _registrationHostClass{ 0 };
winrt::Microsoft::Terminal::Remoting::Monarch _monarch{ nullptr };
winrt::Microsoft::Terminal::Remoting::Peasant _peasant{ nullptr };
wil::unique_event _monarchWaitInterrupt;
std::thread _electionThread;
void _registerAsMonarch();
void _createMonarch();
void _createMonarchAndCallbacks();
bool _areWeTheKing();
winrt::Microsoft::Terminal::Remoting::IPeasant _createOurPeasant();
bool _electionNight2020();
void _createPeasantThread();
void _waitOnMonarchThread();
};
}
namespace winrt::Microsoft::Terminal::Remoting::factory_implementation
{
BASIC_FACTORY(WindowManager);
}

View File

@@ -0,0 +1,13 @@
import "Peasant.idl";
namespace Microsoft.Terminal.Remoting
{
[default_interface] runtimeclass WindowManager
{
WindowManager();
void ProposeCommandline(CommandlineArgs args);
Boolean ShouldCreateWindow { get; };
IPeasant CurrentWindow();
};
}

View File

@@ -0,0 +1,3 @@
EXPORTS
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{27b5aaeb-a548-44cf-9777-f8baa32af7ae}</ProjectGuid>
<ProjectName>Microsoft.Terminal.Remoting</ProjectName>
<RootNamespace>Microsoft.Terminal.Remoting</RootNamespace>
<!-- cppwinrt.build.pre.props depends on these settings: -->
<!-- build a dll, not exe (Application) -->
<ConfigurationType>DynamicLibrary</ConfigurationType>
<SubSystem>Console</SubSystem>
<!-- sets a bunch of Windows Universal properties -->
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
</PropertyGroup>
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<!-- ========================= XAML files ======================== -->
<ItemGroup>
<!-- DON'T PUT XAML FILES HERE! Put them in TerminalAppLib.vcxproj -->
</ItemGroup>
<!-- ========================= Headers ======================== -->
<ItemGroup>
<!-- Only put headers for winrt types in here. Don't put other header files
in here - put them in the lib's vcxproj instead! -->
<ClInclude Include="../Monarch.h" />
<ClInclude Include="../Peasant.h" />
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<!-- Don't put source files in here - put them in the lib's vcxproj instead! -->
<!-- ========================= idl Files ======================== -->
<ItemGroup>
<!-- DON'T PUT IDL FILES HERE! Put them in the lib's vcxproj -->
</ItemGroup>
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
<None Include="packages.config" />
<None Include="Microsoft.Terminal.Remoting.def" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>
<!--
the packaging project won't 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\types\lib\types.vcxproj">
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
</ProjectReference>
<!-- Reference Microsoft.Terminal.RemotingLib here, so we can use it's winmd as
our winmd. This didn't work correctly in VS2017, you'd need to
manually reference the lib -->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\Remoting\Microsoft.Terminal.RemotingLib.vcxproj">
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>User32.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<!-- TSM Lib contains a DllMain that we need to force the use of. -->
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12</AdditionalOptions>
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain</AdditionalOptions>
</Link>
<Reference>
<!-- Do not propagate microsoft.ui.xaml upwards as a private dependency. -->
<Private>false</Private>
</Reference>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
</Project>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.201017.1" targetFramework="native" />
</packages>

View File

@@ -0,0 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"

View File

@@ -0,0 +1,50 @@
// 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 <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 <wil/cppwinrt.h>
#include <unknwn.h>
#include <hstring.h>
#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.System.h>
// Including TraceLogging essentials for the binary
#include <TraceLoggingProvider.h>
#include <winmeta.h>
TRACELOGGING_DECLARE_PROVIDER(g_hSettingsModelProvider);
#include <telemetry/ProjectTelemetry.h>
#include <TraceLoggingActivity.h>
#include <shellapi.h>
#include <winrt/Microsoft.Terminal.Settings.Model.h>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h"

View File

@@ -17,7 +17,6 @@ using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace ::TerminalApp;
namespace winrt
{
@@ -453,7 +452,7 @@ namespace winrt::TerminalApp::implementation
if (_startupActions.Size() != 0)
{
actionArgs.Handled(true);
_ProcessStartupActions(actions, false);
ProcessStartupActions(actions, false);
}
}
}

View File

@@ -17,7 +17,7 @@ using namespace winrt::Windows::System;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace ::TerminalApp;
using namespace ::CommandlineArgs;
namespace winrt
{
@@ -1111,6 +1111,19 @@ namespace winrt::TerminalApp::implementation
return result;
}
int32_t AppLogic::ExecuteCommandline(array_view<const winrt::hstring> args)
{
::CommandlineArgs::AppCommandlineArgs appArgs;
auto result = appArgs.ParseArgs(args);
if (result == 0)
{
auto actions = winrt::single_threaded_vector<ActionAndArgs>(std::move(appArgs.GetStartupActions()));
_root->ProcessStartupActions(actions, false);
}
return result; // TODO:MG does a return value make sense
}
// Method Description:
// - If there were any errors parsing the commandline that was used to
// initialize the terminal, this will return a string containing that

View File

@@ -29,6 +29,7 @@ namespace winrt::TerminalApp::implementation
[[nodiscard]] Microsoft::Terminal::Settings::Model::CascadiaSettings GetSettings() const noexcept;
int32_t SetStartupCommandline(array_view<const winrt::hstring> actions);
int32_t ExecuteCommandline(array_view<const winrt::hstring> actions);
winrt::hstring ParseCommandlineMessage();
bool ShouldExitEarly();
@@ -84,7 +85,7 @@ namespace winrt::TerminalApp::implementation
std::atomic<bool> _settingsReloadQueued{ false };
::TerminalApp::AppCommandlineArgs _appArgs;
::CommandlineArgs::AppCommandlineArgs _appArgs;
int _ParseArgs(winrt::array_view<const hstring>& args);
void _ShowLoadErrorsDialog(const winrt::hstring& titleKey, const winrt::hstring& contentKey, HRESULT settingsLoadedResult);

View File

@@ -29,6 +29,7 @@ namespace TerminalApp
Boolean IsElevated();
Int32 SetStartupCommandline(String[] commands);
Int32 ExecuteCommandline(String[] commands);
String ParseCommandlineMessage { get; };
Boolean ShouldExitEarly { get; };

View File

@@ -291,6 +291,7 @@ namespace winrt::TerminalApp::implementation
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
auto key = e.OriginalKey();
auto const ctrlDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
if (key == VirtualKey::Up)
{

View File

@@ -5,7 +5,7 @@
#include "FilteredCommand.h"
#include "CommandPalette.g.h"
#include "AppCommandlineArgs.h"
#include "../CommandlineArgs/AppCommandlineArgs.h"
#include "../../cascadia/inc/cppwinrt_utils.h"
// fwdecl unittest classes
@@ -130,7 +130,7 @@ namespace winrt::TerminalApp::implementation
static constexpr int CommandLineHistoryLength = 10;
Windows::Foundation::Collections::IVector<winrt::TerminalApp::FilteredCommand> _commandLineHistory{ nullptr };
::TerminalApp::AppCommandlineArgs _appArgs;
::CommandlineArgs::AppCommandlineArgs _appArgs;
friend class TerminalAppLocalTests::TabTests;
};

View File

@@ -17,7 +17,7 @@ using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::Microsoft::Terminal::TerminalConnection;
using namespace winrt::TerminalApp;
using namespace TerminalApp;
static const int PaneBorderSize = 2;
static const int CombinedPaneBorderSize = 2 * PaneBorderSize;

View File

@@ -25,7 +25,8 @@
<ClCompile>
<!-- For CLI11: It uses dynamic_cast to cast types around, which depends
on being compiled with RTTI (/GR). -->
on being compiled with RTTI (/GR). We need this in this project, because
we're including the CLI11 header via the CommandlineArgs project. -->
<RuntimeTypeInfo>true</RuntimeTypeInfo>
</ClCompile>
</ItemDefinitionGroup>
@@ -71,8 +72,6 @@
<ItemGroup>
<ClInclude Include="ActionPaletteItem.h" />
<ClInclude Include="App.base.h" />
<ClInclude Include="AppCommandlineArgs.h" />
<ClInclude Include="Commandline.h" />
<ClInclude Include="CommandLinePaletteItem.h" />
<ClInclude Include="Jumplist.h" />
<ClInclude Include="MinMaxCloseControl.h">
@@ -144,8 +143,6 @@
<ClCompile Include="ActionPaletteItem.cpp" />
<ClCompile Include="CommandLinePaletteItem.cpp" />
<ClCompile Include="init.cpp" />
<ClCompile Include="AppCommandlineArgs.cpp" />
<ClCompile Include="Commandline.cpp" />
<ClCompile Include="Jumplist.cpp" />
<ClCompile Include="MinMaxCloseControl.cpp">
<DependentUpon>MinMaxCloseControl.xaml</DependentUpon>
@@ -288,6 +285,14 @@
you also update all the consumers
-->
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\CommandlineArgs\CommandlineArgs.vcxproj" >
<Private>true</Private>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
<!-- Make sure to set ReferenceOutputAssembly=false, or we'll try and
MDMERGE with MUX from the CommandlineArgs output, and get duplicate type
errors everywhere. -->
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\WinRTUtils\WinRTUtils.vcxproj">
<Project>{CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>

View File

@@ -331,7 +331,7 @@ namespace winrt::TerminalApp::implementation
}
else
{
_ProcessStartupActions(_startupActions, true);
ProcessStartupActions(_startupActions, true);
}
}
}
@@ -347,8 +347,8 @@ namespace winrt::TerminalApp::implementation
// should fire an Initialized event.
// Return Value:
// - <none>
winrt::fire_and_forget TerminalPage::_ProcessStartupActions(Windows::Foundation::Collections::IVector<ActionAndArgs> actions,
const bool initial)
winrt::fire_and_forget TerminalPage::ProcessStartupActions(Windows::Foundation::Collections::IVector<ActionAndArgs> actions,
const bool initial)
{
// If there are no actions left, do nothing.
if (actions.Size() == 0)
@@ -2698,7 +2698,7 @@ namespace winrt::TerminalApp::implementation
// - an empty list if we failed to parse, otherwise a list of actions to execute.
std::vector<ActionAndArgs> TerminalPage::ConvertExecuteCommandlineToActions(const ExecuteCommandlineArgs& args)
{
::TerminalApp::AppCommandlineArgs appArgs;
::CommandlineArgs::AppCommandlineArgs appArgs;
if (appArgs.ParseArgs(args) == 0)
{
return appArgs.GetStartupActions();

View File

@@ -10,7 +10,7 @@
#include <winrt/Microsoft.Terminal.TerminalControl.h>
#include "AppCommandlineArgs.h"
#include "../CommandlineArgs/AppCommandlineArgs.h"
static constexpr uint32_t DefaultRowsToScroll{ 3 };
static constexpr std::wstring_view TabletInputServiceKey{ L"TabletInputService" };
@@ -81,6 +81,8 @@ namespace winrt::TerminalApp::implementation
void ShowKeyboardServiceWarning();
winrt::hstring KeyboardServiceDisabledText();
winrt::fire_and_forget ProcessStartupActions(Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::ActionAndArgs> actions, const bool initial);
// -------------------------------- WinRT Events ---------------------------------
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(TitleChanged, _titleChangeHandlers, winrt::Windows::Foundation::IInspectable, winrt::hstring);
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(LastTabClosed, _lastTabClosedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs);
@@ -137,7 +139,6 @@ namespace winrt::TerminalApp::implementation
StartupState _startupState{ StartupState::NotInitialized };
Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::ActionAndArgs> _startupActions;
winrt::fire_and_forget _ProcessStartupActions(Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::ActionAndArgs> actions, const bool initial);
void _ShowAboutDialog();
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowCloseWarningDialog();

View File

@@ -50,6 +50,7 @@ namespace winrt::TerminalApp::implementation
tab->SetTabText(title);
}
});
// Use our header control as the TabViewItem's header
TabViewItem().Header(_headerControl);
}
@@ -75,13 +76,6 @@ namespace winrt::TerminalApp::implementation
_RecalculateAndApplyTabColor();
}
void TerminalTab::_SetToolTip(const winrt::hstring& tabTitle)
{
WUX::Controls::ToolTip toolTip{};
toolTip.Content(winrt::box_value(tabTitle));
WUX::Controls::ToolTipService::SetToolTip(TabViewItem(), toolTip);
}
// Method Description:
// - Returns nullptr if no children of this tab were the last control to be
// focused, or the TermControl that _was_ the last control to be focused (if
@@ -271,7 +265,6 @@ namespace winrt::TerminalApp::implementation
// Update the control to reflect the changed title
_headerControl.Title(activeTitle);
_SetToolTip(activeTitle);
}
}

View File

@@ -98,8 +98,6 @@ namespace winrt::TerminalApp::implementation
void _MakeTabViewItem();
void _SetToolTip(const winrt::hstring& tabTitle);
void _CreateContextMenu() override;
void _RefreshVisualState();

View File

@@ -76,7 +76,5 @@ TRACELOGGING_DECLARE_PROVIDER(g_hTerminalAppProvider);
#include <winrt/Windows.UI.Popups.h>
#include <CLI11/CLI11.hpp>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h"

View File

@@ -329,7 +329,7 @@ void Terminal::UpdateSettings(ICoreSettings settings)
{
try
{
auto& row = newTextBuffer->GetRowByOffset(::base::ClampSub(proposedTop, 1));
auto row = newTextBuffer->GetRowByOffset(::base::ClampSub(proposedTop, 1));
if (row.GetCharRow().WasWrapForced())
{
proposedTop--;

View File

@@ -11,7 +11,6 @@
using namespace winrt;
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Navigation;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Media;
@@ -39,20 +38,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
RS_(L"ColorScheme_BrightWhite/Header")
};
static const std::array<std::wstring, 9> InBoxSchemes = {
L"Campbell",
L"Campbell Powershell",
L"Vintage",
L"One Half Dark",
L"One Half Light",
L"Solarized Dark",
L"Solarized Light",
L"Tango Dark",
L"Tango Light"
};
ColorSchemes::ColorSchemes() :
_ColorSchemeList{ single_threaded_observable_vector<Model::ColorScheme>() },
_ColorSchemeList{ single_threaded_observable_vector<hstring>() },
_CurrentColorTable{ single_threaded_observable_vector<Editor::ColorTableEntry>() }
{
InitializeComponent();
@@ -86,23 +73,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
SelectionChangedEventArgs const& args)
{
// Update the color scheme this page is modifying
const auto colorScheme{ args.AddedItems().GetAt(0).try_as<Model::ColorScheme>() };
auto str = winrt::unbox_value<hstring>(args.AddedItems().GetAt(0));
auto colorScheme = _State.Globals().ColorSchemes().Lookup(str);
CurrentColorScheme(colorScheme);
_UpdateColorTable(colorScheme);
// Set the text disclaimer for the text box
hstring disclaimer{};
const std::wstring schemeName{ colorScheme.Name() };
if (std::find(std::begin(InBoxSchemes), std::end(InBoxSchemes), schemeName) != std::end(InBoxSchemes))
{
// load disclaimer for in-box profiles
disclaimer = RS_(L"ColorScheme_DeleteButtonDisclaimerInBox");
}
DeleteButtonDisclaimer().Text(disclaimer);
// Update the state of the page
_PropertyChangedHandlers(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"CanDeleteCurrentScheme" });
IsRenaming(false);
}
// Function Description:
@@ -118,7 +92,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
const auto& colorSchemeMap{ _State.Globals().ColorSchemes() };
for (const auto& pair : colorSchemeMap)
{
_ColorSchemeList.Append(pair.Value());
_ColorSchemeList.Append(pair.Key());
}
}
@@ -146,101 +120,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
bool ColorSchemes::CanDeleteCurrentScheme() const
{
if (const auto scheme{ CurrentColorScheme() })
{
// Only allow this color scheme to be deleted if it's not provided in-box
const std::wstring myName{ scheme.Name() };
return std::find(std::begin(InBoxSchemes), std::end(InBoxSchemes), myName) == std::end(InBoxSchemes);
}
return false;
}
void ColorSchemes::DeleteConfirmation_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
const auto schemeName{ CurrentColorScheme().Name() };
_State.Globals().RemoveColorScheme(schemeName);
const auto removedSchemeIndex{ ColorSchemeComboBox().SelectedIndex() };
if (static_cast<uint32_t>(removedSchemeIndex) < _ColorSchemeList.Size() - 1)
{
// select same index
ColorSchemeComboBox().SelectedIndex(removedSchemeIndex + 1);
}
else
{
// select last color scheme (avoid out of bounds error)
ColorSchemeComboBox().SelectedIndex(removedSchemeIndex - 1);
}
_ColorSchemeList.RemoveAt(removedSchemeIndex);
DeleteButton().Flyout().Hide();
}
void ColorSchemes::AddNew_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
// Give the new scheme a distinct name
const hstring schemeName{ fmt::format(L"Color Scheme {}", _State.Globals().ColorSchemes().Size() + 1) };
Model::ColorScheme scheme{ schemeName };
// Add the new color scheme
_State.Globals().AddColorScheme(scheme);
// Update current page
_ColorSchemeList.Append(scheme);
ColorSchemeComboBox().SelectedItem(scheme);
}
// Function Description:
// - Pre-populates/focuses the name TextBox, updates the UI
// Arguments:
// - <unused>
// Return Value:
// - <none>
void ColorSchemes::Rename_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
NameBox().Text(CurrentColorScheme().Name());
IsRenaming(true);
NameBox().Focus(FocusState::Programmatic);
NameBox().SelectAll();
}
void ColorSchemes::RenameAccept_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
_RenameCurrentScheme(NameBox().Text());
}
void ColorSchemes::RenameCancel_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
IsRenaming(false);
}
void ColorSchemes::NameBox_PreviewKeyDown(IInspectable const& /*sender*/, winrt::Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
if (e.OriginalKey() == winrt::Windows::System::VirtualKey::Enter)
{
_RenameCurrentScheme(NameBox().Text());
e.Handled(true);
}
else if (e.OriginalKey() == winrt::Windows::System::VirtualKey::Escape)
{
IsRenaming(false);
e.Handled(true);
}
}
void ColorSchemes::_RenameCurrentScheme(hstring newName)
{
CurrentColorScheme().Name(newName);
IsRenaming(false);
// The color scheme is renamed appropriately, but the ComboBox still shows the old name (until you open it)
// We need to manually force the ComboBox to refresh itself.
const auto selectedIndex{ ColorSchemeComboBox().SelectedIndex() };
ColorSchemeComboBox().SelectedIndex((selectedIndex + 1) % ColorSchemeList().Size());
ColorSchemeComboBox().SelectedIndex(selectedIndex);
}
// Function Description:
// - Updates the currently modifiable color table based on the given current color scheme.
// Arguments:

View File

@@ -27,28 +27,17 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void ColorSchemeSelectionChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::SelectionChangedEventArgs const& args);
void ColorPickerChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::ColorChangedEventArgs const& args);
void AddNew_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void Rename_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void RenameAccept_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void RenameCancel_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void NameBox_PreviewKeyDown(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
bool CanDeleteCurrentScheme() const;
void DeleteConfirmation_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
GETSET_PROPERTY(Editor::ColorSchemesPageNavigationState, State, nullptr);
GETSET_PROPERTY(Windows::Foundation::Collections::IObservableVector<winrt::Microsoft::Terminal::Settings::Editor::ColorTableEntry>, CurrentColorTable, nullptr);
GETSET_PROPERTY(Windows::Foundation::Collections::IObservableVector<Model::ColorScheme>, ColorSchemeList, nullptr);
GETSET_PROPERTY(Windows::Foundation::Collections::IObservableVector<winrt::hstring>, ColorSchemeList, nullptr);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
OBSERVABLE_GETSET_PROPERTY(winrt::Microsoft::Terminal::Settings::Model::ColorScheme, CurrentColorScheme, _PropertyChangedHandlers, nullptr);
OBSERVABLE_GETSET_PROPERTY(bool, IsRenaming, _PropertyChangedHandlers, nullptr);
private:
void _UpdateColorTable(const winrt::Microsoft::Terminal::Settings::Model::ColorScheme& colorScheme);
void _UpdateColorSchemeList();
void _RenameCurrentScheme(hstring newName);
};
struct ColorTableEntry : ColorTableEntryT<ColorTableEntry>

View File

@@ -13,12 +13,9 @@ namespace Microsoft.Terminal.Settings.Editor
ColorSchemes();
ColorSchemesPageNavigationState State { get; };
Boolean CanDeleteCurrentScheme { get; };
Boolean IsRenaming { get; };
Microsoft.Terminal.Settings.Model.ColorScheme CurrentColorScheme { get; };
Windows.Foundation.Collections.IObservableVector<ColorTableEntry> CurrentColorTable;
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Model.ColorScheme> ColorSchemeList { get; };
Windows.Foundation.Collections.IObservableVector<String> ColorSchemeList { get; };
}
[default_interface] runtimeclass ColorTableEntry : Windows.UI.Xaml.Data.INotifyPropertyChanged

View File

@@ -5,7 +5,6 @@ the MIT License. See LICENSE in the project root for license information. -->
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
xmlns:model="using:Microsoft.Terminal.Settings.Model"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
@@ -16,8 +15,8 @@ the MIT License. See LICENSE in the project root for license information. -->
<ResourceDictionary Source="CommonResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Thickness x:Key="ColorSchemesStandardControlMargin">0,0,10,20</Thickness>
<Thickness x:Key="ColorSchemesStandardControlMargin">10,0,0,20</Thickness>
<Style x:Key="ColorStackPanelStyle" TargetType="StackPanel">
<Setter Property="Margin" Value="{StaticResource ColorSchemesStandardControlMargin}"/>
<Setter Property="Height" Value="59"/>
@@ -43,85 +42,32 @@ the MIT License. See LICENSE in the project root for license information. -->
<local:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
<local:ColorToHexConverter x:Key="ColorToHexConverter"/>
<local:InvertedBooleanToVisibilityConverter x:Key="InvertedBooleanToVisibilityConverter"/>
</ResourceDictionary>
</Page.Resources>
<ScrollViewer>
<Grid Margin="{StaticResource StandardIndentMargin}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" MaxWidth="480"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<!--Select Color and Add New Button-->
<StackPanel Orientation="Horizontal"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="{StaticResource StandardControlSpacing}">
<!--Select a color scheme-->
<ComboBox x:Name="ColorSchemeComboBox"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
SelectedIndex="0"
ItemsSource="{x:Bind ColorSchemeList, Mode=OneWay}"
SelectionChanged="ColorSchemeSelectionChanged"
Style="{StaticResource ComboBoxSettingStyle}"
Margin="{StaticResource ColorSchemesStandardControlMargin}"/>
<StackPanel Orientation="Horizontal"
Visibility="{x:Bind IsRenaming, Converter={StaticResource InvertedBooleanToVisibilityConverter}, Mode=OneWay}">
<!--Select a color scheme-->
<ComboBox x:Name="ColorSchemeComboBox"
SelectedIndex="0"
ItemsSource="{x:Bind ColorSchemeList, Mode=OneWay}"
SelectionChanged="ColorSchemeSelectionChanged"
Style="{StaticResource ComboBoxSettingStyle}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="model:ColorScheme">
<TextBlock Text="{x:Bind Name, Mode=OneWay}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!--Rename Button-->
<!--Bind IsEnabled to prevent a the color scheme from returning from the dead-->
<Button x:Uid="Rename"
Style="{StaticResource BrowseButtonStyle}"
Click="Rename_Click"
IsEnabled="{x:Bind CanDeleteCurrentScheme, Mode=OneWay}">
<FontIcon Glyph="&#xE8AC;"/>
</Button>
</StackPanel>
<StackPanel Orientation="Horizontal"
Visibility="{x:Bind IsRenaming, Mode=OneWay}">
<TextBox x:Name="NameBox"
Style="{StaticResource TextBoxSettingStyle}"
PreviewKeyDown="NameBox_PreviewKeyDown"/>
<Button x:Uid="RenameAccept"
Style="{StaticResource AccentBrowseButtonStyle}"
Click="RenameAccept_Click">
<FontIcon Glyph="&#xE8FB;"/>
</Button>
<Button x:Uid="RenameCancel"
Style="{StaticResource BrowseButtonStyle}"
Click="RenameCancel_Click">
<FontIcon Glyph="&#xE711;"/>
</Button>
</StackPanel>
<!--Add new button-->
<Button Click="AddNew_Click"
Style="{StaticResource BrowseButtonStyle}">
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="&#xE710;"
FontSize="15"/>
<TextBlock x:Uid="ColorScheme_AddNewButton"
Margin="10,0,0,0"
FontSize="15"/>
</StackPanel>
</Button>
</StackPanel>
<!-- Color Table (Left Column)-->
<!-- Color Table -->
<ItemsControl x:Name="ColorTableControl"
ItemsSource="{x:Bind CurrentColorTable, Mode=OneWay}"
Grid.Row="1"
@@ -152,8 +98,8 @@ the MIT License. See LICENSE in the project root for license information. -->
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Additional Colors (Right Column) -->
<ItemsControl Grid.Row="1"
<!-- Additional Colors -->
<ItemsControl Grid.Row="2"
Grid.Column="1">
<StackPanel Style="{StaticResource ColorStackPanelStyle}">
<TextBlock x:Uid="ColorScheme_Foreground"
@@ -203,71 +149,6 @@ the MIT License. See LICENSE in the project root for license information. -->
</Button>
</StackPanel>
</ItemsControl>
<!--Delete Button-->
<StackPanel Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="{StaticResource StandardControlSpacing}">
<Button x:Name="DeleteButton"
Style="{StaticResource BaseButtonStyle}"
IsEnabled="{x:Bind CanDeleteCurrentScheme, Mode=OneWay}"
Margin="0,0,0,10">
<Button.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="ButtonBackground" Color="Firebrick"/>
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="#C23232"/>
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="#A21212"/>
<SolidColorBrush x:Key="ButtonForeground" Color="White"/>
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="White"/>
<SolidColorBrush x:Key="ButtonForegroundPressed" Color="White"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="ButtonBackground" Color="Firebrick"/>
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="#C23232"/>
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="#A21212"/>
<SolidColorBrush x:Key="ButtonForeground" Color="White"/>
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="White"/>
<SolidColorBrush x:Key="ButtonForegroundPressed" Color="White"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="ButtonBackground" Color="{ThemeResource SystemColorButtonFaceColor}"/>
<SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="{ThemeResource SystemColorHighlightColor}"/>
<SolidColorBrush x:Key="ButtonBackgroundPressed" Color="{ThemeResource SystemColorHighlightColor}"/>
<SolidColorBrush x:Key="ButtonForeground" Color="{ThemeResource SystemColorButtonTextColor}"/>
<SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="{ThemeResource SystemColorHighlightTextColor}"/>
<SolidColorBrush x:Key="ButtonForegroundPressed" Color="{ThemeResource SystemColorHighlightTextColor}"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Button.Resources>
<Button.Content>
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="&#xE74D;"
FontSize="{StaticResource StandardFontSize}"/>
<TextBlock x:Uid="ColorScheme_DeleteButton"
FontSize="{StaticResource StandardFontSize}"
Margin="10,0,0,0"/>
</StackPanel>
</Button.Content>
<Button.Flyout>
<Flyout>
<StackPanel>
<TextBlock x:Uid="ColorScheme_DeleteConfirmationMessage"
Style="{StaticResource CustomFlyoutTextStyle}"/>
<Button x:Uid="ColorScheme_DeleteConfirmationButton"
Style="{StaticResource BaseButtonStyle}"
Click="DeleteConfirmation_Click"/>
</StackPanel>
</Flyout>
</Button.Flyout>
</Button>
<TextBlock x:Name="DeleteButtonDisclaimer"
Style="{StaticResource DisclaimerStyle}"
VerticalAlignment="Center"/>
</StackPanel>
</Grid>
</ScrollViewer>
</Page>

View File

@@ -5,13 +5,12 @@
<x:Double x:Key="StandardFontSize">15.0</x:Double>
<Thickness x:Key="StandardIndentMargin">20,0,0,0</Thickness>
<Thickness x:Key="StandardControlSpacing">0,0,0,20</Thickness>
<x:Double x:Key="StandardBoxMinWidth">200</x:Double>
<x:Double x:Key="StandardBoxMinWidth">300</x:Double>
<!-- This is for easier transition to the SettingsContainer control.
The SettingsContainer will wrap a setting with inheritance UI.-->
<Style x:Key="SettingContainerStyle" TargetType="ContentPresenter">
<Setter Property="Padding" Value="{StaticResource StandardControlSpacing}"/>
<Setter Property="Padding" Value="0,0,0,20"/>
</Style>
<!--Used to stack a group of settings-->
@@ -64,20 +63,6 @@
<Setter Property="Margin" Value="0,20,0,10"/>
</Style>
<!--Used for disclaimers-->
<Style x:Key="DisclaimerStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="TextWrapping" Value="WrapWholeWords"/>
</Style>
<!--Used for flyout messages-->
<Style x:Key="CustomFlyoutTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BaseTextBlockStyle}">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="0,0,0,12"/>
</Style>
<!--Number Box-->
<Style x:Key="NumberBoxSettingStyle" TargetType="muxc:NumberBox">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
@@ -89,7 +74,6 @@
<!--Button-Related Styling-->
<Style x:Key="BaseButtonStyle" TargetType="Button" BasedOn="{StaticResource DefaultButtonStyle}">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
</Style>
<Style x:Key="BrowseButtonStyle" TargetType="Button" BasedOn="{StaticResource BaseButtonStyle}">
@@ -97,13 +81,6 @@
<Setter Property="VerticalAlignment" Value="Bottom"/>
</Style>
<Style x:Key="AccentBrowseButtonStyle" TargetType="Button" BasedOn="{StaticResource AccentButtonStyle}">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
<Setter Property="ToolTipService.Placement" Value="Mouse"/>
<Setter Property="Margin" Value="10,0,0,0"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
</Style>
<!--Slider-Related Styling-->
<Style x:Key="SliderSettingStyle" TargetType="Slider" BasedOn="{StaticResource DefaultSliderStyle}">
<Setter Property="FontSize" Value="{StaticResource StandardFontSize}"/>
@@ -128,4 +105,5 @@
<Setter Property="Width" Value="300"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
</ResourceDictionary>

View File

@@ -1,28 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "InvertedBooleanToVisibilityConverter.h"
#include "InvertedBooleanToVisibilityConverter.g.cpp"
using namespace winrt::Windows;
using namespace winrt::Windows::UI::Xaml;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
Foundation::IInspectable InvertedBooleanToVisibilityConverter::Convert(Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /* parameter */,
hstring const& /* language */)
{
return winrt::box_value(winrt::unbox_value<bool>(value) ? Visibility::Collapsed : Visibility::Visible);
}
Foundation::IInspectable InvertedBooleanToVisibilityConverter::ConvertBack(Foundation::IInspectable const& /*value*/,
Windows::UI::Xaml::Interop::TypeName const& /* targetType */,
Foundation::IInspectable const& /*parameter*/,
hstring const& /* language */)
{
throw hresult_not_implemented();
}
}

View File

@@ -1,30 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "InvertedBooleanToVisibilityConverter.g.h"
#include "Utils.h"
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
struct InvertedBooleanToVisibilityConverter : InvertedBooleanToVisibilityConverterT<InvertedBooleanToVisibilityConverter>
{
InvertedBooleanToVisibilityConverter() = default;
Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& targetType,
Windows::Foundation::IInspectable const& parameter,
hstring const& language);
Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value,
Windows::UI::Xaml::Interop::TypeName const& targetType,
Windows::Foundation::IInspectable const& parameter,
hstring const& language);
};
}
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
{
BASIC_FACTORY(InvertedBooleanToVisibilityConverter);
}

View File

@@ -1,10 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass InvertedBooleanToVisibilityConverter : [default] Windows.UI.Xaml.Data.IValueConverter
{
InvertedBooleanToVisibilityConverter();
};
}

View File

@@ -10,7 +10,6 @@
#include "Profiles.h"
#include "GlobalAppearance.h"
#include "ColorSchemes.h"
#include "..\types\inc\utils.hpp"
#include <LibraryResources.h>
@@ -198,7 +197,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
else if (const auto profile = clickedItemContainer.Tag().try_as<Editor::ProfileViewModel>())
{
// Navigate to a page with the given profile
_Navigate(profile);
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), winrt::make<ProfilePageNavigationState>(profile, _settingsClone.GlobalSettings().ColorSchemes(), *this));
}
}
}
@@ -219,9 +218,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
else if (clickedItemTag == globalProfileTag)
{
auto profileVM{ _viewModelForProfile(_settingsClone.ProfileDefaults()) };
profileVM.IsBaseLayer(true);
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), winrt::make<ProfilePageNavigationState>(profileVM, _settingsClone.GlobalSettings().ColorSchemes(), *this));
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), winrt::make<ProfilePageNavigationState>(_viewModelForProfile(_settingsClone.ProfileDefaults()), _settingsClone.GlobalSettings().ColorSchemes(), *this));
}
else if (clickedItemTag == colorSchemesTag)
{
@@ -233,16 +230,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}
void MainPage::_Navigate(const Editor::ProfileViewModel& profile)
{
auto state{ winrt::make<ProfilePageNavigationState>(profile, _settingsClone.GlobalSettings().ColorSchemes(), *this) };
// Add an event handler for when the user wants to delete a profile.
state.DeleteProfile({ this, &MainPage::_DeleteProfile });
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), state);
}
void MainPage::OpenJsonTapped(IInspectable const& /*sender*/, Windows::UI::Xaml::Input::TappedRoutedEventArgs const& /*args*/)
{
const CoreWindow window = CoreWindow::GetForCurrentThread();
@@ -310,7 +297,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// Select and navigate to the new profile
SettingsNav().SelectedItem(navItem);
_Navigate(profileViewModel);
contentFrame().Navigate(xaml_typename<Editor::Profiles>(), winrt::make<ProfilePageNavigationState>(profileViewModel, _settingsClone.GlobalSettings().ColorSchemes(), *this));
}
MUX::Controls::NavigationViewItem MainPage::_CreateProfileNavViewItem(const Editor::ProfileViewModel& profile)
@@ -326,31 +313,4 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
return profileNavItem;
}
void MainPage::_DeleteProfile(const IInspectable /*sender*/, const Editor::DeleteProfileEventArgs& args)
{
// Delete profile from settings model
const auto guid{ args.ProfileGuid() };
auto profileList{ _settingsClone.AllProfiles() };
for (uint32_t i = 0; i < profileList.Size(); ++i)
{
if (profileList.GetAt(i).Guid() == guid)
{
profileList.RemoveAt(i);
break;
}
}
// remove selected item
uint32_t index;
auto selectedItem{ SettingsNav().SelectedItem() };
auto menuItems{ SettingsNav().MenuItems() };
menuItems.IndexOf(selectedItem, index);
menuItems.RemoveAt(index);
// navigate to the profile next to this one
const auto newSelectedItem{ menuItems.GetAt(index < menuItems.Size() - 1 ? index : index - 1) };
SettingsNav().SelectedItem(newSelectedItem);
_Navigate(newSelectedItem.try_as<MUX::Controls::NavigationViewItem>().Tag().try_as<Editor::ProfileViewModel>());
}
}

View File

@@ -35,11 +35,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void _InitializeProfilesList();
void _CreateAndNavigateToNewProfile(const uint32_t index);
winrt::Microsoft::UI::Xaml::Controls::NavigationViewItem _CreateProfileNavViewItem(const Editor::ProfileViewModel& profile);
void _DeleteProfile(const Windows::Foundation::IInspectable sender, const Editor::DeleteProfileEventArgs& args);
winrt::Microsoft::UI::Xaml::Controls::NavigationViewItem _CreateProfileNavViewItem(const ProfileViewModel& profile);
void _Navigate(hstring clickedItemTag);
void _Navigate(const Editor::ProfileViewModel& profile);
void _RefreshCurrentPage();
};
}

View File

@@ -44,9 +44,6 @@
<ClInclude Include="FontWeightConverter.h">
<DependentUpon>FontWeightConverter.idl</DependentUpon>
</ClInclude>
<ClInclude Include="InvertedBooleanToVisibilityConverter.h">
<DependentUpon>InvertedBooleanToVisibilityConverter.idl</DependentUpon>
</ClInclude>
<ClInclude Include="PercentageConverter.h">
<DependentUpon>PercentageConverter.idl</DependentUpon>
</ClInclude>
@@ -117,9 +114,6 @@
<ClCompile Include="FontWeightConverter.cpp">
<DependentUpon>FontWeightConverter.idl</DependentUpon>
</ClCompile>
<ClCompile Include="InvertedBooleanToVisibilityConverter.cpp">
<DependentUpon>InvertedBooleanToVisibilityConverter.idl</DependentUpon>
</ClCompile>
<ClCompile Include="PercentageConverter.cpp">
<DependentUpon>PercentageConverter.idl</DependentUpon>
</ClCompile>
@@ -157,7 +151,6 @@
<Midl Include="ColorToBrushConverter.idl" />
<Midl Include="ColorToHexConverter.idl" />
<Midl Include="FontWeightConverter.idl" />
<Midl Include="InvertedBooleanToVisibilityConverter.idl" />
<Midl Include="PercentageConverter.idl" />
<Midl Include="EnumEntry.idl" />
<Midl Include="GlobalAppearance.idl">

View File

@@ -25,9 +25,6 @@
<Midl Include="FontWeightConverter.idl">
<Filter>Converters</Filter>
</Midl>
<Midl Include="InvertedBooleanToVisibilityConverter.idl">
<Filter>Converters</Filter>
</Midl>
<Midl Include="PercentageConverter.idl">
<Filter>Converters</Filter>
</Midl>

View File

@@ -10,7 +10,6 @@
using namespace winrt::Windows::UI::Text;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Navigation;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Collections;
@@ -19,42 +18,8 @@ using namespace winrt::Windows::Storage::AccessCache;
using namespace winrt::Windows::Storage::Pickers;
using namespace winrt::Microsoft::Terminal::Settings::Model;
static const std::array<winrt::guid, 2> InBoxProfileGuids{
winrt::guid{ 0x61c54bbd, 0xc2c6, 0x5271, { 0x96, 0xe7, 0x00, 0x9a, 0x87, 0xff, 0x44, 0xbf } }, // Windows Powershell
winrt::guid{ 0x0caa0dad, 0x35be, 0x5f56, { 0xa8, 0xff, 0xaf, 0xce, 0xee, 0xaa, 0x61, 0x01 } } // Command Prompt
};
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
bool ProfileViewModel::CanDeleteProfile() const
{
const auto guid{ Guid() };
if (IsBaseLayer())
{
return false;
}
else if (std::find(std::begin(InBoxProfileGuids), std::end(InBoxProfileGuids), guid) != std::end(InBoxProfileGuids))
{
// in-box profile
return false;
}
else if (!Source().empty())
{
// dynamic profile
return false;
}
else
{
return true;
}
}
void ProfilePageNavigationState::DeleteProfile()
{
auto deleteProfileArgs{ winrt::make_self<DeleteProfileEventArgs>(_Profile.Guid()) };
_DeleteProfileHandlers(*this, *deleteProfileArgs);
}
Profiles::Profiles() :
_ColorSchemeList{ single_threaded_observable_vector<ColorScheme>() }
{
@@ -99,21 +64,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
biButton.IsChecked(biButton.Tag().as<int32_t>() == biAlignmentVal);
}
// Set the text disclaimer for the text box
hstring disclaimer{};
const auto guid{ _State.Profile().Guid() };
if (std::find(std::begin(InBoxProfileGuids), std::end(InBoxProfileGuids), guid) != std::end(InBoxProfileGuids))
{
// load disclaimer for in-box profiles
disclaimer = RS_(L"Profile_DeleteButtonDisclaimerInBox");
}
else if (!_State.Profile().Source().empty())
{
// load disclaimer for dynamic profiles
disclaimer = RS_(L"Profile_DeleteButtonDisclaimerDynamic");
}
DeleteButtonDisclaimer().Text(disclaimer);
}
ColorScheme Profiles::CurrentColorScheme()
@@ -136,12 +86,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_State.Profile().ColorSchemeName(val.Name());
}
void Profiles::DeleteConfirmation_Click(IInspectable const& /*sender*/, RoutedEventArgs const& /*e*/)
{
auto state{ winrt::get_self<ProfilePageNavigationState>(_State) };
state->DeleteProfile();
}
fire_and_forget Profiles::BackgroundImage_Click(IInspectable const&, RoutedEventArgs const&)
{
auto lifetime = get_strong();

View File

@@ -5,7 +5,6 @@
#include "Profiles.g.h"
#include "ProfilePageNavigationState.g.h"
#include "DeleteProfileEventArgs.g.h"
#include "ProfileViewModel.g.h"
#include "Utils.h"
#include "ViewModelHelpers.h"
@@ -18,9 +17,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
ProfileViewModel(const Model::Profile& profile) :
_profile{ profile } {}
bool CanDeleteProfile() const;
GETSET_PROPERTY(bool, IsBaseLayer, false);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, Guid);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, ConnectionType);
OBSERVABLE_PROJECTED_SETTING(_profile, Name);
@@ -64,19 +60,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
Model::Profile _profile;
};
struct DeleteProfileEventArgs :
public DeleteProfileEventArgsT<DeleteProfileEventArgs>
{
public:
DeleteProfileEventArgs(guid profileGuid) :
_ProfileGuid(profileGuid) {}
guid ProfileGuid() const noexcept { return _ProfileGuid; }
private:
guid _ProfileGuid{};
};
struct ProfilePageNavigationState : ProfilePageNavigationStateT<ProfilePageNavigationState>
{
public:
@@ -87,12 +70,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
}
void DeleteProfile();
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> Schemes() { return _Schemes; }
void Schemes(const Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme>& val) { _Schemes = val; }
TYPED_EVENT(DeleteProfile, Editor::ProfilePageNavigationState, Editor::DeleteProfileEventArgs);
GETSET_PROPERTY(IHostedInWindow, WindowRoot, nullptr);
GETSET_PROPERTY(Editor::ProfileViewModel, Profile, nullptr);
@@ -115,7 +95,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
fire_and_forget StartingDirectory_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
fire_and_forget Icon_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void BIAlignment_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void DeleteConfirmation_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
// CursorShape visibility logic
void CursorShape_Changed(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);

View File

@@ -10,9 +10,6 @@ namespace Microsoft.Terminal.Settings.Editor
{
runtimeclass ProfileViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
Boolean CanDeleteProfile { get; };
Boolean IsBaseLayer;
OBSERVABLE_PROJECTED_SETTING(String, Name);
OBSERVABLE_PROJECTED_SETTING(Guid, Guid);
OBSERVABLE_PROJECTED_SETTING(String, Source);
@@ -53,19 +50,12 @@ namespace Microsoft.Terminal.Settings.Editor
OBSERVABLE_PROJECTED_SETTING(Microsoft.Terminal.Settings.Model.BellStyle, BellStyle);
}
runtimeclass DeleteProfileEventArgs
{
Guid ProfileGuid { get; };
}
runtimeclass ProfilePageNavigationState
{
Windows.Foundation.Collections.IMapView<String, Microsoft.Terminal.Settings.Model.ColorScheme> Schemes;
IHostedInWindow WindowRoot; // necessary to send the right HWND into the file picker dialogs.
ProfileViewModel Profile { get; };
event Windows.Foundation.TypedEventHandler<ProfilePageNavigationState, DeleteProfileEventArgs> DeleteProfile;
};
[default_interface] runtimeclass Profiles : Windows.UI.Xaml.Controls.Page, Windows.UI.Xaml.Data.INotifyPropertyChanged

File diff suppressed because it is too large Load Diff

View File

@@ -19,8 +19,9 @@ the MIT License. See LICENSE in the project root for license information. -->
<ScrollViewer>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<TextBlock x:Uid="Globals_RenderingDisclaimer"
Style="{StaticResource DisclaimerStyle}"
Margin="{StaticResource StandardControlSpacing}"/>
FontSize="{StaticResource StandardFontSize}"
FontStyle="Italic"
Margin="0,0,0,20"/>
<!--Force Full Repaint-->
<ContentPresenter Style="{StaticResource SettingContainerStyle}">

View File

@@ -722,27 +722,6 @@
<data name="Profile_BellStyleVisual.Content" xml:space="preserve">
<value>Visual (Flash Taskbar)</value>
</data>
<data name="ColorScheme_AddNewButton.Text" xml:space="preserve">
<value>Add new</value>
</data>
<data name="ColorScheme_DeleteButton.Text" xml:space="preserve">
<value>Delete color scheme</value>
</data>
<data name="ColorScheme_Name.Header" xml:space="preserve">
<value>Name</value>
</data>
<data name="ColorScheme_Name.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>The name of the color scheme.</value>
</data>
<data name="Profile_DeleteButton.Text" xml:space="preserve">
<value>Delete profile</value>
</data>
<data name="Profile_Name.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>The name of the profile that appears in the dropdown.</value>
</data>
<data name="Profile_Name.Header" xml:space="preserve">
<value>Name</value>
</data>
<data name="Profile_AcrylicHeader.Text" xml:space="preserve">
<value>Acrylic</value>
</data>
@@ -762,40 +741,4 @@
<value>Open your settings.json file. Alt+Click to open your defaults.json file.</value>
<comment>{Locked="settings.json"}, {Locked="defaults.json"}</comment>
</data>
<data name="ColorScheme_DeleteButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Delete the current color scheme.</value>
</data>
<data name="Rename.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Rename</value>
</data>
<data name="Profile_DeleteButtonDisclaimerInBox" xml:space="preserve">
<value>This profile cannot be deleted because it is included by default.</value>
</data>
<data name="Profile_DeleteButtonDisclaimerDynamic" xml:space="preserve">
<value>This profile cannot be deleted because it is automatically generated.</value>
</data>
<data name="ColorScheme_DeleteButtonDisclaimerInBox" xml:space="preserve">
<value>This color scheme cannot be deleted or renamed because it is included by default.</value>
</data>
<data name="ColorScheme_DeleteConfirmationButton.Content" xml:space="preserve">
<value>Yes, delete color scheme</value>
</data>
<data name="ColorScheme_DeleteConfirmationMessage.Text" xml:space="preserve">
<value>Are you sure you want to delete this color scheme?</value>
</data>
<data name="RenameAccept.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Accept rename</value>
</data>
<data name="RenameCancel.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Cancel rename</value>
</data>
<data name="Profile_BaseLayerDisclaimer.Text" xml:space="preserve">
<value>Settings defined here will apply to all profiles unless they are overridden by a profile's settings.</value>
</data>
<data name="Profile_DeleteConfirmationButton.Content" xml:space="preserve">
<value>Yes, delete profile</value>
</data>
<data name="Profile_DeleteConfirmationMessage.Text" xml:space="preserve">
<value>Are you sure you want to delete this profile?</value>
</data>
</root>

View File

@@ -5,7 +5,6 @@
#include "ColorScheme.h"
#include "DefaultSettings.h"
#include "../../types/inc/Utils.hpp"
#include "../../types/inc/colorTable.hpp"
#include "Utils.h"
#include "JsonUtils.h"
@@ -42,18 +41,14 @@ static constexpr std::array<std::string_view, 16> TableColors = {
};
ColorScheme::ColorScheme() :
ColorScheme(L"", DEFAULT_FOREGROUND_WITH_ALPHA, DEFAULT_BACKGROUND_WITH_ALPHA, DEFAULT_CURSOR_COLOR)
_Foreground{ DEFAULT_FOREGROUND_WITH_ALPHA },
_Background{ DEFAULT_BACKGROUND_WITH_ALPHA },
_SelectionBackground{ DEFAULT_FOREGROUND },
_CursorColor{ DEFAULT_CURSOR_COLOR }
{
Utils::InitializeCampbellColorTable(_table);
}
ColorScheme::ColorScheme(winrt::hstring name) :
ColorScheme(name, DEFAULT_FOREGROUND_WITH_ALPHA, DEFAULT_BACKGROUND_WITH_ALPHA, DEFAULT_CURSOR_COLOR)
{
Utils::InitializeCampbellColorTable(_table);
}
ColorScheme::ColorScheme(winrt::hstring name, COLORREF defaultFg, COLORREF defaultBg, COLORREF cursorColor) :
ColorScheme::ColorScheme(winrt::hstring name, Color defaultFg, Color defaultBg, Color cursorColor) :
_Name{ name },
_Foreground{ defaultFg },
_Background{ defaultBg },

View File

@@ -33,8 +33,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
public:
ColorScheme();
ColorScheme(hstring name);
ColorScheme(hstring name, COLORREF defaultFg, COLORREF defaultBg, COLORREF cursorColor);
ColorScheme(hstring name, Windows::UI::Color defaultFg, Windows::UI::Color defaultBg, Windows::UI::Color cursorColor);
com_ptr<ColorScheme> Copy() const;
static com_ptr<ColorScheme> FromJson(const Json::Value& json);
@@ -61,8 +60,3 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
friend class SettingsModelLocalTests::ColorSchemeTests;
};
}
namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
{
BASIC_FACTORY(ColorScheme);
}

View File

@@ -4,8 +4,6 @@
namespace Microsoft.Terminal.Settings.Model
{
[default_interface] runtimeclass ColorScheme {
ColorScheme(String name);
String Name;
Windows.UI.Color Foreground;

View File

@@ -334,11 +334,6 @@ void GlobalAppSettings::AddColorScheme(const Model::ColorScheme& scheme)
_colorSchemes.Insert(scheme.Name(), scheme);
}
void GlobalAppSettings::RemoveColorScheme(hstring schemeName)
{
_colorSchemes.TryRemove(schemeName);
}
// Method Description:
// - Return the warnings that we've collected during parsing the JSON for the
// keybindings. It's possible that the user provided keybindings have some

View File

@@ -40,7 +40,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
Windows::Foundation::Collections::IMapView<hstring, Model::ColorScheme> ColorSchemes() noexcept;
void AddColorScheme(const Model::ColorScheme& scheme);
void RemoveColorScheme(hstring schemeName);
Model::KeyMapping KeyMap() const noexcept;

View File

@@ -137,7 +137,6 @@ namespace Microsoft.Terminal.Settings.Model
Windows.Foundation.Collections.IMapView<String, ColorScheme> ColorSchemes();
void AddColorScheme(ColorScheme scheme);
void RemoveColorScheme(String schemeName);
KeyMapping KeyMap();

View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- A note about this project: We're building the test code dll from this
project, but it _MUST_ be run in conjunction with the TestHostApp project.
TestHostApp actually will build a TestHost executable and packaging bits
that we can use to run our tests. We need TestHostApp so that our
dependencies, like MUX, can be aggregated correctly, and resources properly
combined into a resources.pri file.
TestHostApp will manually copy the output of this project into it's own
OutDir, so we can run the tests from there. -->
<PropertyGroup>
<ProjectGuid>{68a10cd3-aa64-465b-af5f-ed4e9700543c}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>RemotingUnitTests</RootNamespace>
<ProjectName>UnitTests_Remoting</ProjectName>
<TargetName>Remoting.UnitTests</TargetName>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<WindowsTargetPlatformMinVersion>10.0.18362.0</WindowsTargetPlatformMinVersion>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
<OpenConsoleCppWinRTProject>true</OpenConsoleCppWinRTProject>
</PropertyGroup>
<Import Project="$(SolutionDir)\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)\src\cppwinrt.build.pre.props" />
<!-- ========================= Headers ======================== -->
<ItemGroup>
<ClInclude Include="pch.h" />
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
<ClCompile Include="RemotingTests.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>
<ProjectReference Include="$(OpenConsoleDir)\src\cascadia\Remoting\Microsoft.Terminal.RemotingLib.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)\src\types\lib\types.vcxproj" />
<!-- If you don't reference these projects here, the
_ConsoleGenerateAdditionalWinmdManifests step won't gather the winmd's -->
<ProjectReference Include="$(OpenConsoleDir)\src\cascadia\Remoting\dll\Microsoft.Terminal.Remoting.vcxproj" />
</ItemGroup>
<!-- ========================= Globals ======================== -->
<!-- ====================== Compiler & Linker Flags ===================== -->
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>..;$(OpenConsoleDir)\dep;$(OpenConsoleDir)\dep\jsoncpp\json;$(OpenConsoleDir)src\inc;$(OpenConsoleDir)src\inc\test;$(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)\src\cascadia\Remoting\Generated Files";%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<!-- Manually disable unreachable code warning, because jconcpp has a ton of that. -->
<DisableSpecificWarnings>4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>onecoreuap.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<PropertyGroup>
<GenerateManifest>true</GenerateManifest>
<EmbedManifest>true</EmbedManifest>
</PropertyGroup>
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(OpenConsoleDir)src\common.build.post.props" />
<Import Project="$(OpenConsoleDir)src\common.build.tests.props" />
</Project>

View File

@@ -0,0 +1,295 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "../Remoting/Monarch.h"
using namespace Microsoft::Console;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace WEX::Common;
using namespace winrt;
using namespace winrt::Microsoft::Terminal;
// These are some gross macros that let us call a private ctor for
// Monarch/Peasant. We can't just use make_self, because that doesn't let us
// call a private ctor. We can use com_ptr::attach, but since we're allocating
// the thing on the stack, we need to make sure to call detach before the object
// is destructed.
#define MAKE_MONARCH(name, pid) \
Remoting::implementation::Monarch _local_##name##{ pid }; \
com_ptr<Remoting::implementation::Monarch> name; \
name.attach(&_local_##name##); \
auto cleanup_##name## = wil::scope_exit([&]() { name.detach(); });
#define MAKE_PEASANT(name, pid) \
Remoting::implementation::Peasant _local_##name##{ pid }; \
com_ptr<Remoting::implementation::Peasant> name; \
name.attach(&_local_##name##); \
auto cleanup_##name## = wil::scope_exit([&]() { name.detach(); });
namespace RemotingUnitTests
{
// This is a silly helper struct.
// It will always throw an hresult_error on any of it's methods.
// In the tests, it's hard to emulate a peasant process being totally dead once the Monarch has captured a reference to it. Since everything's in-proc in the tests, we can't decrement the refcount in such a way that the monarch's reference will throw a catchable exception.
// Instead, this class can be used to replace a peasant inside a Monarch, to emulate that peasant process dying. Any time the monarch tries to do something to this peasant, it'll throw an exception.
struct DeadPeasant : implements<DeadPeasant, winrt::Microsoft::Terminal::Remoting::IPeasant>
{
DeadPeasant() = default;
void AssignID(uint64_t /*id*/) { throw winrt::hresult_error{}; };
uint64_t GetID() { throw winrt::hresult_error{}; };
uint64_t GetPID() { throw winrt::hresult_error{}; };
bool ExecuteCommandline(const winrt::Microsoft::Terminal::Remoting::CommandlineArgs& /*args*/) { throw winrt::hresult_error{}; }
winrt::Microsoft::Terminal::Remoting::CommandlineArgs InitialArgs() { throw winrt::hresult_error{}; }
TYPED_EVENT(WindowActivated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(ExecuteCommandlineRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::CommandlineArgs);
};
class RemotingTests
{
BEGIN_TEST_CLASS(RemotingTests)
END_TEST_CLASS()
TEST_METHOD(CreateMonarch);
TEST_METHOD(CreatePeasant);
TEST_METHOD(CreatePeasantWithNew);
TEST_METHOD(AddPeasants);
TEST_METHOD(GetPeasantsByID);
TEST_METHOD(AddPeasantsToNewMonarch);
TEST_METHOD(RemovePeasantFromMonarchWhenFreed);
TEST_CLASS_SETUP(ClassSetup)
{
return true;
}
static void _killPeasant(const com_ptr<Remoting::implementation::Monarch>& m,
const uint64_t peasantID);
};
void RemotingTests::_killPeasant(const com_ptr<Remoting::implementation::Monarch>& m,
const uint64_t peasantID)
{
if (peasantID <= 0)
{
return;
}
com_ptr<DeadPeasant> tombstone;
tombstone.attach(new DeadPeasant());
m->_peasants[peasantID] = *tombstone;
}
void RemotingTests::CreateMonarch()
{
auto m1 = winrt::make_self<Remoting::implementation::Monarch>();
VERIFY_IS_NOT_NULL(m1);
VERIFY_ARE_EQUAL(GetCurrentProcessId(),
m1->GetPID(),
L"A Monarch without an explicit PID should use the current PID");
Log::Comment(L"That's what we need for window process management, but for tests, it'll be more useful to fake the PIDs.");
auto expectedFakePID = 1234u;
MAKE_MONARCH(m2, expectedFakePID);
VERIFY_IS_NOT_NULL(m2);
VERIFY_ARE_EQUAL(expectedFakePID,
m2->GetPID(),
L"A Monarch with an explicit PID should use the one we provided");
}
void RemotingTests::CreatePeasant()
{
auto p1 = winrt::make_self<Remoting::implementation::Peasant>();
VERIFY_IS_NOT_NULL(p1);
VERIFY_ARE_EQUAL(GetCurrentProcessId(),
p1->GetPID(),
L"A Peasant without an explicit PID should use the current PID");
Log::Comment(L"That's what we need for window process management, but for tests, it'll be more useful to fake the PIDs.");
auto expectedFakePID = 2345u;
MAKE_PEASANT(p2, expectedFakePID);
VERIFY_IS_NOT_NULL(p2);
VERIFY_ARE_EQUAL(expectedFakePID,
p2->GetPID(),
L"A Peasant with an explicit PID should use the one we provided");
}
void RemotingTests::CreatePeasantWithNew()
{
Log::Comment(L"The same thing as the above test, but with `new` instead of insanity on the stack");
auto p1 = winrt::make_self<Remoting::implementation::Peasant>();
VERIFY_IS_NOT_NULL(p1);
VERIFY_ARE_EQUAL(GetCurrentProcessId(),
p1->GetPID(),
L"A Peasant without an explicit PID should use the current PID");
auto expectedFakePID = 2345u;
com_ptr<Remoting::implementation::Peasant> p2;
VERIFY_IS_NULL(p2);
p2.attach(new Remoting::implementation::Peasant(expectedFakePID));
VERIFY_IS_NOT_NULL(p2);
VERIFY_ARE_EQUAL(expectedFakePID,
p2->GetPID(),
L"A Peasant with an explicit PID should use the one we provided");
}
void RemotingTests::AddPeasants()
{
const auto monarch0PID = 12345u;
const auto peasant1PID = 23456u;
const auto peasant2PID = 34567u;
com_ptr<Remoting::implementation::Monarch> m0;
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
com_ptr<Remoting::implementation::Peasant> p1;
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
com_ptr<Remoting::implementation::Peasant> p2;
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
VERIFY_IS_NOT_NULL(m0);
VERIFY_IS_NOT_NULL(p1);
VERIFY_IS_NOT_NULL(p2);
VERIFY_ARE_EQUAL(0, p1->GetID());
VERIFY_ARE_EQUAL(0, p2->GetID());
m0->AddPeasant(*p1);
m0->AddPeasant(*p2);
VERIFY_ARE_EQUAL(1, p1->GetID());
VERIFY_ARE_EQUAL(2, p2->GetID());
}
void RemotingTests::GetPeasantsByID()
{
const auto monarch0PID = 12345u;
const auto peasant1PID = 23456u;
const auto peasant2PID = 34567u;
com_ptr<Remoting::implementation::Monarch> m0;
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
com_ptr<Remoting::implementation::Peasant> p1;
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
com_ptr<Remoting::implementation::Peasant> p2;
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
VERIFY_IS_NOT_NULL(m0);
VERIFY_IS_NOT_NULL(p1);
VERIFY_IS_NOT_NULL(p2);
VERIFY_ARE_EQUAL(0, p1->GetID());
VERIFY_ARE_EQUAL(0, p2->GetID());
m0->AddPeasant(*p1);
m0->AddPeasant(*p2);
VERIFY_ARE_EQUAL(1, p1->GetID());
VERIFY_ARE_EQUAL(2, p2->GetID());
auto maybeP1 = m0->_getPeasant(1);
VERIFY_IS_NOT_NULL(maybeP1);
VERIFY_ARE_EQUAL(peasant1PID, maybeP1.GetPID());
auto maybeP2 = m0->_getPeasant(2);
VERIFY_IS_NOT_NULL(maybeP2);
VERIFY_ARE_EQUAL(peasant2PID, maybeP2.GetPID());
}
void RemotingTests::AddPeasantsToNewMonarch()
{
const auto monarch0PID = 12345u;
const auto peasant1PID = 23456u;
const auto peasant2PID = 34567u;
const auto monarch3PID = 45678u;
com_ptr<Remoting::implementation::Monarch> m0;
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
com_ptr<Remoting::implementation::Peasant> p1;
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
com_ptr<Remoting::implementation::Peasant> p2;
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
com_ptr<Remoting::implementation::Monarch> m3;
m3.attach(new Remoting::implementation::Monarch(monarch3PID));
VERIFY_IS_NOT_NULL(m0);
VERIFY_IS_NOT_NULL(p1);
VERIFY_IS_NOT_NULL(p2);
VERIFY_IS_NOT_NULL(m3);
VERIFY_ARE_EQUAL(0, p1->GetID());
VERIFY_ARE_EQUAL(0, p2->GetID());
m0->AddPeasant(*p1);
m0->AddPeasant(*p2);
VERIFY_ARE_EQUAL(1, p1->GetID());
VERIFY_ARE_EQUAL(2, p2->GetID());
m3->AddPeasant(*p1);
m3->AddPeasant(*p2);
VERIFY_ARE_EQUAL(1, p1->GetID());
VERIFY_ARE_EQUAL(2, p2->GetID());
}
void RemotingTests::RemovePeasantFromMonarchWhenFreed()
{
const auto monarch0PID = 12345u;
const auto peasant1PID = 23456u;
const auto peasant2PID = 34567u;
com_ptr<Remoting::implementation::Monarch> m0;
m0.attach(new Remoting::implementation::Monarch(monarch0PID));
com_ptr<Remoting::implementation::Peasant> p1;
p1.attach(new Remoting::implementation::Peasant(peasant1PID));
com_ptr<Remoting::implementation::Peasant> p2;
p2.attach(new Remoting::implementation::Peasant(peasant2PID));
VERIFY_IS_NOT_NULL(m0);
VERIFY_IS_NOT_NULL(p1);
VERIFY_IS_NOT_NULL(p2);
VERIFY_ARE_EQUAL(0, p1->GetID());
VERIFY_ARE_EQUAL(0, p2->GetID());
m0->AddPeasant(*p1);
m0->AddPeasant(*p2);
VERIFY_ARE_EQUAL(1, p1->GetID());
VERIFY_ARE_EQUAL(2, p2->GetID());
VERIFY_ARE_EQUAL(2u, m0->_peasants.size());
Log::Comment(L"Kill peasant 1. Make sure that it gets removed from the monarch.");
RemotingTests::_killPeasant(m0, p1->GetID());
auto maybeP2 = m0->_getPeasant(2);
VERIFY_IS_NOT_NULL(maybeP2);
VERIFY_ARE_EQUAL(peasant2PID, maybeP2.GetPID());
auto maybeP1 = m0->_getPeasant(1);
VERIFY_IS_NULL(maybeP1);
VERIFY_ARE_EQUAL(1u, m0->_peasants.size());
}
}

View File

@@ -0,0 +1,3 @@
EXPORTS
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE

View File

@@ -0,0 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"

View File

@@ -0,0 +1,39 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
--*/
#pragma once
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#define BLOCK_TIL
// This includes support libraries from the CRT, STL, WIL, and GSL
#include "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 <wil/cppwinrt.h>
#include <unknwn.h>
#include <hstring.h>
#include <WexTestClass.h>
#include "consoletaeftemplates.hpp"
#include <winrt/Windows.ApplicationModel.Resources.Core.h>
#include <winrt/Windows.system.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
// Manually include til after we include Windows.Foundation to give it winrt superpowers
#include "til.h"
// Common includes for most tests:
#include "../../inc/argb.h"
#include "../../inc/conattrs.hpp"
#include "../../types/inc/utils.hpp"
#include "../../inc/DefaultSettings.h"

View File

@@ -3529,7 +3529,7 @@ void ConptyRoundtripTests::HyperlinkIdConsistency()
auto verifyData = [](TextBuffer& tb) {
// Check that all the linked cells still have the same ID
auto& attrRow = tb.GetRowByOffset(0).GetAttrRow();
auto attrRow = tb.GetRowByOffset(0).GetAttrRow();
auto id = attrRow.GetAttrByColumn(0).GetHyperlinkId();
for (auto i = 1; i < 4; ++i)
{

View File

@@ -8,13 +8,12 @@
#include "../types/inc/User32Utils.hpp"
#include "resource.h"
#include <winrt/Microsoft.Terminal.TerminalControl.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 winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace ::Microsoft::Console;
using namespace ::Microsoft::Console::Types;
@@ -25,17 +24,24 @@ static constexpr short KeyPressed{ gsl::narrow_cast<short>(0x8000) };
AppHost::AppHost() noexcept :
_app{},
_windowManager{},
_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
_useNonClientArea = _logic.GetShowTabsInTitlebar();
// If there were commandline args to our process, try and process them here.
// Do this before AppLogic::Create, otherwise this will have no effect
// Do this before AppLogic::Create, otherwise this will have no effect.
//
// This will send our commandline to the Monarch, to ask if we should make a
// new window or not. If not, exit immediately.
_HandleCommandlineArgs();
if (!_shouldCreateWindow)
{
return;
}
_useNonClientArea = _logic.GetShowTabsInTitlebar();
if (_useNonClientArea)
{
_window = std::make_unique<NonClientIslandWindow>(_logic.GetRequestedTheme());
@@ -65,6 +71,7 @@ AppHost::AppHost() noexcept :
AppHost::~AppHost()
{
// destruction order is important for proper teardown here
_window = nullptr;
_app.Close();
_app = nullptr;
@@ -96,9 +103,35 @@ void AppHost::SetTaskbarProgress(const winrt::Windows::Foundation::IInspectable&
}
}
void _buildArgsFromCommandline(std::vector<winrt::hstring>& args)
{
if (auto commandline{ GetCommandLineW() })
{
int argc = 0;
// Get the argv, and turn them into a hstring array to pass to the app.
wil::unique_any<LPWSTR*, decltype(&::LocalFree), ::LocalFree> argv{ CommandLineToArgvW(commandline, &argc) };
if (argv)
{
for (auto& elem : wil::make_range(argv.get(), argc))
{
args.emplace_back(elem);
}
}
}
if (args.empty())
{
args.emplace_back(L"wt.exe");
}
}
// Method Description:
// - Retrieve any commandline args passed on the commandline, and pass them to
// the app logic for processing.
// the WindowManager, to ask if we should become a window process.
// - If we should create a window, then pass the arguments to the app logic for
// processing.
// - If we shouldn't become a window, set _shouldCreateWindow to false and exit
// immediately.
// - If the logic determined there's an error while processing that commandline,
// display a message box to the user with the text of the error, and exit.
// * We display a message box because we're a Win32 application (not a
@@ -111,21 +144,24 @@ void AppHost::SetTaskbarProgress(const winrt::Windows::Foundation::IInspectable&
// - <none>
void AppHost::_HandleCommandlineArgs()
{
if (auto commandline{ GetCommandLineW() })
std::vector<winrt::hstring> args;
_buildArgsFromCommandline(args);
std::wstring cwd{ wil::GetCurrentDirectoryW<std::wstring>() };
Remoting::CommandlineArgs eventArgs{ { args }, { cwd } };
_windowManager.ProposeCommandline(eventArgs);
_shouldCreateWindow = _windowManager.ShouldCreateWindow();
if (!_shouldCreateWindow)
{
int argc = 0;
return;
}
// Get the argv, and turn them into a hstring array to pass to the app.
wil::unique_any<LPWSTR*, decltype(&::LocalFree), ::LocalFree> argv{ CommandLineToArgvW(commandline, &argc) };
if (argv)
if (auto peasant{ _windowManager.CurrentWindow() })
{
if (auto args{ peasant.InitialArgs() })
{
std::vector<winrt::hstring> args;
for (auto& elem : wil::make_range(argv.get(), argc))
{
args.emplace_back(elem);
}
const auto result = _logic.SetStartupCommandline({ args });
const auto result = _logic.SetStartupCommandline(args.Args());
const auto message = _logic.ParseCommandlineMessage();
if (!message.empty())
{
@@ -145,7 +181,19 @@ void AppHost::_HandleCommandlineArgs()
}
}
}
// After handling the initial args, hookup the callback for handling
// future commandline invocations. When our peasant is told to execute a
// commandline (in the future), it'll trigger this callback, that we'll
// use to send the actions to the app.
peasant.ExecuteCommandlineRequested({ this, &AppHost::_DispatchCommandline });
}
// TODO:projects/5 if we end up not creating a new window, we crash. I'm
// thinking this is because the XAML host is not happy about being torn
// down before it has a chance to do really anything. Is there some way
// to get the app logic without instantiating the entire app? or at
// least the parts we'll need for remoting?
}
// Method Description:
@@ -462,3 +510,14 @@ void AppHost::_WindowMouseWheeled(const til::point coord, const int32_t delta)
}
}
}
bool AppHost::HasWindow()
{
return _shouldCreateWindow;
}
void AppHost::_DispatchCommandline(winrt::Windows::Foundation::IInspectable /*sender*/,
winrt::Microsoft::Terminal::Remoting::CommandlineArgs args)
{
_logic.ExecuteCommandline(args.Args());
}

View File

@@ -3,9 +3,6 @@
#include "pch.h"
#include <winrt/TerminalApp.h>
#include <winrt/Microsoft.Terminal.Settings.Model.h>
#include "NonClientIslandWindow.h"
class AppHost
@@ -20,12 +17,16 @@ public:
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
void SetTaskbarProgress(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
bool HasWindow();
private:
bool _useNonClientArea;
std::unique_ptr<IslandWindow> _window;
winrt::TerminalApp::App _app;
winrt::TerminalApp::AppLogic _logic;
bool _shouldCreateWindow{ false };
winrt::Microsoft::Terminal::Remoting::WindowManager _windowManager{ nullptr };
void _HandleCommandlineArgs();
@@ -43,4 +44,7 @@ private:
void _RaiseVisualBell(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& arg);
void _WindowMouseWheeled(const til::point coord, const int32_t delta);
void _DispatchCommandline(winrt::Windows::Foundation::IInspectable sender,
winrt::Microsoft::Terminal::Remoting::CommandlineArgs args);
};

View File

@@ -77,6 +77,7 @@
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettingsModel\dll\Microsoft.Terminal.Settings.Model.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalApp\dll\TerminalApp.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\Remoting\dll\Microsoft.Terminal.Remoting.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalSettingsEditor\Microsoft.Terminal.Settings.Editor.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj" />
@@ -98,7 +99,7 @@
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" />
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.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>
@@ -106,7 +107,7 @@
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets'))" />
</Target>

View File

@@ -124,6 +124,10 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
// Terminal App. This MUST BE constructed before the Xaml manager as TermApp
// provides an implementation of Windows.UI.Xaml.Application.
AppHost host;
if (!host.HasWindow())
{
return 0;
}
// Initialize the xaml content. This must be called AFTER the
// WindowsXamlManager is initialized.

View File

@@ -61,6 +61,11 @@ Abstract:
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.ui.xaml.media.h>
#include <winrt/TerminalApp.h>
#include <winrt/Microsoft.Terminal.Settings.Model.h>
#include <winrt/Microsoft.Terminal.Remoting.h>
#include <winrt/Microsoft.Terminal.TerminalControl.h>
#include <wil/resource.h>
#include <wil/win32_helpers.h>

View File

@@ -26,7 +26,7 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="AuditMode|Win32">
<ProjectConfiguration Include="AuditMode|Win32">
<Configuration>AuditMode</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
@@ -90,7 +90,7 @@
<PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)\src\inc;$(SolutionDir)\dep;$(SolutionDir)\dep\Console;$(SolutionDir)\dep\Win32K;$(SolutionDir)\dep\gsl\include;$(SolutionDir)\dep\wil\include;$(SolutionDir)\oss\chromium;$(SolutionDir)\oss\fmt\include;$(SolutionDir)\oss\dynamic_bitset;$(SolutionDir)\oss\libpopcnt;$(SolutionDir)\oss\interval_tree;$(SolutionDir)\oss\boost\boost_1_73_0;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)\src\inc;$(SolutionDir)\dep;$(SolutionDir)\dep\Console;$(SolutionDir)\dep\Win32K;$(SolutionDir)\dep\gsl\include;$(SolutionDir)\dep\wil\include;$(SolutionDir)\oss\chromium;$(SolutionDir)\oss\fmt\include;$(SolutionDir)\oss\dynamic_bitset;$(SolutionDir)\oss\libpopcnt;$(SolutionDir)\oss\interval_tree;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeTypeInfo>false</RuntimeTypeInfo>

View File

@@ -286,7 +286,7 @@ void CONSOLE_INFORMATION::SetTitle(const std::wstring_view newTitle)
// - <none>
void CONSOLE_INFORMATION::SetTitlePrefix(const std::wstring& newTitlePrefix)
{
_TitleAndPrefix = newTitlePrefix + _Title;
_TitlePrefix = newTitlePrefix;
auto* const pRender = ServiceLocator::LocateGlobals().pRender;
if (pRender)
@@ -337,9 +337,9 @@ const std::wstring& CONSOLE_INFORMATION::GetTitle() const noexcept
// - <none>
// Return Value:
// - a new wstring containing the combined prefix and title.
const std::wstring& CONSOLE_INFORMATION::GetTitleAndPrefix() const
const std::wstring CONSOLE_INFORMATION::GetTitleAndPrefix() const
{
return _TitleAndPrefix;
return _TitlePrefix + _Title;
}
// Method Description:

View File

@@ -318,7 +318,7 @@ const bool RenderData::IsGridLineDrawingAllowed() noexcept
// - Retrieves the title information to be displayed in the frame/edge of the window
// Return Value:
// - String with title information
const std::wstring& RenderData::GetConsoleTitle() const noexcept
const std::wstring RenderData::GetConsoleTitle() const noexcept
{
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
return gci.GetTitleAndPrefix();

Some files were not shown because too many files have changed in this diff Show More