diff --git a/.github/actions/spelling/allow/allow.txt b/.github/actions/spelling/allow/allow.txt index 64bd05d091..630edfebce 100644 --- a/.github/actions/spelling/allow/allow.txt +++ b/.github/actions/spelling/allow/allow.txt @@ -23,6 +23,7 @@ dzhe Emacspeak Fitt FTCS +flac gantt gfm ghe diff --git a/.github/actions/spelling/allow/apis.txt b/.github/actions/spelling/allow/apis.txt index 3ffc52f9fb..f7671d04f4 100644 --- a/.github/actions/spelling/allow/apis.txt +++ b/.github/actions/spelling/allow/apis.txt @@ -99,11 +99,9 @@ IImage IInheritable IMap imm -IMonarch IObject iosfwd IPackage -IPeasant isa ISetup isspace diff --git a/.github/actions/spelling/excludes.txt b/.github/actions/spelling/excludes.txt index 4b6ae25b16..896211b8f1 100644 --- a/.github/actions/spelling/excludes.txt +++ b/.github/actions/spelling/excludes.txt @@ -99,6 +99,7 @@ Resources/(?!en) ^NOTICE.md ^oss/ ^samples/PixelShaders/Screenshots/ +^src/cascadia/TerminalSettingsEditor/SegoeFluentIconList.h$ ^src/interactivity/onecore/BgfxEngine\. ^src/renderer/atlas/ ^src/renderer/wddmcon/WddmConRenderer\. diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index b09dcd5223..e78cb97139 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -163,6 +163,7 @@ CBN cbt Ccc CCCBB +CCCDDD cch CCHAR CCmd @@ -171,6 +172,7 @@ CCom CConsole CCRT cdd +cds CELLSIZE cfae cfie @@ -213,6 +215,7 @@ codepages codepath coinit colorizing +COLORONCOLOR COLORREFs colorschemes colorspec @@ -280,6 +283,8 @@ contypes conwinuserrefs coordnew COPYCOLOR +COPYDATA +COPYDATASTRUCT CORESYSTEM cotaskmem countof @@ -366,6 +371,7 @@ DColor dcommon DComposition dde +DDDCCC DDESHARE DDevice DEADCHAR @@ -567,6 +573,7 @@ EOK EPres EQU ERASEBKGND +ERRORONEXIT ESFCIB esrp ESV @@ -837,6 +844,7 @@ IFACEMETHODIMP ification IGNORELANGUAGE iid +IInput IIo ILC ILCo @@ -856,6 +864,7 @@ inkscape INLINEPREFIX inproc Inputkeyinfo +inputpaneinterop Inputreadhandledata INPUTSCOPE INSERTMODE @@ -1348,6 +1357,7 @@ PNMLINK pntm POBJECT Podcast +POINTERUPDATE POINTSLIST policheck POLYTEXTW diff --git a/OpenConsole.sln b/OpenConsole.sln index 7698af450d..fa94a4f8f0 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -178,7 +178,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminal", "src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj", "{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}" ProjectSection(ProjectDependencies) = postProject - {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} @@ -348,26 +347,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_SettingsModel", " {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MonarchPeasantSample", "src\tools\MonarchPeasantSample\MonarchPeasantSample.vcxproj", "{21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}" - ProjectSection(ProjectDependencies) = postProject - {18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263} - EndProjectSection -EndProject -Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "MonarchPeasantPackage", "src\tools\MonarchPeasantPackage\MonarchPeasantPackage.wapproj", "{F75E29D0-D288-478B-8D83-2C190F321A3F}" -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 - {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} - {43CE4CE5-0010-4B99-9569-672670D26E26} = {43CE4CE5-0010-4B99-9569-672670D26E26} - EndProjectSection -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wpf", "wpf", "{4DAF0299-495E-4CD1-A982-9BAC16A45932}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenConsoleProxy", "src\host\proxy\Host.Proxy.vcxproj", "{71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}" @@ -1925,135 +1904,6 @@ 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 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.AuditMode|Any CPU.ActiveCfg = Debug|Win32 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.AuditMode|ARM64.ActiveCfg = Release|ARM64 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.AuditMode|x64.ActiveCfg = Release|x64 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.AuditMode|x86.ActiveCfg = Release|Win32 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Debug|ARM64.Build.0 = Debug|ARM64 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Debug|x64.ActiveCfg = Debug|x64 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Debug|x64.Build.0 = Debug|x64 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Debug|x86.ActiveCfg = Debug|Win32 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Debug|x86.Build.0 = Debug|Win32 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Release|Any CPU.ActiveCfg = Release|Win32 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Release|ARM64.ActiveCfg = Release|ARM64 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Release|ARM64.Build.0 = Release|ARM64 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Release|x64.ActiveCfg = Release|x64 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Release|x64.Build.0 = Release|x64 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Release|x86.ActiveCfg = Release|Win32 - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Release|x86.Build.0 = Release|Win32 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|Any CPU.ActiveCfg = Release|Any CPU - {F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|ARM64.ActiveCfg = Debug|ARM64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|ARM64.Build.0 = Debug|ARM64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|ARM64.Deploy.0 = Debug|ARM64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|x64.ActiveCfg = Debug|x64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|x64.Build.0 = Debug|x64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|x64.Deploy.0 = Debug|x64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|x86.ActiveCfg = Debug|x86 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|x86.Build.0 = Debug|x86 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.AuditMode|x86.Deploy.0 = Debug|x86 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|ARM64.Build.0 = Debug|ARM64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x64.ActiveCfg = Debug|x64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x64.Build.0 = Debug|x64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x64.Deploy.0 = Debug|x64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x86.ActiveCfg = Debug|x86 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x86.Build.0 = Debug|x86 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x86.Deploy.0 = Debug|x86 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|Any CPU.ActiveCfg = Release|Any CPU - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|x64.ActiveCfg = Release|x64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|x86.ActiveCfg = Release|x86 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|ARM64.ActiveCfg = Release|ARM64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|ARM64.Build.0 = Release|ARM64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|ARM64.Deploy.0 = Release|ARM64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|x64.ActiveCfg = Release|x64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|x64.Build.0 = Release|x64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|x64.Deploy.0 = Release|x64 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|x86.ActiveCfg = Release|x86 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|x86.Build.0 = Release|x86 - {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|x86.Deploy.0 = Release|x86 - {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|x64.ActiveCfg = Release|x64 - {43CE4CE5-0010-4B99-9569-672670D26E26}.AuditMode|x64.Build.0 = 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|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}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 - {43CE4CE5-0010-4B99-9569-672670D26E26}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 - {43CE4CE5-0010-4B99-9569-672670D26E26}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 - {43CE4CE5-0010-4B99-9569-672670D26E26}.Fuzzing|x86.ActiveCfg = Fuzzing|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|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|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|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}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 - {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 - {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 - {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Fuzzing|x86.ActiveCfg = Fuzzing|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|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|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|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}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 - {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 - {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 - {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Fuzzing|x86.ActiveCfg = Fuzzing|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|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 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|ARM64.Build.0 = AuditMode|ARM64 @@ -2461,11 +2311,6 @@ Global {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {77875138-BB08-49F9-8BB1-409C2150E0E1} {CA5CAD1A-082C-4476-9F33-94B339494076} = {77875138-BB08-49F9-8BB1-409C2150E0E1} {CA5CAD1A-9B68-456A-B13E-C8218070DC42} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E} - {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D} = {A10C4720-DCA4-4640-9749-67F4314F527C} - {F75E29D0-D288-478B-8D83-2C190F321A3F} = {A10C4720-DCA4-4640-9749-67F4314F527C} - {43CE4CE5-0010-4B99-9569-672670D26E26} = {2D17E75D-2DDC-42C4-AD70-704D95A937AE} - {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {2D17E75D-2DDC-42C4-AD70-704D95A937AE} - {68A10CD3-AA64-465B-AF5F-ED4E9700543C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E} {4DAF0299-495E-4CD1-A982-9BAC16A45932} = {59840756-302F-44DF-AA47-441A9D673202} {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB} {2D17E75D-2DDC-42C4-AD70-704D95A937AE} = {59840756-302F-44DF-AA47-441A9D673202} diff --git a/README.md b/README.md index 14f4c58bfe..71b0daad26 100644 --- a/README.md +++ b/README.md @@ -362,15 +362,6 @@ If you would like to ask a question that you feel doesn't warrant an issue ## Building the Code -This repository uses [git -submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) for some of its -dependencies. To make sure submodules are restored or updated, be sure to run -the following prior to building: - -```shell -git submodule update --init --recursive -``` - OpenConsole.sln may be built from within Visual Studio or from the command-line using a set of convenience scripts & tools in the **/tools** directory: diff --git a/build/StoreSubmission/Preview/PDPs/de-DE/PDP.xml b/build/StoreSubmission/Preview/PDPs/de-DE/PDP.xml index f71e42e202..488e9d0da7 100644 --- a/build/StoreSubmission/Preview/PDPs/de-DE/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/de-DE/PDP.xml @@ -56,15 +56,11 @@ Dies ist ein Open Source-Projekt, und wir freuen uns über die Teilnahme der Com Version __VERSION_NUMBER__ -– Wir haben umgeschrieben, wie Konsolenanwendungen im Terminal gehostet werden! Melden Sie alle auftretenden Fehler. -- Terminal unterstützt jetzt Sixels! -- Sie können jetzt ein angedocktes Fenster öffnen, das Ausschnitte von Befehlen enthält, die Sie gespeichert haben, um sie später zu verwenden. -- Für Benutzer der Eingabeaufforderung der neuesten Version von Windows 11 wird möglicherweise ein „Kurzer Tipp“-Symbol angezeigt, das installierbare Software von WinGet - vorschlägt -- Ausgewählter Text wird jetzt viel sichtbarer (und anpassbarer!) -- Eine Reihe von Zuverlässigkeitsfehlern, Komfortproblemen und Ärgernissen wurden behoben. +- Wir haben der Benutzeroberfläche durchschnittliche Einstellungen hinzugefügt, die nur einmal in der JSON-Datei vorhanden waren, einschließlich einer neuen Seite zum Anpassen des Layouts Ihres Menüs "Neue Registerkarte"! +- Wir haben die Fensterverwaltung zurückgesetzt, um die Zuverlässigkeit zu verbessern; Melden Sie alle Fehler, die mit dem alias "wt.exe" auftreten. +- Profile zeigen jetzt ein Symbol an, wenn sie ausgeblendet wurden oder auf programme verweisen, die deinstalliert wurden. -Weitere Informationen finden Sie auf unserer GitHub-Releaseseite. +Weitere Details finden Sie auf unserer GitHub-Releasesseite. diff --git a/build/StoreSubmission/Preview/PDPs/en-US/PDP.xml b/build/StoreSubmission/Preview/PDPs/en-US/PDP.xml index d535a80251..3e4fa3dbd8 100644 --- a/build/StoreSubmission/Preview/PDPs/en-US/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/en-US/PDP.xml @@ -54,14 +54,11 @@ This is an open source project and we welcome community participation. To partic - Version __VERSION_NUMBER__ + Version __VERSION_NUMBER__ -- We've rewritten how console applications are hosted inside Terminal! Please report any bugs you encounter. -- Terminal now supports Sixels! -- You can now open a docked panel containing snippets of commands you have saved to use later -- Command Prompt users on the latest Windows 11 release may see a "quick tip" icon that suggests installable software from WinGet -- Selected text will now be much more visible (and customizable!) -- A number of reliabilty bugs, convenience issues and annoyances have been fixed. +- We've added dozens of settings to the UI that once only existed in the JSON file, including a new page for customizing the layout of your New Tab menu! +- We have rearchitected window management to improve reliability; please file any bugs you encounter with the wt.exe alias +- Profiles now show an icon if they've been hidden or refer to programs which were uninstalled. Please see our GitHub releases page for additional details. diff --git a/build/StoreSubmission/Preview/PDPs/es-ES/PDP.xml b/build/StoreSubmission/Preview/PDPs/es-ES/PDP.xml index 0a414940f8..d93f10de27 100644 --- a/build/StoreSubmission/Preview/PDPs/es-ES/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/es-ES/PDP.xml @@ -56,14 +56,11 @@ Este es un proyecto de fuente abierta y animamos a la comunidad a participar. Pa Versión __VERSION_NUMBER__ -- Hemos reescrito cómo se hospedan las aplicaciones de consola en Terminal. Informe de los errores que encuentre. -- Terminal ahora admite sixeles. -- Ahora puede abrir un panel acoplado que contenga fragmentos de comandos que haya guardado para usarlos más adelante -- Los usuarios del símbolo del sistema de la versión más reciente de Windows 11 pueden ver un icono de "sugerencia rápida" que sugiere software instalable de WinGet -- El texto seleccionado ahora será mucho más visible (y personalizable) -- Se han corregido varios errores de fiabilidad, problemas de comodidad y molestias. +- Hemos agregado decenas de configuraciones a la interfaz de usuario que solo existían una vez en el archivo JSON, incluida una página nueva para personalizar el diseño del menú Nueva pestaña. +- Tenemos administración de ventanas rearchitecdas para mejorar la confiabilidad; envíe los errores que encuentre con el alias de wt.exe. +- Ahora, los perfiles muestran un icono si se han ocultado o hacen referencia a programas que se han desinstalado. -Consulte la página de versiones de GitHub para más información. +Consulte nuestra página de versiones de GitHub para obtener más detalles. diff --git a/build/StoreSubmission/Preview/PDPs/fr-FR/PDP.xml b/build/StoreSubmission/Preview/PDPs/fr-FR/PDP.xml index d8a1b84250..526be4f3ba 100644 --- a/build/StoreSubmission/Preview/PDPs/fr-FR/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/fr-FR/PDP.xml @@ -54,16 +54,13 @@ Il s’agit d’un projet open source et nous vous invitons à participer dans l - Version __VERSION_NUMBER__ + __VERSION_NUMBER__ de version -- Nous avons réécrit la manière dont les applications de console sont hébergées dans Terminal ! Veuillez signaler tout bug que vous rencontrez. -- Le terminal prend désormais en charge Sixels ! -- Vous pouvez désormais ouvrir un panneau ancré contenant des extraits de commandes que vous avez enregistrées pour les utiliser ultérieurement -- Les utilisateurs de l'invite de commande sur la dernière version de Windows 11 peuvent voir une icône « astuce rapide » qui suggère un logiciel installable à partir de WinGet -- Le texte sélectionné sera désormais beaucoup plus visible (et personnalisable !) -- Un certain nombre de bugs de fiabilité, de problèmes de commodité et de désagréments ont été corrigés. +- Nous avons ajouté des milliers de paramètres à l’interface utilisateur qui n’existaient auparavant que dans le fichier JSON, y compris une nouvelle page pour personnaliser la disposition de votre menu Nouvel onglet ! +- Nous avons réarchitialiser la gestion des fenêtres pour améliorer la fiabilité ; entrez les bogues rencontrés avec l’alias wt.exe +- Les profils affichent désormais une icône s’ils ont été masqués ou s’ils font référence à des programmes qui ont été désinstallés. -Veuillez consulter notre page de versions GitHub pour plus de détails. +Pour plus d’informations, consultez notre page des mises en production GitHub. diff --git a/build/StoreSubmission/Preview/PDPs/it-IT/PDP.xml b/build/StoreSubmission/Preview/PDPs/it-IT/PDP.xml index aa18255f78..8c5ca0a25c 100644 --- a/build/StoreSubmission/Preview/PDPs/it-IT/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/it-IT/PDP.xml @@ -54,16 +54,13 @@ Si tratta di un progetto open source e la partecipazione della community è molt - Versione __VERSION_NUMBER__ + Versione __VERSION_NUMBER__ -- È stato riscritto il modo in cui le applicazioni della console vengono ospitate all'interno di Terminale. Segnala eventuali bug riscontrati. -- Terminal supporta ora Sixel. -- È ora possibile aprire un pannello ancorato contenente frammenti di comandi salvati per usarli in seguito -- Gli utenti del prompt dei comandi nella versione più recente di Windows 11 potrebbero visualizzare un'icona di "suggerimento rapido" che consiglia il software installabile da WinGet -- Il testo selezionato sarà ora molto più visibile, oltre che personalizzabile. -- Sono stati risolti diversi bug di affidabilità, problemi di praticità e fastidi. +- Sono state aggiunte decine di impostazioni all'interfaccia utente che una volta esisteva solo nel file JSON, inclusa una nuova pagina per personalizzare il layout del menu Nuova scheda. +- È stata riattivata la gestione delle finestre per migliorare l'affidabilità; inserire eventuali bug riscontrati con l'alias wt.exe +- I profili ora mostrano un'icona se sono stati nascosti o fanno riferimento ai programmi che sono stati disinstallati. -Per altri dettagli, vedi la pagina delle versioni di GitHub. +Per altri dettagli, vedere la pagina delle versioni di GitHub. diff --git a/build/StoreSubmission/Preview/PDPs/ja-JP/PDP.xml b/build/StoreSubmission/Preview/PDPs/ja-JP/PDP.xml index bc1f0be0fb..0390ceb54b 100644 --- a/build/StoreSubmission/Preview/PDPs/ja-JP/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/ja-JP/PDP.xml @@ -56,14 +56,11 @@ バージョン __VERSION_NUMBER__ -- ターミナル内でのコンソール アプリケーションのホスト方法を書き換えました。発生したバグを報告してください。 -- ターミナルで Sixels がサポートされるようになりました。 -- 後で使用するために保存したコマンドのスニペットを含むドッキング パネルを開けるようになりました -- 最新の Windows 11 リリースのコマンド プロンプト ユーザーには、WinGet からインストール可能なソフトウェアを提案する "クイック ヒント" アイコンが表示される場合があります -- 選択したテキストが大幅に見やすくなりました (カスタマイズも可能です) -- 信頼性に関するバグ、利便性の問題、不快な問題の多くが修正されました。 +- [新しいタブ] メニューのレイアウトをカスタマイズするための新しいページを含む、一度だけ JSON ファイルに存在した UI に多数の設定を追加しました。 +- 信頼性を向上させるためにウィンドウ管理を再選択しました。wt.exe エイリアスで発生したバグを報告してください +- プロファイルが非表示になっているか、アンインストールされたプログラムを参照している場合にアイコンが表示されるようになりました。 -詳細については、GitHub リリース ページをご覧ください。 +詳細については、GitHub リリース ページを参照してください。 diff --git a/build/StoreSubmission/Preview/PDPs/ko-KR/PDP.xml b/build/StoreSubmission/Preview/PDPs/ko-KR/PDP.xml index 6a1a5614ca..5ca7f5102d 100644 --- a/build/StoreSubmission/Preview/PDPs/ko-KR/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/ko-KR/PDP.xml @@ -56,12 +56,9 @@ 버전 __VERSION_NUMBER__ -- 콘솔 애플리케이션이 터미널 내에서 호스팅되는 방법을 다시 작성했습니다! 발생한 버그를 보고하세요. -- 터미널에서 이제 Sixels를 지원합니다! -- 이제 나중에 사용하기 위해 저장한 명령 조각이 포함된 도킹된 패널을 열 수 있습니다. -- 최신 Windows 11 릴리스의 명령 프롬프트 사용자는 WinGet에서 설치 가능한 소프트웨어를 제안하는 "빠른 팁" 아이콘을 볼 수 있습니다. -- 이제 선택한 텍스트가 훨씬 더 잘 표시됩니다(사용자 지정도 가능!). -- 여러 신뢰성 버그, 편의 문제 및 성가신 사항이 수정되었습니다. +- 새 탭 메뉴의 레이아웃을 사용자 지정하기 위한 새 페이지를 포함하여 JSON 파일에 한 번만 존재했던 UI에 수천 개의 설정을 추가했습니다. +- 안정성을 개선하기 위해 창 관리를 다시 보관했습니다. wt.exe 별칭에 발생한 버그를 제출하세요. +- 프로필이 숨겨졌거나 제거된 프로그램을 참조하는 경우 이제 프로필에 아이콘이 표시됩니다. 자세한 내용은 GitHub 릴리스 페이지를 참조하세요. diff --git a/build/StoreSubmission/Preview/PDPs/pt-BR/PDP.xml b/build/StoreSubmission/Preview/PDPs/pt-BR/PDP.xml index 041743bba6..c6c84a6815 100644 --- a/build/StoreSubmission/Preview/PDPs/pt-BR/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/pt-BR/PDP.xml @@ -56,14 +56,11 @@ Este é um projeto de código aberto e a participação da comunidade é bem-vin Versão __VERSION_NUMBER__ -- Reescrevemos a forma como os aplicativos de console são hospedados no Terminal! Certifique-se de reportar os bugs que você encontrar. -- O terminal agora é compatível com o Sixels! -- Agora você pode abrir um painel acoplado contendo snippets de comandos que você salvou para usar mais tarde -- Os usuários do Prompt de Comando na versão mais recente do Windows 11 podem ver um ícone de "dica rápida", que sugere softwares instaláveis a partir do WinGet -- O texto selecionado agora ficará muito mais visível (e personalizável!) -- Vários bugs de confiabilidade, problemas de conveniência e incômodos foram resolvidos. +- Adicionamos várias configurações à interface do usuário que só existiam no arquivo JSON, incluindo uma nova página para personalizar o layout do menu Nova Guia! +- Temos o gerenciamento de janelas rearmado para melhorar a confiabilidade; registre todos os bugs encontrados com o wt.exe alias +- Os perfis agora mostram um ícone se eles foram ocultos ou se referem a programas que foram desinstalados. -Confira nossa página de lançamentos no GitHub para obter mais detalhes. +Consulte nossa página de versões do GitHub para obter detalhes adicionais. diff --git a/build/StoreSubmission/Preview/PDPs/qps-ploc/PDP.xml b/build/StoreSubmission/Preview/PDPs/qps-ploc/PDP.xml index 941d2485de..e21d600da0 100644 --- a/build/StoreSubmission/Preview/PDPs/qps-ploc/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/qps-ploc/PDP.xml @@ -56,14 +56,11 @@ Vėѓѕіöй __VERSION_NUMBER__ !!! !!! ! -- Ẁē'νё ŕéẁѓĭτťёñ ћοώ ĉòπşõℓε άррℓіċªťįõпѕ αяе ĥθѕťэđ įŋšιďé Ţєямїńąℓ! Рļéаšė яёροřτ αņу ьϋģš ýõμ éпćŏџήţęя. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !! -- Ţëямΐʼnαļ ńóẃ ŝüррöятš Śїхέłś! !!! !!! !!! -- ¥оų ĉåи ńòŵ θρėñ д đбčĸэď ράńέļ ċőлŧăīņϊňģ śⁿіφφëťś оƒ ςōмmàⁿďş ŷŏũ ĥªν℮ şåνěđ τσ üśε łαťэŗ !!! !!! !!! !!! !!! !!! !!! !!! !!! -- Ćοмmäлđ Рřōmφť üş℮ŗѕ öη τће ļāťëšτ Щīйđôώѕ 11 řёℓеаѕĕ måў ŝэε ά "qůïςκ ŧĭр" ιсôñ τĥдт šűğģєѕŧѕ ίńśŧăłłавļз šôƒţẁαгέ ƒґόm ЩĩйĞéţ !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! -- Śєļèċťєď ţĕжт ωϊŀļ йǿẃ ьέ mџ¢н мǿѓε νĭŝϊъļė (άŋđ сŭŝтŏмΐżдьļē!) !!! !!! !!! !!! !!! !!! ! -- Ä ņϋmъ℮ŗ ŏƒ ѓēŀїаъïļŧÿ ьüĝś, ςôⁿνėηĭ℮иć℮ îѕšůëş ăπð âлňбγдňçėŝ ћªνε ъēёп ƒΐ×еð. !!! !!! !!! !!! !!! !!! !!! !!! +- Ẁē'νё àðđέď đöžзńş öƒ śėŧťїńģš тб тнè ÛĮ ťħąт ŏņ¢з όⁿℓγ έжіѕŧéð іή тђε ЈŠΩŃ ƒїℓė, ĭňĉŀџđіņģ å ňэẅ φâģé ƒøя ςŭśŧŏmïżϊñģ тħέ ĺαŷöυτ öƒ убµř Йέẁ Ţàъ мęήµ! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Ẁè ĥаνė řэąřčħΐŧέсτέð щįлďοш мǻňαĝēмêиť ťô ϊmрябνé ŗĕŀĩāвîĺïтγ; ρŀěăѕе ƒíŀё αⁿу вûġš ÿøú εʼnćōùлťēѓ ẃïτħ ŧћё wt.exe ǻļĭâś !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Рґøƒíŀêŝ ňöẁ šћθẁ ãй ĭčöñ ίƒ ŧħэŷ'νę ъеєл ђіðδэñ őř řєƒěґ ŧσ φяοġгаmŝ ẅђíçĥ ẁ℮гέ џňϊйşťàľĺèð. !!! !!! !!! !!! !!! !!! !!! !!! !!! ! -Ρĺёàŝ℮ ŝез ǿúг ĢīťНŭъ řěłεαśèŝ φāğ℮ ƒóѓ дďδітĭøиąℓ ð℮тªїľŝ. !!! !!! !!! !!! !!! !!! +Рļèāŝє ŝèĕ θџŗ ĢίťĤцъ řέĺэªşэš ρąĝę ƒόř áďđїτϊōπαľ đэŧдįļŝ. !!! !!! !!! !!! !!! !!! diff --git a/build/StoreSubmission/Preview/PDPs/qps-ploca/PDP.xml b/build/StoreSubmission/Preview/PDPs/qps-ploca/PDP.xml index 941d2485de..e21d600da0 100644 --- a/build/StoreSubmission/Preview/PDPs/qps-ploca/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/qps-ploca/PDP.xml @@ -56,14 +56,11 @@ Vėѓѕіöй __VERSION_NUMBER__ !!! !!! ! -- Ẁē'νё ŕéẁѓĭτťёñ ћοώ ĉòπşõℓε άррℓіċªťįõпѕ αяе ĥθѕťэđ įŋšιďé Ţєямїńąℓ! Рļéаšė яёροřτ αņу ьϋģš ýõμ éпćŏџήţęя. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !! -- Ţëямΐʼnαļ ńóẃ ŝüррöятš Śїхέłś! !!! !!! !!! -- ¥оų ĉåи ńòŵ θρėñ д đбčĸэď ράńέļ ċőлŧăīņϊňģ śⁿіφφëťś оƒ ςōмmàⁿďş ŷŏũ ĥªν℮ şåνěđ τσ üśε łαťэŗ !!! !!! !!! !!! !!! !!! !!! !!! !!! -- Ćοмmäлđ Рřōmφť üş℮ŗѕ öη τће ļāťëšτ Щīйđôώѕ 11 řёℓеаѕĕ måў ŝэε ά "qůïςκ ŧĭр" ιсôñ τĥдт šűğģєѕŧѕ ίńśŧăłłавļз šôƒţẁαгέ ƒґόm ЩĩйĞéţ !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! -- Śєļèċťєď ţĕжт ωϊŀļ йǿẃ ьέ mџ¢н мǿѓε νĭŝϊъļė (άŋđ сŭŝтŏмΐżдьļē!) !!! !!! !!! !!! !!! !!! ! -- Ä ņϋmъ℮ŗ ŏƒ ѓēŀїаъïļŧÿ ьüĝś, ςôⁿνėηĭ℮иć℮ îѕšůëş ăπð âлňбγдňçėŝ ћªνε ъēёп ƒΐ×еð. !!! !!! !!! !!! !!! !!! !!! !!! +- Ẁē'νё àðđέď đöžзńş öƒ śėŧťїńģš тб тнè ÛĮ ťħąт ŏņ¢з όⁿℓγ έжіѕŧéð іή тђε ЈŠΩŃ ƒїℓė, ĭňĉŀџđіņģ å ňэẅ φâģé ƒøя ςŭśŧŏmïżϊñģ тħέ ĺαŷöυτ öƒ убµř Йέẁ Ţàъ мęήµ! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Ẁè ĥаνė řэąřčħΐŧέсτέð щįлďοш мǻňαĝēмêиť ťô ϊmрябνé ŗĕŀĩāвîĺïтγ; ρŀěăѕе ƒíŀё αⁿу вûġš ÿøú εʼnćōùлťēѓ ẃïτħ ŧћё wt.exe ǻļĭâś !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Рґøƒíŀêŝ ňöẁ šћθẁ ãй ĭčöñ ίƒ ŧħэŷ'νę ъеєл ђіðδэñ őř řєƒěґ ŧσ φяοġгаmŝ ẅђíçĥ ẁ℮гέ џňϊйşťàľĺèð. !!! !!! !!! !!! !!! !!! !!! !!! !!! ! -Ρĺёàŝ℮ ŝез ǿúг ĢīťНŭъ řěłεαśèŝ φāğ℮ ƒóѓ дďδітĭøиąℓ ð℮тªїľŝ. !!! !!! !!! !!! !!! !!! +Рļèāŝє ŝèĕ θџŗ ĢίťĤцъ řέĺэªşэš ρąĝę ƒόř áďđїτϊōπαľ đэŧдįļŝ. !!! !!! !!! !!! !!! !!! diff --git a/build/StoreSubmission/Preview/PDPs/qps-plocm/PDP.xml b/build/StoreSubmission/Preview/PDPs/qps-plocm/PDP.xml index 941d2485de..e21d600da0 100644 --- a/build/StoreSubmission/Preview/PDPs/qps-plocm/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/qps-plocm/PDP.xml @@ -56,14 +56,11 @@ Vėѓѕіöй __VERSION_NUMBER__ !!! !!! ! -- Ẁē'νё ŕéẁѓĭτťёñ ћοώ ĉòπşõℓε άррℓіċªťįõпѕ αяе ĥθѕťэđ įŋšιďé Ţєямїńąℓ! Рļéаšė яёροřτ αņу ьϋģš ýõμ éпćŏџήţęя. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !! -- Ţëямΐʼnαļ ńóẃ ŝüррöятš Śїхέłś! !!! !!! !!! -- ¥оų ĉåи ńòŵ θρėñ д đбčĸэď ράńέļ ċőлŧăīņϊňģ śⁿіφφëťś оƒ ςōмmàⁿďş ŷŏũ ĥªν℮ şåνěđ τσ üśε łαťэŗ !!! !!! !!! !!! !!! !!! !!! !!! !!! -- Ćοмmäлđ Рřōmφť üş℮ŗѕ öη τће ļāťëšτ Щīйđôώѕ 11 řёℓеаѕĕ måў ŝэε ά "qůïςκ ŧĭр" ιсôñ τĥдт šűğģєѕŧѕ ίńśŧăłłавļз šôƒţẁαгέ ƒґόm ЩĩйĞéţ !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! -- Śєļèċťєď ţĕжт ωϊŀļ йǿẃ ьέ mџ¢н мǿѓε νĭŝϊъļė (άŋđ сŭŝтŏмΐżдьļē!) !!! !!! !!! !!! !!! !!! ! -- Ä ņϋmъ℮ŗ ŏƒ ѓēŀїаъïļŧÿ ьüĝś, ςôⁿνėηĭ℮иć℮ îѕšůëş ăπð âлňбγдňçėŝ ћªνε ъēёп ƒΐ×еð. !!! !!! !!! !!! !!! !!! !!! !!! +- Ẁē'νё àðđέď đöžзńş öƒ śėŧťїńģš тб тнè ÛĮ ťħąт ŏņ¢з όⁿℓγ έжіѕŧéð іή тђε ЈŠΩŃ ƒїℓė, ĭňĉŀџđіņģ å ňэẅ φâģé ƒøя ςŭśŧŏmïżϊñģ тħέ ĺαŷöυτ öƒ убµř Йέẁ Ţàъ мęήµ! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Ẁè ĥаνė řэąřčħΐŧέсτέð щįлďοш мǻňαĝēмêиť ťô ϊmрябνé ŗĕŀĩāвîĺïтγ; ρŀěăѕе ƒíŀё αⁿу вûġš ÿøú εʼnćōùлťēѓ ẃïτħ ŧћё wt.exe ǻļĭâś !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Рґøƒíŀêŝ ňöẁ šћθẁ ãй ĭčöñ ίƒ ŧħэŷ'νę ъеєл ђіðδэñ őř řєƒěґ ŧσ φяοġгаmŝ ẅђíçĥ ẁ℮гέ џňϊйşťàľĺèð. !!! !!! !!! !!! !!! !!! !!! !!! !!! ! -Ρĺёàŝ℮ ŝез ǿúг ĢīťНŭъ řěłεαśèŝ φāğ℮ ƒóѓ дďδітĭøиąℓ ð℮тªїľŝ. !!! !!! !!! !!! !!! !!! +Рļèāŝє ŝèĕ θџŗ ĢίťĤцъ řέĺэªşэš ρąĝę ƒόř áďđїτϊōπαľ đэŧдįļŝ. !!! !!! !!! !!! !!! !!! diff --git a/build/StoreSubmission/Preview/PDPs/ru-RU/PDP.xml b/build/StoreSubmission/Preview/PDPs/ru-RU/PDP.xml index 7561a5dd7e..c5c90ff6da 100644 --- a/build/StoreSubmission/Preview/PDPs/ru-RU/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/ru-RU/PDP.xml @@ -56,12 +56,9 @@ Версия __VERSION_NUMBER__ -– Мы переписали, как консольные приложения размещаются внутри Терминала! Сообщайте о любых ошибках, с которыми вы столкнулись. -– Терминал теперь поддерживает форматы Sixel! -– Теперь вы можете открыть закрепленную панель, содержащую фрагменты команд, которые вы сохранили для использования в дальнейшем -– Пользователи командной строки в новейшем выпуске Windows 11 могут увидеть значок "краткой подсказки", который предлагает устанавливаемые программы из WinGet -– Выделенный текст теперь станет более видимым (и настраиваемым!) -– Исправлено несколько ошибок надежности, проблем с удобством, а также устранены раздражающие моменты. +- Мы добавили в пользовательский интерфейс десятки параметров, которые существовали только в JSON-файле, включая новую страницу для настройки макета меню "Новая вкладка". +- Для повышения надежности мы переупоряхлили управление окнами; создайте все ошибки, обнаруженные с wt.exe псевдонимом +- Профили теперь показывают значок, если они скрыты или ссылаются на программы, которые были удалены. Дополнительные сведения см. на странице выпусков GitHub. diff --git a/build/StoreSubmission/Preview/PDPs/zh-CN/PDP.xml b/build/StoreSubmission/Preview/PDPs/zh-CN/PDP.xml index 44ef68818c..cd0783394c 100644 --- a/build/StoreSubmission/Preview/PDPs/zh-CN/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/zh-CN/PDP.xml @@ -54,16 +54,13 @@ - Version __VERSION_NUMBER__ + 版本 __VERSION_NUMBER__ -- 我们已改变主机应用程序在终端内的托管方式!请报告遇到的任何 bug。 -- 终端现在支持 Sixels! -- 现在可以打开一个停靠面板,其中包含已保存供以后使用的命令片段 -- 最新 Windows 11 版本上的命令提示用户可能会看到“快速提示”图标,该图标建议从 WinGet 安装软件 -- 所选文本现在将具有更高的可见性(和可自定义性!) -- 修复了许多可靠性 bug、便利性问题和令人烦恼的问题。 +- 我们向用户界面添加了许多设置,这些设置仅存在于 JSON 文件中,包括用于自定义“新建标签页”菜单布局的新页面! +- 我们已重新检测窗口管理以提高可靠性;请将遇到的任何 bug 归档为 wt.exe 别名 +- 如果配置文件已隐藏或引用已卸载的程序,则它们现在将显示一个图标。 -有关其他详细信息,请参阅我们的 GitHub 发布页面。 +有关其他详细信息,请参阅 GitHub 发布页面。 diff --git a/build/StoreSubmission/Preview/PDPs/zh-TW/PDP.xml b/build/StoreSubmission/Preview/PDPs/zh-TW/PDP.xml index e902f1a5e0..eeec299d96 100644 --- a/build/StoreSubmission/Preview/PDPs/zh-TW/PDP.xml +++ b/build/StoreSubmission/Preview/PDPs/zh-TW/PDP.xml @@ -56,14 +56,11 @@ 版本 __VERSION_NUMBER__ -- 我們已重寫主機應用程式在終端機內託管的方式!請報告您遇到的錯誤。 -- 終端機現在支援 Sixels! -- 現在,您可以開啟包含已儲存命令程式碼片段的固定面板,以供稍後使用 -- 最新 Windows 11 版本中的 [命令提示] 使用者可能會看到「快速提示」圖示,建議可自 WinGet 安裝的軟體 -- 選取的文字現在會更明顯 (且可自訂!) -- 已修正一些可靠性錯誤、便利性問題和令人困擾的問題。 +- 我們已新增數十個只存在於 JSON 檔案中的設定到 UI,包括自定義 [新索引標籤] 功能表版面配置的新頁面! +- 我們已重新設定視窗管理,以改善可靠性;請提出您在 wt.exe 別名遇到的任何錯誤 +- 設定文件現在會在隱藏或參照已卸載的程式時顯示圖示。 -如需更多詳細資訊,請參閱我們的 GitHub 發行頁面。 +如需詳細數據,請參閱我們的 GitHub 版本頁面。 diff --git a/build/StoreSubmission/Stable/PDPs/de-DE/PDP.xml b/build/StoreSubmission/Stable/PDPs/de-DE/PDP.xml index 9b03ca9d01..47ff614bd0 100644 --- a/build/StoreSubmission/Stable/PDPs/de-DE/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/de-DE/PDP.xml @@ -56,12 +56,12 @@ Dies ist ein Open Source-Projekt, und wir freuen uns über die Teilnahme an der Version __VERSION_NUMBER__ -– Terminal speichert jetzt den Inhalt des Fensters, wenn Sie die Sitzungswiederherstellung verwenden. -– Sie können jetzt mehrere Schriftarten gleichzeitig verwenden. -– Kästchenzeichnende Zeichen werden jetzt pixelgenau gerendert. -– Die Verwendung eines IME innerhalb des Terminals wurde erheblich verbessert. -– Die Farbschemas in Ihrer JSON-Datei sind jetzt viel einfacher. -– Eine Reihe von Fehlern im Zusammenhang mit der URL-Verarbeitung, Zeilen mit doppelter Breite, Zeilenumbruch und mehr wurden behoben. +– Wir haben umgeschrieben, wie Konsolenanwendungen im Terminal gehostet werden! Melden Sie alle auftretenden Fehler. +– Terminal unterstützt jetzt Sixels! +– Sie können jetzt einen angedockten Bereich öffnen, der Ausschnitte von Befehlen enthält, die Sie gespeichert haben, um sie später zu verwenden. +– Für Benutzer der Eingabeaufforderung der neuesten Version von Windows 11 wird möglicherweise ein QuickInfo-Symbol angezeigt, das installierbare Software von WinGet vorschlägt. +– Ausgewählter Text wird jetzt viel sichtbarer (und anpassbarer!). +- Eine Reihe von Zuverlässigkeitsfehlern, Benutzerfreundlichkeitsproblemen und Ärgernissen wurden behoben. Weitere Informationen finden Sie auf unserer GitHub-Releaseseite. diff --git a/build/StoreSubmission/Stable/PDPs/en-US/PDP.xml b/build/StoreSubmission/Stable/PDPs/en-US/PDP.xml index cab23331c5..993c27e011 100644 --- a/build/StoreSubmission/Stable/PDPs/en-US/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/en-US/PDP.xml @@ -56,12 +56,12 @@ This is an open source project and we welcome community participation. To partic Version __VERSION_NUMBER__ -- Terminal will now remember the contents of the window when you use session restoration. -- You can now use multiple fonts at the same time. -- Box-drawing characters are now rendered with pixel perfection. -- The experience of using an IME inside Terminal has been significantly improved. -- The color schemes inside your JSON file will now be much simpler. -- A number of bugs around URL handling, double-width rows, line wrapping, and more have been fixed. +- We've rewritten how console applications are hosted inside Terminal! Please report any bugs you encounter. +- Terminal now supports Sixels! +- You can now open a docked panel containing snippets of commands you have saved to use later +- Command Prompt users on the latest Windows 11 release may see a "quick tip" icon that suggests installable software from WinGet +- Selected text will now be much more visible (and customizable!) +- A number of reliabilty bugs, convenience issues and annoyances have been fixed. Please see our GitHub releases page for additional details. diff --git a/build/StoreSubmission/Stable/PDPs/es-ES/PDP.xml b/build/StoreSubmission/Stable/PDPs/es-ES/PDP.xml index 1d2c1d5330..84bd2cc399 100644 --- a/build/StoreSubmission/Stable/PDPs/es-ES/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/es-ES/PDP.xml @@ -56,12 +56,12 @@ Este es un proyecto de fuente abierta y animamos a la comunidad a participar. Pa Versión __VERSION_NUMBER__ -- Terminal recordará ahora el contenido de la ventana cuando use la restauración de la sesión. -- Ahora puede usar varias fuentes al mismo tiempo. -- Los caracteres que dibujan recuadros ahora se representan con precisión de píxel. -- Se ha mejorado significativamente la experiencia de utilizar un IME dentro de Terminal. -- Las combinaciones de colores dentro del archivo JSON ahora serán mucho más sencillas. -- Se han corregido varios errores relacionados con el control de direcciones URL, las filas de ancho doble, el ajuste de líneas y mucho más. +- Hemos reescrito cómo se hospedan las aplicaciones de consola en Terminal. Informe de los errores que encuentre. +- Terminal ahora admite síxeles. +- Ahora puede abrir un panel acoplado que contenga fragmentos de comandos que haya guardado para usarlos más adelante +- Los usuarios del símbolo del sistema de la versión más reciente de Windows 11 pueden ver un icono de "sugerencia rápida" que sugiere software instalable de WinGet +- El texto seleccionado ahora será mucho más visible (y personalizable) +- Se han corregido varios errores de fiabilidad, problemas de comodidad y molestias. Consulte la página de versiones de GitHub para más información. diff --git a/build/StoreSubmission/Stable/PDPs/fr-FR/PDP.xml b/build/StoreSubmission/Stable/PDPs/fr-FR/PDP.xml index 73122c2dba..34c6a13ea8 100644 --- a/build/StoreSubmission/Stable/PDPs/fr-FR/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/fr-FR/PDP.xml @@ -56,14 +56,14 @@ Il s’agit d’un projet open source et nous encourageons la participation à l Version __VERSION_NUMBER__ -- Le terminal mémorisera désormais le contenu de la fenêtre lorsque vous utiliserez la restauration de session. -- Vous pouvez désormais utiliser plusieurs polices en même temps. -- Les personnages dessinés en boîte sont désormais rendus avec une perfection de pixel. -- L'expérience d'utilisation d'un IME dans le Terminal a été considérablement améliorée. -- Les schémas de couleurs à l'intérieur de votre fichier JSON seront désormais beaucoup plus simples. -- Un certain nombre de bugs concernant la gestion des URL, les lignes à double largeur, le retour à la ligne, etc. ont été corrigés. +– Nous avons réécrit la manière dont les applications de console sont hébergées dans Terminal ! Veuillez signaler tout bogue que vous rencontrez. +– Terminal prend désormais en charge Sixels ! +– Vous pouvez maintenant ouvrir un panneau ancré contenant des extraits de commandes que vous avez enregistrées pour les utiliser ultérieurement +– Les utilisateurs de l’invite de commande sur la dernière version de Windows 11 peuvent voir une icône « astuce rapide » qui suggère un logiciel installable à partir de WinGet +– Le texte sélectionné sera désormais beaucoup plus visible (et personnalisable !) +– Un certain nombre de bogues de fiabilité, de problèmes de commodité et de désagréments ont été corrigés. -Veuillez consulter notre page de versions GitHub pour plus de détails. +Veuillez consulter notre page des versions GitHub pour découvrir d’autres détails. diff --git a/build/StoreSubmission/Stable/PDPs/it-IT/PDP.xml b/build/StoreSubmission/Stable/PDPs/it-IT/PDP.xml index 1588f40494..9d7ce218e8 100644 --- a/build/StoreSubmission/Stable/PDPs/it-IT/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/it-IT/PDP.xml @@ -54,16 +54,16 @@ Si tratta di un progetto open source e la partecipazione della community è molt - Versione __VERSION_NUMBER__ + Versione __VERSION_NUMBER__ -- Il terminale ricorda ora il contenuto della finestra quando si usa il ripristino della sessione. -- È ora possibile usare più tipi di carattere contemporaneamente. -- I caratteri tracciati vengono ora sottoposti a rendering con pixel di perfezionamento. -- L'esperienza di utilizzo di un IME all'interno di Terminale è stata notevolmente migliorata. -- Le combinazioni di colori all'interno del file JSON saranno ora molto più semplici. -- Sono stati corretti alcuni bug relativi alla gestione degli URL, alle righe a doppia larghezza, al ritorno a capo delle righe e altro ancora. +- Abbiamo cambiato il modo in cui le applicazioni della console vengono ospitate all’interno di Terminale. Segnala eventuali bug riscontrati. +- Ora Terminale supporta i Sixel. +- Puoi aprire un pannello ancorato contenente frammenti di comandi salvati per usarli in seguito +- Gli utenti che usano il prompt dei comandi nella versione più recente di Windows 11 potrebbero visualizzare un’icona di “suggerimento rapido” che consiglia il software installabile da WinGet +- Il testo selezionato sarà ora molto più visibile, oltre che personalizzabile. +- Sono stati risolti diversi bug di affidabilità e problemi di ordine pratico. -Per altri dettagli, vedi la pagina delle versioni di GitHub. +Per altri dettagli, vedi la pagina delle release di GitHub. diff --git a/build/StoreSubmission/Stable/PDPs/ja-JP/PDP.xml b/build/StoreSubmission/Stable/PDPs/ja-JP/PDP.xml index 8a56c14bbe..27a38762bb 100644 --- a/build/StoreSubmission/Stable/PDPs/ja-JP/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/ja-JP/PDP.xml @@ -56,12 +56,12 @@ バージョン __VERSION_NUMBER__ -- セッションの復元を使用すると、ターミナルがウィンドウの内容を記憶するようになりました。 -- 複数のフォントを同時に使用できるようになりました。 -- ボックス描画文字がピクセル単位の精度でレンダリングされるようになりました。 -- ターミナル内での IME の使用エクスペリエンスが大幅に改善されました。 -- JSON ファイル内の配色がはるかにシンプルになりました。 -- URL 処理、二重幅の行、行の折り返しなどに関するいくつかのバグが修正されました。 +- ターミナル内でのコンソール アプリケーションのホスト方法を書き換えました。発生したバグを報告してください。 +- ターミナルで Sixels がサポートされるようになりました。 +- 後で使用するために保存したコマンドのスニペットを含むドッキング パネルを開けるようになりました +- 最新の Windows 11 リリースのコマンド プロンプト ユーザーには、WinGet からインストール可能なソフトウェアを提案する "クイック ヒント" アイコンが表示される場合があります +- 選択したテキストが大幅に見やすくなりました (カスタマイズも可能です) +- 信頼性に関するバグ、利便性の問題、不快な問題の多くが修正されました。 詳細については、GitHub リリース ページをご覧ください。 diff --git a/build/StoreSubmission/Stable/PDPs/ko-KR/PDP.xml b/build/StoreSubmission/Stable/PDPs/ko-KR/PDP.xml index 29be907d86..8dac845667 100644 --- a/build/StoreSubmission/Stable/PDPs/ko-KR/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/ko-KR/PDP.xml @@ -56,12 +56,12 @@ 버전 __VERSION_NUMBER__ -- 터미널은 이제 세션 복원을 사용할 때 창의 내용을 기억합니다. -- 이제 여러 글꼴을 동시에 사용할 수 있습니다. -- 상자 그리기 캐릭터가 이제 픽셀 완성도로 렌더링됩니다. -- 터미널 내에서 IME를 사용하는 환경이 크게 개선되었습니다. -- 이제 JSON 파일 내의 색 구성표가 훨씬 더 간단해집니다. -- URL 처리, 이중 너비 행, 줄 바꿈 등과 관련된 여러 버그가 수정되었습니다. +- 콘솔 애플리케이션이 터미널 내에서 호스팅되는 방법을 다시 작성했습니다. 버그가 발생하면 보고해 주세요. +- 터미널에서 이제 Sixels를 지원합니다. +- 이제 나중에 사용하기 위해 저장한 명령 조각이 포함된 도킹된 패널을 열 수 있습니다. +- 최신 Windows 11 릴리스의 명령 프롬프트 사용자는 WinGet에서 설치 가능한 소프트웨어를 추천하는 "간단한 팁" 아이콘을 볼 수 있습니다. +- 이제 선택한 텍스트가 훨씬 더 잘 보입니다(사용자 지정 가능). +- 여러 안정성 버그, 편의성 문제, 불편 사항이 수정되었습니다. 자세한 내용은 GitHub 릴리스 페이지를 참조하세요. diff --git a/build/StoreSubmission/Stable/PDPs/pt-BR/PDP.xml b/build/StoreSubmission/Stable/PDPs/pt-BR/PDP.xml index 1ddfe8815c..cd3b5ce368 100644 --- a/build/StoreSubmission/Stable/PDPs/pt-BR/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/pt-BR/PDP.xml @@ -56,12 +56,12 @@ Este é um projeto de código aberto e a participação da comunidade é bem-vin Versão __VERSION_NUMBER__ -- O terminal agora se lembra do conteúdo da janela quando você usa a restauração de sessão. -- Agora você pode usar várias fontes ao mesmo tempo. -- Os caracteres da caixa de desenho agora são renderizados com a perfeição de pixels. -- A experiência de usar uma IME dentro do Terminal foi significativamente aprimorada. -- Os esquemas de cores dentro do seu arquivo JSON agora estão muito mais simples. -- Foram corrigidos vários bugs envolvendo o tratamento de URLs, linhas de largura dupla, quebra de linha automática e muito mais. +– Reescrevemos a forma como os aplicativos de console são hospedados no Terminal! Relate os bugs encontrados. +– O terminal agora oferece suporte ao Sixels! +– Agora você pode abrir um painel acoplado contendo snippets de comandos que você salvou para usar mais tarde +– Os usuários do Prompt de Comando na versão mais recente do Windows 11 podem ver um ícone de "dica rápida", que sugere softwares instaláveis a partir do WinGet +– O texto selecionado agora ficará muito mais visível (e personalizável!) +– Vários bugs de confiabilidade, problemas de conveniência e incômodos foram resolvidos. Confira nossa página de lançamentos no GitHub para obter mais detalhes. diff --git a/build/StoreSubmission/Stable/PDPs/qps-ploc/PDP.xml b/build/StoreSubmission/Stable/PDPs/qps-ploc/PDP.xml index 5f716b97c4..d911bbd69b 100644 --- a/build/StoreSubmission/Stable/PDPs/qps-ploc/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/qps-ploc/PDP.xml @@ -56,14 +56,14 @@ Vėѓѕіöй __VERSION_NUMBER__ !!! !!! ! -- Ŧēгмíйǻŀ шιļł ñσщ řėmėmвзґ τђз ςоńţëηťŝ σƒ ŧћé ẅιⁿδőщ ẅђеή ýóύ ŭš℮ şεššîóŋ řėşτŏѓдτіόŋ. !!! !!! !!! !!! !!! !!! !!! !!! !!! -- Ύоџ ςàⁿ ŋóώ ũşэ múľŧìφľё ƒоʼnťş àт ťħе ѕâmз тìме. !!! !!! !!! !!! !!! -- Вό×-ðгăшĭиġ ¢ĥаяäςтеřѕ äřę ηоẁ ѓëńđêяεď ẁϊτђ φïжêĺ φėŗƒēςŧΐøй. !!! !!! !!! !!! !!! !!! ! -- Ťħέ ĕхφêŕï℮ηĉε ŏƒ ύѕïйġ ǻʼn ÎМË îńšïďê Τєřmíлäļ нαŝ ьēέň ѕιĝήîƒіčäπţŀý ĩмφґθνзđ. !!! !!! !!! !!! !!! !!! !!! !!! -- Ťĥę čöℓοг şçђėmęš ιʼnśΐδê убџѓ ĴŠОИ ƒϊŀε ωĭŀł ʼnθω вз мúçĥ ѕїмρℓёґ. !!! !!! !!! !!! !!! !!! !! -- Á ήũmьéŕ òƒ вµġŝ άřòūñδ ÛҐĿ ħàŋδľįйģ, ðőџъŀε-ŵĭďτђ ŗōẁš, ŀϊπė ẃяąрρΐηğ, âⁿđ мŏř℮ ĥāνě везŋ ƒï×έð. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Ẁē'νё ŕéẁѓĭτťёñ ћοώ ĉòπşõℓε άррℓіċªťįõпѕ αяе ĥθѕťэđ įŋšιďé Ţєямїńąℓ! Рļéаšė яёροřτ αņу ьϋģš ýõμ éпćŏџήţęя. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !! +- Ţëямΐʼnαļ ńóẃ ŝüррöятš Śїхέłś! !!! !!! !!! +- ¥оų ĉåи ńòŵ θρėñ д đбčĸэď ράńέļ ċőлŧăīņϊňģ śⁿіφφëťś оƒ ςōмmàⁿďş ŷŏũ ĥªν℮ şåνěđ τσ üśε łαťэŗ !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Ćοмmäлđ Рřōmφť üş℮ŗѕ öη τће ļāťëšτ Щīйđôώѕ 11 řёℓеаѕĕ måў ŝэε ά "qůïςκ ŧĭр" ιсôñ τĥдт šűğģєѕŧѕ ίńśŧăłłавļз šôƒţẁαгέ ƒґόm ЩĩйĞéţ !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Śєļèċťєď ţĕжт ωϊŀļ йǿẃ ьέ mџ¢н мǿѓε νĭŝϊъļė (άŋđ сŭŝтŏмΐżдьļē!) !!! !!! !!! !!! !!! !!! ! +- Ä ņϋmъ℮ŗ ŏƒ ѓēŀїаъïļŧÿ ьüĝś, ςôⁿνėηĭ℮иć℮ îѕšůëş ăπð âлňбγдňçėŝ ћªνε ъēёп ƒΐ×еð. !!! !!! !!! !!! !!! !!! !!! !!! -Ρļēªšê ŝέė őůг ĜīтĤųъ яëŀεäśēś рдġэ ƒõя ãδðìτϊöňãł δèτâĩĺѕ. !!! !!! !!! !!! !!! !!! +Ρĺёàŝ℮ ŝез ǿúг ĢīťНŭъ řěłεαśèŝ φāğ℮ ƒóѓ дďδітĭøиąℓ ð℮тªїľŝ. !!! !!! !!! !!! !!! !!! diff --git a/build/StoreSubmission/Stable/PDPs/qps-ploca/PDP.xml b/build/StoreSubmission/Stable/PDPs/qps-ploca/PDP.xml index 5f716b97c4..d911bbd69b 100644 --- a/build/StoreSubmission/Stable/PDPs/qps-ploca/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/qps-ploca/PDP.xml @@ -56,14 +56,14 @@ Vėѓѕіöй __VERSION_NUMBER__ !!! !!! ! -- Ŧēгмíйǻŀ шιļł ñσщ řėmėmвзґ τђз ςоńţëηťŝ σƒ ŧћé ẅιⁿδőщ ẅђеή ýóύ ŭš℮ şεššîóŋ řėşτŏѓдτіόŋ. !!! !!! !!! !!! !!! !!! !!! !!! !!! -- Ύоџ ςàⁿ ŋóώ ũşэ múľŧìφľё ƒоʼnťş àт ťħе ѕâmз тìме. !!! !!! !!! !!! !!! -- Вό×-ðгăшĭиġ ¢ĥаяäςтеřѕ äřę ηоẁ ѓëńđêяεď ẁϊτђ φïжêĺ φėŗƒēςŧΐøй. !!! !!! !!! !!! !!! !!! ! -- Ťħέ ĕхφêŕï℮ηĉε ŏƒ ύѕïйġ ǻʼn ÎМË îńšïďê Τєřmíлäļ нαŝ ьēέň ѕιĝήîƒіčäπţŀý ĩмφґθνзđ. !!! !!! !!! !!! !!! !!! !!! !!! -- Ťĥę čöℓοг şçђėmęš ιʼnśΐδê убџѓ ĴŠОИ ƒϊŀε ωĭŀł ʼnθω вз мúçĥ ѕїмρℓёґ. !!! !!! !!! !!! !!! !!! !! -- Á ήũmьéŕ òƒ вµġŝ άřòūñδ ÛҐĿ ħàŋδľįйģ, ðőџъŀε-ŵĭďτђ ŗōẁš, ŀϊπė ẃяąрρΐηğ, âⁿđ мŏř℮ ĥāνě везŋ ƒï×έð. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Ẁē'νё ŕéẁѓĭτťёñ ћοώ ĉòπşõℓε άррℓіċªťįõпѕ αяе ĥθѕťэđ įŋšιďé Ţєямїńąℓ! Рļéаšė яёροřτ αņу ьϋģš ýõμ éпćŏџήţęя. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !! +- Ţëямΐʼnαļ ńóẃ ŝüррöятš Śїхέłś! !!! !!! !!! +- ¥оų ĉåи ńòŵ θρėñ д đбčĸэď ράńέļ ċőлŧăīņϊňģ śⁿіφφëťś оƒ ςōмmàⁿďş ŷŏũ ĥªν℮ şåνěđ τσ üśε łαťэŗ !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Ćοмmäлđ Рřōmφť üş℮ŗѕ öη τће ļāťëšτ Щīйđôώѕ 11 řёℓеаѕĕ måў ŝэε ά "qůïςκ ŧĭр" ιсôñ τĥдт šűğģєѕŧѕ ίńśŧăłłавļз šôƒţẁαгέ ƒґόm ЩĩйĞéţ !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Śєļèċťєď ţĕжт ωϊŀļ йǿẃ ьέ mџ¢н мǿѓε νĭŝϊъļė (άŋđ сŭŝтŏмΐżдьļē!) !!! !!! !!! !!! !!! !!! ! +- Ä ņϋmъ℮ŗ ŏƒ ѓēŀїаъïļŧÿ ьüĝś, ςôⁿνėηĭ℮иć℮ îѕšůëş ăπð âлňбγдňçėŝ ћªνε ъēёп ƒΐ×еð. !!! !!! !!! !!! !!! !!! !!! !!! -Ρļēªšê ŝέė őůг ĜīтĤųъ яëŀεäśēś рдġэ ƒõя ãδðìτϊöňãł δèτâĩĺѕ. !!! !!! !!! !!! !!! !!! +Ρĺёàŝ℮ ŝез ǿúг ĢīťНŭъ řěłεαśèŝ φāğ℮ ƒóѓ дďδітĭøиąℓ ð℮тªїľŝ. !!! !!! !!! !!! !!! !!! diff --git a/build/StoreSubmission/Stable/PDPs/qps-plocm/PDP.xml b/build/StoreSubmission/Stable/PDPs/qps-plocm/PDP.xml index 5f716b97c4..d911bbd69b 100644 --- a/build/StoreSubmission/Stable/PDPs/qps-plocm/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/qps-plocm/PDP.xml @@ -56,14 +56,14 @@ Vėѓѕіöй __VERSION_NUMBER__ !!! !!! ! -- Ŧēгмíйǻŀ шιļł ñσщ řėmėmвзґ τђз ςоńţëηťŝ σƒ ŧћé ẅιⁿδőщ ẅђеή ýóύ ŭš℮ şεššîóŋ řėşτŏѓдτіόŋ. !!! !!! !!! !!! !!! !!! !!! !!! !!! -- Ύоџ ςàⁿ ŋóώ ũşэ múľŧìφľё ƒоʼnťş àт ťħе ѕâmз тìме. !!! !!! !!! !!! !!! -- Вό×-ðгăшĭиġ ¢ĥаяäςтеřѕ äřę ηоẁ ѓëńđêяεď ẁϊτђ φïжêĺ φėŗƒēςŧΐøй. !!! !!! !!! !!! !!! !!! ! -- Ťħέ ĕхφêŕï℮ηĉε ŏƒ ύѕïйġ ǻʼn ÎМË îńšïďê Τєřmíлäļ нαŝ ьēέň ѕιĝήîƒіčäπţŀý ĩмφґθνзđ. !!! !!! !!! !!! !!! !!! !!! !!! -- Ťĥę čöℓοг şçђėmęš ιʼnśΐδê убџѓ ĴŠОИ ƒϊŀε ωĭŀł ʼnθω вз мúçĥ ѕїмρℓёґ. !!! !!! !!! !!! !!! !!! !! -- Á ήũmьéŕ òƒ вµġŝ άřòūñδ ÛҐĿ ħàŋδľįйģ, ðőџъŀε-ŵĭďτђ ŗōẁš, ŀϊπė ẃяąрρΐηğ, âⁿđ мŏř℮ ĥāνě везŋ ƒï×έð. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Ẁē'νё ŕéẁѓĭτťёñ ћοώ ĉòπşõℓε άррℓіċªťįõпѕ αяе ĥθѕťэđ įŋšιďé Ţєямїńąℓ! Рļéаšė яёροřτ αņу ьϋģš ýõμ éпćŏџήţęя. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !! +- Ţëямΐʼnαļ ńóẃ ŝüррöятš Śїхέłś! !!! !!! !!! +- ¥оų ĉåи ńòŵ θρėñ д đбčĸэď ράńέļ ċőлŧăīņϊňģ śⁿіφφëťś оƒ ςōмmàⁿďş ŷŏũ ĥªν℮ şåνěđ τσ üśε łαťэŗ !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Ćοмmäлđ Рřōmφť üş℮ŗѕ öη τће ļāťëšτ Щīйđôώѕ 11 řёℓеаѕĕ måў ŝэε ά "qůïςκ ŧĭр" ιсôñ τĥдт šűğģєѕŧѕ ίńśŧăłłавļз šôƒţẁαгέ ƒґόm ЩĩйĞéţ !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! +- Śєļèċťєď ţĕжт ωϊŀļ йǿẃ ьέ mџ¢н мǿѓε νĭŝϊъļė (άŋđ сŭŝтŏмΐżдьļē!) !!! !!! !!! !!! !!! !!! ! +- Ä ņϋmъ℮ŗ ŏƒ ѓēŀїаъïļŧÿ ьüĝś, ςôⁿνėηĭ℮иć℮ îѕšůëş ăπð âлňбγдňçėŝ ћªνε ъēёп ƒΐ×еð. !!! !!! !!! !!! !!! !!! !!! !!! -Ρļēªšê ŝέė őůг ĜīтĤųъ яëŀεäśēś рдġэ ƒõя ãδðìτϊöňãł δèτâĩĺѕ. !!! !!! !!! !!! !!! !!! +Ρĺёàŝ℮ ŝез ǿúг ĢīťНŭъ řěłεαśèŝ φāğ℮ ƒóѓ дďδітĭøиąℓ ð℮тªїľŝ. !!! !!! !!! !!! !!! !!! diff --git a/build/StoreSubmission/Stable/PDPs/ru-RU/PDP.xml b/build/StoreSubmission/Stable/PDPs/ru-RU/PDP.xml index 16779a4422..011e5152d7 100644 --- a/build/StoreSubmission/Stable/PDPs/ru-RU/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/ru-RU/PDP.xml @@ -56,12 +56,12 @@ Версия __VERSION_NUMBER__ -– Терминал теперь будет запоминать содержимое окна при восстановлении сеанса. -– Теперь вы можете использовать несколько шрифтов одновременно. -– Символы псевдографики теперь отрисовываются с пиксельной точностью. -– Значительно улучшена возможность использования IME внутри Терминала. -– Цветовые схемы в JSON-файле теперь будут намного проще. -– Исправлено несколько ошибок в обработке URL-адресов, строках двойной ширины, переносе строк и т. д. +– Мы переписали, как консольные приложения размещаются внутри Терминала! Сообщайте о любых ошибках, с которыми вы столкнулись. +– Терминал теперь поддерживает форматы Sixel! +– Теперь вы можете открыть закрепленную панель, содержащую фрагменты команд, которые вы сохранили для использования в дальнейшем +– Пользователи командной строки в новейшем выпуске Windows 11 могут увидеть значок "краткой подсказки", который предлагает устанавливаемые программы из WinGet +– Выделенный текст теперь станет более видимым (и настраиваемым!) +– Исправлено несколько ошибок надежности, проблем с удобством, а также устранены раздражающие моменты. Дополнительные сведения см. на странице выпусков GitHub. diff --git a/build/StoreSubmission/Stable/PDPs/zh-CN/PDP.xml b/build/StoreSubmission/Stable/PDPs/zh-CN/PDP.xml index 17d6c841c5..21db7d2c3d 100644 --- a/build/StoreSubmission/Stable/PDPs/zh-CN/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/zh-CN/PDP.xml @@ -56,12 +56,12 @@ Version __VERSION_NUMBER__ -- 现在,使用会话还原时,终端将记住窗口的内容。 -- 现在可以同时使用多种字体。 -- 现在以像素为单位呈现框绘图字符。 -- 在终端内使用输入法的体验已得到显著提升。 -- JSON 文件中的配色方案现在要简单得多。 -- 已修复有关 URL 处理、双倍行宽、换行等大量 bug。 +- 我们已改变主机应用程序在终端内的托管方式!请报告遇到的任何 bug。 +- 终端现在支持 Sixels! +- 现在可以打开一个停靠面板,其中包含已保存供以后使用的命令片段 +- 最新 Windows 11 版本上的命令提示用户可能会看到“快速提示”图标,该图标建议从 WinGet 安装软件 +- 所选文本现在将具有更高的可见性(和可自定义性!) +- 修复了许多可靠性 bug、便利性问题和令人烦恼的问题。 有关其他详细信息,请参阅我们的 GitHub 发布页面。 diff --git a/build/StoreSubmission/Stable/PDPs/zh-TW/PDP.xml b/build/StoreSubmission/Stable/PDPs/zh-TW/PDP.xml index df182dd95a..02e5b69a3c 100644 --- a/build/StoreSubmission/Stable/PDPs/zh-TW/PDP.xml +++ b/build/StoreSubmission/Stable/PDPs/zh-TW/PDP.xml @@ -56,12 +56,12 @@ 版本 __VERSION_NUMBER__ -- 當您使用工作階段還原時,終端機現在會記住視窗的內容。 -- 現在您可以同時使用多個字型。 -- 製表格圖字元現在會以完美像素模式呈現。 -- 在終端機內使用 IME 的體驗已大幅改善。 -- JSON 檔案內的色彩配置現在將變得更簡單了。 -- 已修正一些 URL 處理、雙寬度列、換行等相關錯誤。 +- 我們已重寫主機應用程式在終端機內託管的方式!請報告您遇到的錯誤。 +- 終端機現在支援 Sixels! +- 現在,您可以開啟包含已儲存命令程式碼片段的固定面板,以供稍後使用 +- 最新 Windows 11 版本中的 [命令提示] 使用者可能會看到「快速提示」圖示,建議可自 WinGet 安裝的軟體 +- 選取的文字現在會更明顯 (且可自訂!) +- 已修正一些可靠性錯誤、便利性問題和令人困擾的問題。 如需更多詳細資訊,請參閱我們的 GitHub 發行頁面。 diff --git a/build/pipelines/ob-nightly.yml b/build/pipelines/ob-nightly.yml index ca863eb00f..033d075cd6 100644 --- a/build/pipelines/ob-nightly.yml +++ b/build/pipelines/ob-nightly.yml @@ -37,6 +37,8 @@ extends: akvName: $(SigningAKVName) authCertName: $(SigningAuthCertName) signCertName: $(SigningSignCertName) + useManagedIdentity: $(SigningUseManagedIdentity) + clientId: $(SigningOriginalClientId) publishSymbolsToPublic: true publishVpackToWindows: false symbolExpiryTime: 15 diff --git a/build/pipelines/ob-release.yml b/build/pipelines/ob-release.yml index c403920b54..d7de0e0a3a 100644 --- a/build/pipelines/ob-release.yml +++ b/build/pipelines/ob-release.yml @@ -85,6 +85,8 @@ extends: akvName: $(SigningAKVName) authCertName: $(SigningAuthCertName) signCertName: $(SigningSignCertName) + useManagedIdentity: $(SigningUseManagedIdentity) + clientId: $(SigningOriginalClientId) terminalInternalPackageVersion: ${{ parameters.terminalInternalPackageVersion }} publishSymbolsToPublic: ${{ parameters.publishSymbolsToPublic }} publishVpackToWindows: ${{ parameters.publishVpackToWindows }} diff --git a/build/pipelines/templates-v2/steps-esrp-signing.yml b/build/pipelines/templates-v2/steps-esrp-signing.yml index 9a8e6dbd9a..ef5a8d776b 100644 --- a/build/pipelines/templates-v2/steps-esrp-signing.yml +++ b/build/pipelines/templates-v2/steps-esrp-signing.yml @@ -19,4 +19,6 @@ steps: AuthAKVName: ${{ parameters.signingIdentity.akvName }} AuthCertName: ${{ parameters.signingIdentity.authCertName }} AuthSignCertName: ${{ parameters.signingIdentity.signCertName }} + UseMSIAuthentication: ${{ coalesce(parameters.signingIdentity.useManagedIdentity, 'false') }} + EsrpClientId: ${{ parameters.signingIdentity.clientId }} ${{ insert }}: ${{ parameters.inputs }} diff --git a/build/scripts/New-UnpackagedTerminalDistribution.ps1 b/build/scripts/New-UnpackagedTerminalDistribution.ps1 index 9605f13256..9f8d295be8 100644 --- a/build/scripts/New-UnpackagedTerminalDistribution.ps1 +++ b/build/scripts/New-UnpackagedTerminalDistribution.ps1 @@ -34,7 +34,7 @@ Param( ) $filesToRemove = @("*.xml", "*.winmd", "Appx*", "Images/*Tile*", "Images/*Logo*") # Remove from Terminal -$filesToKeep = @("Microsoft.Terminal.Remoting.winmd") # ... except for these +$filesToKeep = @() # ... except for these $filesToCopyFromXaml = @("Microsoft.UI.Xaml.dll", "Microsoft.UI.Xaml") # We don't need the .winmd $ErrorActionPreference = 'Stop' diff --git a/build/scripts/Set-LatestVCToolsVersion.ps1 b/build/scripts/Set-LatestVCToolsVersion.ps1 index 54a43b3a01..3156fff1bc 100644 --- a/build/scripts/Set-LatestVCToolsVersion.ps1 +++ b/build/scripts/Set-LatestVCToolsVersion.ps1 @@ -1,6 +1,6 @@ $VSInstances = ([xml](& 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -include packages -format xml)) $VSPackages = $VSInstances.instances.instance.packages.package -$LatestVCPackage = ($VSInstances.instances.instance.packages.package | ? { $_.id -eq "Microsoft.VisualCpp.CRT.Source" }) +$LatestVCPackage = ($VSInstances.instances.instance.packages.package | ? { $_.id -eq "Microsoft.VisualCpp.Tools.Core" }) $LatestVCToolsVersion = $LatestVCPackage.version; Write-Output "Latest VCToolsVersion: $LatestVCToolsVersion" diff --git a/build/scripts/Test-WindowsTerminalPackage.ps1 b/build/scripts/Test-WindowsTerminalPackage.ps1 index b405d98c21..b492eca05f 100644 --- a/build/scripts/Test-WindowsTerminalPackage.ps1 +++ b/build/scripts/Test-WindowsTerminalPackage.ps1 @@ -58,7 +58,7 @@ Try { ### Check the activatable class entries for a few DLLs we need. $inProcServers = $Manifest.Package.Extensions.Extension.InProcessServer.Path - $RequiredInProcServers = ("TerminalApp.dll", "Microsoft.Terminal.Control.dll", "Microsoft.Terminal.Remoting.dll", "Microsoft.Terminal.Settings.Editor.dll", "Microsoft.Terminal.Settings.Model.dll", "TerminalConnection.dll") + $RequiredInProcServers = ("TerminalApp.dll", "Microsoft.Terminal.Control.dll", "Microsoft.Terminal.Settings.Editor.dll", "Microsoft.Terminal.Settings.Model.dll", "TerminalConnection.dll") Write-Verbose "InProc Servers: $inProcServers" diff --git a/consolegit2gitfilters.json b/consolegit2gitfilters.json index 3dbcfdc9a2..1d570f2497 100644 --- a/consolegit2gitfilters.json +++ b/consolegit2gitfilters.json @@ -24,8 +24,6 @@ "/doc/specs/", "/doc/cascadia/", "/doc/user-docs/", - "/src/tools/MonarchPeasantSample/", - "/src/tools/MonarchPeasantPackage/", "/src/tools/ansi-color/", "/src/tools/ColorTool/", "/scratch/", diff --git a/custom.props b/custom.props index e25b9e8e97..8e358b3e0b 100644 --- a/custom.props +++ b/custom.props @@ -3,9 +3,9 @@ true - 2024 + 2025 1 - 23 + 24 Windows Terminal diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 09be784c15..315d103c53 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -35,7 +35,8 @@ "enum": [ "Windows.Terminal.Wsl", "Windows.Terminal.Azure", - "Windows.Terminal.PowershellCore" + "Windows.Terminal.PowershellCore", + "Windows.Terminal.VisualStudio" ], "type": "string" }, @@ -2372,16 +2373,6 @@ "description": "When set to true, Windows Terminal will run in the background. This allows globalSummon and quakeMode actions to work even when no windows are open.", "type": "boolean" }, - "compatibility.isolatedMode": { - "default": false, - "description": "When set to true, Terminal windows will not be able to interact with each other (including global hotkeys, tab drag/drop, running commandlines in existing windows, etc.). This is a compatibility escape hatch for users who are running into certain windowing issues.", - "type": "boolean" - }, - "compatibility.allowDECRQCRA": { - "default": false, - "description": "When set to true, the terminal will support the DECRQCRA (Request Checksum of Rectangular Area) escape sequence.", - "type": "boolean" - }, "compatibility.textMeasurement": { "default": "graphemes", "description": "This changes the way incoming text is grouped into cells. The \"graphemes\" option is the most modern and Unicode-correct way to do so, while \"wcswidth\" is a common approach on UNIX, and \"console\" replicates the way it used to work on Windows.", @@ -2541,6 +2532,11 @@ "description": "When set to true, the Terminal's tab row will display a shield icon when the Terminal is running with administrator privileges", "type": "boolean" }, + "showTabsFullscreen": { + "default": false, + "description": "When set to true, tabs remain visible in fullscreen mode. When set to false, tabs will be hidden when entering fullscreen mode.", + "type": "boolean" + }, "useAcrylicInTabRow": { "default": false, "description": "When set to true, the tab row will have an acrylic material background with 50% opacity.", @@ -2730,6 +2726,16 @@ "description": "When set to true, when opening a new tab or pane it will get reloaded environment variables.", "type": "boolean" }, + "compatibility.allowDECRQCRA": { + "default": false, + "description": "When set to true, the terminal will support the DECRQCRA (Request Checksum of Rectangular Area) escape sequence.", + "type": "boolean" + }, + "compatibility.allowOSC52": { + "default": true, + "description": "When set to true, VT applications will be allowed to set the contents of the local clipboard using OSC 52 (Manipulate Selection Data).", + "type": "boolean" + }, "unfocusedAppearance": { "$ref": "#/$defs/AppearanceConfig", "description": "Sets the appearance of the terminal when it is unfocused.", @@ -2911,7 +2917,7 @@ }, "experimental.rightClickContextMenu": { "default": false, - "description": "When set to true, right-clicking on the terminal will show a context menu. When set to false, right-click will copy", + "description": "When true, right-click shows a context menu; otherwise, it pastes from the clipboard or copies selection.", "type": "boolean" }, "experimental.repositionCursorWithMouse": { diff --git a/res/fonts/CascadiaCode.ttf b/res/fonts/CascadiaCode.ttf index 4e55e88db5..bba59c9600 100644 Binary files a/res/fonts/CascadiaCode.ttf and b/res/fonts/CascadiaCode.ttf differ diff --git a/res/fonts/CascadiaCodeItalic.ttf b/res/fonts/CascadiaCodeItalic.ttf index c0233a1b7a..7941ecd712 100644 Binary files a/res/fonts/CascadiaCodeItalic.ttf and b/res/fonts/CascadiaCodeItalic.ttf differ diff --git a/res/fonts/CascadiaMono.ttf b/res/fonts/CascadiaMono.ttf index 4c9f3d2158..f6f62d49c3 100644 Binary files a/res/fonts/CascadiaMono.ttf and b/res/fonts/CascadiaMono.ttf differ diff --git a/res/fonts/CascadiaMonoItalic.ttf b/res/fonts/CascadiaMonoItalic.ttf index c13eddbb6f..35bfe6f197 100644 Binary files a/res/fonts/CascadiaMonoItalic.ttf and b/res/fonts/CascadiaMonoItalic.ttf differ diff --git a/res/fonts/README.md b/res/fonts/README.md index e30d23aa8b..7d4e0ada97 100644 --- a/res/fonts/README.md +++ b/res/fonts/README.md @@ -8,5 +8,5 @@ Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadi ### Fonts Included -* Cascadia Code, Cascadia Mono (2404.23) - * from microsoft/cascadia-code@1034791e5fc6e060a448d2b29cd94a6c683edb36 +* Cascadia Code, Cascadia Mono (2407.24) + * from microsoft/cascadia-code@56bcca3f2c1e4cb19458954f0e2bb4635960df91 diff --git a/src/Terminal.wprp b/src/Terminal.wprp index 1abe7df41a..754cc1af26 100644 --- a/src/Terminal.wprp +++ b/src/Terminal.wprp @@ -10,7 +10,6 @@ - @@ -30,7 +29,6 @@ - @@ -51,7 +49,6 @@ - diff --git a/src/buffer/out/Row.cpp b/src/buffer/out/Row.cpp index 7a46215b6f..63ba83f4cd 100644 --- a/src/buffer/out/Row.cpp +++ b/src/buffer/out/Row.cpp @@ -80,11 +80,12 @@ constexpr OutIt copy_n_small(InIt first, Diff count, OutIt dest) return dest; } -CharToColumnMapper::CharToColumnMapper(const wchar_t* chars, const uint16_t* charOffsets, ptrdiff_t lastCharOffset, til::CoordType currentColumn) noexcept : +CharToColumnMapper::CharToColumnMapper(const wchar_t* chars, const uint16_t* charOffsets, ptrdiff_t charsLength, til::CoordType currentColumn, til::CoordType columnCount) noexcept : _chars{ chars }, _charOffsets{ charOffsets }, - _lastCharOffset{ lastCharOffset }, - _currentColumn{ currentColumn } + _charsLength{ charsLength }, + _currentColumn{ currentColumn }, + _columnCount{ columnCount } { } @@ -92,7 +93,7 @@ CharToColumnMapper::CharToColumnMapper(const wchar_t* chars, const uint16_t* cha // This function in particular returns the glyph's first column. til::CoordType CharToColumnMapper::GetLeadingColumnAt(ptrdiff_t targetOffset) noexcept { - targetOffset = clamp(targetOffset, 0, _lastCharOffset); + targetOffset = clamp(targetOffset, 0, _charsLength); // This code needs to fulfill two conditions on top of the obvious (a forward/backward search): // A: We never want to stop on a column that is marked with CharOffsetsTrailer (= "GetLeadingColumn"). @@ -130,10 +131,14 @@ til::CoordType CharToColumnMapper::GetLeadingColumnAt(ptrdiff_t targetOffset) no til::CoordType CharToColumnMapper::GetTrailingColumnAt(ptrdiff_t offset) noexcept { auto col = GetLeadingColumnAt(offset); - // This loop is a little redundant with the forward search loop in GetLeadingColumnAt() - // but it's realistically not worth caring about this. This code is not a bottleneck. - for (; WI_IsFlagSet(_charOffsets[col + 1], CharOffsetsTrailer); ++col) + + if (col < _columnCount) { + // This loop is a little redundant with the forward search loop in GetLeadingColumnAt() + // but it's realistically not worth caring about this. This code is not a bottleneck. + for (; WI_IsFlagSet(_charOffsets[col + 1], CharOffsetsTrailer); ++col) + { + } } return col; } @@ -1114,6 +1119,9 @@ std::wstring_view ROW::GetText() const noexcept return { _chars.data(), width }; } +// Arguments: +// - columnBegin: inclusive +// - columnEnd: exclusive std::wstring_view ROW::GetText(til::CoordType columnBegin, til::CoordType columnEnd) const noexcept { const auto columns = GetReadableColumnCount(); @@ -1219,15 +1227,15 @@ T ROW::_adjustForward(T column) const noexcept } // Creates a CharToColumnMapper given an offset into _chars.data(). -// In other words, for a 120 column ROW with just ASCII text, the offset should be [0,120). +// In other words, for a 120 column ROW with just ASCII text, the offset should be [0,120]. CharToColumnMapper ROW::_createCharToColumnMapper(ptrdiff_t offset) const noexcept { const auto charsSize = _charSize(); - const auto lastChar = gsl::narrow_cast(charsSize - 1); + const auto lastChar = gsl::narrow_cast(charsSize); // We can sort of guess what column belongs to what offset because BMP glyphs are very common and // UTF-16 stores them in 1 char. In other words, usually a ROW will have N chars for N columns. const auto guessedColumn = gsl::narrow_cast(clamp(offset, 0, _columnCount)); - return CharToColumnMapper{ _chars.data(), _charOffsets.data(), lastChar, guessedColumn }; + return CharToColumnMapper{ _chars.data(), _charOffsets.data(), lastChar, guessedColumn, _columnCount }; } const std::optional& ROW::GetScrollbarData() const noexcept diff --git a/src/buffer/out/Row.hpp b/src/buffer/out/Row.hpp index d2c19036ba..44156d1b88 100644 --- a/src/buffer/out/Row.hpp +++ b/src/buffer/out/Row.hpp @@ -71,7 +71,7 @@ struct RowCopyTextFromState // into a ROW's text this class can tell you what cell that pointer belongs to. struct CharToColumnMapper { - CharToColumnMapper(const wchar_t* chars, const uint16_t* charOffsets, ptrdiff_t lastCharOffset, til::CoordType currentColumn) noexcept; + CharToColumnMapper(const wchar_t* chars, const uint16_t* charOffsets, ptrdiff_t lastCharOffset, til::CoordType currentColumn, til::CoordType columnCount) noexcept; til::CoordType GetLeadingColumnAt(ptrdiff_t targetOffset) noexcept; til::CoordType GetTrailingColumnAt(ptrdiff_t offset) noexcept; @@ -85,8 +85,9 @@ private: const wchar_t* _chars; const uint16_t* _charOffsets; - ptrdiff_t _lastCharOffset; + ptrdiff_t _charsLength; til::CoordType _currentColumn; + til::CoordType _columnCount; }; class ROW final diff --git a/src/buffer/out/UTextAdapter.cpp b/src/buffer/out/UTextAdapter.cpp index ff0861ce54..717d97812a 100644 --- a/src/buffer/out/UTextAdapter.cpp +++ b/src/buffer/out/UTextAdapter.cpp @@ -411,16 +411,13 @@ Microsoft::Console::ICU::unique_uregex Microsoft::Console::ICU::CreateRegex(cons return unique_uregex{ re }; } -// Returns an inclusive point range given a text start and end position. +// Returns a half-open [beg,end) range given a text start and end position. // This function is designed to be used with uregex_start64/uregex_end64. til::point_span Microsoft::Console::ICU::BufferRangeFromMatch(UText* ut, URegularExpression* re) { UErrorCode status = U_ZERO_ERROR; const auto nativeIndexBeg = uregex_start64(re, 0, &status); - auto nativeIndexEnd = uregex_end64(re, 0, &status); - - // The parameters are given as a half-open [beg,end) range, but the point_span we return in closed [beg,end]. - nativeIndexEnd--; + const auto nativeIndexEnd = uregex_end64(re, 0, &status); const auto& textBuffer = *static_cast(ut->context); til::point_span ret; @@ -439,7 +436,7 @@ til::point_span Microsoft::Console::ICU::BufferRangeFromMatch(UText* ut, URegula if (utextAccess(ut, nativeIndexEnd, true)) { const auto y = accessCurrentRow(ut); - ret.end.x = textBuffer.GetRowByOffset(y).GetTrailingColumnAtCharOffset(ut->chunkOffset); + ret.end.x = textBuffer.GetRowByOffset(y).GetLeadingColumnAtCharOffset(ut->chunkOffset); ret.end.y = y; } else diff --git a/src/buffer/out/textBuffer.cpp b/src/buffer/out/textBuffer.cpp index a920854b73..df30a3ffb2 100644 --- a/src/buffer/out/textBuffer.cpp +++ b/src/buffer/out/textBuffer.cpp @@ -1118,6 +1118,14 @@ void TextBuffer::TriggerNewTextNotification(const std::wstring_view newText) } } +void TextBuffer::TriggerSelection() +{ + if (_isActiveBuffer && _renderer) + { + _renderer->TriggerSelection(); + } +} + // Method Description: // - get delimiter class for buffer cell position // - used for double click selection and uia word navigation @@ -1132,6 +1140,213 @@ DelimiterClass TextBuffer::_GetDelimiterClassAt(const til::point pos, const std: return GetRowByOffset(realPos.y).DelimiterClassAt(realPos.x, wordDelimiters); } +til::point TextBuffer::GetWordStart2(til::point pos, const std::wstring_view wordDelimiters, bool includeWhitespace, std::optional limitOptional) const +{ + const auto bufferSize{ GetSize() }; + const auto limit{ limitOptional.value_or(bufferSize.BottomInclusiveRightExclusive()) }; + + if (pos < bufferSize.Origin()) + { + // can't move further back, so return early at origin + return bufferSize.Origin(); + } + else if (pos >= limit) + { + // clamp to limit, + // but still do movement + pos = limit; + } + + // Consider the delimiter classes represented as these chars: + // - ControlChar: "_" + // - DelimiterChar: "D" + // - RegularChar: "C" + // Expected results ("|" is the position): + // includeWhitespace: true false + // CCC___| --> |CCC___ CCC|___ + // DDD___| --> |DDD___ DDD|___ + // ___CCC| --> ___|CCC ___|CCC + // DDDCCC| --> DDD|CCC DDD|CCC + // ___DDD| --> ___|DDD ___|DDD + // CCCDDD| --> CCC|DDD CCC|DDD + // So the heuristic we use is: + // 1. move to the beginning of the delimiter class run + // 2. (includeWhitespace) if we were on a ControlChar, go back one more delimiter class run + const auto initialDelimiter = bufferSize.IsInBounds(pos) ? _GetDelimiterClassAt(pos, wordDelimiters) : DelimiterClass::ControlChar; + pos = _GetDelimiterClassRunStart(pos, wordDelimiters); + if (!includeWhitespace || pos.x == bufferSize.Left()) + { + // Special case: + // we're at the left boundary (and end of a delimiter class run), + // we already know we can't wrap, so return early + return pos; + } + else if (initialDelimiter == DelimiterClass::ControlChar) + { + bufferSize.DecrementInExclusiveBounds(pos); + pos = _GetDelimiterClassRunStart(pos, wordDelimiters); + } + return pos; +} + +til::point TextBuffer::GetWordEnd2(til::point pos, const std::wstring_view wordDelimiters, bool includeWhitespace, std::optional limitOptional) const +{ + const auto bufferSize{ GetSize() }; + const auto limit{ limitOptional.value_or(bufferSize.BottomInclusiveRightExclusive()) }; + + if (pos >= limit) + { + // can't move further forward, + // so return early at limit + return limit; + } + else if (const auto origin{ bufferSize.Origin() }; pos < origin) + { + // clamp to origin, + // but still do movement + pos = origin; + } + + // Consider the delimiter classes represented as these chars: + // - ControlChar: "_" + // - DelimiterChar: "D" + // - RegularChar: "C" + // Expected results ("|" is the position): + // includeWhitespace: true false + // |CCC___ --> CCC___| CCC|___ + // |DDD___ --> DDD___| DDD|___ + // |___CCC --> ___|CCC ___|CCC + // |DDDCCC --> DDD|CCC DDD|CCC + // |___DDD --> ___|DDD ___|DDD + // |CCCDDD --> CCC|DDD CCC|DDD + // So the heuristic we use is: + // 1. move to the end of the delimiter class run + // 2. (includeWhitespace) if the next delimiter class run is a ControlChar, go forward one more delimiter class run + pos = _GetDelimiterClassRunEnd(pos, wordDelimiters); + if (!includeWhitespace || pos.x == bufferSize.RightExclusive()) + { + // Special case: + // we're at the right boundary (and end of a delimiter class run), + // we already know we can't wrap, so return early + return pos; + } + + if (const auto nextDelimClass = bufferSize.IsInBounds(pos) ? _GetDelimiterClassAt(pos, wordDelimiters) : DelimiterClass::ControlChar; + nextDelimClass == DelimiterClass::ControlChar) + { + return _GetDelimiterClassRunEnd(pos, wordDelimiters); + } + return pos; +} + +bool TextBuffer::IsWordBoundary(const til::point pos, const std::wstring_view wordDelimiters) const +{ + const auto bufferSize = GetSize(); + if (!bufferSize.IsInExclusiveBounds(pos)) + { + // not in bounds + return false; + } + + // buffer boundaries are always word boundaries + if (pos == bufferSize.Origin() || pos == bufferSize.BottomInclusiveRightExclusive()) + { + return true; + } + + // at beginning of the row, but we didn't wrap + if (pos.x == bufferSize.Left()) + { + const auto& row = GetRowByOffset(pos.y - 1); + if (!row.WasWrapForced()) + { + return true; + } + } + + // at end of the row, but we didn't wrap + if (pos.x == bufferSize.RightExclusive()) + { + const auto& row = GetRowByOffset(pos.y); + if (!row.WasWrapForced()) + { + return true; + } + } + + // we can treat text as contiguous, + // use DecrementInBounds (not exclusive) here + auto prevPos = pos; + bufferSize.DecrementInBounds(prevPos); + const auto prevDelimiterClass = _GetDelimiterClassAt(prevPos, wordDelimiters); + + // if we changed delimiter class + // and the current delimiter class is not a control char, + // we're at a word boundary + const auto currentDelimiterClass = _GetDelimiterClassAt(pos, wordDelimiters); + return prevDelimiterClass != currentDelimiterClass && currentDelimiterClass != DelimiterClass::ControlChar; +} + +til::point TextBuffer::_GetDelimiterClassRunStart(til::point pos, const std::wstring_view wordDelimiters) const +{ + const auto bufferSize = GetSize(); + const auto initialDelimClass = bufferSize.IsInBounds(pos) ? _GetDelimiterClassAt(pos, wordDelimiters) : DelimiterClass::ControlChar; + for (auto nextPos = pos; nextPos != bufferSize.Origin(); pos = nextPos) + { + bufferSize.DecrementInExclusiveBounds(nextPos); + + if (nextPos.x == bufferSize.RightExclusive()) + { + // wrapped onto previous line, + // check if it was forced to wrap + const auto& row = GetRowByOffset(nextPos.y); + if (!row.WasWrapForced()) + { + return pos; + } + } + else if (_GetDelimiterClassAt(nextPos, wordDelimiters) != initialDelimClass) + { + // if we changed delim class, we're done (don't apply move) + return pos; + } + } + return pos; +} + +// Method Description: +// - Get the exclusive position for the end of the current delimiter class run +// Arguments: +// - pos - the buffer position being within the current delimiter class +// - wordDelimiters - what characters are we considering for the separation of words +til::point TextBuffer::_GetDelimiterClassRunEnd(til::point pos, const std::wstring_view wordDelimiters) const +{ + const auto bufferSize = GetSize(); + const auto initialDelimClass = bufferSize.IsInBounds(pos) ? _GetDelimiterClassAt(pos, wordDelimiters) : DelimiterClass::ControlChar; + for (auto nextPos = pos; nextPos != bufferSize.BottomInclusiveRightExclusive(); pos = nextPos) + { + bufferSize.IncrementInExclusiveBounds(nextPos); + + if (nextPos.x == bufferSize.Left()) + { + // wrapped onto next line, + // check if it was forced to wrap or switched delimiter class + const auto& row = GetRowByOffset(pos.y); + if (!row.WasWrapForced() || _GetDelimiterClassAt(nextPos, wordDelimiters) != initialDelimClass) + { + return pos; + } + } + else if (bufferSize.IsInBounds(nextPos) && _GetDelimiterClassAt(nextPos, wordDelimiters) != initialDelimClass) + { + // if we changed delim class, + // apply the move and return + return nextPos; + } + } + return pos; +} + // Method Description: // - Get the til::point for the beginning of the word you are on // Arguments: @@ -1520,13 +1735,14 @@ til::point TextBuffer::GetGlyphStart(const til::point pos, std::optional 0) + if (resultPos > limit) { - resultPos = limit; + return limit; } - // limit is exclusive, so we need to move back to be within valid bounds - if (resultPos != limit && GetCellDataAt(resultPos)->DbcsAttr() == DbcsAttribute::Trailing) + // if we're on a trailing byte, move to the leading byte + if (bufferSize.IsInBounds(resultPos) && + GetCellDataAt(resultPos)->DbcsAttr() == DbcsAttribute::Trailing) { bufferSize.DecrementInBounds(resultPos, true); } @@ -1548,12 +1764,13 @@ til::point TextBuffer::GetGlyphEnd(const til::point pos, bool accessibilityMode, const auto limit{ limitOptional.value_or(bufferSize.EndExclusive()) }; // Clamp pos to limit - if (bufferSize.CompareInBounds(resultPos, limit, true) > 0) + if (resultPos > limit) { - resultPos = limit; + return limit; } - if (resultPos != limit && GetCellDataAt(resultPos)->DbcsAttr() == DbcsAttribute::Leading) + if (bufferSize.IsInBounds(resultPos) && + GetCellDataAt(resultPos)->DbcsAttr() == DbcsAttribute::Leading) { bufferSize.IncrementInBounds(resultPos, true); } @@ -1610,6 +1827,31 @@ bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowExclusiveEnd, std::o return success; } +bool TextBuffer::MoveToNextGlyph2(til::point& pos, std::optional limitOptional) const +{ + const auto bufferSize = GetSize(); + const auto limit{ limitOptional.value_or(bufferSize.BottomInclusiveRightExclusive()) }; + + if (pos >= limit) + { + // Corner Case: we're on/past the limit + // Clamp us to the limit + pos = limit; + return false; + } + + // Try to move forward, but if we hit the buffer boundary, we fail to move. + const bool success = bufferSize.IncrementInExclusiveBounds(pos); + if (success && + bufferSize.IsInBounds(pos) && + GetCellDataAt(pos)->DbcsAttr() == DbcsAttribute::Trailing) + { + // Move again if we're on a wide glyph + bufferSize.IncrementInExclusiveBounds(pos); + } + return success; +} + // Method Description: // - Update pos to be the beginning of the previous glyph/character. This is used for accessibility // Arguments: @@ -1642,6 +1884,31 @@ bool TextBuffer::MoveToPreviousGlyph(til::point& pos, std::optional return success; } +bool TextBuffer::MoveToPreviousGlyph2(til::point& pos, std::optional limitOptional) const +{ + const auto bufferSize = GetSize(); + const auto limit{ limitOptional.value_or(bufferSize.BottomInclusiveRightExclusive()) }; + + if (pos >= limit) + { + // Corner Case: we're on/past the limit + // Clamp us to the limit + pos = limit; + return false; + } + + // Try to move backward, but if we hit the buffer boundary, we fail to move. + const bool success = bufferSize.DecrementInExclusiveBounds(pos); + if (success && + bufferSize.IsInBounds(pos) && + GetCellDataAt(pos)->DbcsAttr() == DbcsAttribute::Trailing) + { + // Move again if we're on a wide glyph + bufferSize.DecrementInExclusiveBounds(pos); + } + return success; +} + // Method Description: // - Determines the line-by-line rectangles based on two COORDs // - expands the rectangles to support wide glyphs @@ -1660,12 +1927,10 @@ const std::vector TextBuffer::GetTextRects(til::point start { std::vector textRects; - const auto bufferSize = GetSize(); - // (0,0) is the top-left of the screen // the physically "higher" coordinate is closer to the top-left // the physically "lower" coordinate is closer to the bottom-right - const auto [higherCoord, lowerCoord] = bufferSize.CompareInBounds(start, end) <= 0 ? + const auto [higherCoord, lowerCoord] = start <= end ? std::make_tuple(start, end) : std::make_tuple(end, start); @@ -1686,6 +1951,7 @@ const std::vector TextBuffer::GetTextRects(til::point start } else { + const auto bufferSize = GetSize(); textRow.left = (row == higherCoord.y) ? higherCoord.x : bufferSize.Left(); textRow.right = (row == lowerCoord.y) ? lowerCoord.x : bufferSize.RightInclusive(); } @@ -1710,7 +1976,7 @@ const std::vector TextBuffer::GetTextRects(til::point start // - Else if a blockSelection, returns spans corresponding to each line in the block selection // Arguments: // - start: beginning of the text region of interest (inclusive) -// - end: the other end of the text region of interest (inclusive) +// - end: the other end of the text region of interest (exclusive) // - blockSelection: when enabled, get spans for each line covered by the block // - bufferCoordinates: when enabled, treat the coordinates as relative to // the buffer rather than the screen. @@ -1780,31 +2046,17 @@ void TextBuffer::_ExpandTextRow(til::inclusive_rect& textRow) const // expand left side of rect til::point targetPoint{ textRow.left, textRow.top }; - if (GetCellDataAt(targetPoint)->DbcsAttr() == DbcsAttribute::Trailing) + if (bufferSize.IsInBounds(targetPoint) && GetCellDataAt(targetPoint)->DbcsAttr() == DbcsAttribute::Trailing) { - if (targetPoint.x == bufferSize.Left()) - { - bufferSize.IncrementInBounds(targetPoint); - } - else - { - bufferSize.DecrementInBounds(targetPoint); - } + bufferSize.DecrementInExclusiveBounds(targetPoint); textRow.left = targetPoint.x; } // expand right side of rect targetPoint = { textRow.right, textRow.bottom }; - if (GetCellDataAt(targetPoint)->DbcsAttr() == DbcsAttribute::Leading) + if (bufferSize.IsInBounds(targetPoint) && GetCellDataAt(targetPoint)->DbcsAttr() == DbcsAttribute::Trailing) { - if (targetPoint.x == bufferSize.RightInclusive()) - { - bufferSize.DecrementInBounds(targetPoint); - } - else - { - bufferSize.IncrementInBounds(targetPoint); - } + bufferSize.IncrementInExclusiveBounds(targetPoint); textRow.right = targetPoint.x; } } @@ -1821,8 +2073,8 @@ size_t TextBuffer::SpanLength(const til::point coordStart, const til::point coor // - Retrieves the plain text data between the specified coordinates. // Arguments: // - trimTrailingWhitespace - remove the trailing whitespace at the end of the result. -// - start - where to start getting text (should be at or prior to "end") -// - end - where to end getting text +// - start - where to start getting text (should be at or prior to "end") (inclusive) +// - end - where to end getting text (exclusive) // Return Value: // - Just the text. std::wstring TextBuffer::GetPlainText(const til::point start, const til::point end) const @@ -1851,7 +2103,7 @@ std::tuple TextBuffer::_RowCopyHelper(cons const auto maxX = req.bufferCoordinates ? req.maxX : ScreenToBufferLineInclusive(til::point{ req.maxX, iRow }, lineRendition).x; rowBeg = minX; - rowEnd = maxX + 1; // +1 to get an exclusive end + rowEnd = maxX; } else { @@ -1860,7 +2112,7 @@ std::tuple TextBuffer::_RowCopyHelper(cons const auto end = req.bufferCoordinates ? req.end : ScreenToBufferLineInclusive(req.end, lineRendition); rowBeg = iRow != beg.y ? 0 : beg.x; - rowEnd = iRow != end.y ? row.GetReadableColumnCount() : end.x + 1; // +1 to get an exclusive end + rowEnd = iRow != end.y ? row.GetReadableColumnCount() : end.x; } // Our selection mechanism doesn't stick to glyph boundaries at the moment. @@ -1905,7 +2157,7 @@ std::wstring TextBuffer::GetPlainText(const CopyRequest& req) const const auto& row = GetRowByOffset(iRow); const auto& [rowBeg, rowEnd, addLineBreak] = _RowCopyHelper(req, iRow, row); - // save selected text + // save selected text (exclusive end) selectedText += row.GetText(rowBeg, rowEnd); if (addLineBreak && iRow != req.end.y) diff --git a/src/buffer/out/textBuffer.hpp b/src/buffer/out/textBuffer.hpp index c97de9e752..775417caab 100644 --- a/src/buffer/out/textBuffer.hpp +++ b/src/buffer/out/textBuffer.hpp @@ -170,9 +170,15 @@ public: void TriggerScroll(); void TriggerScroll(const til::point delta); void TriggerNewTextNotification(const std::wstring_view newText); + void TriggerSelection(); til::point GetWordStart(const til::point target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional limitOptional = std::nullopt) const; til::point GetWordEnd(const til::point target, const std::wstring_view wordDelimiters, bool accessibilityMode = false, std::optional limitOptional = std::nullopt) const; + + til::point GetWordStart2(til::point pos, const std::wstring_view wordDelimiters, bool includeWhitespace, std::optional limitOptional = std::nullopt) const; + til::point GetWordEnd2(til::point pos, const std::wstring_view wordDelimiters, bool includeWhitespace, std::optional limitOptional = std::nullopt) const; + + bool IsWordBoundary(const til::point pos, const std::wstring_view wordDelimiters) const; bool MoveToNextWord(til::point& pos, const std::wstring_view wordDelimiters, std::optional limitOptional = std::nullopt) const; bool MoveToPreviousWord(til::point& pos, const std::wstring_view wordDelimiters) const; @@ -180,6 +186,8 @@ public: til::point GetGlyphEnd(const til::point pos, bool accessibilityMode = false, std::optional limitOptional = std::nullopt) const; bool MoveToNextGlyph(til::point& pos, bool allowBottomExclusive = false, std::optional limitOptional = std::nullopt) const; bool MoveToPreviousGlyph(til::point& pos, std::optional limitOptional = std::nullopt) const; + bool MoveToNextGlyph2(til::point& pos, std::optional limitOptional = std::nullopt) const; + bool MoveToPreviousGlyph2(til::point& pos, std::optional limitOptional = std::nullopt) const; const std::vector GetTextRects(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const; std::vector GetTextSpans(til::point start, til::point end, bool blockSelection, bool bufferCoordinates) const; @@ -322,6 +330,8 @@ private: void _SetFirstRowIndex(const til::CoordType FirstRowIndex) noexcept; void _ExpandTextRow(til::inclusive_rect& selectionRow) const; DelimiterClass _GetDelimiterClassAt(const til::point pos, const std::wstring_view wordDelimiters) const; + til::point _GetDelimiterClassRunStart(til::point pos, const std::wstring_view wordDelimiters) const; + til::point _GetDelimiterClassRunEnd(til::point pos, const std::wstring_view wordDelimiters) const; til::point _GetWordStartForAccessibility(const til::point target, const std::wstring_view wordDelimiters) const; til::point _GetWordStartForSelection(const til::point target, const std::wstring_view wordDelimiters) const; til::point _GetWordEndForAccessibility(const til::point target, const std::wstring_view wordDelimiters, const til::point limit) const; diff --git a/src/buffer/out/ut_textbuffer/UTextAdapterTests.cpp b/src/buffer/out/ut_textbuffer/UTextAdapterTests.cpp index be9e941c75..81974fe83a 100644 --- a/src/buffer/out/ut_textbuffer/UTextAdapterTests.cpp +++ b/src/buffer/out/ut_textbuffer/UTextAdapterTests.cpp @@ -49,15 +49,15 @@ class UTextAdapterTests return { { beg, 0 }, { end, 0 } }; }; - auto expected = std::vector{ s(0, 2), s(8, 10) }; + auto expected = std::vector{ s(0, 3), s(8, 11) }; auto actual = buffer.SearchText(L"abc", SearchFlag::None); VERIFY_ARE_EQUAL(expected, actual); - expected = std::vector{ s(5, 5) }; + expected = std::vector{ s(5, 6) }; actual = buffer.SearchText(L"𝒷", SearchFlag::None); VERIFY_ARE_EQUAL(expected, actual); - expected = std::vector{ s(12, 15) }; + expected = std::vector{ s(12, 16) }; actual = buffer.SearchText(L"ネコ", SearchFlag::None); VERIFY_ARE_EQUAL(expected, actual); } diff --git a/src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp b/src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp index f3c0efa463..ff69ebf51e 100644 --- a/src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp +++ b/src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp @@ -8,7 +8,6 @@ #include "../TerminalApp/TerminalPage.h" #include "../TerminalApp/AppLogic.h" #include "../TerminalApp/AppCommandlineArgs.h" -#include "../inc/WindowingBehavior.h" using namespace WEX::Logging; using namespace WEX::Common; @@ -74,10 +73,6 @@ namespace TerminalAppLocalTests TEST_METHOD(TestMultipleSplitPaneSizes); - TEST_METHOD(TestFindTargetWindow); - TEST_METHOD(TestFindTargetWindowHelp); - TEST_METHOD(TestFindTargetWindowVersion); - private: void _buildCommandlinesHelper(AppCommandlineArgs& appArgs, const size_t expectedSubcommands, @@ -1934,209 +1929,4 @@ namespace TerminalAppLocalTests } } } - - void CommandlineTest::TestFindTargetWindow() - { - { - Log::Comment(L"wt.exe with no args should always use the value from" - L" the settings (passed as the second argument)."); - - std::vector args{ L"wt.exe" }; - auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseExisting, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseAnyExisting, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - } - { - Log::Comment(L"-w -1 should always result in a new window"); - - std::vector args{ L"wt.exe", L"-w", L"-1" }; - auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - } - { - Log::Comment(L"\"new\" should always result in a new window"); - - std::vector args{ L"wt.exe", L"-w", L"new" }; - auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - } - { - Log::Comment(L"-w with a negative number should always result in a " - L"new window"); - - std::vector args{ L"wt.exe", L"-w", L"-12345" }; - auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - } - { - Log::Comment(L"-w with a positive number should result in us trying" - L" to either make a new one or find an existing one " - L"with that ID, depending on the provided argument"); - - std::vector args{ L"wt.exe", L"-w", L"12345" }; - auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew); - VERIFY_ARE_EQUAL(12345, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting); - VERIFY_ARE_EQUAL(12345, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting); - VERIFY_ARE_EQUAL(12345, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - } - { - Log::Comment(L"-w 0 should always use the \"current\" window"); - - std::vector args{ L"wt.exe", L"-w", L"0" }; - auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew); - VERIFY_ARE_EQUAL(WindowingBehaviorUseCurrent, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseCurrent, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseCurrent, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - } - { - Log::Comment(L"-w last should always use the most recent window on " - L"this desktop"); - - std::vector args{ L"wt.exe", L"-w", L"last" }; - auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew); - VERIFY_ARE_EQUAL(WindowingBehaviorUseExisting, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseExisting, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseExisting, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - } - { - Log::Comment(L"Make sure we follow the provided argument when a " - L"--window-id wasn't explicitly provided"); - - std::vector args{ L"wt.exe", L"new-tab" }; - auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseExisting, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseAnyExisting, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - } - { - Log::Comment(L"Even if someone uses a subcommand as a window name, " - L"that should work"); - - std::vector args{ L"wt.exe", L"-w", L"new-tab" }; - auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew); - VERIFY_ARE_EQUAL(WindowingBehaviorUseName, result.WindowId()); - VERIFY_ARE_EQUAL(L"new-tab", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseName, result.WindowId()); - VERIFY_ARE_EQUAL(L"new-tab", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseName, result.WindowId()); - VERIFY_ARE_EQUAL(L"new-tab", result.WindowName()); - } - } - - void CommandlineTest::TestFindTargetWindowHelp() - { - Log::Comment(L"--help should always create a new window"); - - // This is a little helper to make sure that these args _always_ return - // UseNew, regardless of the windowing behavior. - auto testHelper = [](auto&& args) { - auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - }; - - testHelper(std::vector{ L"wt.exe", L"--help" }); - testHelper(std::vector{ L"wt.exe", L"new-tab", L"--help" }); - testHelper(std::vector{ L"wt.exe", L"-w", L"0", L"new-tab", L"--help" }); - testHelper(std::vector{ L"wt.exe", L"-w", L"foo", L"new-tab", L"--help" }); - testHelper(std::vector{ L"wt.exe", L"new-tab", L";", L"--help" }); - } - - void CommandlineTest::TestFindTargetWindowVersion() - { - Log::Comment(L"--version should always create a new window"); - - // This is a little helper to make sure that these args _always_ return - // UseNew, regardless of the windowing behavior. - auto testHelper = [](auto&& args) { - auto result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseNew); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - - result = appImpl::AppLogic::_doFindTargetWindow({ args }, WindowingMode::UseAnyExisting); - VERIFY_ARE_EQUAL(WindowingBehaviorUseNew, result.WindowId()); - VERIFY_ARE_EQUAL(L"", result.WindowName()); - }; - - testHelper(std::vector{ L"wt.exe", L"--version" }); - } } diff --git a/src/cascadia/LocalTests_TerminalApp/TabTests.cpp b/src/cascadia/LocalTests_TerminalApp/TabTests.cpp index d21497a51d..477e6dcf0e 100644 --- a/src/cascadia/LocalTests_TerminalApp/TabTests.cpp +++ b/src/cascadia/LocalTests_TerminalApp/TabTests.cpp @@ -1288,12 +1288,6 @@ namespace TerminalAppLocalTests END_TEST_METHOD_PROPERTIES() auto page = _commonSetup(); - page->RenameWindowRequested([&page](auto&&, auto&&) { - // In the real terminal, this would bounce up to the monarch and - // come back down. Instead, immediately call back to tell the terminal it failed. - page->RenameFailed(); - }); - auto windowNameChanged = false; page->PropertyChanged([&page, &windowNameChanged](auto&&, const winrt::WUX::Data::PropertyChangedEventArgs& args) mutable { diff --git a/src/cascadia/Remoting/CommandlineArgs.cpp b/src/cascadia/Remoting/CommandlineArgs.cpp deleted file mode 100644 index db76316932..0000000000 --- a/src/cascadia/Remoting/CommandlineArgs.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#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::Commandline(const winrt::array_view& value) - { - _args = { value.begin(), value.end() }; - } - - winrt::com_array CommandlineArgs::Commandline() - { - return winrt::com_array{ _args.begin(), _args.end() }; - } -} diff --git a/src/cascadia/Remoting/CommandlineArgs.h b/src/cascadia/Remoting/CommandlineArgs.h deleted file mode 100644 index 2f618e53ef..0000000000 --- a/src/cascadia/Remoting/CommandlineArgs.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include "CommandlineArgs.g.h" - -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - struct CommandlineArgs : public CommandlineArgsT - { - public: - CommandlineArgs() : - _args{}, - _cwd{ L"" } - { - } - - CommandlineArgs(const winrt::array_view& args, - winrt::hstring currentDirectory, - const uint32_t showWindowCommand, - winrt::hstring envString) : - _args{ args.begin(), args.end() }, - _cwd{ currentDirectory }, - _ShowWindowCommand{ showWindowCommand }, - CurrentEnvironment{ envString } - { - } - - winrt::hstring CurrentDirectory() { return _cwd; }; - - void Commandline(const winrt::array_view& value); - winrt::com_array Commandline(); - - til::property CurrentEnvironment; - - WINRT_PROPERTY(uint32_t, ShowWindowCommand, SW_NORMAL); // SW_NORMAL is 1, 0 is SW_HIDE - - private: - winrt::com_array _args; - winrt::hstring _cwd; - }; - -} - -namespace winrt::Microsoft::Terminal::Remoting::factory_implementation -{ - BASIC_FACTORY(CommandlineArgs); -} diff --git a/src/cascadia/Remoting/FindTargetWindowArgs.cpp b/src/cascadia/Remoting/FindTargetWindowArgs.cpp deleted file mode 100644 index 1781c1c9c1..0000000000 --- a/src/cascadia/Remoting/FindTargetWindowArgs.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -#include "pch.h" -#include "FindTargetWindowArgs.h" -#include "FindTargetWindowArgs.g.cpp" diff --git a/src/cascadia/Remoting/FindTargetWindowArgs.h b/src/cascadia/Remoting/FindTargetWindowArgs.h deleted file mode 100644 index b6dfc7638f..0000000000 --- a/src/cascadia/Remoting/FindTargetWindowArgs.h +++ /dev/null @@ -1,35 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation -Licensed under the MIT license. - -Class Name: -- FindTargetWindowArgs.h - -Abstract: -- This is a helper class for determining which window a specific commandline is - intended for. The Monarch will create one of these, then toss it over to - TerminalApp. TerminalApp actually contains the logic for parsing a - commandline, as well as settings like the windowing behavior. Once the - TerminalApp determines the correct window, it'll fill in the - ResultTargetWindow property. The monarch will then read that value out to - invoke the commandline in the appropriate window. - ---*/ - -#pragma once - -#include "FindTargetWindowArgs.g.h" - -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - struct FindTargetWindowArgs : public FindTargetWindowArgsT - { - WINRT_PROPERTY(winrt::Microsoft::Terminal::Remoting::CommandlineArgs, Args, nullptr); - WINRT_PROPERTY(int, ResultTargetWindow, -1); - WINRT_PROPERTY(winrt::hstring, ResultTargetWindowName); - - public: - FindTargetWindowArgs(winrt::Microsoft::Terminal::Remoting::CommandlineArgs args) : - _Args{ args } {}; - }; -} diff --git a/src/cascadia/Remoting/Microsoft.Terminal.RemotingLib.vcxproj b/src/cascadia/Remoting/Microsoft.Terminal.RemotingLib.vcxproj deleted file mode 100644 index b5c7ada479..0000000000 --- a/src/cascadia/Remoting/Microsoft.Terminal.RemotingLib.vcxproj +++ /dev/null @@ -1,135 +0,0 @@ - - - - {43ce4ce5-0010-4b99-9569-672670d26e26} - Win32Proj - Microsoft.Terminal.Remoting.Lib - Microsoft.Terminal.Remoting - Microsoft.Terminal.Remoting.Lib - StaticLibrary - Console - true - true - - - - - - - - Monarch.idl - - - Monarch.idl - - - Monarch.idl - - - Monarch.idl - - - Peasant.idl - - - Peasant.idl - - - Peasant.idl - - - - - Peasant.idl - - - WindowManager.idl - - - Peasant.idl - - - - - - Monarch.idl - - - Monarch.idl - - - Monarch.idl - - - Monarch.idl - - - Peasant.idl - - - Peasant.idl - - - Peasant.idl - - - Create - - - Peasant.idl - - - WindowManager.idl - - - Peasant.idl - - - - - - - - - - - - - - - - - - - - - {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE} - false - - - - - - - pch.h - - - WindowsApp.lib;user32.lib;shell32.lib;%(AdditionalDependencies) - - - false - - - - - - - - - diff --git a/src/cascadia/Remoting/Monarch.cpp b/src/cascadia/Remoting/Monarch.cpp deleted file mode 100644 index b986bfc863..0000000000 --- a/src/cascadia/Remoting/Monarch.cpp +++ /dev/null @@ -1,1114 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "pch.h" -#include "../inc/WindowingBehavior.h" -#include "Monarch.h" -#include "CommandlineArgs.h" -#include "FindTargetWindowArgs.h" -#include "ProposeCommandlineResult.h" - -#include "Monarch.g.cpp" -#include "WindowRequestedArgs.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() } - { - try - { - _desktopManager = winrt::create_instance(__uuidof(VirtualDesktopManager)); - } - CATCH_LOG(); - } - - // This constructor is intended to be used in unit tests, - // but we need to make it public in order to use make_self - // in the tests. It's not exposed through the idl though - // so it's not _truly_ fully public which should be acceptable. - Monarch::Monarch(const uint64_t testPID) : - _ourPID{ testPID } - { - } - - Monarch::~Monarch() = default; - - 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. - // - NB: this takes a unique_lock on _peasantsMutex. - // Arguments: - // - peasant: the new Peasant to track. - // Return Value: - // - the ID assigned to the peasant. - uint64_t Monarch::AddPeasant(Remoting::IPeasant peasant) - { - try - { - // 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 - const 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. - // If multiple peasants are added concurrently we keep trying to update - // until we get to set the new id. - uint64_t current; - do - { - current = _nextPeasantID.load(std::memory_order_relaxed); - } while (current <= providedID && !_nextPeasantID.compare_exchange_weak(current, providedID + 1, std::memory_order_relaxed)); - } - - auto newPeasantsId = peasant.GetID(); - - // Keep track of which peasant we are - // SAFETY: this is only true for one peasant, and each peasant - // is only added to a monarch once, so we do not need synchronization here. - if (peasant.GetPID() == _ourPID) - { - _ourPeasantId = newPeasantsId; - } - // Add an event listener to the peasant's WindowActivated event. - peasant.WindowActivated({ this, &Monarch::_peasantWindowActivated }); - peasant.IdentifyWindowsRequested({ this, &Monarch::_identifyWindows }); - peasant.RenameRequested({ this, &Monarch::_renameRequested }); - - peasant.ShowNotificationIconRequested([this](auto&&, auto&&) { ShowNotificationIconRequested.raise(*this, nullptr); }); - peasant.HideNotificationIconRequested([this](auto&&, auto&&) { HideNotificationIconRequested.raise(*this, nullptr); }); - - { - std::unique_lock lock{ _peasantsMutex }; - _peasants[newPeasantsId] = peasant; - } - - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_AddPeasant", - TraceLoggingUInt64(providedID, "providedID", "the provided ID for the peasant"), - TraceLoggingUInt64(newPeasantsId, "peasantID", "the ID of the new peasant"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - WindowCreated.raise(nullptr, nullptr); - return newPeasantsId; - } - catch (...) - { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_AddPeasant_Failed", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - // We can only get into this try/catch if the peasant died on us. So - // the return value doesn't _really_ matter. They're not about to - // get it. - return -1; - } - } - - // Method Description: - // - Gives the host process an opportunity to run any pre-close logic then - // requests all peasants to close. - // Arguments: - // - used - // Return Value: - // - - void Monarch::QuitAll() - { - if (_quitting.exchange(true, std::memory_order_relaxed)) - { - return; - } - - const auto callback = [&](const auto& id, const auto& p) { - // We want to tell our peasant to quit last, so that we don't try - // to perform a bunch of elections on quit. - if (id != _ourPeasantId) - { - p.Quit(); - } - }; - const auto onError = [&](const auto& id) { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_handleQuitAll_Failed", - TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not close"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - }; - - _forEachPeasant(callback, onError); - - { - std::shared_lock lock{ _peasantsMutex }; - const auto peasantSearch = _peasants.find(_ourPeasantId); - if (peasantSearch != _peasants.end()) - { - peasantSearch->second.Quit(); - } - } - } - - // Method Description: - // - Tells the monarch that a peasant is being closed. - // - NB: this (separately) takes unique locks on _peasantsMutex and - // _mruPeasantsMutex. - // Arguments: - // - peasantId: the id of the peasant - // Return Value: - // - - void Monarch::SignalClose(const uint64_t peasantId) - { - // If we are quitting we don't care about maintaining our list of - // peasants anymore, and don't need to notify the host that something - // changed. - if (_quitting.load(std::memory_order_relaxed)) - { - return; - } - - _clearOldMruEntries({ peasantId }); - { - std::unique_lock lock{ _peasantsMutex }; - _peasants.erase(peasantId); - } - WindowClosed.raise(nullptr, nullptr); - } - - // Method Description: - // - Counts the number of living peasants. - // Arguments: - // - - // Return Value: - // - the number of active peasants. - uint64_t Monarch::GetNumberOfPeasants() - { - std::shared_lock lock{ _peasantsMutex }; - return _peasants.size(); - } - - // 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! - // - args: a bundle of the peasant ID, timestamp, and desktop ID, for the activated peasant - // Return Value: - // - - void Monarch::_peasantWindowActivated(const winrt::Windows::Foundation::IInspectable& /*sender*/, - const Remoting::WindowActivatedArgs& args) - { - HandleActivatePeasant(args); - } - - // Method Description: - // - Lookup a peasant by its ID. If the peasant has died, this will also - // remove the peasant from our list of peasants. - // - NB: this (separately) takes unique locks on _peasantsMutex and - // _mruPeasantsMutex. - // Arguments: - // - peasantID: The ID Of the peasant to find - // - clearMruPeasantOnFailure: When true this function will handle clearing - // from _mruPeasants if a peasant was not found, otherwise the caller is - // expected to handle that cleanup themselves. - // Return Value: - // - the peasant if it exists in our map, otherwise null - Remoting::IPeasant Monarch::_getPeasant(uint64_t peasantID, bool clearMruPeasantOnFailure) - { - try - { - IPeasant maybeThePeasant = nullptr; - { - std::shared_lock lock{ _peasantsMutex }; - const auto peasantSearch = _peasants.find(peasantID); - maybeThePeasant = peasantSearch == _peasants.end() ? nullptr : peasantSearch->second; - } - // Ask the peasant for their PID. This will validate that they're - // actually still alive. - if (maybeThePeasant) - { - maybeThePeasant.GetPID(); - } - return maybeThePeasant; - } - catch (...) - { - LOG_CAUGHT_EXCEPTION(); - - // Remove the peasant from the list of peasants - { - std::unique_lock lock{ _peasantsMutex }; - _peasants.erase(peasantID); - } - - if (clearMruPeasantOnFailure) - { - // Remove the peasant from the list of MRU windows. They're dead. - // They can't be the MRU anymore. - _clearOldMruEntries({ peasantID }); - } - return nullptr; - } - } - - // Method Description: - // - Find the ID of the peasant with the given name. If no such peasant - // exists, then we'll return 0. If we encounter any peasants who have died - // during this process, then we'll remove them from the set of _peasants - // Arguments: - // - name: The window name to look for - // Return Value: - // - 0 if we didn't find the given peasant, otherwise a positive number for - // the window's ID. - uint64_t Monarch::_lookupPeasantIdForName(std::wstring_view name) - { - if (name.empty()) - { - return 0; - } - if (name == L"new") - { - return 0; - } - - uint64_t result = 0; - - const auto callback = [&](const auto& id, const auto& p) { - auto otherName = p.WindowName(); - if (otherName == name) - { - result = id; - return false; - } - return true; - }; - - const auto onError = [&](const auto& id) { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_lookupPeasantIdForName_Failed", - TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not get the name of"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - }; - - _forEachPeasant(callback, onError); - - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_lookupPeasantIdForName", - TraceLoggingWideString(std::wstring{ name }.c_str(), "name", "the name we're looking for"), - TraceLoggingUInt64(result, "peasantID", "the ID of the peasant with that name"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - return result; - } - - // Method Description: - // - Handler for the `Peasant::WindowActivated` event. We'll make a in-proc - // copy of the WindowActivatedArgs from the peasant. That way, we won't - // need to worry about the origin process dying when working with the - // WindowActivatedArgs. - // - If the peasant process dies while we're making this copy, then we'll - // just log it and do nothing. We certainly don't want to track a dead - // peasant. - // - We'll pass that copy of the WindowActivatedArgs to - // _doHandleActivatePeasant, which will actually insert the - // WindowActivatedArgs into the list we're using to track the most recent - // peasants. - // Arguments: - // - args: the WindowActivatedArgs describing when and where the peasant was activated. - // Return Value: - // - - void Monarch::HandleActivatePeasant(const Remoting::WindowActivatedArgs& args) - { - if (args == nullptr) - { - // MSFT:35731327, GH #12624. There's a chance that the way the - // window gets set up for defterm, the ActivatedArgs haven't been - // created for this window yet. Check here and just ignore them if - // they're null. They'll come back with real args soon - return; - } - // Start by making a local copy of these args. It's easier for us if our - // tracking of these args is all in-proc. That way, the only thing that - // could fail due to the peasant dying is _this first copy_. - winrt::com_ptr localArgs{ nullptr }; - try - { - localArgs = winrt::make_self(args); - // This method will actually do the hard work - _doHandleActivatePeasant(localArgs); - } - catch (...) - { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_HandleActivatePeasant_Failed", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - } - - // Method Description: - // - Helper for removing a peasant from the list of MRU peasants. We want to - // do this both when the peasant dies, and also when the peasant is newly - // activated (so that we don't leave an old entry for it in the list). - // - NB: This takes a unique lock on _mruPeasantsMutex. - // Arguments: - // - peasantIds: The list of peasant IDs to remove from the MRU list - // Return Value: - // - - void Monarch::_clearOldMruEntries(const std::unordered_set& peasantIds) - { - if (peasantIds.size() == 0) - { - return; - } - - std::unique_lock lock{ _mruPeasantsMutex }; - auto partition = std::remove_if(_mruPeasants.begin(), _mruPeasants.end(), [&](const auto& p) { - const auto id = p.PeasantID(); - // remove the element if it was found in the list to erase. - if (peasantIds.count(id) == 1) - { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_RemovedPeasantFromDesktop", - TraceLoggingUInt64(id, "peasantID", "The ID of the peasant"), - TraceLoggingGuid(p.DesktopID(), "desktopGuid", "The GUID of the previous desktop the window was on"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - return true; - } - return false; - }); - - // Remove everything that was in the list - _mruPeasants.erase(partition, _mruPeasants.end()); - } - - // Method Description: - // - Actually handle inserting the WindowActivatedArgs into our list of MRU windows. - // - NB: this takes a unique_lock on _mruPeasantsMutex. - // Arguments: - // - localArgs: an in-proc WindowActivatedArgs that we should add to our list of MRU windows. - // Return Value: - // - - void Monarch::_doHandleActivatePeasant(const winrt::com_ptr& localArgs) - { - // We're sure that localArgs isn't null here, we checked before in our - // one caller (in Monarch::HandleActivatePeasant) - - const auto newLastActiveTime = localArgs->ActivatedTime().time_since_epoch().count(); - - // * Check all the current lists to look for this peasant. - // remove it from any where it exists. - _clearOldMruEntries({ localArgs->PeasantID() }); - - // * If the current desktop doesn't have a vector, add one. - const auto desktopGuid{ localArgs->DesktopID() }; - - { - std::unique_lock lock{ _mruPeasantsMutex }; - // * Add this args list. By using lower_bound with insert, we can get it - // into exactly the right spot, without having to re-sort the whole - // array. - _mruPeasants.insert(std::lower_bound(_mruPeasants.begin(), - _mruPeasants.end(), - *localArgs, - [](const auto& first, const auto& second) { return first.ActivatedTime() > second.ActivatedTime(); }), - *localArgs); - } - - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_SetMostRecentPeasant", - TraceLoggingUInt64(localArgs->PeasantID(), "peasantID", "the ID of the activated peasant"), - TraceLoggingGuid(desktopGuid, "desktopGuid", "The GUID of the desktop the window is on"), - TraceLoggingInt64(newLastActiveTime, "newLastActiveTime", "The provided localArgs->ActivatedTime()"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - - // Method Description: - // - Retrieves the ID of the MRU peasant window. If requested, will limit - // the search to windows that are on the current desktop. - // - NB: This method will hold a shared lock on _mruPeasantsMutex and - // potentially a unique_lock on _peasantsMutex at the same time. - // Separately it might hold a unique_lock on _mruPeasantsMutex. - // Arguments: - // - limitToCurrentDesktop: if true, only return the MRU peasant that's - // actually on the current desktop. - // - ignoreQuakeWindow: if true, then don't return the _quake window when we - // find it. This allows us to change our behavior for glomming vs - // summoning. When summoning the window, this parameter should be true. - // When glomming, this should be false, as to prevent glomming to the - // _quake window. - // Return Value: - // - the ID of the most recent peasant, otherwise 0 if we could not find one. - uint64_t Monarch::_getMostRecentPeasantID(const bool limitToCurrentDesktop, const bool ignoreQuakeWindow) - { - std::shared_lock lock{ _mruPeasantsMutex }; - if (_mruPeasants.empty()) - { - // unlock the mruPeasants mutex to make sure we can't deadlock here. - lock.unlock(); - // Only need a shared lock for read - std::shared_lock peasantsLock{ _peasantsMutex }; - // We haven't yet been told the MRU peasant. Just use the first one. - // This is just gonna be a random one, but really shouldn't happen - // in practice. The WindowManager should set the MRU peasant - // immediately as soon as it creates the monarch/peasant for the - // first window. - if (_peasants.size() > 0) - { - try - { - return _peasants.begin()->second.GetID(); - } - catch (...) - { - // This shouldn't really happen. If we're the monarch, then the - // first peasant should also _be us_. So we should be able to - // get our own ID. - return 0; - } - } - - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_getMostRecentPeasantID_NoPeasants", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - return 0; - } - - // Here, there's at least one MRU peasant. - // - // We're going to iterate over these peasants until we find one that both: - // 1. Is alive - // 2. Meets our selection criteria (do we care if it is on this desktop?) - // - // If the peasant is dead, then we'll remove it, and try the next one. - // Once we find one that's alive, we'll either: - // * check if we only want a peasant on the current desktop, and if so, - // check if this peasant is on the current desktop. - // - If it isn't on the current desktop, we'll loop again, on the - // following peasant. - // * If we don't care, then we'll just return that one. - uint64_t result = 0; - std::unordered_set peasantsToErase{}; - for (const auto& mruWindowArgs : _mruPeasants) - { - // Try to get the peasant, but do not have _getPeasant clean up old - // _mruPeasants because we are iterating here. - // SAFETY: _getPeasant can take a unique_lock on _peasantsMutex if - // it detects a peasant is dead. Currently _getMostRecentPeasantId - // is the only method that holds a lock on both _mruPeasantsMutex and - // _peasantsMutex at the same time so there cannot be a deadlock here. - const auto peasant{ _getPeasant(mruWindowArgs.PeasantID(), false) }; - if (!peasant) - { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_Collect_WasDead", - TraceLoggingUInt64(mruWindowArgs.PeasantID(), - "peasantID", - "We thought this peasant was the MRU one, but it was actually already dead."), - TraceLoggingGuid(mruWindowArgs.DesktopID(), "desktopGuid", "The GUID of the desktop the window is on"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - // We'll go through the loop again. We removed the current one - // at positionInList, so the next one in positionInList will be - // a new, different peasant. - peasantsToErase.emplace(mruWindowArgs.PeasantID()); - continue; - } - - if (ignoreQuakeWindow && peasant.WindowName() == QuakeWindowName) - { - // The _quake window should never be treated as the MRU window. - // Skip it if we see it. Users can still target it with `wt -w - // _quake`, which will hit `_lookupPeasantIdForName` instead. - } - else if (limitToCurrentDesktop && _desktopManager) - { - // Check if this peasant is actually on this desktop. We can't - // simply get the GUID of the current desktop. We have to ask if - // the HWND is on the current desktop. - BOOL onCurrentDesktop{ false }; - - // SUCCEEDED_LOG will log if it failed, and return true if it SUCCEEDED - if (SUCCEEDED_LOG(_desktopManager->IsWindowOnCurrentVirtualDesktop(reinterpret_cast(mruWindowArgs.Hwnd()), - &onCurrentDesktop)) && - onCurrentDesktop) - { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_Collect", - TraceLoggingUInt64(mruWindowArgs.PeasantID(), - "peasantID", - "the ID of the MRU peasant for a desktop"), - TraceLoggingGuid(mruWindowArgs.DesktopID(), - "desktopGuid", - "The GUID of the desktop the window is on"), - TraceLoggingBoolean(limitToCurrentDesktop, - "limitToCurrentDesktop", - "True if we should only search for a window on the current desktop"), - TraceLoggingBool(onCurrentDesktop, - "onCurrentDesktop", - "true if this window was in fact on the current desktop"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - result = mruWindowArgs.PeasantID(); - break; - } - // If this window wasn't on the current desktop, another one - // might be. We'll increment positionInList below, and try - // again. - } - else - { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_getMostRecentPeasantID_Found", - TraceLoggingUInt64(mruWindowArgs.PeasantID(), "peasantID", "The ID of the MRU peasant"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - result = mruWindowArgs.PeasantID(); - break; - } - } - - lock.unlock(); - - if (peasantsToErase.size() > 0) - { - _clearOldMruEntries(peasantsToErase); - } - - if (result == 0) - { - // Here, we've checked all the windows, and none of them was both alive - // and the most recent (on this desktop). Just return 0 - the caller - // will use this to create a new window. - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_getMostRecentPeasantID_NotFound", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - - return result; - } - - // 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: - // - - // Return Value: - // - true if the caller should create a new window for this commandline. - // False otherwise - the monarch should have dispatched this commandline - // to another window in this case. - Remoting::ProposeCommandlineResult Monarch::ProposeCommandline(const Remoting::CommandlineArgs& args) - { - // Raise an event, to ask how to handle this commandline. We can't ask - // the app ourselves - we exist isolated from that knowledge (and - // dependency hell). The WindowManager will raise this up to the app - // host, which will then ask the AppLogic, who will then parse the - // commandline and determine the provided ID of the window. - auto findWindowArgs{ winrt::make_self(args) }; - - // This is handled by some handler in-proc - FindTargetWindowRequested.raise(*this, *findWindowArgs); - - // After the event was handled, ResultTargetWindow() will be filled with - // the parsed result. - const auto targetWindow = findWindowArgs->ResultTargetWindow(); - const auto targetWindowName = findWindowArgs->ResultTargetWindowName(); - - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_ProposeCommandline", - TraceLoggingInt64(targetWindow, "targetWindow", "The window ID the args specified"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - if (targetWindow == WindowingBehaviorUseNone) - { - // In this case, the targetWindow was UseNone, which means that we - // want to make a message box, but otherwise not make a Terminal - // window. - return winrt::make(false); - } - // If there's a valid ID returned, then let's try and find the peasant - // that goes with it. Alternatively, if we were given a magic windowing - // constant, we can use that to look up an appropriate peasant. - if (targetWindow >= 0 || - targetWindow == WindowingBehaviorUseName || - targetWindow == WindowingBehaviorUseExisting || - targetWindow == WindowingBehaviorUseAnyExisting) - { - uint64_t windowID = 0; - switch (targetWindow) - { - case WindowingBehaviorUseCurrent: - case WindowingBehaviorUseExisting: - // TODO:projects/5 for now, just use the MRU window. Technically, - // UseExisting and UseCurrent are different. - // UseCurrent implies that we should try to do the WT_SESSION - // lookup to find the window that spawned this process (then - // fall back to sameDesktop if we can't find a match). For now, - // it's good enough to just try to find a match on this desktop. - // - // GH#projects/5#card-60325142 - Don't try to glom to the quake window. - windowID = _getMostRecentPeasantID(true, true); - break; - case WindowingBehaviorUseAnyExisting: - windowID = _getMostRecentPeasantID(false, true); - break; - case WindowingBehaviorUseName: - windowID = _lookupPeasantIdForName(targetWindowName); - break; - case WindowingBehaviorUseNone: - // This should be impossible. The if statement above should have - // prevented WindowingBehaviorUseNone from falling in here. - // Explode, because this is a programming error. - THROW_HR(E_UNEXPECTED); - default: - windowID = ::base::saturated_cast(targetWindow); - break; - } - - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_ProposeCommandline", - TraceLoggingInt64(windowID, - "windowID", - "The actual peasant ID we evaluated the window ID as"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - // If_getMostRecentPeasantID returns 0 above, then we couldn't find - // a matching window for that style of windowing. _getPeasant will - // return nullptr, and we'll fall through to the "create a new - // window" branch below. - - if (auto targetPeasant{ _getPeasant(windowID) }) - { - auto result{ winrt::make_self(false) }; - try - { - // This will raise the peasant's ExecuteCommandlineRequested - // event, which will then ask the AppHost to handle the - // commandline, which will then pass it to AppLogic for - // handling. - targetPeasant.ExecuteCommandline(args); - } - catch (...) - { - // If we fail to propose the commandline to the peasant (it - // died?) then just tell this process to become a new window - // instead. - result->WindowName(targetWindowName); - result->ShouldCreateWindow(true); - - RequestNewWindow.raise(*this, *winrt::make_self(*result, args)); - - // If this fails, it'll be logged in the following - // TraceLoggingWrite statement, with succeeded=false - } - - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_ProposeCommandline_Existing", - TraceLoggingUInt64(windowID, - "peasantID", - "the ID of the peasant the commandline waws intended for"), - TraceLoggingBoolean(true, "foundMatch", "true if we found a peasant with that ID"), - TraceLoggingBoolean(!result->ShouldCreateWindow(), - "succeeded", - "true if we successfully dispatched the commandline to the peasant"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - return *result; - } - else if (windowID > 0) - { - // In this case, an ID was provided, but there's no - // peasant with that ID. Instead, we should tell the caller that - // they should make a new window, but _with that ID_. - - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_ProposeCommandline_Existing", - TraceLoggingUInt64(windowID, - "peasantID", - "the ID of the peasant the commandline waws intended for"), - TraceLoggingBoolean(false, "foundMatch", "true if we found a peasant with that ID"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - auto result{ winrt::make_self(true) }; - result->Id(windowID); - result->WindowName(targetWindowName); - - RequestNewWindow.raise(*this, *winrt::make_self(*result, args)); - - return *result; - } - } - - // If we get here, we couldn't find an existing window. Make a new one. - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_ProposeCommandline_NewWindow", - TraceLoggingInt64(targetWindow, "targetWindow", "The provided ID"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - // In this case, no usable ID was provided. Return { true, nullopt } - auto result = winrt::make_self(true); - result->WindowName(targetWindowName); - - RequestNewWindow.raise(*this, *winrt::make_self(*result, args)); - - return *result; - } - - // Method Description: - // - This is an event handler for the IdentifyWindowsRequested event. A - // Peasant may raise that event if they want _all_ windows to identify - // themselves. - // - This will tell each and every peasant to identify themselves. This will - // eventually propagate down to TerminalPage::IdentifyWindow. - // Arguments: - // - - // Return Value: - // - - void Monarch::_identifyWindows(const winrt::Windows::Foundation::IInspectable& /*sender*/, - const winrt::Windows::Foundation::IInspectable& /*args*/) - { - // Notify all the peasants to display their ID. - const auto callback = [&](const auto& /*id*/, const auto& p) { - p.DisplayWindowId(); - }; - const auto onError = [&](const auto& id) { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_identifyWindows_Failed", - TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not identify"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - }; - - _forEachPeasant(callback, onError); - } - - // Method Description: - // - This is an event handler for the RenameRequested event. A - // Peasant may raise that event when they want to be renamed to something else. - // - We will check if there are any other windows with this name. If there - // are, then we'll reject the rename by setting args.Succeeded=false. - // - If there aren't any other windows with this name, then we'll set - // args.Succeeded=true, allowing the window to keep this name. - // Arguments: - // - args: Contains the requested window name and a boolean (Succeeded) - // indicating if the request was successful. - // Return Value: - // - - void Monarch::_renameRequested(const winrt::Windows::Foundation::IInspectable& /*sender*/, - const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args) - { - auto successfullyRenamed = false; - - try - { - args.Succeeded(false); - const auto name{ args.NewName() }; - // Try to find a peasant that currently has this name - const auto id = _lookupPeasantIdForName(name); - if (_getPeasant(id) == nullptr) - { - // If there is one, then oh no! The requestor is not allowed to - // be renamed. - args.Succeeded(true); - successfullyRenamed = true; - } - - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_renameRequested", - TraceLoggingWideString(name.c_str(), "name", "The newly proposed name"), - TraceLoggingInt64(successfullyRenamed, "successfullyRenamed", "true if the peasant is allowed to rename themselves to that name."), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - catch (...) - { - LOG_CAUGHT_EXCEPTION(); - // If this fails, we don't _really_ care. The peasant died, but - // they're the only one who cares about the result. - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_renameRequested_Failed", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - } - - // Method Description: - // - Attempt to summon a window. `args` contains information about which - // window we should try to summon: - // * if a WindowName is provided, we'll try to find a window with exactly - // that name, and fail if there isn't one. - // - Calls Peasant::Summon on the matching peasant (which might be an RPC call) - // - This should only ever be called by the WindowManager in the monarch - // process itself. The monarch is the one registering for global hotkeys, - // so it's the one calling this method. - // Arguments: - // - args: contains information about the window that should be summoned. - // Return Value: - // - - // - Sets args.FoundMatch when a window matching args is found successfully. - void Monarch::SummonWindow(const Remoting::SummonWindowSelectionArgs& args) - { - const auto searchedForName{ args.WindowName() }; - try - { - args.FoundMatch(false); - - // If a WindowID is provided from the args, use that first. - uint64_t windowId = 0; - if (args.WindowID()) - { - windowId = args.WindowID().Value(); - } - else - { - // If no name was provided, then just summon the MRU window. - if (searchedForName.empty()) - { - // Use the value of the `desktop` arg to determine if we should - // limit to the current desktop (desktop:onCurrent) or not - // (desktop:any or desktop:toCurrent) - windowId = _getMostRecentPeasantID(args.OnCurrentDesktop(), false); - } - else - { - // Try to find a peasant that currently has this name - windowId = _lookupPeasantIdForName(searchedForName); - } - } - - if (auto targetPeasant{ _getPeasant(windowId) }) - { - targetPeasant.Summon(args.SummonBehavior()); - args.FoundMatch(true); - - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_SummonWindow_Success", - TraceLoggingWideString(searchedForName.c_str(), "searchedForName", "The name of the window we tried to summon"), - TraceLoggingUInt64(windowId, "peasantID", "The id of the window we tried to summon"), - TraceLoggingBoolean(args.OnCurrentDesktop(), "OnCurrentDesktop", "true iff the window needs to be on the current virtual desktop"), - TraceLoggingBoolean(args.SummonBehavior().MoveToCurrentDesktop(), "MoveToCurrentDesktop", "if true, move the window to the current virtual desktop"), - TraceLoggingBoolean(args.SummonBehavior().ToggleVisibility(), "ToggleVisibility", "true if we should toggle the visibility of the window"), - TraceLoggingUInt32(args.SummonBehavior().DropdownDuration(), "DropdownDuration", "the duration to dropdown the window"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - else - { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_SummonWindow_NoPeasant", - TraceLoggingWideString(searchedForName.c_str(), "searchedForName", "The name of the window we tried to summon"), - TraceLoggingUInt64(windowId, "peasantID", "The id of the window we tried to summon"), - TraceLoggingBoolean(args.OnCurrentDesktop(), "OnCurrentDesktop", "true iff the window needs to be on the current virtual desktop"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - } - catch (...) - { - LOG_CAUGHT_EXCEPTION(); - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_SummonWindow_Failed", - TraceLoggingWideString(searchedForName.c_str(), "searchedForName", "The name of the window we tried to summon"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - } - - // Method Description: - // - This method creates a map of peasant IDs to peasant names - // while removing dead peasants. - // Arguments: - // - - // Return Value: - // - A map of peasant IDs to their names. - Windows::Foundation::Collections::IVectorView Monarch::GetPeasantInfos() - { - std::vector names; - { - std::shared_lock lock{ _peasantsMutex }; - names.reserve(_peasants.size()); - } - - const auto func = [&](const auto& id, const auto& p) -> void { - names.push_back({ id, p.WindowName(), p.ActiveTabTitle() }); - }; - - const auto onError = [&](const auto& id) { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_identifyWindows_Failed", - TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not identify"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - }; - - _forEachPeasant(func, onError); - - return winrt::single_threaded_vector(std::move(names)).GetView(); - } - - bool Monarch::DoesQuakeWindowExist() - { - auto result = false; - const auto func = [&](const auto& /*id*/, const auto& p) { - if (p.WindowName() == QuakeWindowName) - { - result = true; - } - // continue if we didn't get a positive result - return !result; - }; - - const auto onError = [&](const auto& id) { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_DoesQuakeWindowExist_Failed", - TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not ask for its name"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - }; - - _forEachPeasant(func, onError); - return result; - } - - void Monarch::SummonAllWindows() - { - const auto func = [&](const auto& /*id*/, const auto& p) { - SummonWindowBehavior args{}; - args.ToggleVisibility(false); - p.Summon(args); - }; - - const auto onError = [&](const auto& id) { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_SummonAll_Failed", - TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not summon"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - }; - - _forEachPeasant(func, onError); - } - - void Monarch::RequestMoveContent(winrt::hstring window, - winrt::hstring content, - uint32_t tabIndex, - const Windows::Foundation::IReference& windowBounds) - { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_MoveContent_Requested", - TraceLoggingWideString(window.c_str(), "window", "The name of the window we tried to move to"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - uint64_t windowId = _lookupPeasantIdForName(window); - if (windowId == 0) - { - // Try the name as an integer ID - uint32_t temp; - if (!Utils::StringToUint(window.c_str(), temp)) - { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_MoveContent_FailedToParseId", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - else - { - windowId = temp; - } - } - - if (auto targetPeasant{ _getPeasant(windowId) }) - { - auto request = winrt::make_self(content, tabIndex); - targetPeasant.AttachContentToWindow(*request); - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_MoveContent_Completed", - TraceLoggingInt64(windowId, "windowId", "The ID of the peasant which we sent the content to"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - else - { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_MoveContent_NoWindow", - TraceLoggingInt64(windowId, "windowId", "We could not find a peasant with this ID"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - // In the case where window couldn't be found, then create a window - // for that name / ID. - // - // Don't let the window literally be named "-1", because that's silly. Same with "new" - const bool nameIsReserved = window == L"-1" || window == L"new"; - auto request = winrt::make_self(nameIsReserved ? L"" : window, - content, - windowBounds); - RequestNewWindow.raise(*this, *request); - } - } - - // Very similar to the above. Someone came and told us that they were the target of a drag/drop, and they know who started it. - // We will go tell the person who started it that they should send that target the content which was dragged. - void Monarch::RequestSendContent(const Remoting::RequestReceiveContentArgs& args) - { - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_SendContent_Requested", - TraceLoggingUInt64(args.SourceWindow(), "source", "The window which started the drag"), - TraceLoggingUInt64(args.TargetWindow(), "target", "The window which was the target of the drop"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - if (auto senderPeasant{ _getPeasant(args.SourceWindow()) }) - { - senderPeasant.SendContent(args); - - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_SendContent_Completed", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - else - { - // We couldn't find the peasant that started the drag. Well that - // sure is weird, but that would indicate that the sender closed - // after starting the drag. No matter. We can just do nothing. - - TraceLoggingWrite(g_hRemotingProvider, - "Monarch_SendContent_NoWindow", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - } -} diff --git a/src/cascadia/Remoting/Monarch.h b/src/cascadia/Remoting/Monarch.h deleted file mode 100644 index 4cc74d0c5b..0000000000 --- a/src/cascadia/Remoting/Monarch.h +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#pragma once - -#include "Monarch.g.h" -#include "Peasant.h" -#include "WindowActivatedArgs.h" -#include "WindowRequestedArgs.g.h" -#include - -// We sure different GUIDs here depending on whether we're running a Release, -// Preview, or Dev build. This ensures that different installs don't -// accidentally talk to one another. -// -// * Release: {06171993-7eb1-4f3e-85f5-8bdd7386cce3} -// * Preview: {04221993-7eb1-4f3e-85f5-8bdd7386cce3} -// * Canary: {09222022-7eb1-4f3e-85f5-8bdd7386cce3} -// * Dev: {08302020-7eb1-4f3e-85f5-8bdd7386cce3} -constexpr GUID Monarch_clsid -{ -#if defined(WT_BRANDING_RELEASE) - 0x06171993, -#elif defined(WT_BRANDING_PREVIEW) - 0x04221993, -#elif defined(WT_BRANDING_CANARY) - 0x09222022, -#else - 0x08302020, -#endif - 0x7eb1, - 0x4f3e, - { - 0x85, 0xf5, 0x8b, 0xdd, 0x73, 0x86, 0xcc, 0xe4 - } -}; - -namespace RemotingUnitTests -{ - class RemotingTests; -}; - -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - struct WindowRequestedArgs : public WindowRequestedArgsT - { - public: - WindowRequestedArgs(const Remoting::ProposeCommandlineResult& windowInfo, const Remoting::CommandlineArgs& command) : - _Id{ windowInfo.Id() ? windowInfo.Id().Value() : 0 }, // We'll use 0 as a sentinel, since no window will ever get to have that ID - _WindowName{ windowInfo.WindowName() }, - _args{ command.Commandline() }, - _CurrentDirectory{ command.CurrentDirectory() }, - _ShowWindowCommand{ command.ShowWindowCommand() }, - _CurrentEnvironment{ command.CurrentEnvironment() } {}; - - WindowRequestedArgs(const winrt::hstring& window, const winrt::hstring& content, const Windows::Foundation::IReference& bounds) : - _Id{ 0u }, - _WindowName{ window }, - _args{}, - _CurrentDirectory{}, - _Content{ content }, - _InitialBounds{ bounds } {}; - - void Commandline(const winrt::array_view& value) { _args = { value.begin(), value.end() }; }; - winrt::com_array Commandline() { return winrt::com_array{ _args.begin(), _args.end() }; } - - WINRT_PROPERTY(uint64_t, Id); - WINRT_PROPERTY(winrt::hstring, WindowName); - WINRT_PROPERTY(winrt::hstring, CurrentDirectory); - WINRT_PROPERTY(winrt::hstring, Content); - WINRT_PROPERTY(uint32_t, ShowWindowCommand, SW_NORMAL); - WINRT_PROPERTY(winrt::hstring, CurrentEnvironment); - WINRT_PROPERTY(Windows::Foundation::IReference, InitialBounds); - - private: - winrt::com_array _args; - }; - - struct Monarch : public MonarchT - { - Monarch(); - Monarch(const uint64_t testPID); - ~Monarch(); - - uint64_t GetPID(); - - uint64_t AddPeasant(winrt::Microsoft::Terminal::Remoting::IPeasant peasant); - void SignalClose(const uint64_t peasantId); - void QuitAll(); - - uint64_t GetNumberOfPeasants(); - - winrt::Microsoft::Terminal::Remoting::ProposeCommandlineResult ProposeCommandline(const winrt::Microsoft::Terminal::Remoting::CommandlineArgs& args); - void HandleActivatePeasant(const winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs& args); - void SummonWindow(const Remoting::SummonWindowSelectionArgs& args); - - void SummonAllWindows(); - bool DoesQuakeWindowExist(); - Windows::Foundation::Collections::IVectorView GetPeasantInfos(); - - void RequestMoveContent(winrt::hstring window, winrt::hstring content, uint32_t tabIndex, const Windows::Foundation::IReference& windowBounds); - void RequestSendContent(const Remoting::RequestReceiveContentArgs& args); - - til::typed_event FindTargetWindowRequested; - til::typed_event<> ShowNotificationIconRequested; - til::typed_event<> HideNotificationIconRequested; - til::typed_event<> WindowCreated; - til::typed_event<> WindowClosed; - - til::typed_event RequestNewWindow; - - private: - uint64_t _ourPID; - - std::atomic _nextPeasantID{ 1 }; - uint64_t _ourPeasantId{ 0 }; - - // When we're quitting we do not care as much about handling some events that we know will be triggered - std::atomic _quitting{ false }; - - winrt::com_ptr _desktopManager{ nullptr }; - - std::unordered_map _peasants; - std::vector _mruPeasants; - // These should not be locked at the same time to prevent deadlocks - // unless they are both shared_locks. - std::shared_mutex _peasantsMutex{}; - std::shared_mutex _mruPeasantsMutex{}; - - winrt::Microsoft::Terminal::Remoting::IPeasant _getPeasant(uint64_t peasantID, bool clearMruPeasantOnFailure = true); - uint64_t _getMostRecentPeasantID(bool limitToCurrentDesktop, const bool ignoreQuakeWindow); - uint64_t _lookupPeasantIdForName(std::wstring_view name); - - void _peasantWindowActivated(const winrt::Windows::Foundation::IInspectable& sender, - const winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs& args); - void _doHandleActivatePeasant(const winrt::com_ptr& args); - void _clearOldMruEntries(const std::unordered_set& peasantIds); - - void _forAllPeasantsIgnoringTheDead(std::function callback, - std::function errorCallback); - - void _identifyWindows(const winrt::Windows::Foundation::IInspectable& sender, - const winrt::Windows::Foundation::IInspectable& args); - - void _renameRequested(const winrt::Windows::Foundation::IInspectable& sender, - const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args); - - void _handleQuitAll(const winrt::Windows::Foundation::IInspectable& sender, - const winrt::Windows::Foundation::IInspectable& args); - - // Method Description: - // - Helper for doing something on each and every peasant. - // - We'll try calling func on every peasant. - // - If the return type of func is void, it will perform it for all peasants. - // - If the return type is a boolean, we'll break out of the loop once func - // returns false. - // - If any single peasant is dead, then we'll call onError and then add it to a - // list of peasants to clean up once the loop ends. - // - NB: this (separately) takes unique locks on _peasantsMutex and - // _mruPeasantsMutex. - // Arguments: - // - func: The function to call on each peasant - // - onError: The function to call if a peasant is dead. - // Return Value: - // - - template - void _forEachPeasant(F&& func, T&& onError) - { - using Map = decltype(_peasants); - using R = std::invoke_result_t; - static constexpr auto IsVoid = std::is_void_v; - - std::unordered_set peasantsToErase; - { - std::shared_lock lock{ _peasantsMutex }; - - for (const auto& [id, p] : _peasants) - { - try - { - if constexpr (IsVoid) - { - func(id, p); - } - else - { - if (!func(id, p)) - { - break; - } - } - } - catch (const winrt::hresult_error& exception) - { - onError(id); - - if (exception.code() == 0x800706ba) // The RPC server is unavailable. - { - peasantsToErase.emplace(id); - } - else - { - LOG_CAUGHT_EXCEPTION(); - throw; - } - } - } - } - - if (peasantsToErase.size() > 0) - { - // Don't hold a lock on _peasants and _mruPeasants at the same - // time to avoid deadlocks. - { - std::unique_lock lock{ _peasantsMutex }; - for (const auto& id : peasantsToErase) - { - _peasants.erase(id); - } - } - _clearOldMruEntries(peasantsToErase); - - // A peasant died, let the app host know that the number of - // windows has changed. - WindowClosed.raise(nullptr, nullptr); - } - } - - friend class RemotingUnitTests::RemotingTests; - }; -} - -namespace winrt::Microsoft::Terminal::Remoting::factory_implementation -{ - BASIC_FACTORY(Monarch); - BASIC_FACTORY(WindowRequestedArgs); -} diff --git a/src/cascadia/Remoting/Monarch.idl b/src/cascadia/Remoting/Monarch.idl deleted file mode 100644 index ba00cf47cf..0000000000 --- a/src/cascadia/Remoting/Monarch.idl +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -import "Peasant.idl"; - -namespace Microsoft.Terminal.Remoting -{ - - [default_interface] runtimeclass FindTargetWindowArgs { - CommandlineArgs Args { get; }; - Int32 ResultTargetWindow; - String ResultTargetWindowName; - } - - [default_interface] runtimeclass ProposeCommandlineResult { - Windows.Foundation.IReference Id { get; }; - String WindowName { get; }; - Boolean ShouldCreateWindow { get; }; // If you name this `CreateWindow`, the compiler will explode - } - - [default_interface] runtimeclass WindowRequestedArgs { - WindowRequestedArgs(ProposeCommandlineResult windowInfo, CommandlineArgs command); - - UInt64 Id { get; }; - String WindowName { get; }; - - String[] Commandline { get; }; - String CurrentDirectory { get; }; - UInt32 ShowWindowCommand { get; }; - String CurrentEnvironment { get; }; - - String Content { get; }; - Windows.Foundation.IReference InitialBounds { get; }; - } - - [default_interface] runtimeclass SummonWindowSelectionArgs { - SummonWindowSelectionArgs(); - SummonWindowSelectionArgs(String windowName); - String WindowName; - Boolean OnCurrentDesktop; - // TODO GH#8888 Other options: - // * CurrentMonitor - - Boolean FoundMatch; - SummonWindowBehavior SummonBehavior; - Windows.Foundation.IReference WindowID; - } - - struct PeasantInfo - { - UInt64 Id; - String Name; - String TabTitle; - }; - - interface IMonarch - { - - UInt64 GetPID(); - UInt64 AddPeasant(IPeasant peasant); - UInt64 GetNumberOfPeasants(); - ProposeCommandlineResult ProposeCommandline(CommandlineArgs args); - void HandleActivatePeasant(WindowActivatedArgs args); - void SummonWindow(SummonWindowSelectionArgs args); - void SignalClose(UInt64 peasantId); - void QuitAll(); - - void SummonAllWindows(); - Boolean DoesQuakeWindowExist(); - Windows.Foundation.Collections.IVectorView GetPeasantInfos { get; }; - - void RequestMoveContent(String window, String content, UInt32 tabIndex, Windows.Foundation.IReference bounds); - void RequestSendContent(RequestReceiveContentArgs args); - - event Windows.Foundation.TypedEventHandler FindTargetWindowRequested; - event Windows.Foundation.TypedEventHandler ShowNotificationIconRequested; - event Windows.Foundation.TypedEventHandler HideNotificationIconRequested; - event Windows.Foundation.TypedEventHandler WindowCreated; - event Windows.Foundation.TypedEventHandler WindowClosed; - - event Windows.Foundation.TypedEventHandler RequestNewWindow; - }; - - runtimeclass Monarch : [default] IMonarch - { - Monarch(); - }; -} diff --git a/src/cascadia/Remoting/MonarchFactory.h b/src/cascadia/Remoting/MonarchFactory.h deleted file mode 100644 index 496a609468..0000000000 --- a/src/cascadia/Remoting/MonarchFactory.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#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. - -struct MonarchFactory : winrt::implements -{ - MonarchFactory() = default; - - HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept - { - static winrt::weak_ref g_weak{ nullptr }; - - *result = nullptr; - if (outer) - { - return CLASS_E_NOAGGREGATION; - } - - // Lock the ref immediately. We don't want it freed from out beneath us - auto strong = g_weak.get(); - if (!strong) - { - // Create a new Monarch instance - strong = winrt::make_self(); - g_weak = (*strong).get_weak(); - return strong.as(iid, result); - } - else - { - // We already instantiated one Monarch, let's just return that one! - return strong.as(iid, result); - } - } - - HRESULT __stdcall LockServer(BOOL) noexcept - { - return S_OK; - } -}; diff --git a/src/cascadia/Remoting/Peasant.cpp b/src/cascadia/Remoting/Peasant.cpp deleted file mode 100644 index e09f5ac67e..0000000000 --- a/src/cascadia/Remoting/Peasant.cpp +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "pch.h" -#include "Peasant.h" -#include "CommandlineArgs.h" -#include "SummonWindowBehavior.h" -#include "Peasant.g.cpp" -#include "../../types/inc/utils.hpp" -#include "AttachRequest.g.cpp" -#include "RequestReceiveContentArgs.g.cpp" - -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 constructor is intended to be used in unit tests, - // but we need to make it public in order to use make_self - // in the tests. It's not exposed through the idl though - // so it's not _truly_ fully public which should be acceptable. - 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; - } - - TraceLoggingWrite(g_hRemotingProvider, - "Peasant_ExecuteCommandline", - TraceLoggingUInt64(GetID(), "peasantID", "Our ID"), - TraceLoggingWideString(args.CurrentDirectory().c_str(), "directory", "the provided cwd"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - // 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. - ExecuteCommandlineRequested.raise(*this, args); - - return true; - } - - Remoting::CommandlineArgs Peasant::InitialArgs() - { - return _initialArgs; - } - - void Peasant::ActivateWindow(const Remoting::WindowActivatedArgs& args) - { - // TODO: projects/5 - somehow, pass an identifier for the current - // desktop into this method. The Peasant shouldn't need to be able to - // figure it out, but it will need to report it to the monarch. - - // Store these new args as our last activated state. If a new monarch - // comes looking, we can use this info to tell them when we were last - // activated. - _lastActivatedArgs = args; - - auto successfullyNotified = false; - // Raise our WindowActivated event, to let the monarch know we've been - // activated. - try - { - // Try/catch this, because the other side of this event is handled - // by the monarch. The monarch might have died. If they have, this - // will throw an exception. Just eat it, the election thread will - // handle hooking up the new one. - WindowActivated.raise(*this, args); - successfullyNotified = true; - } - catch (...) - { - LOG_CAUGHT_EXCEPTION(); - } - - TraceLoggingWrite(g_hRemotingProvider, - "Peasant_ActivateWindow", - TraceLoggingUInt64(GetID(), "peasantID", "Our ID"), - TraceLoggingBoolean(successfullyNotified, "successfullyNotified", "true if we successfully notified the monarch"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - - // Method Description: - // - Retrieve the WindowActivatedArgs describing the last activation of this - // peasant. New monarchs can use this state to determine when we were last - // activated. - // Arguments: - // - - // Return Value: - // - a WindowActivatedArgs with info about when and where we were last activated. - Remoting::WindowActivatedArgs Peasant::GetLastActivatedArgs() - { - return _lastActivatedArgs; - } - - // Method Description: - // - Summon this peasant to become the active window. Currently, it just - // causes the peasant to become the active window wherever the window - // already was. - // - Will raise a SummonRequested event to ask the hosting window to handle for us. - // Arguments: - // - - // Return Value: - // - - void Peasant::Summon(const Remoting::SummonWindowBehavior& summonBehavior) - { - auto localCopy = winrt::make(summonBehavior); - - TraceLoggingWrite(g_hRemotingProvider, - "Peasant_Summon", - TraceLoggingUInt64(GetID(), "peasantID", "Our ID"), - TraceLoggingUInt64(localCopy.MoveToCurrentDesktop(), "MoveToCurrentDesktop", "true if we should move to the current desktop"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - SummonRequested.raise(*this, localCopy); - } - - // Method Description: - // - Tell this window to display its window ID. We'll raise a - // DisplayWindowIdRequested event, which will get handled in the AppHost, - // and used to tell the app to display the ID toast. - // Arguments: - // - - // Return Value: - // - - void Peasant::DisplayWindowId() - { - // Not worried about try/catching this. The handler is in AppHost, which - // is in-proc for us. - DisplayWindowIdRequested.raise(*this, nullptr); - } - - // Method Description: - // - Raises an event to ask that all windows be identified. This will come - // back to us when the Monarch handles the event and calls our - // DisplayWindowId method. - // Arguments: - // - - // Return Value: - // - - void Peasant::RequestIdentifyWindows() - { - auto successfullyNotified = false; - - try - { - // Try/catch this, because the other side of this event is handled - // by the monarch. The monarch might have died. If they have, this - // will throw an exception. Just eat it, the election thread will - // handle hooking up the new one. - IdentifyWindowsRequested.raise(*this, nullptr); - successfullyNotified = true; - } - catch (...) - { - LOG_CAUGHT_EXCEPTION(); - } - TraceLoggingWrite(g_hRemotingProvider, - "Peasant_RequestIdentifyWindows", - TraceLoggingUInt64(GetID(), "peasantID", "Our ID"), - TraceLoggingBoolean(successfullyNotified, "successfullyNotified", "true if we successfully notified the monarch"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - - void Peasant::RequestRename(const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args) - { - auto successfullyNotified = false; - const auto oldName{ _WindowName }; - try - { - // Try/catch this, because the other side of this event is handled - // by the monarch. The monarch might have died. If they have, this - // will throw an exception. Just eat it, the election thread will - // handle hooking up the new one. - RenameRequested.raise(*this, args); - if (args.Succeeded()) - { - _WindowName = args.NewName(); - } - successfullyNotified = true; - } - catch (...) - { - LOG_CAUGHT_EXCEPTION(); - } - TraceLoggingWrite(g_hRemotingProvider, - "Peasant_RequestRename", - TraceLoggingUInt64(GetID(), "peasantID", "Our ID"), - TraceLoggingWideString(oldName.c_str(), "oldName", "Our old name"), - TraceLoggingWideString(args.NewName().c_str(), "newName", "The proposed name"), - TraceLoggingBoolean(args.Succeeded(), "succeeded", "true if the monarch ok'd this new name for us."), - TraceLoggingBoolean(successfullyNotified, "successfullyNotified", "true if we successfully notified the monarch"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - - void Peasant::RequestShowNotificationIcon() - { - try - { - ShowNotificationIconRequested.raise(*this, nullptr); - } - catch (...) - { - LOG_CAUGHT_EXCEPTION(); - } - TraceLoggingWrite(g_hRemotingProvider, - "Peasant_RequestShowNotificationIcon", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - - void Peasant::RequestHideNotificationIcon() - { - try - { - HideNotificationIconRequested.raise(*this, nullptr); - } - catch (...) - { - LOG_CAUGHT_EXCEPTION(); - } - TraceLoggingWrite(g_hRemotingProvider, - "Peasant_RequestHideNotificationIcon", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - - void Peasant::AttachContentToWindow(Remoting::AttachRequest request) - { - try - { - AttachRequested.raise(*this, request); - } - catch (...) - { - LOG_CAUGHT_EXCEPTION(); - } - TraceLoggingWrite(g_hRemotingProvider, - "Peasant_AttachContentToWindow", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - - void Peasant::Quit() - { - try - { - QuitRequested.raise(*this, nullptr); - } - catch (...) - { - LOG_CAUGHT_EXCEPTION(); - } - TraceLoggingWrite(g_hRemotingProvider, - "Peasant_Quit", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - - void Peasant::SendContent(const Remoting::RequestReceiveContentArgs& args) - { - SendContentRequested.raise(*this, args); - } -} diff --git a/src/cascadia/Remoting/Peasant.h b/src/cascadia/Remoting/Peasant.h deleted file mode 100644 index 1291c8287b..0000000000 --- a/src/cascadia/Remoting/Peasant.h +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#pragma once - -#include "Peasant.g.h" -#include "RenameRequestArgs.h" -#include "AttachRequest.g.h" -#include "RequestReceiveContentArgs.g.h" - -namespace RemotingUnitTests -{ - class RemotingTests; -}; -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - struct AttachRequest : public AttachRequestT - { - WINRT_PROPERTY(winrt::hstring, Content); - WINRT_PROPERTY(uint32_t, TabIndex); - - public: - AttachRequest(winrt::hstring content, - uint32_t tabIndex) : - _Content{ content }, - _TabIndex{ tabIndex } {}; - }; - - struct RequestReceiveContentArgs : RequestReceiveContentArgsT - { - WINRT_PROPERTY(uint64_t, SourceWindow); - WINRT_PROPERTY(uint64_t, TargetWindow); - WINRT_PROPERTY(uint32_t, TabIndex); - - public: - RequestReceiveContentArgs(const uint64_t src, const uint64_t tgt, const uint32_t tabIndex) : - _SourceWindow{ src }, - _TargetWindow{ tgt }, - _TabIndex{ tabIndex } {}; - }; - - struct Peasant : public PeasantT - { - Peasant(); - - void AssignID(uint64_t id); - uint64_t GetID(); - uint64_t GetPID(); - - bool ExecuteCommandline(const winrt::Microsoft::Terminal::Remoting::CommandlineArgs& args); - void ActivateWindow(const winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs& args); - - void Summon(const Remoting::SummonWindowBehavior& summonBehavior); - void RequestIdentifyWindows(); - void DisplayWindowId(); - void RequestRename(const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args); - void RequestShowNotificationIcon(); - void RequestHideNotificationIcon(); - void Quit(); - - void AttachContentToWindow(Remoting::AttachRequest request); - - winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs GetLastActivatedArgs(); - - winrt::Microsoft::Terminal::Remoting::CommandlineArgs InitialArgs(); - - void SendContent(const winrt::Microsoft::Terminal::Remoting::RequestReceiveContentArgs& args); - - til::typed_event WindowActivated; - til::typed_event ExecuteCommandlineRequested; - til::typed_event<> IdentifyWindowsRequested; - til::typed_event<> DisplayWindowIdRequested; - til::typed_event RenameRequested; - til::typed_event SummonRequested; - - til::typed_event<> ShowNotificationIconRequested; - til::typed_event<> HideNotificationIconRequested; - til::typed_event<> QuitRequested; - - til::typed_event AttachRequested; - til::typed_event SendContentRequested; - - WINRT_PROPERTY(winrt::hstring, WindowName); - WINRT_PROPERTY(winrt::hstring, ActiveTabTitle); - - private: - Peasant(const uint64_t testPID); - uint64_t _ourPID; - - uint64_t _id{ 0 }; - - winrt::Microsoft::Terminal::Remoting::CommandlineArgs _initialArgs{ nullptr }; - winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs _lastActivatedArgs{ nullptr }; - - friend class RemotingUnitTests::RemotingTests; - }; -} - -namespace winrt::Microsoft::Terminal::Remoting::factory_implementation -{ - BASIC_FACTORY(Peasant); - BASIC_FACTORY(RequestReceiveContentArgs); -} diff --git a/src/cascadia/Remoting/Peasant.idl b/src/cascadia/Remoting/Peasant.idl deleted file mode 100644 index 3e01e6a6d3..0000000000 --- a/src/cascadia/Remoting/Peasant.idl +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -namespace Microsoft.Terminal.Remoting -{ - - runtimeclass CommandlineArgs - { - CommandlineArgs(); - CommandlineArgs(String[] args, String cwd, UInt32 showWindowCommand, String env); - - String[] Commandline { get; set; }; - String CurrentDirectory { get; }; - UInt32 ShowWindowCommand { get; }; - String CurrentEnvironment { get; }; - }; - - runtimeclass RenameRequestArgs - { - RenameRequestArgs(String newName); - String NewName { get; }; - Boolean Succeeded; - }; - - runtimeclass WindowActivatedArgs - { - WindowActivatedArgs(UInt64 peasantID, Guid desktopID, Windows.Foundation.DateTime activatedTime); - WindowActivatedArgs(UInt64 peasantID, UInt64 hwnd, Guid desktopID, Windows.Foundation.DateTime activatedTime); - UInt64 PeasantID { get; }; - UInt64 Hwnd { get; }; - Guid DesktopID { get; }; - Windows.Foundation.DateTime ActivatedTime { get; }; - }; - - enum MonitorBehavior - { - InPlace, - ToCurrent, - ToMouse, - }; - - [default_interface] runtimeclass SummonWindowBehavior { - SummonWindowBehavior(); - Boolean MoveToCurrentDesktop; - Boolean ToggleVisibility; - UInt32 DropdownDuration; - MonitorBehavior ToMonitor; - } - - [default_interface] runtimeclass AttachRequest { - String Content { get; }; - UInt32 TabIndex { get; }; - } - [default_interface] runtimeclass RequestReceiveContentArgs { - RequestReceiveContentArgs(UInt64 src, UInt64 tgt, UInt32 tabIndex); - - UInt64 SourceWindow { get; }; - UInt64 TargetWindow { get; }; - UInt32 TabIndex { get; }; - }; - - interface IPeasant - { - CommandlineArgs InitialArgs { get; }; - - void AssignID(UInt64 id); - UInt64 GetID(); - UInt64 GetPID(); - Boolean ExecuteCommandline(CommandlineArgs args); - void ActivateWindow(WindowActivatedArgs args); - WindowActivatedArgs GetLastActivatedArgs(); - - void DisplayWindowId(); // Tells us to display its own ID (which causes a DisplayWindowIdRequested to be raised) - - String WindowName { get; }; - String ActiveTabTitle { get; }; - void RequestIdentifyWindows(); // Tells us to raise a IdentifyWindowsRequested - void RequestRename(RenameRequestArgs args); // Tells us to raise a RenameRequested - void Summon(SummonWindowBehavior behavior); - - void RequestShowNotificationIcon(); - void RequestHideNotificationIcon(); - void Quit(); - - void AttachContentToWindow(AttachRequest request); - void SendContent(RequestReceiveContentArgs args); - - event Windows.Foundation.TypedEventHandler WindowActivated; - event Windows.Foundation.TypedEventHandler ExecuteCommandlineRequested; - event Windows.Foundation.TypedEventHandler IdentifyWindowsRequested; - event Windows.Foundation.TypedEventHandler DisplayWindowIdRequested; - event Windows.Foundation.TypedEventHandler RenameRequested; - event Windows.Foundation.TypedEventHandler SummonRequested; - - event Windows.Foundation.TypedEventHandler ShowNotificationIconRequested; - event Windows.Foundation.TypedEventHandler HideNotificationIconRequested; - event Windows.Foundation.TypedEventHandler QuitRequested; - - event Windows.Foundation.TypedEventHandler AttachRequested; - - event Windows.Foundation.TypedEventHandler SendContentRequested; - }; - - [default_interface] runtimeclass Peasant : IPeasant - { - Peasant(); - }; -} diff --git a/src/cascadia/Remoting/ProposeCommandlineResult.cpp b/src/cascadia/Remoting/ProposeCommandlineResult.cpp deleted file mode 100644 index fc9cc8f616..0000000000 --- a/src/cascadia/Remoting/ProposeCommandlineResult.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -#include "pch.h" -#include "ProposeCommandlineResult.h" -#include "ProposeCommandlineResult.g.cpp" diff --git a/src/cascadia/Remoting/ProposeCommandlineResult.h b/src/cascadia/Remoting/ProposeCommandlineResult.h deleted file mode 100644 index 2578ce8378..0000000000 --- a/src/cascadia/Remoting/ProposeCommandlineResult.h +++ /dev/null @@ -1,41 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation -Licensed under the MIT license. - -Class Name: -- ProposeCommandlineResult.h - -Abstract: -- This is a helper class for encapsulating the result of a - Monarch::ProposeCommandline call. The monarch will be telling the new process - whether it should create a new window or not. If the value of - ShouldCreateWindow is false, that implies that some other window process was - given the commandline for handling, and the caller should just exit. -- If ShouldCreateWindow is true, the Id property may or may not contain an ID - that the new window should use as its ID. - ---*/ - -#pragma once - -#include "ProposeCommandlineResult.g.h" - -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - struct ProposeCommandlineResult : public ProposeCommandlineResultT - { - public: - ProposeCommandlineResult(const Remoting::ProposeCommandlineResult& other) : - _Id{ other.Id() }, - _WindowName{ other.WindowName() }, - _ShouldCreateWindow{ other.ShouldCreateWindow() } {}; - - WINRT_PROPERTY(Windows::Foundation::IReference, Id); - WINRT_PROPERTY(winrt::hstring, WindowName); - WINRT_PROPERTY(bool, ShouldCreateWindow, true); - - public: - ProposeCommandlineResult(bool shouldCreateWindow) : - _ShouldCreateWindow{ shouldCreateWindow } {}; - }; -} diff --git a/src/cascadia/Remoting/RenameRequestArgs.cpp b/src/cascadia/Remoting/RenameRequestArgs.cpp deleted file mode 100644 index cab69f4086..0000000000 --- a/src/cascadia/Remoting/RenameRequestArgs.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -#include "pch.h" -#include "RenameRequestArgs.h" -#include "RenameRequestArgs.g.cpp" diff --git a/src/cascadia/Remoting/RenameRequestArgs.h b/src/cascadia/Remoting/RenameRequestArgs.h deleted file mode 100644 index b22cbeb074..0000000000 --- a/src/cascadia/Remoting/RenameRequestArgs.h +++ /dev/null @@ -1,29 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation -Licensed under the MIT license. - -Class Name: -- RenameRequestArgs.h - ---*/ -#pragma once - -#include "RenameRequestArgs.g.h" - -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - struct RenameRequestArgs : public RenameRequestArgsT - { - WINRT_PROPERTY(winrt::hstring, NewName); - WINRT_PROPERTY(bool, Succeeded, false); - - public: - RenameRequestArgs(winrt::hstring newName) : - _NewName{ newName } {}; - }; -} - -namespace winrt::Microsoft::Terminal::Remoting::factory_implementation -{ - BASIC_FACTORY(RenameRequestArgs); -} diff --git a/src/cascadia/Remoting/Resources/de-DE/Resources.resw b/src/cascadia/Remoting/Resources/de-DE/Resources.resw deleted file mode 100644 index 4f24d55cd6..0000000000 --- a/src/cascadia/Remoting/Resources/de-DE/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/cascadia/Remoting/Resources/en-US/Resources.resw b/src/cascadia/Remoting/Resources/en-US/Resources.resw deleted file mode 100644 index ed0aef9346..0000000000 --- a/src/cascadia/Remoting/Resources/en-US/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - diff --git a/src/cascadia/Remoting/Resources/es-ES/Resources.resw b/src/cascadia/Remoting/Resources/es-ES/Resources.resw deleted file mode 100644 index 4f24d55cd6..0000000000 --- a/src/cascadia/Remoting/Resources/es-ES/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/cascadia/Remoting/Resources/fr-FR/Resources.resw b/src/cascadia/Remoting/Resources/fr-FR/Resources.resw deleted file mode 100644 index 4f24d55cd6..0000000000 --- a/src/cascadia/Remoting/Resources/fr-FR/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/cascadia/Remoting/Resources/it-IT/Resources.resw b/src/cascadia/Remoting/Resources/it-IT/Resources.resw deleted file mode 100644 index 4f24d55cd6..0000000000 --- a/src/cascadia/Remoting/Resources/it-IT/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/cascadia/Remoting/Resources/ja-JP/Resources.resw b/src/cascadia/Remoting/Resources/ja-JP/Resources.resw deleted file mode 100644 index 4f24d55cd6..0000000000 --- a/src/cascadia/Remoting/Resources/ja-JP/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/cascadia/Remoting/Resources/ko-KR/Resources.resw b/src/cascadia/Remoting/Resources/ko-KR/Resources.resw deleted file mode 100644 index 4f24d55cd6..0000000000 --- a/src/cascadia/Remoting/Resources/ko-KR/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/cascadia/Remoting/Resources/pt-BR/Resources.resw b/src/cascadia/Remoting/Resources/pt-BR/Resources.resw deleted file mode 100644 index 4f24d55cd6..0000000000 --- a/src/cascadia/Remoting/Resources/pt-BR/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/cascadia/Remoting/Resources/qps-ploc/Resources.resw b/src/cascadia/Remoting/Resources/qps-ploc/Resources.resw deleted file mode 100644 index ed0aef9346..0000000000 --- a/src/cascadia/Remoting/Resources/qps-ploc/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - diff --git a/src/cascadia/Remoting/Resources/qps-ploca/Resources.resw b/src/cascadia/Remoting/Resources/qps-ploca/Resources.resw deleted file mode 100644 index ed0aef9346..0000000000 --- a/src/cascadia/Remoting/Resources/qps-ploca/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - diff --git a/src/cascadia/Remoting/Resources/qps-plocm/Resources.resw b/src/cascadia/Remoting/Resources/qps-plocm/Resources.resw deleted file mode 100644 index ed0aef9346..0000000000 --- a/src/cascadia/Remoting/Resources/qps-plocm/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - diff --git a/src/cascadia/Remoting/Resources/ru-RU/Resources.resw b/src/cascadia/Remoting/Resources/ru-RU/Resources.resw deleted file mode 100644 index 4f24d55cd6..0000000000 --- a/src/cascadia/Remoting/Resources/ru-RU/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/cascadia/Remoting/Resources/zh-CN/Resources.resw b/src/cascadia/Remoting/Resources/zh-CN/Resources.resw deleted file mode 100644 index 4f24d55cd6..0000000000 --- a/src/cascadia/Remoting/Resources/zh-CN/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/cascadia/Remoting/Resources/zh-TW/Resources.resw b/src/cascadia/Remoting/Resources/zh-TW/Resources.resw deleted file mode 100644 index 4f24d55cd6..0000000000 --- a/src/cascadia/Remoting/Resources/zh-TW/Resources.resw +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/cascadia/Remoting/SummonWindowBehavior.cpp b/src/cascadia/Remoting/SummonWindowBehavior.cpp deleted file mode 100644 index 516acff06d..0000000000 --- a/src/cascadia/Remoting/SummonWindowBehavior.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -#include "pch.h" -#include "SummonWindowBehavior.h" -#include "SummonWindowBehavior.g.cpp" diff --git a/src/cascadia/Remoting/SummonWindowBehavior.h b/src/cascadia/Remoting/SummonWindowBehavior.h deleted file mode 100644 index d8d96a90bd..0000000000 --- a/src/cascadia/Remoting/SummonWindowBehavior.h +++ /dev/null @@ -1,44 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation -Licensed under the MIT license. - -Class Name: -- SummonWindowBehavior.h - -Abstract: -- This is a helper class for encapsulating all the information about how a - window should be summoned. Includes info like if we should switch desktops or - monitors, if we should dropdown (and how fast), and if we should toggle to - hidden if we're already visible. Used by the Monarch to tell a Peasant how it - should behave. - ---*/ - -#pragma once - -#include "SummonWindowBehavior.g.h" - -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - struct SummonWindowBehavior : public SummonWindowBehaviorT - { - public: - SummonWindowBehavior() = default; - WINRT_PROPERTY(bool, MoveToCurrentDesktop, true); - WINRT_PROPERTY(bool, ToggleVisibility, true); - WINRT_PROPERTY(uint32_t, DropdownDuration, 0); - WINRT_PROPERTY(Remoting::MonitorBehavior, ToMonitor, Remoting::MonitorBehavior::ToCurrent); - - public: - SummonWindowBehavior(const Remoting::SummonWindowBehavior& other) : - _MoveToCurrentDesktop{ other.MoveToCurrentDesktop() }, - _ToMonitor{ other.ToMonitor() }, - _DropdownDuration{ other.DropdownDuration() }, - _ToggleVisibility{ other.ToggleVisibility() } {}; - }; -} - -namespace winrt::Microsoft::Terminal::Remoting::factory_implementation -{ - BASIC_FACTORY(SummonWindowBehavior); -} diff --git a/src/cascadia/Remoting/SummonWindowSelectionArgs.cpp b/src/cascadia/Remoting/SummonWindowSelectionArgs.cpp deleted file mode 100644 index 6db4cad330..0000000000 --- a/src/cascadia/Remoting/SummonWindowSelectionArgs.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -#include "pch.h" -#include "SummonWindowSelectionArgs.h" -#include "SummonWindowSelectionArgs.g.cpp" diff --git a/src/cascadia/Remoting/SummonWindowSelectionArgs.h b/src/cascadia/Remoting/SummonWindowSelectionArgs.h deleted file mode 100644 index 5f15e0985b..0000000000 --- a/src/cascadia/Remoting/SummonWindowSelectionArgs.h +++ /dev/null @@ -1,44 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation -Licensed under the MIT license. - -Class Name: -- SummonWindowSelectionArgs.h - -Abstract: -- This is a helper class for determining which window a should be summoned when - a global hotkey is pressed. Parameters from a GlobalSummon action will be - filled in here. The Monarch will use these to find the window that matches - these args, and Summon() that Peasant. -- When the monarch finds a match, it will set FoundMatch to true. If it doesn't, - then the Monarch window might need to create a new window matching these args - instead. ---*/ - -#pragma once - -#include "SummonWindowSelectionArgs.g.h" - -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - struct SummonWindowSelectionArgs : public SummonWindowSelectionArgsT - { - public: - SummonWindowSelectionArgs() = default; - SummonWindowSelectionArgs(winrt::hstring name) : - _WindowName{ name } {}; - - WINRT_PROPERTY(winrt::hstring, WindowName); - - WINRT_PROPERTY(bool, FoundMatch, false); - WINRT_PROPERTY(bool, OnCurrentDesktop, false); - WINRT_PROPERTY(SummonWindowBehavior, SummonBehavior); - - WINRT_PROPERTY(Windows::Foundation::IReference, WindowID); - }; -} - -namespace winrt::Microsoft::Terminal::Remoting::factory_implementation -{ - BASIC_FACTORY(SummonWindowSelectionArgs); -} diff --git a/src/cascadia/Remoting/WindowActivatedArgs.cpp b/src/cascadia/Remoting/WindowActivatedArgs.cpp deleted file mode 100644 index 4466383c2c..0000000000 --- a/src/cascadia/Remoting/WindowActivatedArgs.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -#include "pch.h" -#include "WindowActivatedArgs.h" -#include "WindowActivatedArgs.g.cpp" diff --git a/src/cascadia/Remoting/WindowActivatedArgs.h b/src/cascadia/Remoting/WindowActivatedArgs.h deleted file mode 100644 index 353aeb152c..0000000000 --- a/src/cascadia/Remoting/WindowActivatedArgs.h +++ /dev/null @@ -1,60 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation -Licensed under the MIT license. - -Class Name: -- WindowActivatedArgs.h - -Abstract: -- This is a helper class for encapsulating all the information about when and - where a window was activated. This will be used by the Monarch to determine - who the most recent peasant is. - ---*/ -#pragma once - -#include "WindowActivatedArgs.g.h" - -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - struct CompareWindowActivatedArgs - { - bool operator()(const Remoting::WindowActivatedArgs& lhs, const Remoting::WindowActivatedArgs& rhs) const - { - return lhs.ActivatedTime() > rhs.ActivatedTime(); - } - }; - struct WindowActivatedArgs : public WindowActivatedArgsT - { - WINRT_PROPERTY(uint64_t, PeasantID, 0); - WINRT_PROPERTY(winrt::guid, DesktopID); - WINRT_PROPERTY(winrt::Windows::Foundation::DateTime, ActivatedTime, {}); - WINRT_PROPERTY(uint64_t, Hwnd, 0); - - public: - WindowActivatedArgs(uint64_t peasantID, - uint64_t hwnd, - winrt::guid desktopID, - winrt::Windows::Foundation::DateTime timestamp) : - _PeasantID{ peasantID }, - _Hwnd{ hwnd }, - _DesktopID{ desktopID }, - _ActivatedTime{ timestamp } {}; - - WindowActivatedArgs(uint64_t peasantID, - winrt::guid desktopID, - winrt::Windows::Foundation::DateTime timestamp) : - WindowActivatedArgs(peasantID, 0, desktopID, timestamp){}; - - WindowActivatedArgs(const Remoting::WindowActivatedArgs& other) : - _PeasantID{ other.PeasantID() }, - _Hwnd{ other.Hwnd() }, - _DesktopID{ other.DesktopID() }, - _ActivatedTime{ other.ActivatedTime() } {}; - }; -} - -namespace winrt::Microsoft::Terminal::Remoting::factory_implementation -{ - BASIC_FACTORY(WindowActivatedArgs); -} diff --git a/src/cascadia/Remoting/WindowManager.cpp b/src/cascadia/Remoting/WindowManager.cpp deleted file mode 100644 index 11ddbf45f4..0000000000 --- a/src/cascadia/Remoting/WindowManager.cpp +++ /dev/null @@ -1,459 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "pch.h" - -#include "WindowManager.h" - -#include "../inc/WindowingBehavior.h" -#include "MonarchFactory.h" - -#include "CommandlineArgs.h" -#include "FindTargetWindowArgs.h" -#include "ProposeCommandlineResult.h" - -#include "WindowManager.g.cpp" -#include "../../types/inc/utils.hpp" - -#include - -using namespace winrt; -using namespace winrt::Microsoft::Terminal; -using namespace winrt::Windows::Foundation; -using namespace ::Microsoft::Console; - -namespace -{ - const GUID& MonarchCLSID() - { - if (!IsPackaged()) [[unlikely]] - { - // Unpackaged installations don't have the luxury of magic package isolation - // to stop them from accidentally touching each other's monarchs. - // We need to enforce that ourselves by making their monarch CLSIDs unique - // per install. - // This applies in both portable mode and normal unpackaged mode. - // We'll use a v5 UUID based on the install folder to unique them. - static GUID processRootHashedGuid = []() { - // {5456C4DB-557D-4A22-B043-B1577418E4AF} - static constexpr GUID processRootHashedGuidBase = { 0x5456c4db, 0x557d, 0x4a22, { 0xb0, 0x43, 0xb1, 0x57, 0x74, 0x18, 0xe4, 0xaf } }; - - // Make a temporary monarch CLSID based on the unpackaged install root - std::filesystem::path modulePath{ wil::GetModuleFileNameW(wil::GetModuleInstanceHandle()) }; - modulePath.remove_filename(); - - return Utils::CreateV5Uuid(processRootHashedGuidBase, std::as_bytes(std::span{ modulePath.native() })); - }(); - return processRootHashedGuid; - } - return Monarch_clsid; - } -} - -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - WindowManager::WindowManager() - { - } - 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; - } - - 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 = try_create_instance(MonarchCLSID(), - CLSCTX_LOCAL_SERVER); - } - - // Check if we became the king, and if we are, wire up callbacks. - void WindowManager::_createCallbacks() - { - assert(_monarch); - // Here, we're the king! - // - // This is where you should do any additional setup that might need to be - // done when we become the king. This will be called both for the first - // window, and when the current monarch dies. - - _monarch.WindowCreated({ get_weak(), &WindowManager::_bubbleWindowCreated }); - _monarch.WindowClosed({ get_weak(), &WindowManager::_bubbleWindowClosed }); - _monarch.FindTargetWindowRequested({ this, &WindowManager::_raiseFindTargetWindowRequested }); - - _monarch.RequestNewWindow({ get_weak(), &WindowManager::_raiseRequestNewWindow }); - } - - void WindowManager::_registerAsMonarch() - { - winrt::check_hresult(CoRegisterClassObject(MonarchCLSID(), - winrt::make<::MonarchFactory>().get(), - CLSCTX_LOCAL_SERVER, - REGCLS_MULTIPLEUSE, - &_registrationHostClass)); - } - - void WindowManager::_raiseFindTargetWindowRequested(const winrt::Windows::Foundation::IInspectable& sender, - const winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs& args) - { - FindTargetWindowRequested.raise(sender, args); - } - void WindowManager::_raiseRequestNewWindow(const winrt::Windows::Foundation::IInspectable& sender, - const winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs& args) - { - RequestNewWindow.raise(sender, args); - } - - Remoting::ProposeCommandlineResult WindowManager::ProposeCommandline(const Remoting::CommandlineArgs& args, const bool isolatedMode) - { - if (!isolatedMode) - { - // _createMonarch always attempts to connect an existing monarch. In - // isolated mode, we don't want to do that. - _createMonarch(); - } - - if (_monarch) - { - // We connected to a monarch instance, not us though. This won't hit - // in isolated mode. - - LOG_IF_FAILED(CoAllowSetForegroundWindow(winrt::get_unknown(_monarch), nullptr)); - - // Send the commandline over to the monarch process - if (_proposeToMonarch(args)) - { - // If that succeeded, then we don't need to make a new window. - // Our job is done. Either the monarch is going to run the - // commandline in an existing window, or a new one, but either way, - // this process doesn't need to make a new window. - - return winrt::make(false); - } - // Otherwise, we'll try to handle this ourselves. - } - - // Theoretically, this condition is always true here: - // - // if (_monarch == nullptr) - // - // If we do still have a _monarch at this point, then we must have - // successfully proposed to it in _proposeToMonarch, so we can't get - // here with a monarch. - { - // No preexisting instance. - - // Raise an event, to ask how to handle this commandline. We can't ask - // the app ourselves - we exist isolated from that knowledge (and - // dependency hell). The WindowManager will raise this up to the app - // host, which will then ask the AppLogic, who will then parse the - // commandline and determine the provided ID of the window. - auto findWindowArgs{ winrt::make_self(args) }; - - // This is handled by some handler in-proc - FindTargetWindowRequested.raise(*this, *findWindowArgs); - - // After the event was handled, ResultTargetWindow() will be filled with - // the parsed result. - const auto targetWindow = findWindowArgs->ResultTargetWindow(); - const auto targetWindowName = findWindowArgs->ResultTargetWindowName(); - - if (targetWindow == WindowingBehaviorUseNone) - { - // This commandline doesn't deserve a window. Don't make a monarch - // either. - return winrt::make(false); - } - else - { - // This commandline _does_ want a window, which means we do want - // to create a window, and a monarch. - // - // Congrats! This is now THE PROCESS. It's the only one that's - // getting any windows. - - // In isolated mode, we don't want to register as the monarch, - // we just want to make a local one. So we'll skip this step. - // The condition below it will handle making the unregistered - // local monarch. - - if (!isolatedMode) - { - _registerAsMonarch(); - _createMonarch(); - } - else - { - TraceLoggingWrite(g_hRemotingProvider, - "WindowManager_IntentionallyIsolated", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - - if (!_monarch) - { - // Something catastrophically bad happened here OR we were - // intentionally in isolated mode. We don't want to just - // exit immediately. Instead, we'll just instantiate a local - // Monarch instance, without registering it. We're firmly in - // the realm of undefined behavior, but better to have some - // window than not. - _monarch = winrt::make(); - TraceLoggingWrite(g_hRemotingProvider, - "WindowManager_FailedToCoCreate", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - _createCallbacks(); - - // So, we wanted a new peasant. Cool! - // - // We need to fill in args.ResultTargetWindow, - // args.ResultTargetWindowName so that we can create the new - // window with those values. Otherwise, the very first window - // won't obey the given name / ID. - // - // So let's just ask the monarch (ourselves) to get those values. - return _monarch.ProposeCommandline(args); - } - } - } - - // Method Description: - // - Helper attempting to call to the monarch multiple times. If the monarch - // fails to respond, or we encounter any sort of error, we'll try again - // until we find one, or decisively determine there isn't one. - bool WindowManager::_proposeToMonarch(const Remoting::CommandlineArgs& args) - { - // these two errors are Win32 errors, convert them to HRESULTS so we can actually compare below. - static constexpr auto RPC_SERVER_UNAVAILABLE_HR = HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE); - static constexpr auto RPC_CALL_FAILED_HR = HRESULT_FROM_WIN32(RPC_S_CALL_FAILED); - - // The monarch may respond back "you should be a new - // window, with ID,name of (id, name)". Really the responses are: - // * You should not create a new window - // * Create a new window (but without a given ID or name). The - // Monarch will assign your ID/name later - // * Create a new window, and you'll have this ID or name - // - This is the case where the user provides `wt -w 1`, and - // there's no existing window 1 - - // You can emulate the monarch dying by: starting a terminal, sticking a - // breakpoint in - // TerminalApp!winrt::TerminalApp::implementation::AppLogic::_doFindTargetWindow, - // starting a defterm, and when that BP gets hit, kill the original - // monarch, and see what happens here. - - auto proposedCommandline = false; - Remoting::ProposeCommandlineResult result{ nullptr }; - auto attempts = 0; - while (!proposedCommandline) - { - try - { - // MSFT:38542548 _We believe_ that this is the source of the - // crash here. After we get the result, stash its values into a - // local copy, so that we can check them later. If the Monarch - // dies between now and the inspection of - // `result.ShouldCreateWindow` below, we don't want to explode - // (since _proposeToMonarch is not try/caught). - - _monarch.ProposeCommandline(args); - return true; - } - catch (...) - { - // We did not successfully ask the king what to do. This could - // be for many reasons. Most commonly, the monarch died as we - // were talking to it. That could be a RPC_SERVER_UNAVAILABLE_HR - // or RPC_CALL_FAILED_HR (GH#12666). We also saw a - // RPC_S_CALL_FAILED_DNE in GH#11790. Ultimately, if this is - // gonna fail, we want to just try again, regardless of the - // cause. That's why we're no longer checking what the exception - // was, we're just always gonna try again regardless. - // - // They hopefully just died here. That's okay, let's just go - // ask the next in the line of succession. At the very worst, - // we'll find _us_, (likely last in the line). - TraceLoggingWrite(g_hRemotingProvider, - "WindowManager_proposeToMonarch_unexpectedExceptionFromKing", - TraceLoggingInt32(attempts, "attempts", "How many times we've tried"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - LOG_CAUGHT_EXCEPTION(); - attempts++; - - if (attempts >= 10) - { - // We've tried 10 times to find the monarch, failing each - // time. Since we have no idea why, we're guessing that in - // this case, there's just a Monarch registered that's - // misbehaving. In this case, just fall back to - // "IsolatedMonarchMode" - we can't trust the currently - // registered one. - TraceLoggingWrite(g_hRemotingProvider, - "WindowManager_TooManyAttempts_NullMonarchIsolateMode", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - // Set the monarch to null, so that we'll create a new one - // (or just generally check if we need to even make a window - // for this commandline.) - _monarch = nullptr; - return false; - } - else - { - // We failed to ask the monarch. It must have died. Try and - // find another monarch. - _createMonarch(); - if (!_monarch) - { - // We failed to create a monarch. That means there - // aren't any other windows, and we can become the monarch. - return false; - } - // Go back around the loop. - TraceLoggingWrite(g_hRemotingProvider, - "WindowManager_proposeToMonarch_tryAgain", - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - } - } - } - - // I don't think we can ever get here, but the compiler doesn't know - return false; - } - - Remoting::Peasant WindowManager::CreatePeasant(const Remoting::WindowRequestedArgs& args) - { - auto p = winrt::make_self(); - // This will be false if the Id is 0, which is our sentinel for "no specific ID was requested" - if (const auto id = args.Id()) - { - p->AssignID(id); - } - - // If the name wasn't specified, this will be an empty string. - p->WindowName(args.WindowName()); - - p->ExecuteCommandline(*winrt::make_self(args.Commandline(), - args.CurrentDirectory(), - args.ShowWindowCommand(), - args.CurrentEnvironment())); - - _monarch.AddPeasant(*p); - - TraceLoggingWrite(g_hRemotingProvider, - "WindowManager_CreateOurPeasant", - TraceLoggingUInt64(p->GetID(), "peasantID", "The ID of our new peasant"), - TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE), - TraceLoggingKeyword(TIL_KEYWORD_TRACE)); - - return *p; - } - - void WindowManager::_bubbleWindowCreated(const winrt::Windows::Foundation::IInspectable& s, const winrt::Windows::Foundation::IInspectable& e) - { - WindowCreated.raise(s, e); - } - void WindowManager::_bubbleWindowClosed(const winrt::Windows::Foundation::IInspectable& s, const winrt::Windows::Foundation::IInspectable& e) - { - WindowClosed.raise(s, e); - } - - void WindowManager::QuitAll() - { - if (_monarch) - { - try - { - _monarch.QuitAll(); - } - CATCH_LOG() - } - } - - void WindowManager::SignalClose(const Remoting::Peasant& peasant) - { - if (_monarch) - { - try - { - _monarch.SignalClose(peasant.GetID()); - } - CATCH_LOG() - } - } - - void WindowManager::SummonWindow(const Remoting::SummonWindowSelectionArgs& args) - { - // We should only ever get called when we are the monarch, because only - // the monarch ever registers for the global hotkey. So the monarch is - // the only window that will be calling this. - _monarch.SummonWindow(args); - } - - void WindowManager::SummonAllWindows() - { - _monarch.SummonAllWindows(); - } - - Windows::Foundation::Collections::IVectorView WindowManager::GetPeasantInfos() - { - // We should only get called when we're the monarch since the monarch - // is the only one that knows about all peasants. - return _monarch.GetPeasantInfos(); - } - - uint64_t WindowManager::GetNumberOfPeasants() - { - if (_monarch) - { - try - { - return _monarch.GetNumberOfPeasants(); - } - CATCH_LOG() - } - return 0; - } - - bool WindowManager::DoesQuakeWindowExist() - { - return _monarch.DoesQuakeWindowExist(); - } - - void WindowManager::UpdateActiveTabTitle(const winrt::hstring& title, const Remoting::Peasant& peasant) - { - winrt::get_self(peasant)->ActiveTabTitle(title); - } - - safe_void_coroutine WindowManager::RequestMoveContent(winrt::hstring window, - winrt::hstring content, - uint32_t tabIndex, - Windows::Foundation::IReference windowBounds) - { - co_await winrt::resume_background(); - _monarch.RequestMoveContent(window, content, tabIndex, windowBounds); - } - - safe_void_coroutine WindowManager::RequestSendContent(Remoting::RequestReceiveContentArgs args) - { - co_await winrt::resume_background(); - _monarch.RequestSendContent(args); - } -} diff --git a/src/cascadia/Remoting/WindowManager.h b/src/cascadia/Remoting/WindowManager.h deleted file mode 100644 index b2aa219aee..0000000000 --- a/src/cascadia/Remoting/WindowManager.h +++ /dev/null @@ -1,77 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation -Licensed under the MIT license. -Class Name: -- WindowManager.h -Abstract: -- The Window Manager takes care of coordinating the monarch and peasant for this - process. -- It's responsible for registering as a potential future monarch. It's also - responsible for creating the Peasant for this process when it's determined - this process should become a window process. -- If we aren't the monarch, it's responsible for watching the current monarch - process, and finding the new one if the current monarch dies. -- When the monarch needs to ask the TerminalApp about how to parse a - commandline, it'll ask by raising an event that we'll bubble up to the - AppHost. ---*/ -#pragma once - -#include "WindowManager.g.h" -#include "Peasant.h" -#include "Monarch.h" - -namespace winrt::Microsoft::Terminal::Remoting::implementation -{ - struct WindowManager : public WindowManagerT - { - public: - WindowManager(); - ~WindowManager(); - winrt::Microsoft::Terminal::Remoting::ProposeCommandlineResult ProposeCommandline(const winrt::Microsoft::Terminal::Remoting::CommandlineArgs& args, const bool isolatedMode); - Remoting::Peasant CreatePeasant(const Remoting::WindowRequestedArgs& args); - - void SignalClose(const Remoting::Peasant& peasant); - void QuitAll(); - void SummonWindow(const Remoting::SummonWindowSelectionArgs& args); - void SummonAllWindows(); - Windows::Foundation::Collections::IVectorView GetPeasantInfos(); - - uint64_t GetNumberOfPeasants(); - - void UpdateActiveTabTitle(const winrt::hstring& title, const Remoting::Peasant& peasant); - - bool DoesQuakeWindowExist(); - - safe_void_coroutine RequestMoveContent(winrt::hstring window, winrt::hstring content, uint32_t tabIndex, Windows::Foundation::IReference windowBounds); - safe_void_coroutine RequestSendContent(Remoting::RequestReceiveContentArgs args); - - til::typed_event FindTargetWindowRequested; - - til::typed_event<> WindowCreated; - til::typed_event<> WindowClosed; - til::typed_event RequestNewWindow; - - private: - DWORD _registrationHostClass{ 0 }; - winrt::Microsoft::Terminal::Remoting::IMonarch _monarch{ nullptr }; - - void _createMonarch(); - void _registerAsMonarch(); - - bool _proposeToMonarch(const Remoting::CommandlineArgs& args); - - void _createCallbacks(); - void _raiseFindTargetWindowRequested(const winrt::Windows::Foundation::IInspectable& sender, - const winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs& args); - void _raiseRequestNewWindow(const winrt::Windows::Foundation::IInspectable& sender, - const winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs& args); - void _bubbleWindowCreated(const winrt::Windows::Foundation::IInspectable& s, const winrt::Windows::Foundation::IInspectable& e); - void _bubbleWindowClosed(const winrt::Windows::Foundation::IInspectable& s, const winrt::Windows::Foundation::IInspectable& e); - }; -} - -namespace winrt::Microsoft::Terminal::Remoting::factory_implementation -{ - BASIC_FACTORY(WindowManager); -} diff --git a/src/cascadia/Remoting/WindowManager.idl b/src/cascadia/Remoting/WindowManager.idl deleted file mode 100644 index 1f1b4c4345..0000000000 --- a/src/cascadia/Remoting/WindowManager.idl +++ /dev/null @@ -1,39 +0,0 @@ -import "Peasant.idl"; -import "Monarch.idl"; - - -namespace Microsoft.Terminal.Remoting -{ - [default_interface] runtimeclass WindowManager - { - WindowManager(); - - ProposeCommandlineResult ProposeCommandline(CommandlineArgs args, Boolean isolatedMode); - Peasant CreatePeasant(WindowRequestedArgs args); - - void SignalClose(Peasant p); - void QuitAll(); - - void UpdateActiveTabTitle(String title, Peasant p); - - void SummonWindow(SummonWindowSelectionArgs args); - void SummonAllWindows(); - - Windows.Foundation.Collections.IVectorView GetPeasantInfos(); - - UInt64 GetNumberOfPeasants(); - - Boolean DoesQuakeWindowExist(); - - void RequestMoveContent(String window, String content, UInt32 tabIndex, Windows.Foundation.IReference bounds); - void RequestSendContent(RequestReceiveContentArgs args); - - event Windows.Foundation.TypedEventHandler FindTargetWindowRequested; - - event Windows.Foundation.TypedEventHandler WindowCreated; - event Windows.Foundation.TypedEventHandler WindowClosed; - - event Windows.Foundation.TypedEventHandler RequestNewWindow; - - }; -} diff --git a/src/cascadia/Remoting/dll/Microsoft.Terminal.Remoting.def b/src/cascadia/Remoting/dll/Microsoft.Terminal.Remoting.def deleted file mode 100644 index ba15818ddb..0000000000 --- a/src/cascadia/Remoting/dll/Microsoft.Terminal.Remoting.def +++ /dev/null @@ -1,3 +0,0 @@ -EXPORTS -DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE -DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/src/cascadia/Remoting/dll/Microsoft.Terminal.Remoting.vcxproj b/src/cascadia/Remoting/dll/Microsoft.Terminal.Remoting.vcxproj deleted file mode 100644 index e5eb455914..0000000000 --- a/src/cascadia/Remoting/dll/Microsoft.Terminal.Remoting.vcxproj +++ /dev/null @@ -1,78 +0,0 @@ - - - - {27b5aaeb-a548-44cf-9777-f8baa32af7ae} - Microsoft.Terminal.Remoting - Microsoft.Terminal.Remoting - - - DynamicLibrary - Console - - true - true - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {18D09A24-8240-42D6-8CB6-236EEE820263} - - - - true - true - - - - - - - User32.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies) - - /INCLUDE:_DllMain@12 %(AdditionalOptions) - /INCLUDE:DllMain %(AdditionalOptions) - - - - false - - - - - - - diff --git a/src/cascadia/Remoting/init.cpp b/src/cascadia/Remoting/init.cpp deleted file mode 100644 index 51496a8f71..0000000000 --- a/src/cascadia/Remoting/init.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Microsoft Corporation -// Licensed under the MIT license. - -#include "pch.h" -#include -#include - -// Note: Generate GUID using TlgGuid.exe tool -#pragma warning(suppress : 26477) // One of the macros uses 0/NULL. We don't have control to make it nullptr. -TRACELOGGING_DEFINE_PROVIDER( - g_hRemotingProvider, - "Microsoft.Windows.Terminal.Remoting", - // {d6f04aad-629f-539a-77c1-73f5c3e4aa7b} - (0xd6f04aad, 0x629f, 0x539a, 0x77, 0xc1, 0x73, 0xf5, 0xc3, 0xe4, 0xaa, 0x7b), - TraceLoggingOptionMicrosoftTelemetry()); - -BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD reason, LPVOID /*reserved*/) -{ - switch (reason) - { - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls(hInstDll); - TraceLoggingRegister(g_hRemotingProvider); - Microsoft::Console::ErrorReporting::EnableFallbackFailureReporting(g_hRemotingProvider); - break; - case DLL_PROCESS_DETACH: - if (g_hRemotingProvider) - { - TraceLoggingUnregister(g_hRemotingProvider); - } - break; - } - - return TRUE; -} - -UTILS_DEFINE_LIBRARY_RESOURCE_SCOPE(L"Microsoft.Terminal.Remoting/Resources"); diff --git a/src/cascadia/Remoting/pch.cpp b/src/cascadia/Remoting/pch.cpp deleted file mode 100644 index 398a99f665..0000000000 --- a/src/cascadia/Remoting/pch.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "pch.h" diff --git a/src/cascadia/Remoting/pch.h b/src/cascadia/Remoting/pch.h deleted file mode 100644 index cde15a8589..0000000000 --- a/src/cascadia/Remoting/pch.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -// -// pch.h -// Header for platform projection include files -// - -#pragma once - -// Block minwindef.h min/max macros to prevent conflict -#define NOMINMAX - -#define WIN32_LEAN_AND_MEAN -#define NOMCX -#define NOHELP -#define NOCOMM - -#include -#include - -// Manually include til after we include Windows.Foundation to give it winrt superpowers -#define BLOCK_TIL -#include -// This is inexplicable, but for whatever reason, cppwinrt conflicts with the -// SDK definition of this function, so the only fix is to undef it. -// from WinBase.h -// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime -#ifdef GetCurrentTime -#undef GetCurrentTime -#endif - -#include - -#include - -#include -#include -#include - -#include - -// Including TraceLogging essentials for the binary -#include -#include -TRACELOGGING_DECLARE_PROVIDER(g_hRemotingProvider); -#include -#include - -#include - -// Manually include til after we include Windows.Foundation to give it winrt superpowers -#include "til.h" - -#include -#include diff --git a/src/cascadia/TerminalApp/App.cpp b/src/cascadia/TerminalApp/App.cpp index 017129ca5f..b51fcb3abc 100644 --- a/src/cascadia/TerminalApp/App.cpp +++ b/src/cascadia/TerminalApp/App.cpp @@ -4,7 +4,6 @@ #include "pch.h" #include "App.h" #include "App.g.cpp" -#include using namespace winrt; using namespace winrt::Windows::ApplicationModel::Activation; @@ -37,27 +36,6 @@ namespace winrt::TerminalApp::implementation if (!dispatcherQueue) { _windowsXamlManager = xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread(); - - // As of Process Model v3, terminal windows are all created on their - // own threads, but we still initiate XAML for the App on the main - // thread. Thing is, just initializing XAML creates a CoreWindow for - // us. On Windows 10, that CoreWindow will show up as a visible - // window on the taskbar, unless we hide it manually. So, go get it - // and do the SW_HIDE thing on it. - if (const auto& coreWindow{ winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread() }) - { - if (const auto& interop{ coreWindow.try_as() }) - { - HWND coreHandle{ 0 }; - interop->get_WindowHandle(&coreHandle); - if (coreHandle) - { - // This prevents an empty "DesktopWindowXamlSource" from - // appearing on the taskbar - ShowWindow(coreHandle, SW_HIDE); - } - } - } } else { @@ -71,31 +49,6 @@ namespace winrt::TerminalApp::implementation return logic; } - void App::Close() - { - if (_bIsClosed) - { - return; - } - - _bIsClosed = true; - - if (_windowsXamlManager) - { - _windowsXamlManager.Close(); - } - _windowsXamlManager = nullptr; - - Exit(); - { - MSG msg = {}; - while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) - { - ::DispatchMessageW(&msg); - } - } - } - /// /// Invoked when the application is launched normally by the end user. Other entry points /// will be used such as when the application is launched to open a specific file. diff --git a/src/cascadia/TerminalApp/App.h b/src/cascadia/TerminalApp/App.h index a2c9b6a7c0..0f3d7a771f 100644 --- a/src/cascadia/TerminalApp/App.h +++ b/src/cascadia/TerminalApp/App.h @@ -18,7 +18,6 @@ namespace winrt::TerminalApp::implementation TerminalApp::AppLogic Logic(); - void Close(); void PrepareForSettingsUI(); bool IsDisposed() const diff --git a/src/cascadia/TerminalApp/App.idl b/src/cascadia/TerminalApp/App.idl index 516442148c..3319f7b646 100644 --- a/src/cascadia/TerminalApp/App.idl +++ b/src/cascadia/TerminalApp/App.idl @@ -7,7 +7,7 @@ namespace TerminalApp { // ADD ARBITRARY APP LOGIC TO AppLogic.idl, NOT HERE. // This is for XAML platform setup only. - [default_interface] runtimeclass App : Windows.UI.Xaml.Application, Windows.Foundation.IClosable + [default_interface] runtimeclass App : Windows.UI.Xaml.Application { App(); diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 7b4893fef1..b2ae698205 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -118,7 +118,7 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_HandleCloseWindow(const IInspectable& /*sender*/, const ActionEventArgs& args) { - CloseRequested.raise(nullptr, nullptr); + CloseWindow(); args.Handled(true); } diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index ca67dac64d..1e4b7a3b10 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -833,7 +833,7 @@ void AppCommandlineArgs::_resetStateToDefault() // Return Value: // - a list of Commandline objects, where each one represents a single // commandline to parse. -std::vector AppCommandlineArgs::BuildCommands(winrt::array_view& args) +std::vector AppCommandlineArgs::BuildCommands(winrt::array_view args) { std::vector commands; commands.emplace_back(Commandline{}); @@ -983,7 +983,7 @@ bool AppCommandlineArgs::IsHandoffListener() const noexcept // Return Value: // - The help text, or an error message, generated from parsing the input // provided by the user. -const std::string& AppCommandlineArgs::GetExitMessage() +const std::string& AppCommandlineArgs::GetExitMessage() const noexcept { return _exitMessage; } @@ -1080,7 +1080,7 @@ std::optional AppCommandlineArgs::GetSize() const noexcept // - args: an array of strings to process as a commandline. These args can contain spaces // Return Value: // - 0 if the commandline was successfully parsed -int AppCommandlineArgs::ParseArgs(winrt::array_view& args) +int AppCommandlineArgs::ParseArgs(winrt::array_view args) { for (const auto& arg : args) { diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index 7eb2516bb3..9f580e957b 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -28,15 +28,15 @@ public: ~AppCommandlineArgs() = default; int ParseCommand(const Commandline& command); - int ParseArgs(winrt::array_view& args); + int ParseArgs(winrt::array_view args); static std::vector BuildCommands(const std::vector& args); - static std::vector BuildCommands(winrt::array_view& args); + static std::vector BuildCommands(winrt::array_view args); void ValidateStartupCommands(); std::vector& GetStartupActions(); bool IsHandoffListener() const noexcept; - const std::string& GetExitMessage(); + const std::string& GetExitMessage() const noexcept; bool ShouldExitEarly() const noexcept; std::optional GetPersistedLayoutIdx() const noexcept; diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 812a1cf1b7..c1c56ca9af 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -3,9 +3,7 @@ #include "pch.h" #include "AppLogic.h" -#include "../inc/WindowingBehavior.h" #include "AppLogic.g.cpp" -#include "FindTargetWindowResult.g.cpp" #include "SettingsLoadEventArgs.h" #include @@ -121,7 +119,7 @@ namespace winrt::TerminalApp::implementation { auto appLogic{ ::winrt::TerminalApp::implementation::AppLogic::Current() }; THROW_HR_IF_NULL(E_INVALIDARG, appLogic); - return appLogic->GetSettings(); + return appLogic->Settings(); } AppLogic::AppLogic() @@ -507,179 +505,18 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Returns a pointer to the global shared settings. - [[nodiscard]] CascadiaSettings AppLogic::GetSettings() const noexcept + [[nodiscard]] CascadiaSettings AppLogic::Settings() const noexcept { return _settings; } - // Method Description: - // - Parse the given commandline args in an attempt to find the specified - // window. The rest of the args are ignored for now (they'll be handled - // whenever the commandline gets to the window it was intended for). - // - Note that this function will only ever be called by the monarch. A - // return value of `0` in this case does not mean "run the commandline in - // _this_ process", rather it means "run the commandline in the current - // process", whoever that may be. - // Arguments: - // - args: an array of strings to process as a commandline. These args can contain spaces - // Return Value: - // - 0: We should handle the args "in the current window". - // - WindowingBehaviorUseNew: We should handle the args in a new window - // - WindowingBehaviorUseExisting: We should handle the args "in - // the current window ON THIS DESKTOP" - // - WindowingBehaviorUseAnyExisting: We should handle the args "in the current - // window ON ANY DESKTOP" - // - anything else: We should handle the commandline in the window with the given ID. - TerminalApp::FindTargetWindowResult AppLogic::FindTargetWindow(array_view args) - { - if (!_loadedInitialSettings) - { - // Load settings if we haven't already - ReloadSettings(); - } - - return AppLogic::_doFindTargetWindow(args, _settings.GlobalSettings().WindowingBehavior()); - } - - // The main body of this function is a static helper, to facilitate unit-testing - TerminalApp::FindTargetWindowResult AppLogic::_doFindTargetWindow(array_view args, - const Microsoft::Terminal::Settings::Model::WindowingMode& windowingBehavior) - { - ::TerminalApp::AppCommandlineArgs appArgs; - const auto result = appArgs.ParseArgs(args); - if (result == 0) - { - if (!appArgs.GetExitMessage().empty()) - { - return winrt::make(WindowingBehaviorUseNone); - } - - // Validate the args now. This will make sure that in the case of a - // single x-save command, we toss that commandline to the current - // terminal window - appArgs.ValidateStartupCommands(); - const std::string parsedTarget{ appArgs.GetTargetWindow() }; - - // If the user did not provide any value on the commandline, - // then lookup our windowing behavior to determine what to do - // now. - if (parsedTarget.empty()) - { - auto windowId = WindowingBehaviorUseNew; - switch (windowingBehavior) - { - case WindowingMode::UseNew: - windowId = WindowingBehaviorUseNew; - break; - case WindowingMode::UseExisting: - windowId = WindowingBehaviorUseExisting; - break; - case WindowingMode::UseAnyExisting: - windowId = WindowingBehaviorUseAnyExisting; - break; - } - return winrt::make(windowId); - } - - // Here, the user _has_ provided a window-id on the commandline. - // What is it? Let's start by checking if it's an int, for the - // window's ID: - try - { - auto windowId = ::base::saturated_cast(std::stoi(parsedTarget)); - - // If the user provides _any_ negative number, then treat it as - // -1, for "use a new window". - if (windowId < 0) - { - windowId = -1; - } - - // Hooray! This is a valid integer. The set of possible values - // here is {-1, 0, ℤ+}. Let's return that window ID. - return winrt::make(windowId); - } - catch (...) - { - // Value was not a valid int. It could be any other string to - // use as a title though! - // - // First, check the reserved keywords: - if (parsedTarget == NewWindow) - { - return winrt::make(WindowingBehaviorUseNew); - } - else if (parsedTarget == MostRecentlyUsedWindow) - { - return winrt::make(WindowingBehaviorUseExisting); - } - else - { - // The string they provided wasn't an int, it wasn't "new" - // or "last", so whatever it is, that's the name they get. - winrt::hstring winrtName{ til::u8u16(parsedTarget) }; - return winrt::make(WindowingBehaviorUseName, winrtName); - } - } - } - - // Any unsuccessful parse will result in _no_ window. We will indicate - // to the caller that they shouldn't make a window. They can still find - // the commandline failed to parse and choose to display the message - // box. - // - // This will also work for the case where the user specifies an invalid - // commandline in conjunction with `-w 0`. - return winrt::make(WindowingBehaviorUseNone); - } - Windows::Foundation::Collections::IMapView AppLogic::GlobalHotkeys() { return _settings.GlobalSettings().ActionMap().GlobalHotkeys(); } - Microsoft::Terminal::Settings::Model::Theme AppLogic::Theme() - { - return _settings.GlobalSettings().CurrentTheme(); - } - - bool AppLogic::IsolatedMode() - { - if (!_loadedInitialSettings) - { - ReloadSettings(); - } - return _settings.GlobalSettings().IsolatedMode(); - } - bool AppLogic::RequestsTrayIcon() - { - if (!_loadedInitialSettings) - { - // Load settings if we haven't already - ReloadSettings(); - } - const auto& globals{ _settings.GlobalSettings() }; - return globals.AlwaysShowNotificationIcon() || - globals.MinimizeToNotificationArea(); - } - - bool AppLogic::AllowHeadless() - { - if (!_loadedInitialSettings) - { - // Load settings if we haven't already - ReloadSettings(); - } - return _settings.GlobalSettings().AllowHeadless(); - } - TerminalApp::TerminalWindow AppLogic::CreateNewWindow() { - if (_settings == nullptr) - { - ReloadSettings(); - } - auto warnings{ winrt::multi_threaded_vector() }; for (auto&& warn : _warnings) { @@ -705,18 +542,6 @@ namespace winrt::TerminalApp::implementation return _contentManager; } - bool AppLogic::ShouldUsePersistedLayout() const - { - return _settings.GlobalSettings().ShouldUsePersistedLayout(); - } - - TerminalApp::ParseCommandlineResult AppLogic::GetParseCommandlineMessage(array_view args) - { - ::TerminalApp::AppCommandlineArgs _appArgs; - const auto r = _appArgs.ParseArgs(args); - return TerminalApp::ParseCommandlineResult{ winrt::to_hstring(_appArgs.GetExitMessage()), r }; - } - // Function Description // * Adds a `WT_SETTINGS_DIR` env var to our own environment block, that // points at our settings directory. This allows portable installs to diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index 42f89942ad..8960a476f2 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -4,7 +4,6 @@ #pragma once #include "AppLogic.g.h" -#include "FindTargetWindowResult.g.h" #include "Jumplist.h" #include "LanguageProfileNotifier.h" @@ -25,19 +24,6 @@ namespace TerminalAppLocalTests namespace winrt::TerminalApp::implementation { - struct FindTargetWindowResult : FindTargetWindowResultT - { - WINRT_PROPERTY(int32_t, WindowId, -1); - WINRT_PROPERTY(winrt::hstring, WindowName, L""); - - public: - FindTargetWindowResult(const int32_t id, const winrt::hstring& name) : - _WindowId{ id }, _WindowName{ name } {}; - - FindTargetWindowResult(const int32_t id) : - FindTargetWindowResult(id, L""){}; - }; - struct AppLogic : AppLogicT { public: @@ -53,25 +39,15 @@ namespace winrt::TerminalApp::implementation void NotifyRootInitialized(); bool HasSettingsStartupActions() const noexcept; - bool ShouldUsePersistedLayout() const; - [[nodiscard]] Microsoft::Terminal::Settings::Model::CascadiaSettings GetSettings() const noexcept; - - TerminalApp::FindTargetWindowResult FindTargetWindow(array_view actions); + Microsoft::Terminal::Settings::Model::CascadiaSettings Settings() const noexcept; Windows::Foundation::Collections::IMapView GlobalHotkeys(); - Microsoft::Terminal::Settings::Model::Theme Theme(); - bool IsolatedMode(); - bool AllowHeadless(); - bool RequestsTrayIcon(); - TerminalApp::TerminalWindow CreateNewWindow(); winrt::TerminalApp::ContentManager ContentManager(); - TerminalApp::ParseCommandlineResult GetParseCommandlineMessage(array_view args); - til::typed_event SettingsChanged; private: @@ -99,9 +75,6 @@ namespace winrt::TerminalApp::implementation TerminalApp::ContentManager _contentManager{ winrt::make() }; - static TerminalApp::FindTargetWindowResult _doFindTargetWindow(winrt::array_view args, - const Microsoft::Terminal::Settings::Model::WindowingMode& windowingBehavior); - void _ApplyLanguageSettingChange() noexcept; safe_void_coroutine _ApplyStartupTaskStateChange(); diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index 362c740564..4f6bc262c3 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -4,18 +4,6 @@ import "TerminalWindow.idl"; namespace TerminalApp { - [default_interface] runtimeclass FindTargetWindowResult - { - Int32 WindowId { get; }; - String WindowName { get; }; - }; - - struct ParseCommandlineResult - { - String Message; - Int32 ExitCode; - }; - // See IDialogPresenter and TerminalPage's DialogPresenter for more // information. [default_interface] runtimeclass AppLogic @@ -36,22 +24,11 @@ namespace TerminalApp Boolean HasSettingsStartupActions(); - Boolean ShouldUsePersistedLayout(); - void ReloadSettings(); - - // Selected settings to expose - Microsoft.Terminal.Settings.Model.Theme Theme { get; }; - Boolean IsolatedMode { get; }; - Boolean AllowHeadless { get; }; - Boolean RequestsTrayIcon { get; }; - - FindTargetWindowResult FindTargetWindow(String[] args); + Microsoft.Terminal.Settings.Model.CascadiaSettings Settings { get; }; TerminalWindow CreateNewWindow(); - ParseCommandlineResult GetParseCommandlineMessage(String[] args); - IMapView GlobalHotkeys(); event Windows.Foundation.TypedEventHandler SettingsChanged; diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index 4817cd5242..bcee25c72d 100644 --- a/src/cascadia/TerminalApp/CommandPalette.cpp +++ b/src/cascadia/TerminalApp/CommandPalette.cpp @@ -359,7 +359,7 @@ namespace winrt::TerminalApp::implementation _switchToMode(CommandPaletteMode::CommandlineMode); e.Handled(true); } - else if (key == VirtualKey::C && ctrlDown) + else if ((key == VirtualKey::C || key == VirtualKey::Insert) && ctrlDown) { _searchBox().CopySelectionToClipboard(); e.Handled(true); diff --git a/src/cascadia/TerminalApp/Remoting.cpp b/src/cascadia/TerminalApp/Remoting.cpp new file mode 100644 index 0000000000..8383fb98fd --- /dev/null +++ b/src/cascadia/TerminalApp/Remoting.cpp @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "Remoting.h" + +#include "CommandlineArgs.g.cpp" +#include "RequestReceiveContentArgs.g.cpp" +#include "SummonWindowBehavior.g.cpp" +#include "WindowRequestedArgs.g.cpp" + +using namespace winrt; +using namespace winrt::Microsoft::Terminal; +using namespace winrt::Windows::Foundation; + +namespace winrt::TerminalApp::implementation +{ + CommandlineArgs::CommandlineArgs(winrt::array_view args, winrt::hstring currentDirectory, uint32_t showWindowCommand, winrt::hstring envString) : + _args{ args.begin(), args.end() }, + _cwd{ std::move(currentDirectory) }, + ShowWindowCommand{ showWindowCommand }, + CurrentEnvironment{ std::move(envString) } + { + _parseResult = _parsed.ParseArgs(_args); + if (_parseResult == 0) + { + _parsed.ValidateStartupCommands(); + } + } + + ::TerminalApp::AppCommandlineArgs& CommandlineArgs::ParsedArgs() noexcept + { + return _parsed; + } + + winrt::com_array& CommandlineArgs::CommandlineRef() noexcept + { + return _args; + } + + int32_t CommandlineArgs::ExitCode() const noexcept + { + return _parseResult; + } + + winrt::hstring CommandlineArgs::ExitMessage() const + { + return winrt::to_hstring(_parsed.GetExitMessage()); + } + + winrt::hstring CommandlineArgs::TargetWindow() const + { + return winrt::to_hstring(_parsed.GetTargetWindow()); + } + + void CommandlineArgs::Commandline(const winrt::array_view& value) + { + _args = { value.begin(), value.end() }; + } + + winrt::com_array CommandlineArgs::Commandline() + { + return winrt::com_array{ _args.begin(), _args.end() }; + } +} diff --git a/src/cascadia/TerminalApp/Remoting.h b/src/cascadia/TerminalApp/Remoting.h new file mode 100644 index 0000000000..a86619c4dc --- /dev/null +++ b/src/cascadia/TerminalApp/Remoting.h @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "AppCommandlineArgs.h" +#include "CommandlineArgs.g.h" +#include "RequestReceiveContentArgs.g.h" +#include "SummonWindowBehavior.g.h" +#include "WindowRequestedArgs.g.h" + +namespace winrt::TerminalApp::implementation +{ + struct CommandlineArgs : public CommandlineArgsT + { + CommandlineArgs() = default; + CommandlineArgs(winrt::array_view args, winrt::hstring currentDirectory, uint32_t showWindowCommand, winrt::hstring envString); + + ::TerminalApp::AppCommandlineArgs& ParsedArgs() noexcept; + winrt::com_array& CommandlineRef() noexcept; + + // These bits are exposed via WinRT: + public: + int32_t ExitCode() const noexcept; + winrt::hstring ExitMessage() const; + winrt::hstring TargetWindow() const; + + void Commandline(const winrt::array_view& value); + winrt::com_array Commandline(); + + til::property CurrentDirectory; + til::property CurrentEnvironment; + til::property ShowWindowCommand{ static_cast(SW_NORMAL) }; // SW_NORMAL is 1, 0 is SW_HIDE + + private: + ::TerminalApp::AppCommandlineArgs _parsed; + int32_t _parseResult = 0; + winrt::com_array _args; + winrt::hstring _cwd; + }; + + struct RequestReceiveContentArgs : RequestReceiveContentArgsT + { + WINRT_PROPERTY(uint64_t, SourceWindow); + WINRT_PROPERTY(uint64_t, TargetWindow); + WINRT_PROPERTY(uint32_t, TabIndex); + + public: + RequestReceiveContentArgs(const uint64_t src, const uint64_t tgt, const uint32_t tabIndex) : + _SourceWindow{ src }, + _TargetWindow{ tgt }, + _TabIndex{ tabIndex } {}; + }; + + struct SummonWindowBehavior : public SummonWindowBehaviorT + { + public: + SummonWindowBehavior() = default; + WINRT_PROPERTY(bool, MoveToCurrentDesktop, true); + WINRT_PROPERTY(bool, ToggleVisibility, true); + WINRT_PROPERTY(uint32_t, DropdownDuration, 0); + WINRT_PROPERTY(MonitorBehavior, ToMonitor, MonitorBehavior::ToCurrent); + + public: + SummonWindowBehavior(const SummonWindowBehavior& other) : + _MoveToCurrentDesktop{ other.MoveToCurrentDesktop() }, + _ToMonitor{ other.ToMonitor() }, + _DropdownDuration{ other.DropdownDuration() }, + _ToggleVisibility{ other.ToggleVisibility() } {}; + }; + + struct WindowRequestedArgs : public WindowRequestedArgsT + { + public: + WindowRequestedArgs(uint64_t id, const winrt::TerminalApp::CommandlineArgs& command) : + _Id{ id }, + _Command{ std::move(command) } + { + } + + WindowRequestedArgs(const winrt::hstring& window, const winrt::hstring& content, const Windows::Foundation::IReference& bounds) : + _WindowName{ window }, + _Content{ content }, + _InitialBounds{ bounds } + { + } + + WINRT_PROPERTY(uint64_t, Id); + WINRT_PROPERTY(winrt::hstring, WindowName); + WINRT_PROPERTY(TerminalApp::CommandlineArgs, Command); + WINRT_PROPERTY(winrt::hstring, Content); + WINRT_PROPERTY(Windows::Foundation::IReference, InitialBounds); + + private: + }; +} + +namespace winrt::TerminalApp::factory_implementation +{ + BASIC_FACTORY(SummonWindowBehavior); + BASIC_FACTORY(CommandlineArgs); + BASIC_FACTORY(RequestReceiveContentArgs); + BASIC_FACTORY(WindowRequestedArgs); +} diff --git a/src/cascadia/TerminalApp/Remoting.idl b/src/cascadia/TerminalApp/Remoting.idl new file mode 100644 index 0000000000..17f1318422 --- /dev/null +++ b/src/cascadia/TerminalApp/Remoting.idl @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace TerminalApp +{ + runtimeclass CommandlineArgs + { + CommandlineArgs(); + CommandlineArgs(String[] args, String cwd, UInt32 showWindowCommand, String env); + + Int32 ExitCode { get; }; + String ExitMessage { get; }; + String TargetWindow { get; }; + + String[] Commandline; + String CurrentDirectory { get; }; + UInt32 ShowWindowCommand { get; }; + String CurrentEnvironment { get; }; + }; + + enum MonitorBehavior + { + InPlace, + ToCurrent, + ToMouse, + }; + + [default_interface] runtimeclass SummonWindowBehavior { + SummonWindowBehavior(); + Boolean MoveToCurrentDesktop; + Boolean ToggleVisibility; + UInt32 DropdownDuration; + MonitorBehavior ToMonitor; + } + + [default_interface] runtimeclass RequestReceiveContentArgs { + RequestReceiveContentArgs(UInt64 src, UInt64 tgt, UInt32 tabIndex); + + UInt64 SourceWindow { get; }; + UInt64 TargetWindow { get; }; + UInt32 TabIndex { get; }; + }; + + [default_interface] runtimeclass WindowRequestedArgs { + WindowRequestedArgs(UInt64 id, CommandlineArgs command); + WindowRequestedArgs(String window, String content, Windows.Foundation.IReference bounds); + + UInt64 Id; + String WindowName; + + CommandlineArgs Command { get; }; + String Content { get; }; + Windows.Foundation.IReference InitialBounds { get; }; + }; +} diff --git a/src/cascadia/TerminalApp/Resources/de-DE/Resources.resw b/src/cascadia/TerminalApp/Resources/de-DE/Resources.resw index eec7f854bd..dafd51d375 100644 --- a/src/cascadia/TerminalApp/Resources/de-DE/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/de-DE/Resources.resw @@ -728,12 +728,6 @@ Abbrechen - - Das Fenster konnte nicht umbenannt werden - - - Ein anderes Fenster mit diesem Namen existiert bereits - Maximieren diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 217f4e8887..74d09214ba 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -733,12 +733,6 @@ Cancel - - Failed to rename window - - - Another window with that name already exists - Maximize diff --git a/src/cascadia/TerminalApp/Resources/es-ES/Resources.resw b/src/cascadia/TerminalApp/Resources/es-ES/Resources.resw index 1b107a9bdb..5554ab65d9 100644 --- a/src/cascadia/TerminalApp/Resources/es-ES/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/es-ES/Resources.resw @@ -725,12 +725,6 @@ Cancelar - - No se pudo cambiar el nombre de la ventana - - - Ya existe otra ventana con ese nombre - Maximizar diff --git a/src/cascadia/TerminalApp/Resources/fr-FR/Resources.resw b/src/cascadia/TerminalApp/Resources/fr-FR/Resources.resw index e0a08f7033..7985c115fe 100644 --- a/src/cascadia/TerminalApp/Resources/fr-FR/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/fr-FR/Resources.resw @@ -725,12 +725,6 @@ Annuler - - Échec du renommage de la fenêtre - - - Une autre fenêtre portant ce nom existe déjà - Agrandir diff --git a/src/cascadia/TerminalApp/Resources/it-IT/Resources.resw b/src/cascadia/TerminalApp/Resources/it-IT/Resources.resw index fd00567510..09638c2271 100644 --- a/src/cascadia/TerminalApp/Resources/it-IT/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/it-IT/Resources.resw @@ -725,12 +725,6 @@ Annulla - - Non è stato possibile rinominare la finestra - - - Un'altra finestra con questo nome esiste già - Ingrandisci diff --git a/src/cascadia/TerminalApp/Resources/ja-JP/Resources.resw b/src/cascadia/TerminalApp/Resources/ja-JP/Resources.resw index 22567ab8ec..bf2fe3e519 100644 --- a/src/cascadia/TerminalApp/Resources/ja-JP/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/ja-JP/Resources.resw @@ -726,12 +726,6 @@ キャンセル - - ウィンドウの名前を変更できませんでした - - - その名前の別のウィンドウがすでに存在します - 最大化 diff --git a/src/cascadia/TerminalApp/Resources/ko-KR/Resources.resw b/src/cascadia/TerminalApp/Resources/ko-KR/Resources.resw index 4686a859bf..af54a3ad3e 100644 --- a/src/cascadia/TerminalApp/Resources/ko-KR/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/ko-KR/Resources.resw @@ -725,12 +725,6 @@ 취소 - - 창 이름을 바꾸지 못함 - - - 해당 이름으로 된 다른 창이 이미 있습니다 - 최대화 diff --git a/src/cascadia/TerminalApp/Resources/pt-BR/Resources.resw b/src/cascadia/TerminalApp/Resources/pt-BR/Resources.resw index 90d7a068ff..4fb173f76c 100644 --- a/src/cascadia/TerminalApp/Resources/pt-BR/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/pt-BR/Resources.resw @@ -725,12 +725,6 @@ Cancelar - - Falha ao renomear janela - - - Já existe outra janela com esse nome - Maximizar diff --git a/src/cascadia/TerminalApp/Resources/qps-ploc/Resources.resw b/src/cascadia/TerminalApp/Resources/qps-ploc/Resources.resw index 63c3326dc6..f9c83a98c9 100644 --- a/src/cascadia/TerminalApp/Resources/qps-ploc/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/qps-ploc/Resources.resw @@ -733,12 +733,6 @@ Сªⁿċĕĺ ! - - ₣âιļĕđ ŧо ѓëňąмë щϊπδǿω !!! !!! - - - Άņόтĥěŗ ẃїлðοω ẁιťĥ ťћаť пâmě ăļřéàδў ёжìśŧѕ !!! !!! !!! !!! ! - Μą×ìmϊżé !! diff --git a/src/cascadia/TerminalApp/Resources/qps-ploca/Resources.resw b/src/cascadia/TerminalApp/Resources/qps-ploca/Resources.resw index 63c3326dc6..f9c83a98c9 100644 --- a/src/cascadia/TerminalApp/Resources/qps-ploca/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/qps-ploca/Resources.resw @@ -733,12 +733,6 @@ Сªⁿċĕĺ ! - - ₣âιļĕđ ŧо ѓëňąмë щϊπδǿω !!! !!! - - - Άņόтĥěŗ ẃїлðοω ẁιťĥ ťћаť пâmě ăļřéàδў ёжìśŧѕ !!! !!! !!! !!! ! - Μą×ìmϊżé !! diff --git a/src/cascadia/TerminalApp/Resources/qps-plocm/Resources.resw b/src/cascadia/TerminalApp/Resources/qps-plocm/Resources.resw index 63c3326dc6..f9c83a98c9 100644 --- a/src/cascadia/TerminalApp/Resources/qps-plocm/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/qps-plocm/Resources.resw @@ -733,12 +733,6 @@ Сªⁿċĕĺ ! - - ₣âιļĕđ ŧо ѓëňąмë щϊπδǿω !!! !!! - - - Άņόтĥěŗ ẃїлðοω ẁιťĥ ťћаť пâmě ăļřéàδў ёжìśŧѕ !!! !!! !!! !!! ! - Μą×ìmϊżé !! diff --git a/src/cascadia/TerminalApp/Resources/ru-RU/Resources.resw b/src/cascadia/TerminalApp/Resources/ru-RU/Resources.resw index 811bc2f61c..c1410ce2dd 100644 --- a/src/cascadia/TerminalApp/Resources/ru-RU/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/ru-RU/Resources.resw @@ -725,12 +725,6 @@ Отмена - - Не удалось переименовать окно - - - Окно с таким именем уже существует - Развернуть diff --git a/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw b/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw index 7e3b5bc07e..a2e85cd607 100644 --- a/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/zh-CN/Resources.resw @@ -725,12 +725,6 @@ 取消 - - 未能重命名窗口 - - - 已存在另一个具有该名称的窗口 - 最大化 diff --git a/src/cascadia/TerminalApp/Resources/zh-TW/Resources.resw b/src/cascadia/TerminalApp/Resources/zh-TW/Resources.resw index e4c77d1893..ec80712720 100644 --- a/src/cascadia/TerminalApp/Resources/zh-TW/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/zh-TW/Resources.resw @@ -725,12 +725,6 @@ 取消 - - 無法重新命名視窗 - - - 已存在另一個具有該名稱的視窗 - 最大化 diff --git a/src/cascadia/TerminalApp/TabBase.cpp b/src/cascadia/TerminalApp/TabBase.cpp index 7c80e36686..8407296e29 100644 --- a/src/cascadia/TerminalApp/TabBase.cpp +++ b/src/cascadia/TerminalApp/TabBase.cpp @@ -7,7 +7,6 @@ #include "TabBase.g.cpp" #include "Utils.h" #include "ColorHelper.h" -#include "../inc/WindowingBehavior.h" using namespace winrt; using namespace winrt::Windows::UI::Xaml; @@ -75,7 +74,7 @@ namespace winrt::TerminalApp::implementation _moveToNewWindowMenuItem.Click([weakThis](auto&&, auto&&) { if (auto tab{ weakThis.get() }) { - MoveTabArgs args{ winrt::to_hstring(NewWindow), MoveTabDirection::Forward }; + MoveTabArgs args{ L"new", MoveTabDirection::Forward }; ActionAndArgs actionAndArgs{ ShortcutAction::MoveTab, args }; tab->_dispatch.DoAction(*tab, actionAndArgs); } @@ -528,6 +527,9 @@ namespace winrt::TerminalApp::implementation tabItemThemeResources.Insert(winrt::box_value(L"Dark"), darkThemeDictionary); tabItemThemeResources.Insert(winrt::box_value(L"HighContrast"), highContrastThemeDictionary); + // Apply the color to the tab + TabViewItem().Background(deselectedTabBrush); + // Now actually set the resources we want in them. // Before, we used to put these on the ResourceDictionary directly. // However, HighContrast mode may require some adjustments. So let's just add @@ -560,7 +562,6 @@ namespace winrt::TerminalApp::implementation currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderSelectedCloseButtonForeground"), fontBrush); // TabViewItem.CloseButton.Background (aka X button) - currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackground"), deselectedTabBrush); currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackgroundPressed"), isHighContrast ? selectedTabBrush : subtleFillColorTertiaryBrush); currentDictionary.Insert(winrt::box_value(L"TabViewItemHeaderCloseButtonBackgroundPointerOver"), isHighContrast ? selectedTabBrush : subtleFillColorSecondaryBrush); diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index 0eba4511a9..cf0df03175 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -243,10 +243,12 @@ namespace winrt::TerminalApp::implementation // - Handle changes in tab layout. void TerminalPage::_UpdateTabView() { - // Never show the tab row when we're fullscreen. Otherwise: - // Show tabs when there's more than 1, or the user has chosen to always - // show the tab bar. - const auto isVisible = (!_isFullscreen && !_isInFocusMode) && + // The tab row should only be visible if: + // - we're not in focus mode + // - we're not in full screen, or the user has enabled fullscreen tabs + // - there is more than one tab, or the user has chosen to always show tabs + const auto isVisible = !_isInFocusMode && + (!_isFullscreen || _showTabsFullscreen) && (_settings.GlobalSettings().ShowTabsInTitlebar() || (_tabs.Size() > 1) || _settings.GlobalSettings().AlwaysShowTabs()); diff --git a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj index a1c6a4e6a8..0896bc114a 100644 --- a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj +++ b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj @@ -91,6 +91,9 @@ MinMaxCloseControl.xaml + + Remoting.idl + PaletteItemTemplateSelector.idl Code @@ -198,6 +201,9 @@ MinMaxCloseControl.xaml + + Remoting.idl + PaletteItemTemplateSelector.idl Code @@ -320,6 +326,7 @@ App.xaml + Designer diff --git a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters index 0f6468fd6b..12b3fa2add 100644 --- a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters +++ b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters @@ -2,9 +2,11 @@ + + @@ -21,9 +23,6 @@ - - tab - commandPalette @@ -44,6 +43,8 @@ + + @@ -58,9 +59,6 @@ - - tab - commandPalette @@ -81,6 +79,9 @@ + + + @@ -92,10 +93,6 @@ settings - - - tab - tab @@ -110,9 +107,11 @@ - - - + + + + + @@ -151,6 +150,9 @@ highlightedText + + + diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index c831c48c75..c71596b708 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -19,11 +19,11 @@ #include "SnippetsPaneContent.h" #include "MarkdownPaneContent.h" #include "TabRowControl.h" +#include "Remoting.h" #include "TerminalPage.g.cpp" #include "RenameWindowRequestedArgs.g.cpp" #include "RequestMoveContentArgs.g.cpp" -#include "RequestReceiveContentArgs.g.cpp" #include "LaunchPositionRequest.g.cpp" using namespace winrt; @@ -171,7 +171,6 @@ namespace winrt::TerminalApp::implementation const auto canDragDrop = CanDragDrop(); - _tabRow.PointerMoved({ get_weak(), &TerminalPage::_RestorePointerCursorHandler }); _tabView.CanReorderTabs(canDragDrop); _tabView.CanDragTabs(canDragDrop); _tabView.TabDragStarting({ get_weak(), &TerminalPage::_TabDragStarted }); @@ -270,23 +269,13 @@ namespace winrt::TerminalApp::implementation _layoutUpdatedRevoker = _tabContent.LayoutUpdated(winrt::auto_revoke, { this, &TerminalPage::_OnFirstLayout }); _isAlwaysOnTop = _settings.GlobalSettings().AlwaysOnTop(); + _showTabsFullscreen = _settings.GlobalSettings().ShowTabsFullscreen(); // DON'T set up Toasts/TeachingTips here. They should be loaded and // initialized the first time they're opened, in whatever method opens // them. - // Setup mouse vanish attributes - SystemParametersInfoW(SPI_GETMOUSEVANISH, 0, &_shouldMouseVanish, false); - _tabRow.ShowElevationShield(IsRunningElevated() && _settings.GlobalSettings().ShowAdminShield()); - - // Store cursor, so we can restore it, e.g., after mouse vanishing - // (we'll need to adapt this logic once we make cursor context aware) - try - { - _defaultPointerCursor = CoreWindow::GetForCurrentThread().PointerCursor(); - } - CATCH_LOG(); } Windows::UI::Xaml::Automation::Peers::AutomationPeer TerminalPage::OnCreateAutomationPeer() @@ -1724,8 +1713,6 @@ namespace winrt::TerminalApp::implementation term.OpenHyperlink({ this, &TerminalPage::_OpenHyperlinkHandler }); - term.HidePointerCursor({ get_weak(), &TerminalPage::_HidePointerCursorHandler }); - term.RestorePointerCursor({ get_weak(), &TerminalPage::_RestorePointerCursorHandler }); // Add an event handler for when the terminal or tab wants to set a // progress indicator on the taskbar term.SetTaskbarProgress({ get_weak(), &TerminalPage::_SetTaskbarProgressHandler }); @@ -2360,18 +2347,14 @@ namespace winrt::TerminalApp::implementation // reattach instead of create new content, so this method simply needs to // parse the JSON and pump it into our action handler. Almost the same as // doing something like `wt -w 0 nt`. - safe_void_coroutine TerminalPage::AttachContent(IVector args, - uint32_t tabIndex) + void TerminalPage::AttachContent(IVector args, uint32_t tabIndex) { if (args == nullptr || args.Size() == 0) { - co_return; + return; } - // Switch to the UI thread before selecting a tab or dispatching actions. - co_await wil::resume_foreground(Dispatcher(), CoreDispatcherPriority::High); - const auto& firstAction = args.GetAt(0); const bool firstIsSplitPane{ firstAction.Action() == ShortcutAction::SplitPane }; @@ -3617,6 +3600,8 @@ namespace winrt::TerminalApp::implementation _isAlwaysOnTop = _settings.GlobalSettings().AlwaysOnTop(); AlwaysOnTopChanged.raise(*this, nullptr); + _showTabsFullscreen = _settings.GlobalSettings().ShowTabsFullscreen(); + // Settings AllowDependentAnimations will affect whether animations are // enabled application-wide, so we don't need to check it each time we // want to create an animation. @@ -4041,6 +4026,37 @@ namespace winrt::TerminalApp::implementation return _isAlwaysOnTop; } + // Method Description: + // - Returns true if the tab row should be visible when we're in full screen + // state. + // Arguments: + // - + // Return Value: + // - true if the tab row should be visible in full screen state + bool TerminalPage::ShowTabsFullscreen() const + { + return _showTabsFullscreen; + } + + // Method Description: + // - Updates the visibility of the tab row when in fullscreen state. + void TerminalPage::SetShowTabsFullscreen(bool newShowTabsFullscreen) + { + if (_showTabsFullscreen == newShowTabsFullscreen) + { + return; + } + + _showTabsFullscreen = newShowTabsFullscreen; + + // if we're currently in fullscreen, update tab view to make + // sure tabs are given the correct visibility + if (_isFullscreen) + { + _UpdateTabView(); + } + } + void TerminalPage::SetFullscreen(bool newFullscreen) { if (_isFullscreen == newFullscreen) @@ -4311,46 +4327,6 @@ namespace winrt::TerminalApp::implementation return winrt::hstring{ text }; } - // Method Description: - // - Hides cursor if required - // Return Value: - // - - void TerminalPage::_HidePointerCursorHandler(const IInspectable& /*sender*/, const IInspectable& /*eventArgs*/) - { - if (_shouldMouseVanish && !_isMouseHidden) - { - if (auto window{ CoreWindow::GetForCurrentThread() }) - { - try - { - window.PointerCursor(nullptr); - _isMouseHidden = true; - } - CATCH_LOG(); - } - } - } - - // Method Description: - // - Restores cursor if required - // Return Value: - // - - void TerminalPage::_RestorePointerCursorHandler(const IInspectable& /*sender*/, const IInspectable& /*eventArgs*/) - { - if (_isMouseHidden) - { - if (auto window{ CoreWindow::GetForCurrentThread() }) - { - try - { - window.PointerCursor(_defaultPointerCursor); - _isMouseHidden = false; - } - CATCH_LOG(); - } - } - } - // Method Description: // - Update the RequestedTheme of the specified FrameworkElement and all its // Parent elements. We need to do this so that we can actually theme all @@ -4381,93 +4357,49 @@ namespace winrt::TerminalApp::implementation // - // Return Value: // - - safe_void_coroutine TerminalPage::IdentifyWindow() + void TerminalPage::IdentifyWindow() { - auto weakThis{ get_weak() }; - co_await wil::resume_foreground(Dispatcher()); - if (auto page{ weakThis.get() }) + // If we haven't ever loaded the TeachingTip, then do so now and + // create the toast for it. + if (_windowIdToast == nullptr) { - // If we haven't ever loaded the TeachingTip, then do so now and - // create the toast for it. - if (page->_windowIdToast == nullptr) + if (auto tip{ FindName(L"WindowIdToast").try_as() }) { - if (auto tip{ page->FindName(L"WindowIdToast").try_as() }) - { - page->_windowIdToast = std::make_shared(tip); - // Make sure to use the weak ref when setting up this - // callback. - tip.Closed({ page->get_weak(), &TerminalPage::_FocusActiveControl }); - } + _windowIdToast = std::make_shared(tip); + // IsLightDismissEnabled == true is bugged and poorly interacts with multi-windowing. + // It causes the tip to be immediately dismissed when another tip is opened in another window. + tip.IsLightDismissEnabled(false); + // Make sure to use the weak ref when setting up this callback. + tip.Closed({ get_weak(), &TerminalPage::_FocusActiveControl }); } - _UpdateTeachingTipTheme(WindowIdToast().try_as()); + } + _UpdateTeachingTipTheme(WindowIdToast().try_as()); - if (page->_windowIdToast != nullptr) - { - page->_windowIdToast->Open(); - } + if (_windowIdToast != nullptr) + { + _windowIdToast->Open(); } } - // Method Description: - // - Called when an attempt to rename the window has failed. This will open - // the toast displaying a message to the user that the attempt to rename - // the window has failed. - // - This will load the RenameFailedToast TeachingTip the first time it's called. - // Arguments: - // - - // Return Value: - // - - safe_void_coroutine TerminalPage::RenameFailed() + void TerminalPage::ShowTerminalWorkingDirectory() { - auto weakThis{ get_weak() }; - co_await wil::resume_foreground(Dispatcher()); - if (auto page{ weakThis.get() }) + // If we haven't ever loaded the TeachingTip, then do so now and + // create the toast for it. + if (_windowCwdToast == nullptr) { - // If we haven't ever loaded the TeachingTip, then do so now and - // create the toast for it. - if (page->_windowRenameFailedToast == nullptr) + if (auto tip{ FindName(L"WindowCwdToast").try_as() }) { - if (auto tip{ page->FindName(L"RenameFailedToast").try_as() }) - { - page->_windowRenameFailedToast = std::make_shared(tip); - // Make sure to use the weak ref when setting up this - // callback. - tip.Closed({ page->get_weak(), &TerminalPage::_FocusActiveControl }); - } - } - _UpdateTeachingTipTheme(RenameFailedToast().try_as()); - - if (page->_windowRenameFailedToast != nullptr) - { - page->_windowRenameFailedToast->Open(); + _windowCwdToast = std::make_shared(tip); + // Make sure to use the weak ref when setting up this + // callback. + tip.Closed({ get_weak(), &TerminalPage::_FocusActiveControl }); } } - } + _UpdateTeachingTipTheme(WindowCwdToast().try_as()); - safe_void_coroutine TerminalPage::ShowTerminalWorkingDirectory() - { - auto weakThis{ get_weak() }; - co_await wil::resume_foreground(Dispatcher()); - if (auto page{ weakThis.get() }) + if (_windowCwdToast != nullptr) { - // If we haven't ever loaded the TeachingTip, then do so now and - // create the toast for it. - if (page->_windowCwdToast == nullptr) - { - if (auto tip{ page->FindName(L"WindowCwdToast").try_as() }) - { - page->_windowCwdToast = std::make_shared(tip); - // Make sure to use the weak ref when setting up this - // callback. - tip.Closed({ page->get_weak(), &TerminalPage::_FocusActiveControl }); - } - } - _UpdateTeachingTipTheme(WindowCwdToast().try_as()); - - if (page->_windowCwdToast != nullptr) - { - page->_windowCwdToast->Open(); - } + _windowCwdToast->Open(); } } @@ -4475,8 +4407,7 @@ namespace winrt::TerminalApp::implementation // - Called when the user hits the "Ok" button on the WindowRenamer TeachingTip. // - Will raise an event that will bubble up to the monarch, asking if this // name is acceptable. - // - If it is, we'll eventually get called back in TerminalPage::WindowName(hstring). - // - If not, then TerminalPage::RenameFailed will get called. + // - we'll eventually get called back in TerminalPage::WindowName(hstring). // Arguments: // - // Return Value: @@ -5173,25 +5104,18 @@ namespace winrt::TerminalApp::implementation // Handler for our WindowProperties's PropertyChanged event. We'll use this // to pop the "Identify Window" toast when the user renames our window. - safe_void_coroutine TerminalPage::_windowPropertyChanged(const IInspectable& /*sender*/, - const WUX::Data::PropertyChangedEventArgs& args) + void TerminalPage::_windowPropertyChanged(const IInspectable& /*sender*/, const WUX::Data::PropertyChangedEventArgs& args) { if (args.PropertyName() != L"WindowName") { - co_return; + return; } - auto weakThis{ get_weak() }; - // On the foreground thread, raise property changed notifications, and - // display the success toast. - co_await wil::resume_foreground(Dispatcher()); - if (auto page{ weakThis.get() }) + + // DON'T display the confirmation if this is the name we were + // given on startup! + if (_startupState == StartupState::Initialized) { - // DON'T display the confirmation if this is the name we were - // given on startup! - if (page->_startupState == StartupState::Initialized) - { - page->IdentifyWindow(); - } + IdentifyWindow(); } } @@ -5212,19 +5136,12 @@ namespace winrt::TerminalApp::implementation // Stash the offset from where we started the drag to the // tab's origin. We'll use that offset in the future to help // position the dropped window. - - // First, the position of the pointer, from the CoreWindow - const auto pointerPosition = CoreWindow::GetForCurrentThread().PointerPosition(); - // Next, the position of the tab itself: - const auto tabPosition = eventTab.TransformToVisual(nullptr).TransformPoint({ 0, 0 }); - // Now, we need to add the origin of our CoreWindow to the tab - // position. - const auto windowOrigin = CoreWindow::GetForCurrentThread().Bounds(); - // Subtract the two to get the offset. - _stashed.dragOffset = { - pointerPosition.X - windowOrigin.X - tabPosition.X, - pointerPosition.Y - windowOrigin.Y - tabPosition.Y, - }; + const auto inverseScale = 1.0f / static_cast(eventTab.XamlRoot().RasterizationScale()); + POINT cursorPos; + GetCursorPos(&cursorPos); + ScreenToClient(*_hostingHwnd, &cursorPos); + _stashed.dragOffset.X = cursorPos.x * inverseScale; + _stashed.dragOffset.Y = cursorPos.y * inverseScale; // Into the DataPackage, let's stash our own window ID. const auto id{ _WindowProperties.WindowId() }; @@ -5271,8 +5188,8 @@ namespace winrt::TerminalApp::implementation // - Called on the TARGET of a tab drag/drop. We'll unpack the DataPackage // to find who the tab came from. We'll then ask the Monarch to ask the // sender to move that tab to us. - safe_void_coroutine TerminalPage::_onTabStripDrop(winrt::Windows::Foundation::IInspectable /*sender*/, - winrt::Windows::UI::Xaml::DragEventArgs e) + void TerminalPage::_onTabStripDrop(winrt::Windows::Foundation::IInspectable /*sender*/, + winrt::Windows::UI::Xaml::DragEventArgs e) { // Get the PID and make sure it is the same as ours. if (const auto& pidObj{ e.DataView().Properties().TryLookup(L"pid") }) @@ -5281,20 +5198,20 @@ namespace winrt::TerminalApp::implementation if (pid != GetCurrentProcessId()) { // The PID doesn't match ours. We can't handle this drop. - co_return; + return; } } else { // No PID? We can't handle this drop. Bail. - co_return; + return; } const auto& windowIdObj{ e.DataView().Properties().TryLookup(L"windowId") }; if (windowIdObj == nullptr) { // No windowId? Bail. - co_return; + return; } const uint64_t src{ winrt::unbox_value(windowIdObj) }; @@ -5302,38 +5219,32 @@ namespace winrt::TerminalApp::implementation // index to the request. This is largely taken from the WinUI sample // app. - // We need to be on OUR UI thread to figure out where we dropped - auto weakThis{ get_weak() }; - co_await wil::resume_foreground(Dispatcher()); - if (const auto& page{ weakThis.get() }) - { - // First we need to get the position in the List to drop to - auto index = -1; + // First we need to get the position in the List to drop to + auto index = -1; - // Determine which items in the list our pointer is between. - for (auto i = 0u; i < _tabView.TabItems().Size(); i++) + // Determine which items in the list our pointer is between. + for (auto i = 0u; i < _tabView.TabItems().Size(); i++) + { + if (const auto& item{ _tabView.ContainerFromIndex(i).try_as() }) { - if (const auto& item{ _tabView.ContainerFromIndex(i).try_as() }) + const auto posX{ e.GetPosition(item).X }; // The point of the drop, relative to the tab + const auto itemWidth{ item.ActualWidth() }; // The right of the tab + // If the drag point is on the left half of the tab, then insert here. + if (posX < itemWidth / 2) { - const auto posX{ e.GetPosition(item).X }; // The point of the drop, relative to the tab - const auto itemWidth{ item.ActualWidth() }; // The right of the tab - // If the drag point is on the left half of the tab, then insert here. - if (posX < itemWidth / 2) - { - index = i; - break; - } + index = i; + break; } } - - // `this` is safe to use - const auto request = winrt::make_self(src, _WindowProperties.WindowId(), index); - - // This will go up to the monarch, who will then dispatch the request - // back down to the source TerminalPage, who will then perform a - // RequestMoveContent to move their tab to us. - RequestReceiveContent.raise(*this, *request); } + + // `this` is safe to use + const auto request = winrt::make_self(src, _WindowProperties.WindowId(), index); + + // This will go up to the monarch, who will then dispatch the request + // back down to the source TerminalPage, who will then perform a + // RequestMoveContent to move their tab to us. + RequestReceiveContent.raise(*this, *request); } // Method Description: @@ -5343,33 +5254,23 @@ namespace winrt::TerminalApp::implementation // the destination window. // - Fortunately, sending the tab is basically just a MoveTab action, so we // can largely reuse that. - safe_void_coroutine TerminalPage::SendContentToOther(winrt::TerminalApp::RequestReceiveContentArgs args) + void TerminalPage::SendContentToOther(winrt::TerminalApp::RequestReceiveContentArgs args) { // validate that we're the source window of the tab in this request if (args.SourceWindow() != _WindowProperties.WindowId()) { - co_return; + return; } if (!_stashed.draggedTab) { - co_return; + return; } - // must do the work of adding/removing tabs on the UI thread. - auto weakThis{ get_weak() }; - co_await wil::resume_foreground(Dispatcher(), CoreDispatcherPriority::Normal); - if (const auto& page{ weakThis.get() }) - { - // `this` is safe to use in here. - - _sendDraggedTabToWindow(winrt::to_hstring(args.TargetWindow()), - args.TabIndex(), - std::nullopt); - } + _sendDraggedTabToWindow(winrt::to_hstring(args.TargetWindow()), args.TabIndex(), std::nullopt); } - safe_void_coroutine TerminalPage::_onTabDroppedOutside(winrt::IInspectable sender, - winrt::MUX::Controls::TabViewTabDroppedOutsideEventArgs e) + void TerminalPage::_onTabDroppedOutside(winrt::IInspectable sender, + winrt::MUX::Controls::TabViewTabDroppedOutsideEventArgs e) { // Get the current pointer point from the CoreWindow const auto& pointerPoint{ CoreWindow::GetForCurrentThread().PointerPosition() }; @@ -5381,29 +5282,21 @@ namespace winrt::TerminalApp::implementation if (!_stashed.draggedTab) { - co_return; + return; } - // must do the work of adding/removing tabs on the UI thread. - auto weakThis{ get_weak() }; - co_await wil::resume_foreground(Dispatcher(), CoreDispatcherPriority::Normal); - if (const auto& page{ weakThis.get() }) - { - // `this` is safe to use in here. + // We need to convert the pointer point to a point that we can use + // to position the new window. We'll use the drag offset from before + // so that the tab in the new window is positioned so that it's + // basically still directly under the cursor. - // We need to convert the pointer point to a point that we can use - // to position the new window. We'll use the drag offset from before - // so that the tab in the new window is positioned so that it's - // basically still directly under the cursor. - - // -1 is the magic number for "new window" - // 0 as the tab index, because we don't care. It's making a new window. It'll be the only tab. - const winrt::Windows::Foundation::Point adjusted = { - pointerPoint.X - _stashed.dragOffset.X, - pointerPoint.Y - _stashed.dragOffset.Y, - }; - _sendDraggedTabToWindow(winrt::hstring{ L"-1" }, 0, adjusted); - } + // -1 is the magic number for "new window" + // 0 as the tab index, because we don't care. It's making a new window. It'll be the only tab. + const winrt::Windows::Foundation::Point adjusted = { + pointerPoint.X - _stashed.dragOffset.X, + pointerPoint.Y - _stashed.dragOffset.Y, + }; + _sendDraggedTabToWindow(winrt::hstring{ L"-1" }, 0, adjusted); } void TerminalPage::_sendDraggedTabToWindow(const winrt::hstring& windowId, diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 415bbec811..368cb77cd8 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -9,7 +9,6 @@ #include "AppCommandlineArgs.h" #include "RenameWindowRequestedArgs.g.h" #include "RequestMoveContentArgs.g.h" -#include "RequestReceiveContentArgs.g.h" #include "LaunchPositionRequest.g.h" #include "Toast.h" @@ -69,19 +68,6 @@ namespace winrt::TerminalApp::implementation _TabIndex{ tabIndex } {}; }; - struct RequestReceiveContentArgs : RequestReceiveContentArgsT - { - WINRT_PROPERTY(uint64_t, SourceWindow); - WINRT_PROPERTY(uint64_t, TargetWindow); - WINRT_PROPERTY(uint32_t, TabIndex); - - public: - RequestReceiveContentArgs(const uint64_t src, const uint64_t tgt, const uint32_t tabIndex) : - _SourceWindow{ src }, - _TargetWindow{ tgt }, - _TabIndex{ tabIndex } {}; - }; - struct LaunchPositionRequest : LaunchPositionRequestT { LaunchPositionRequest() = default; @@ -135,6 +121,8 @@ namespace winrt::TerminalApp::implementation bool FocusMode() const; bool Fullscreen() const; bool AlwaysOnTop() const; + bool ShowTabsFullscreen() const; + void SetShowTabsFullscreen(bool newShowTabsFullscreen); void SetFullscreen(bool); void SetFocusMode(const bool inFocusMode); void Maximized(bool newMaximized); @@ -153,11 +141,10 @@ namespace winrt::TerminalApp::implementation void ShowKeyboardServiceWarning() const; winrt::hstring KeyboardServiceDisabledText(); - safe_void_coroutine IdentifyWindow(); + void IdentifyWindow(); void ActionSaved(winrt::hstring input, winrt::hstring name, winrt::hstring keyChord); void ActionSaveFailed(winrt::hstring message); - safe_void_coroutine RenameFailed(); - safe_void_coroutine ShowTerminalWorkingDirectory(); + void ShowTerminalWorkingDirectory(); safe_void_coroutine ProcessStartupActions(Windows::Foundation::Collections::IVector actions, const bool initial, @@ -174,8 +161,8 @@ namespace winrt::TerminalApp::implementation bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down); - safe_void_coroutine AttachContent(Windows::Foundation::Collections::IVector args, uint32_t tabIndex); - safe_void_coroutine SendContentToOther(winrt::TerminalApp::RequestReceiveContentArgs args); + void AttachContent(Windows::Foundation::Collections::IVector args, uint32_t tabIndex); + void SendContentToOther(winrt::TerminalApp::RequestReceiveContentArgs args); uint32_t NumberOfTabs() const; @@ -197,7 +184,6 @@ namespace winrt::TerminalApp::implementation til::typed_event SummonWindowRequested; til::typed_event WindowSizeChanged; - til::typed_event CloseRequested; til::typed_event OpenSystemMenu; til::typed_event QuitRequested; til::typed_event ShowWindowChanged; @@ -244,6 +230,7 @@ namespace winrt::TerminalApp::implementation bool _isFullscreen{ false }; bool _isMaximized{ false }; bool _isAlwaysOnTop{ false }; + bool _showTabsFullscreen{ false }; std::optional _loadFromPersistedLayoutIdx{}; @@ -275,7 +262,6 @@ namespace winrt::TerminalApp::implementation std::shared_ptr _windowIdToast{ nullptr }; std::shared_ptr _actionSavedToast{ nullptr }; std::shared_ptr _actionSaveFailedToast{ nullptr }; - std::shared_ptr _windowRenameFailedToast{ nullptr }; std::shared_ptr _windowCwdToast{ nullptr }; winrt::Windows::UI::Xaml::Controls::TextBox::LayoutUpdated_revoker _renamerLayoutUpdatedRevoker; @@ -496,12 +482,6 @@ namespace winrt::TerminalApp::implementation void _TryMoveTab(const uint32_t currentTabIndex, const int32_t suggestedNewTabIndex); - bool _shouldMouseVanish{ false }; - bool _isMouseHidden{ false }; - Windows::UI::Core::CoreCursor _defaultPointerCursor{ nullptr }; - void _HidePointerCursorHandler(const IInspectable& sender, const IInspectable& eventArgs); - void _RestorePointerCursorHandler(const IInspectable& sender, const IInspectable& eventArgs); - void _PreviewAction(const Microsoft::Terminal::Settings::Model::ActionAndArgs& args); void _PreviewActionHandler(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::Command& args); void _EndPreview(); @@ -549,12 +529,12 @@ namespace winrt::TerminalApp::implementation Windows::Foundation::IAsyncOperation> _FindPackageAsync(hstring query); void _WindowSizeChanged(const IInspectable sender, const winrt::Microsoft::Terminal::Control::WindowSizeChangedEventArgs args); - safe_void_coroutine _windowPropertyChanged(const IInspectable& sender, const winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs& args); + void _windowPropertyChanged(const IInspectable& sender, const winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs& args); void _onTabDragStarting(const winrt::Microsoft::UI::Xaml::Controls::TabView& sender, const winrt::Microsoft::UI::Xaml::Controls::TabViewTabDragStartingEventArgs& e); void _onTabStripDragOver(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::DragEventArgs& e); - safe_void_coroutine _onTabStripDrop(winrt::Windows::Foundation::IInspectable sender, winrt::Windows::UI::Xaml::DragEventArgs e); - safe_void_coroutine _onTabDroppedOutside(winrt::Windows::Foundation::IInspectable sender, winrt::Microsoft::UI::Xaml::Controls::TabViewTabDroppedOutsideEventArgs e); + void _onTabStripDrop(winrt::Windows::Foundation::IInspectable sender, winrt::Windows::UI::Xaml::DragEventArgs e); + void _onTabDroppedOutside(winrt::Windows::Foundation::IInspectable sender, winrt::Microsoft::UI::Xaml::Controls::TabViewTabDroppedOutsideEventArgs e); void _DetachPaneFromWindow(std::shared_ptr pane); void _DetachTabFromWindow(const winrt::com_ptr& terminalTab); @@ -590,5 +570,4 @@ namespace winrt::TerminalApp::implementation namespace winrt::TerminalApp::factory_implementation { BASIC_FACTORY(TerminalPage); - BASIC_FACTORY(RequestReceiveContentArgs); } diff --git a/src/cascadia/TerminalApp/TerminalPage.idl b/src/cascadia/TerminalApp/TerminalPage.idl index 56d30eb3d6..2788cedd10 100644 --- a/src/cascadia/TerminalApp/TerminalPage.idl +++ b/src/cascadia/TerminalApp/TerminalPage.idl @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. import "TaskbarState.idl"; +import "Remoting.idl"; namespace TerminalApp { @@ -25,13 +26,6 @@ namespace TerminalApp UInt32 TabIndex { get; }; Windows.Foundation.IReference WindowPosition { get; }; }; - [default_interface] runtimeclass RequestReceiveContentArgs { - RequestReceiveContentArgs(UInt64 src, UInt64 tgt, UInt32 tabIndex); - - UInt64 SourceWindow { get; }; - UInt64 TargetWindow { get; }; - UInt32 TabIndex { get; }; - }; interface IDialogPresenter { @@ -70,7 +64,6 @@ namespace TerminalApp WindowProperties WindowProperties { get; }; void IdentifyWindow(); - void RenameFailed(); String SavedActionName { get; }; String SavedActionKeyChord { get; }; @@ -102,7 +95,6 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler SummonWindowRequested; event Windows.Foundation.TypedEventHandler WindowSizeChanged; - event Windows.Foundation.TypedEventHandler CloseRequested; event Windows.Foundation.TypedEventHandler OpenSystemMenu; event Windows.Foundation.TypedEventHandler ShowWindowChanged; diff --git a/src/cascadia/TerminalApp/TerminalPage.xaml b/src/cascadia/TerminalApp/TerminalPage.xaml index ce6fc57607..2feb9cd33a 100644 --- a/src/cascadia/TerminalApp/TerminalPage.xaml +++ b/src/cascadia/TerminalApp/TerminalPage.xaml @@ -180,11 +180,6 @@ IsLightDismissEnabled="True" Subtitle="{x:Bind WindowProperties.WindowNameForDisplay, Mode=OneWay}" /> - - +#include #include "TerminalWindow.g.cpp" #include "SettingsLoadEventArgs.g.cpp" @@ -169,9 +169,9 @@ namespace winrt::TerminalApp::implementation } _root->SetStartupActions(actions); } - else + else if (_appArgs) { - _root->SetStartupActions(_appArgs.GetStartupActions()); + _root->SetStartupActions(_appArgs->ParsedArgs().GetStartupActions()); } } @@ -181,7 +181,7 @@ namespace winrt::TerminalApp::implementation // to register a handler to hear about the requests first and is all ready to receive // them before the COM server registers itself. Otherwise, the request might come // in and be routed to an event with no handlers or a non-ready Page. - if (_appArgs.IsHandoffListener()) + if (_appArgs && _appArgs->ParsedArgs().IsHandoffListener()) { _root->SetInboundListener(true); } @@ -219,6 +219,7 @@ namespace winrt::TerminalApp::implementation _root->Loaded({ get_weak(), &TerminalWindow::_OnLoaded }); _root->Initialized({ get_weak(), &TerminalWindow::_pageInitialized }); _root->WindowSizeChanged({ get_weak(), &TerminalWindow::_WindowSizeChanged }); + _root->RenameWindowRequested({ get_weak(), &TerminalWindow::_RenameWindowRequested }); _root->Create(); AppLogic::Current()->SettingsChanged({ get_weak(), &TerminalWindow::UpdateSettingsHandler }); @@ -288,6 +289,11 @@ namespace winrt::TerminalApp::implementation return _settings.GlobalSettings().AlwaysOnTop(); } + bool TerminalWindow::GetInitialShowTabsFullscreen() + { + return _settings.GlobalSettings().ShowTabsFullscreen(); + } + bool TerminalWindow::GetMinimizeToNotificationArea() { return _settings.GlobalSettings().MinimizeToNotificationArea(); @@ -569,7 +575,7 @@ namespace winrt::TerminalApp::implementation // --focusMode on the commandline here, and the mode in the settings. // Below, we'll also account for if focus mode was persisted into the // session for restoration. - bool focusMode = _appArgs.GetLaunchMode().value_or(_settings.GlobalSettings().LaunchMode()) == LaunchMode::FocusMode; + bool focusMode = _appArgs && _appArgs->ParsedArgs().GetLaunchMode().value_or(_settings.GlobalSettings().LaunchMode()) == LaunchMode::FocusMode; const auto scale = static_cast(dpi) / static_cast(USER_DEFAULT_SCREEN_DPI); if (const auto layout = LoadPersistedLayout()) @@ -589,13 +595,13 @@ namespace winrt::TerminalApp::implementation } } - if (_appArgs.GetSize().has_value() || (proposedSize.Width == 0 && proposedSize.Height == 0)) + if ((_appArgs && _appArgs->ParsedArgs().GetSize().has_value()) || (proposedSize.Width == 0 && proposedSize.Height == 0)) { // Use the default profile to determine how big of a window we need. const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, nullptr, nullptr) }; const til::size emptySize{}; - const auto commandlineSize = _appArgs.GetSize().value_or(emptySize); + const auto commandlineSize = _appArgs ? _appArgs->ParsedArgs().GetSize().value_or(emptySize) : til::size{}; proposedSize = TermControl::GetProposedDimensions(settings.DefaultSettings(), dpi, commandlineSize.width, @@ -668,7 +674,7 @@ namespace winrt::TerminalApp::implementation // GH#4620/#5801 - If the user passed --maximized or --fullscreen on the // commandline, then use that to override the value from the settings. const auto valueFromSettings = _settings.GlobalSettings().LaunchMode(); - const auto valueFromCommandlineArgs = _appArgs.GetLaunchMode(); + const auto valueFromCommandlineArgs = _appArgs ? _appArgs->ParsedArgs().GetLaunchMode() : std::nullopt; if (const auto layout = LoadPersistedLayout()) { if (layout.LaunchMode()) @@ -704,9 +710,9 @@ namespace winrt::TerminalApp::implementation } // Commandline args trump everything except for content bounds (tear-out) - if (_appArgs.GetPosition().has_value()) + if (_appArgs && _appArgs->ParsedArgs().GetPosition().has_value()) { - initialPosition = _appArgs.GetPosition().value(); + initialPosition = _appArgs->ParsedArgs().GetPosition().value(); } if (_contentBounds) @@ -715,11 +721,10 @@ namespace winrt::TerminalApp::implementation // that to determine the initial position of the window. This is // used when the user is dragging a tab out of the window, to create // a new window. - // - // contentBounds is in screen pixels, but that's okay! we want to - // return screen pixels out of here. Nailed it. + // BODY: Technically we aren't guaranteed to be within the XAML stack right now to have a "current view". + const auto scale = static_cast(DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel()); const auto bounds = _contentBounds.Value(); - initialPosition = { lroundf(bounds.X), lroundf(bounds.Y) }; + initialPosition = { lroundf(bounds.X * scale), lroundf(bounds.Y * scale) }; } return { initialPosition.X ? initialPosition.X.Value() : defaultInitialX, @@ -743,7 +748,7 @@ namespace winrt::TerminalApp::implementation return !_contentBounds && !hadPersistedPosition && _settings.GlobalSettings().CenterOnLaunch() && - !_appArgs.GetPosition().has_value(); + (_appArgs && !_appArgs->ParsedArgs().GetPosition().has_value()); } // Method Description: @@ -767,51 +772,36 @@ namespace winrt::TerminalApp::implementation // This may be called on a background thread, or the main thread, but almost // definitely not on OUR UI thread. - safe_void_coroutine TerminalWindow::UpdateSettings(winrt::TerminalApp::SettingsLoadEventArgs args) + void TerminalWindow::UpdateSettings(winrt::TerminalApp::SettingsLoadEventArgs args) { - // GH#17620: We have a bug somewhere where a window doesn't get unregistered from the window list. - // This causes UpdateSettings calls where the thread dispatcher is already null. - const auto dispatcher = _root->Dispatcher(); - if (!dispatcher) + _settings = args.NewSettings(); + + // Update the settings in TerminalPage + // We're on our UI thread right now, so this is safe + _root->SetSettings(_settings, true); + + // Bubble the notification up to the AppHost, now that we've updated our _settings. + SettingsChanged.raise(*this, args); + + if (FAILED(args.Result())) { - co_return; + const winrt::hstring titleKey = USES_RESOURCE(L"ReloadJsonParseErrorTitle"); + const winrt::hstring textKey = USES_RESOURCE(L"ReloadJsonParseErrorText"); + _ShowLoadErrorsDialog(titleKey, + textKey, + gsl::narrow_cast(args.Result()), + args.ExceptionText()); + return; } - - const auto weakThis{ get_weak() }; - co_await wil::resume_foreground(dispatcher); - - // Back on our UI thread... - if (auto logic{ weakThis.get() }) + else if (args.Result() == S_FALSE) { - _settings = args.NewSettings(); - - // Update the settings in TerminalPage - // We're on our UI thread right now, so this is safe - _root->SetSettings(_settings, true); - - // Bubble the notification up to the AppHost, now that we've updated our _settings. - SettingsChanged.raise(*this, args); - - if (FAILED(args.Result())) - { - const winrt::hstring titleKey = USES_RESOURCE(L"ReloadJsonParseErrorTitle"); - const winrt::hstring textKey = USES_RESOURCE(L"ReloadJsonParseErrorText"); - _ShowLoadErrorsDialog(titleKey, - textKey, - gsl::narrow_cast(args.Result()), - args.ExceptionText()); - co_return; - } - else if (args.Result() == S_FALSE) - { - _ShowLoadWarningsDialog(args.Warnings()); - } - else if (args.Result() == S_OK) - { - DismissDialog(); - } - _RefreshThemeRoutine(); + _ShowLoadWarningsDialog(args.Warnings()); } + else if (args.Result() == S_OK) + { + DismissDialog(); + } + _RefreshThemeRoutine(); } void TerminalWindow::_OpenSettingsUI() @@ -973,19 +963,6 @@ namespace winrt::TerminalApp::implementation } } - // Method Description: - // - Returns true if we should exit the application before even starting the - // window. We might want to do this if we're displaying an error message or - // the version string, or if we want to open the settings file. - // Arguments: - // - - // Return Value: - // - true iff we should exit the application before even starting the window - bool TerminalWindow::ShouldExitEarly() - { - return _appArgs.ShouldExitEarly(); - } - bool TerminalWindow::FocusMode() const { return _root ? _root->FocusMode() : false; @@ -1009,6 +986,11 @@ namespace winrt::TerminalApp::implementation return _root ? _root->AlwaysOnTop() : false; } + bool TerminalWindow::ShowTabsFullscreen() const + { + return _root ? _root->ShowTabsFullscreen() : false; + } + void TerminalWindow::SetSettingsStartupArgs(const std::vector& actions) { for (const auto& action : actions) @@ -1038,34 +1020,33 @@ namespace winrt::TerminalApp::implementation // Return Value: // - the result of the first command who's parsing returned a non-zero code, // or 0. (see TerminalWindow::_ParseArgs) - int32_t TerminalWindow::SetStartupCommandline(array_view args, - winrt::hstring cwd, - winrt::hstring env) + int32_t TerminalWindow::SetStartupCommandline(TerminalApp::CommandlineArgs args) { - _WindowProperties->SetInitialCwd(std::move(cwd)); - _WindowProperties->VirtualEnvVars(std::move(env)); + _appArgs = winrt::get_self(args); + auto& parsedArgs = _appArgs->ParsedArgs(); + + _WindowProperties->SetInitialCwd(_appArgs->CurrentDirectory()); + _WindowProperties->VirtualEnvVars(_appArgs->CurrentEnvironment()); // This is called in AppHost::ctor(), before we've created the window // (or called TerminalWindow::Initialize) - const auto result = _appArgs.ParseArgs(args); - if (result == 0) + if (_appArgs->ExitCode() == 0) { // If the size of the arguments list is 1, // then it contains only the executable name and no other arguments. - _hasCommandLineArguments = args.size() > 1; - _appArgs.ValidateStartupCommands(); + _hasCommandLineArguments = _appArgs->CommandlineRef().size() > 1; // DON'T pass the args into the page yet. It doesn't exist yet. // Instead, we'll handle that in Initialize, when we first instantiate the page. } // If we have a -s param passed to us to load a saved layout, cache that now. - if (const auto idx = _appArgs.GetPersistedLayoutIdx()) + if (const auto idx = parsedArgs.GetPersistedLayoutIdx()) { SetPersistedLayoutIdx(idx.value()); } - return result; + return _appArgs->ExitCode(); } void TerminalWindow::SetStartupContent(const winrt::hstring& content, @@ -1097,43 +1078,24 @@ namespace winrt::TerminalApp::implementation // Return Value: // - the result of the first command who's parsing returned a non-zero code, // or 0. (see TerminalWindow::_ParseArgs) - int32_t TerminalWindow::ExecuteCommandline(array_view args, - const winrt::hstring& cwd, - const winrt::hstring& env) + int32_t TerminalWindow::ExecuteCommandline(TerminalApp::CommandlineArgs args) { - ::TerminalApp::AppCommandlineArgs appArgs; - auto result = appArgs.ParseArgs(args); - if (result == 0) + _appArgs = winrt::get_self(args); + + if (_appArgs->ExitCode() == 0) { - auto actions = winrt::single_threaded_vector(std::move(appArgs.GetStartupActions())); + auto& parsedArgs = _appArgs->ParsedArgs(); + auto actions = winrt::single_threaded_vector(std::move(parsedArgs.GetStartupActions())); - _root->ProcessStartupActions(actions, false, cwd, env); + _root->ProcessStartupActions(actions, false, _appArgs->CurrentDirectory(), _appArgs->CurrentEnvironment()); - if (appArgs.IsHandoffListener()) + if (parsedArgs.IsHandoffListener()) { _root->SetInboundListener(true); } } // Return the result of parsing with commandline, though it may or may not be used. - return result; - } - - // Method Description: - // - If there were any errors parsing the commandline that was used to - // initialize the terminal, this will return a string containing that - // message. If there were no errors, this message will be blank. - // - If the user requested help on any command (using --help), this will - // contain the help message. - // - If the user requested the version number (using --version), this will - // contain the version string. - // Arguments: - // - - // Return Value: - // - the help text or error message for the provided commandline, if one - // exists, otherwise the empty string. - winrt::hstring TerminalWindow::ParseCommandlineMessage() - { - return winrt::to_hstring(_appArgs.GetExitMessage()); + return _appArgs->ExitCode(); } void TerminalWindow::SetPersistedLayoutIdx(const uint32_t idx) @@ -1205,14 +1167,6 @@ namespace winrt::TerminalApp::implementation } } - void TerminalWindow::RenameFailed() - { - if (_root) - { - _root->RenameFailed(); - } - } - void TerminalWindow::WindowName(const winrt::hstring& name) { const auto oldIsQuakeMode = _WindowProperties->IsQuakeWindow(); @@ -1368,6 +1322,11 @@ namespace winrt::TerminalApp::implementation WindowSizeChanged.raise(*this, args); } + void TerminalWindow::_RenameWindowRequested(const IInspectable&, const winrt::TerminalApp::RenameWindowRequestedArgs args) + { + WindowName(args.ProposedName()); + } + winrt::hstring WindowProperties::WindowName() const noexcept { return _WindowName; @@ -1428,7 +1387,7 @@ namespace winrt::TerminalApp::implementation bool WindowProperties::IsQuakeWindow() const noexcept { - return _WindowName == QuakeWindowName; + return _WindowName == L"_quake"; } }; diff --git a/src/cascadia/TerminalApp/TerminalWindow.h b/src/cascadia/TerminalApp/TerminalWindow.h index 29eda95158..eef9efaf21 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.h +++ b/src/cascadia/TerminalApp/TerminalWindow.h @@ -7,12 +7,10 @@ #include "SystemMenuChangeArgs.g.h" #include "WindowProperties.g.h" -#include "SettingsLoadEventArgs.h" +#include "Remoting.h" #include "TerminalPage.h" -#include "SettingsLoadEventArgs.h" -#include -#include +#include #ifdef UNIT_TESTING // fwdecl unittest classes @@ -75,16 +73,14 @@ namespace winrt::TerminalApp::implementation void PersistState(); - safe_void_coroutine UpdateSettings(winrt::TerminalApp::SettingsLoadEventArgs args); + void UpdateSettings(winrt::TerminalApp::SettingsLoadEventArgs args); bool HasCommandlineArguments() const noexcept; - int32_t SetStartupCommandline(array_view actions, winrt::hstring cwd, winrt::hstring env); + int32_t SetStartupCommandline(TerminalApp::CommandlineArgs args); void SetStartupContent(const winrt::hstring& content, const Windows::Foundation::IReference& contentBounds); - int32_t ExecuteCommandline(array_view actions, const winrt::hstring& cwd, const winrt::hstring& env); + int32_t ExecuteCommandline(TerminalApp::CommandlineArgs args); void SetSettingsStartupArgs(const std::vector& actions); - winrt::hstring ParseCommandlineMessage(); - bool ShouldExitEarly(); bool ShouldImmediatelyHandoffToElevated(); void HandoffToElevated(); @@ -93,10 +89,9 @@ namespace winrt::TerminalApp::implementation bool Fullscreen() const; void Maximized(bool newMaximized); bool AlwaysOnTop() const; + bool ShowTabsFullscreen() const; bool AutoHideWindow(); - void IdentifyWindow(); - void RenameFailed(); std::optional LoadPersistedLayoutIdx() const; winrt::Microsoft::Terminal::Settings::Model::WindowLayout LoadPersistedLayout(); @@ -112,6 +107,7 @@ namespace winrt::TerminalApp::implementation Microsoft::Terminal::Settings::Model::LaunchMode GetLaunchMode(); bool GetShowTabsInTitlebar(); bool GetInitialAlwaysOnTop(); + bool GetInitialShowTabsFullscreen(); float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const; Windows::UI::Xaml::UIElement GetRoot() noexcept; @@ -174,8 +170,8 @@ namespace winrt::TerminalApp::implementation winrt::Windows::UI::Xaml::Controls::ContentDialog _dialog{ nullptr }; std::shared_mutex _dialogLock; + wil::com_ptr _appArgs{ nullptr }; bool _hasCommandLineArguments{ false }; - ::TerminalApp::AppCommandlineArgs _appArgs; bool _gotSettingsStartupActions{ false }; std::vector _settingsStartupArgs{}; Windows::Foundation::IReference _contentBounds{ nullptr }; @@ -204,6 +200,7 @@ namespace winrt::TerminalApp::implementation void _pageInitialized(const IInspectable& sender, const IInspectable& eventArgs); void _OpenSettingsUI(); void _WindowSizeChanged(const IInspectable& sender, winrt::Microsoft::Terminal::Control::WindowSizeChangedEventArgs args); + void _RenameWindowRequested(const IInspectable& sender, const winrt::TerminalApp::RenameWindowRequestedArgs args); winrt::Windows::Foundation::Collections::IVector _contentStringToActions(const winrt::hstring& content, const bool replaceFirstWithNewTab); @@ -223,9 +220,7 @@ namespace winrt::TerminalApp::implementation FORWARDED_TYPED_EVENT(RaiseVisualBell, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, RaiseVisualBell); FORWARDED_TYPED_EVENT(SetTaskbarProgress, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, SetTaskbarProgress); FORWARDED_TYPED_EVENT(IdentifyWindowsRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IdentifyWindowsRequested); - FORWARDED_TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs, _root, RenameWindowRequested); FORWARDED_TYPED_EVENT(SummonWindowRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, SummonWindowRequested); - FORWARDED_TYPED_EVENT(CloseRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, CloseRequested); FORWARDED_TYPED_EVENT(OpenSystemMenu, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, OpenSystemMenu); FORWARDED_TYPED_EVENT(QuitRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, QuitRequested); FORWARDED_TYPED_EVENT(ShowWindowChanged, Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Control::ShowWindowArgs, _root, ShowWindowChanged); diff --git a/src/cascadia/TerminalApp/TerminalWindow.idl b/src/cascadia/TerminalApp/TerminalWindow.idl index 8b1bca78f9..a8fa0c97c5 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.idl +++ b/src/cascadia/TerminalApp/TerminalWindow.idl @@ -52,11 +52,9 @@ namespace TerminalApp Boolean HasCommandlineArguments(); - Int32 SetStartupCommandline(String[] commands, String cwd, String env); + Int32 SetStartupCommandline(CommandlineArgs args); void SetStartupContent(String json, Windows.Foundation.IReference bounds); - Int32 ExecuteCommandline(String[] commands, String cwd, String env); - String ParseCommandlineMessage { get; }; - Boolean ShouldExitEarly { get; }; + Int32 ExecuteCommandline(CommandlineArgs args); Boolean ShouldImmediatelyHandoffToElevated(); void HandoffToElevated(); @@ -71,11 +69,10 @@ namespace TerminalApp void Maximized(Boolean newMaximized); Boolean AlwaysOnTop { get; }; Boolean AutoHideWindow { get; }; + Boolean ShowTabsFullscreen { get; }; void IdentifyWindow(); void SetPersistedLayoutIdx(UInt32 idx); - - void RenameFailed(); void RequestExitFullscreen(); Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi); @@ -86,6 +83,7 @@ namespace TerminalApp Microsoft.Terminal.Settings.Model.LaunchMode GetLaunchMode(); Boolean GetShowTabsInTitlebar(); Boolean GetInitialAlwaysOnTop(); + Boolean GetInitialShowTabsFullscreen(); Single CalcSnappedDimension(Boolean widthOrHeight, Single dimension); void TitlebarClicked(); void CloseWindow(); @@ -124,10 +122,8 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler RaiseVisualBell; event Windows.Foundation.TypedEventHandler SetTaskbarProgress; event Windows.Foundation.TypedEventHandler IdentifyWindowsRequested; - event Windows.Foundation.TypedEventHandler RenameWindowRequested; event Windows.Foundation.TypedEventHandler IsQuakeWindowChanged; event Windows.Foundation.TypedEventHandler SummonWindowRequested; - event Windows.Foundation.TypedEventHandler CloseRequested; event Windows.Foundation.TypedEventHandler OpenSystemMenu; event Windows.Foundation.TypedEventHandler QuitRequested; event Windows.Foundation.TypedEventHandler SystemMenuChangeRequested; diff --git a/src/cascadia/TerminalApp/TitlebarControl.cpp b/src/cascadia/TerminalApp/TitlebarControl.cpp index 1debd03054..1ed82f39ca 100644 --- a/src/cascadia/TerminalApp/TitlebarControl.cpp +++ b/src/cascadia/TerminalApp/TitlebarControl.cpp @@ -12,6 +12,8 @@ #include "TitlebarControl.g.cpp" +using namespace winrt::Windows::UI::Xaml; + namespace winrt::TerminalApp::implementation { TitlebarControl::TitlebarControl(uint64_t handle) : @@ -77,6 +79,11 @@ namespace winrt::TerminalApp::implementation } } + void TitlebarControl::FullscreenChanged(const bool fullscreen) + { + MinMaxCloseControl().Visibility(fullscreen ? Visibility::Collapsed : Visibility::Visible); + } + void TitlebarControl::_OnMaximizeOrRestore(byte flag) { POINT point1 = {}; diff --git a/src/cascadia/TerminalApp/TitlebarControl.h b/src/cascadia/TerminalApp/TitlebarControl.h index 8020ff9095..1008253ba8 100644 --- a/src/cascadia/TerminalApp/TitlebarControl.h +++ b/src/cascadia/TerminalApp/TitlebarControl.h @@ -22,6 +22,7 @@ namespace winrt::TerminalApp::implementation void SetWindowVisualState(WindowVisualState visualState); void Root_SizeChanged(const IInspectable& sender, const Windows::UI::Xaml::SizeChangedEventArgs& e); + void FullscreenChanged(const bool fullscreen); void Minimize_Click(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e); void Maximize_Click(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e); diff --git a/src/cascadia/TerminalApp/TitlebarControl.idl b/src/cascadia/TerminalApp/TitlebarControl.idl index b7a06ba987..8f934fae95 100644 --- a/src/cascadia/TerminalApp/TitlebarControl.idl +++ b/src/cascadia/TerminalApp/TitlebarControl.idl @@ -22,6 +22,7 @@ namespace TerminalApp { TitlebarControl(UInt64 parentWindowHandle); void SetWindowVisualState(WindowVisualState visualState); + void FullscreenChanged(Boolean fullscreen); void HoverButton(CaptionButton button); void PressButton(CaptionButton button); diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index b46da5236a..72a8e85ad5 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1200,7 +1200,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto bufferSize{ _terminal->GetTextBuffer().GetSize() }; info.StartAtLeftBoundary = _terminal->GetSelectionAnchor().x == bufferSize.Left(); - info.EndAtRightBoundary = _terminal->GetSelectionEnd().x == bufferSize.RightInclusive(); + info.EndAtRightBoundary = _terminal->GetSelectionEnd().x == bufferSize.RightExclusive(); return info; } @@ -1217,8 +1217,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation return; } + // clamp the converted position to be within the viewport bounds + // x: allow range of [0, RightExclusive] + // GH #18106: right exclusive needed for selection to support exclusive end til::point terminalPosition{ - std::clamp(position.x, 0, _terminal->GetViewport().Width() - 1), + std::clamp(position.x, 0, _terminal->GetViewport().Width()), std::clamp(position.y, 0, _terminal->GetViewport().Height() - 1) }; @@ -2722,7 +2725,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation bufferSize.DecrementInBounds(inclusiveEnd); _terminal->SelectNewRegion(s.start, inclusiveEnd); - _renderer->TriggerSelection(); } void ControlCore::SelectCommand(const bool goUp) diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 1da3b89ab1..0fd2840a58 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -241,7 +241,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const Core::Point pixelPosition) { - const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }); + // Un-rounded coordinates; we only round when selecting text + const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }, false); const auto altEnabled = modifiers.IsAltPressed(); const auto shiftEnabled = modifiers.IsShiftPressed(); @@ -285,7 +286,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation } const auto isOnOriginalPosition = _lastMouseClickPosNoSelection == pixelPosition; - _core->LeftClickOnTerminal(terminalPosition, + // Rounded coordinates for text selection + _core->LeftClickOnTerminal(_getTerminalPosition(til::point{ pixelPosition }, true), multiClickMapper, altEnabled, shiftEnabled, @@ -338,7 +340,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const Core::Point pixelPosition, const bool pointerPressedInBounds) { - const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }); + const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }, true); // Returning true from this function indicates that the caller should do no further processing of this movement. bool handledCompletely = false; @@ -372,7 +374,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation // _touchdown_ point here. We want to start the selection // from where the user initially clicked, not where they are // now. - _core->SetSelectionAnchor(_getTerminalPosition(til::point{ touchdownPoint })); + auto termPos = _getTerminalPosition(til::point{ touchdownPoint }, false); + if (dx < 0) + { + // _getTerminalPosition(_, false) will floor the x-value, + // meaning that the selection will start on the left-side + // of the current cell. This is great if the use is dragging + // towards the right. + // If the user is dragging towards the left (dx < 0), + // we want to select the current cell, so place the anchor on the right + // side of the current cell. + termPos.x++; + } + _core->SetSelectionAnchor(termPos); // stop tracking the touchdown point _singleClickTouchdownPos = std::nullopt; @@ -428,7 +442,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const Core::Point pixelPosition) { - const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }); + const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }, false); // Short-circuit isReadOnly check to avoid warning dialog if (!_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers)) { @@ -475,7 +489,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const Core::Point pixelPosition, const Control::MouseButtonState buttonState) { - const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }); + const auto terminalPosition = _getTerminalPosition(til::point{ pixelPosition }, true); // Short-circuit isReadOnly check to avoid warning dialog. // @@ -662,7 +676,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - cursorPosition: in pixels, relative to the origin of the control void ControlInteractivity::SetEndSelectionPoint(const Core::Point pixelPosition) { - _core->SetEndSelectionPoint(_getTerminalPosition(til::point{ pixelPosition })); + _core->SetEndSelectionPoint(_getTerminalPosition(til::point{ pixelPosition }, true)); _selectionNeedsToBeCopied = true; } @@ -672,12 +686,22 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Arguments: // - pixelPosition: the (x,y) position of a given point (i.e.: mouse cursor). // NOTE: origin (0,0) is top-left. + // - roundToNearestCell: if true, round the x-value. Otherwise, floor it (standard int division) // Return Value: // - the corresponding viewport terminal position for the given Point parameter - til::point ControlInteractivity::_getTerminalPosition(const til::point pixelPosition) + til::point ControlInteractivity::_getTerminalPosition(const til::point pixelPosition, bool roundToNearestCell) { // Get the size of the font, which is in pixels - const til::size fontSize{ _core->GetFont().GetSize() }; + const auto fontSize{ _core->GetFont().GetSize() }; + + if (roundToNearestCell) + { + // GH#5099: round the x-value to the nearest cell + til::point result; + result.x = gsl::narrow_cast(std::round(gsl::narrow_cast(pixelPosition.x) / fontSize.width)); + result.y = pixelPosition.y / fontSize.height; + return result; + } // Convert the location in pixels to characters within the current viewport. return pixelPosition / fontSize; } diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 18d55b53cf..dcf2c811d0 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -155,7 +155,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool _canSendVTMouseInput(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers); bool _shouldSendAlternateScroll(const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta); - til::point _getTerminalPosition(const til::point pixelPosition); + til::point _getTerminalPosition(const til::point pixelPosition, bool roundToNearestCell); bool _sendMouseEventHelper(const til::point terminalPosition, const unsigned int pointerUpdateKind, diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 9540c53196..a20b5f9d4c 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -5,6 +5,7 @@ #include "TermControl.h" #include +#include #include "TermControlAutomationPeer.h" #include "../../renderer/atlas/AtlasEngine.h" @@ -46,13 +47,44 @@ constexpr std::wstring_view StateCollapsed{ L"Collapsed" }; DEFINE_ENUM_FLAG_OPERATORS(winrt::Microsoft::Terminal::Control::CopyFormat); DEFINE_ENUM_FLAG_OPERATORS(winrt::Microsoft::Terminal::Control::MouseButtonState); +// InputPane::GetForCurrentView() does not reliably work for XAML islands, +// as it assumes that there's a 1:1 relationship between windows and threads. +// +// During testing, I found that the input pane shows up when touching into the terminal even if +// TryShow is never called. This surprised me, but I figured it's worth trying it without this. +static void setInputPaneVisibility(HWND hwnd, bool visible) +{ + static const auto inputPaneInterop = []() { + return winrt::try_get_activation_factory(); + }(); + + if (!inputPaneInterop) + { + return; + } + + winrt::com_ptr inputPane; + if (FAILED(inputPaneInterop->GetForWindow(hwnd, winrt::guid_of(), inputPane.put_void()))) + { + return; + } + + bool result; + if (visible) + { + std::ignore = inputPane->TryShow(&result); + } + else + { + std::ignore = inputPane->TryHide(&result); + } +} + static Microsoft::Console::TSF::Handle& GetTSFHandle() { - // https://en.cppreference.com/w/cpp/language/storage_duration - // > Variables declared at block scope with the specifier static or thread_local - // > [...] are initialized the first time control passes through their declaration - // --> Lazy, per-(window-)thread initialization of the TSF handle - thread_local auto s_tsf = ::Microsoft::Console::TSF::Handle::Create(); + // NOTE: If we ever go back to 1 thread per 1 window, + // you need to swap the `static` with a `thread_local`. + static auto s_tsf = ::Microsoft::Console::TSF::Handle::Create(); return s_tsf; } @@ -156,22 +188,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation RECT TsfDataProvider::GetViewport() { - const auto scaleFactor = static_cast(DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel()); - const auto globalOrigin = CoreWindow::GetForCurrentThread().Bounds(); - const auto localOrigin = _termControl->TransformToVisual(nullptr).TransformPoint({}); - const auto size = _termControl->ActualSize(); - - const auto left = globalOrigin.X + localOrigin.X; - const auto top = globalOrigin.Y + localOrigin.Y; - const auto right = left + size.x; - const auto bottom = top + size.y; - - return { - lroundf(left * scaleFactor), - lroundf(top * scaleFactor), - lroundf(right * scaleFactor), - lroundf(bottom * scaleFactor), - }; + const auto hwnd = reinterpret_cast(_termControl->OwningHwnd()); + RECT clientRect; + GetWindowRect(hwnd, &clientRect); + return clientRect; } RECT TsfDataProvider::GetCursorPosition() @@ -182,16 +202,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation return {}; } + const auto hwnd = reinterpret_cast(_termControl->OwningHwnd()); + RECT clientRect; + GetWindowRect(hwnd, &clientRect); + const auto scaleFactor = static_cast(DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel()); - const auto globalOrigin = CoreWindow::GetForCurrentThread().Bounds(); const auto localOrigin = _termControl->TransformToVisual(nullptr).TransformPoint({}); const auto padding = _termControl->GetPadding(); const auto cursorPosition = core->CursorPosition(); const auto fontSize = core->FontSize(); // fontSize is not in DIPs, so we need to first multiply by scaleFactor and then do the rest. - const auto left = (globalOrigin.X + localOrigin.X + static_cast(padding.Left)) * scaleFactor + cursorPosition.X * fontSize.Width; - const auto top = (globalOrigin.Y + localOrigin.Y + static_cast(padding.Top)) * scaleFactor + cursorPosition.Y * fontSize.Height; + const auto left = clientRect.left + (localOrigin.X + static_cast(padding.Left)) * scaleFactor + cursorPosition.X * fontSize.Width; + const auto top = clientRect.top + (localOrigin.Y + static_cast(padding.Top)) * scaleFactor + cursorPosition.Y * fontSize.Height; const auto right = left + fontSize.Width; const auto bottom = top + fontSize.Height; @@ -768,40 +791,22 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Given Settings having been updated, applies the settings to the current terminal. // Return Value: // - - safe_void_coroutine TermControl::UpdateControlSettings(IControlSettings settings, - IControlAppearance unfocusedAppearance) + void TermControl::UpdateControlSettings(IControlSettings settings, IControlAppearance unfocusedAppearance) { - auto weakThis{ get_weak() }; + _core.UpdateSettings(settings, unfocusedAppearance); - // Dispatch a call to the UI thread to apply the new settings to the - // terminal. - co_await wil::resume_foreground(Dispatcher()); + _UpdateSettingsFromUIThread(); - if (auto strongThis{ weakThis.get() }) - { - _core.UpdateSettings(settings, unfocusedAppearance); - - _UpdateSettingsFromUIThread(); - - _UpdateAppearanceFromUIThread(_focused ? _core.FocusedAppearance() : _core.UnfocusedAppearance()); - } + _UpdateAppearanceFromUIThread(_focused ? _core.FocusedAppearance() : _core.UnfocusedAppearance()); } // Method Description: // - Dispatches a call to the UI thread and updates the appearance // Arguments: // - newAppearance: the new appearance to set - safe_void_coroutine TermControl::UpdateAppearance(IControlAppearance newAppearance) + void TermControl::UpdateAppearance(IControlAppearance newAppearance) { - auto weakThis{ get_weak() }; - - // Dispatch a call to the UI thread - co_await wil::resume_foreground(Dispatcher()); - - if (auto strongThis{ weakThis.get() }) - { - _UpdateAppearanceFromUIThread(newAppearance); - } + _UpdateAppearanceFromUIThread(newAppearance); } // Method Description: @@ -902,7 +907,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation auto settings{ _core.Settings() }; // Apply padding as swapChainPanel's margin - const auto newMargin = ParseThicknessFromPadding(settings.Padding()); + const auto newMargin = StringToXamlThickness(settings.Padding()); SwapChainPanel().Margin(newMargin); // Apply settings for scrollbar @@ -1486,8 +1491,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation return; } - HidePointerCursor.raise(*this, nullptr); - const auto ch = e.Character(); const auto keyStatus = e.KeyStatus(); const auto scanCode = gsl::narrow_cast(keyStatus.ScanCode); @@ -1895,8 +1898,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown) { - const auto window = CoreWindow::GetForCurrentThread(); - // If the terminal translated the key, mark the event as handled. // This will prevent the system from trying to get the character out // of it and sending us a CharacterReceived event. @@ -1931,6 +1932,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation void TermControl::_TappedHandler(const IInspectable& /*sender*/, const TappedRoutedEventArgs& e) { Focus(FocusState::Pointer); + + if (e.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Touch) + { + // Normally TSF would be responsible for showing the touch keyboard, but it's buggy for us: + // If you have focus on a TermControl and type on your physical keyboard then touching + // the TermControl will not show the touch keyboard ever again unless you focus another app. + // Why that happens is unclear, but it can be fixed by us showing it manually. + setInputPaneVisibility(reinterpret_cast(OwningHwnd()), true); + } + e.Handled(true); } @@ -1955,12 +1966,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation const auto point = args.GetCurrentPoint(*this); const auto type = ptr.PointerDeviceType(); - // We also TryShow in GotFocusHandler, but this call is specifically - // for the case where the Terminal is in focus but the user closed the - // on-screen keyboard. This lets the user simply tap on the terminal - // again to bring it up. - InputPane::GetForCurrentView().TryShow(); - if (!_focused) { Focus(FocusState::Pointer); @@ -2182,10 +2187,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - // Return Value: // - - safe_void_coroutine TermControl::_coreTransparencyChanged(IInspectable /*sender*/, - Control::TransparencyChangedEventArgs /*args*/) + void TermControl::_coreTransparencyChanged(IInspectable /*sender*/, Control::TransparencyChangedEventArgs /*args*/) { - co_await wil::resume_foreground(Dispatcher()); try { _changeBackgroundOpacity(); @@ -2363,8 +2366,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _focused = true; - InputPane::GetForCurrentView().TryShow(); - // GH#5421: Enable the UiaEngine before checking for the SearchBox // That way, new selections are notified to automation clients. // The _uiaEngine lives in _interactivity, so call into there to enable it. @@ -2858,7 +2859,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation } float height = rows * static_cast(actualFontSize.height); - const auto thickness = ParseThicknessFromPadding(padding); + const auto thickness = StringToXamlThickness(padding); // GH#2061 - make sure to account for the size the padding _will be_ scaled to width += scale * static_cast(thickness.Left + thickness.Right); height += scale * static_cast(thickness.Top + thickness.Bottom); @@ -2894,7 +2895,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation width += scrollbarSize; } - const auto thickness = ParseThicknessFromPadding(padding); + const auto thickness = StringToXamlThickness(padding); // GH#2061 - make sure to account for the size the padding _will be_ scaled to width += scale * static_cast(thickness.Left + thickness.Right); height += scale * static_cast(thickness.Top + thickness.Bottom); @@ -2993,63 +2994,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation _core.WindowVisibilityChanged(showOrHide); } - // Method Description: - // - Create XAML Thickness object based on padding props provided. - // Used for controlling the TermControl XAML Grid container's Padding prop. - // Arguments: - // - padding: 2D padding values - // Single Double value provides uniform padding - // Two Double values provide isometric horizontal & vertical padding - // Four Double values provide independent padding for 4 sides of the bounding rectangle - // Return Value: - // - Windows::UI::Xaml::Thickness object - Windows::UI::Xaml::Thickness TermControl::ParseThicknessFromPadding(const hstring padding) - { - const auto singleCharDelim = L','; - std::wstringstream tokenStream(padding.c_str()); - std::wstring token; - uint8_t paddingPropIndex = 0; - std::array thicknessArr = {}; - size_t* idx = nullptr; - - // Get padding values till we run out of delimiter separated values in the stream - // or we hit max number of allowable values (= 4) for the bounding rectangle - // Non-numeral values detected will default to 0 - // std::getline will not throw exception unless flags are set on the wstringstream - // std::stod will throw invalid_argument exception if the input is an invalid double value - // std::stod will throw out_of_range exception if the input value is more than DBL_MAX - try - { - for (; std::getline(tokenStream, token, singleCharDelim) && (paddingPropIndex < thicknessArr.size()); paddingPropIndex++) - { - // std::stod internally calls wcstod which handles whitespace prefix (which is ignored) - // & stops the scan when first char outside the range of radix is encountered - // We'll be permissive till the extent that stod function allows us to be by default - // Ex. a value like 100.3#535w2 will be read as 100.3, but ;df25 will fail - thicknessArr[paddingPropIndex] = std::stod(token, idx); - } - } - catch (...) - { - // If something goes wrong, even if due to a single bad padding value, we'll reset the index & return default 0 padding - paddingPropIndex = 0; - LOG_CAUGHT_EXCEPTION(); - } - - switch (paddingPropIndex) - { - case 1: - return ThicknessHelper::FromUniformLength(thicknessArr[0]); - case 2: - return ThicknessHelper::FromLengths(thicknessArr[0], thicknessArr[1], thicknessArr[0], thicknessArr[1]); - // No case for paddingPropIndex = 3, since it's not a norm to provide just Left, Top & Right padding values leaving out Bottom - case 4: - return ThicknessHelper::FromLengths(thicknessArr[0], thicknessArr[1], thicknessArr[2], thicknessArr[3]); - default: - return Thickness(); - } - } - // Method Description: // - Get the modifier keys that are currently pressed. This can be used to // find out which modifiers (ctrl, alt, shift) are pressed in events that @@ -3995,14 +3939,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation void TermControl::_contextMenuHandler(IInspectable /*sender*/, Control::ContextMenuRequestedEventArgs args) { - // Position the menu where the pointer is. This was the best way I found how. - const auto absolutePointerPos = CoreWindow::GetForCurrentThread().PointerPosition(); - const auto absoluteWindowOrigin = CoreWindow::GetForCurrentThread().Bounds(); - // Get the offset (margin + tabs, etc..) of the control within the window - const auto controlOrigin = TransformToVisual(nullptr).TransformPoint({}); + const auto inverseScale = 1.0f / static_cast(XamlRoot().RasterizationScale()); + const auto padding = GetPadding(); + const auto pos = args.Position(); _showContextMenuAt({ - absolutePointerPos.X - absoluteWindowOrigin.X - controlOrigin.X, - absolutePointerPos.Y - absoluteWindowOrigin.Y - controlOrigin.Y, + pos.X * inverseScale + static_cast(padding.Left), + pos.Y * inverseScale + static_cast(padding.Top), }); } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 507b08155a..2e8fadd850 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -53,7 +53,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation static Control::TermControl NewControlByAttachingContent(Control::ControlInteractivity content, const Microsoft::Terminal::Control::IKeyBindings& keyBindings); void UpdateControlSettings(Control::IControlSettings settings); - safe_void_coroutine UpdateControlSettings(Control::IControlSettings settings, Control::IControlAppearance unfocusedAppearance); + void UpdateControlSettings(Control::IControlSettings settings, Control::IControlAppearance unfocusedAppearance); IControlSettings Settings() const; uint64_t ContentId() const; @@ -346,7 +346,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void _UpdateAppearanceFromUIThread(Control::IControlAppearance newAppearance); void _ApplyUISettings(); - safe_void_coroutine UpdateAppearance(Control::IControlAppearance newAppearance); + void UpdateAppearance(Control::IControlAppearance newAppearance); void _SetBackgroundImage(const IControlAppearance& newAppearance); void _InitializeBackgroundBrush(); @@ -427,7 +427,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation safe_void_coroutine _updateSelectionMarkers(IInspectable sender, Control::UpdateSelectionMarkersEventArgs args); void _coreFontSizeChanged(const IInspectable& s, const Control::FontSizeChangedArgs& args); - safe_void_coroutine _coreTransparencyChanged(IInspectable sender, Control::TransparencyChangedEventArgs args); + void _coreTransparencyChanged(IInspectable sender, Control::TransparencyChangedEventArgs args); void _coreRaisedNotice(const IInspectable& s, const Control::NoticeEventArgs& args); void _coreWarningBell(const IInspectable& sender, const IInspectable& args); void _coreOutputIdle(const IInspectable& sender, const IInspectable& args); diff --git a/src/cascadia/TerminalCore/ICoreSettings.idl b/src/cascadia/TerminalCore/ICoreSettings.idl index ff6588c2ea..804b4f4687 100644 --- a/src/cascadia/TerminalCore/ICoreSettings.idl +++ b/src/cascadia/TerminalCore/ICoreSettings.idl @@ -22,6 +22,7 @@ namespace Microsoft.Terminal.Core Boolean ForceVTInput; Boolean AllowVtChecksumReport; + Boolean AllowVtClipboardWrite; Boolean TrimBlockSelection; Boolean DetectURLs; diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index c77ab1ab76..9e6350df04 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -89,6 +89,7 @@ void Terminal::UpdateSettings(ICoreSettings settings) _trimBlockSelection = settings.TrimBlockSelection(); _autoMarkPrompts = settings.AutoMarkPrompts(); _rainbowSuggestions = settings.RainbowSuggestions(); + _clipboardOperationsAllowed = settings.AllowVtClipboardWrite(); if (_stateMachine) { @@ -477,7 +478,7 @@ bool Terminal::ShouldSendAlternateScroll(const unsigned int uiButton, // - The position relative to the viewport std::wstring Terminal::GetHyperlinkAtViewportPosition(const til::point viewportPos) { - return GetHyperlinkAtBufferPosition(_ConvertToBufferCell(viewportPos)); + return GetHyperlinkAtBufferPosition(_ConvertToBufferCell(viewportPos, false)); } std::wstring Terminal::GetHyperlinkAtBufferPosition(const til::point bufferPos) @@ -501,12 +502,8 @@ std::wstring Terminal::GetHyperlinkAtBufferPosition(const til::point bufferPos) result = GetHyperlinkIntervalFromViewportPosition(viewportPos); if (result.has_value()) { - // GetPlainText and _ConvertToBufferCell work with inclusive coordinates, but interval's - // stop point is (horizontally) exclusive, so let's just update it. - result->stop.x--; - - result->start = _ConvertToBufferCell(result->start); - result->stop = _ConvertToBufferCell(result->stop); + result->start = _ConvertToBufferCell(result->start, false); + result->stop = _ConvertToBufferCell(result->stop, true); } } else @@ -543,7 +540,7 @@ std::wstring Terminal::GetHyperlinkAtBufferPosition(const til::point bufferPos) // - The hyperlink ID uint16_t Terminal::GetHyperlinkIdAtViewportPosition(const til::point viewportPos) { - return _activeBuffer().GetCellDataAt(_ConvertToBufferCell(viewportPos))->TextAttr().GetHyperlinkId(); + return _activeBuffer().GetCellDataAt(_ConvertToBufferCell(viewportPos, false))->TextAttr().GetHyperlinkId(); } // Method description: @@ -1465,7 +1462,6 @@ PointTree Terminal::_getPatterns(til::CoordType beg, til::CoordType end) const // PointTree uses half-open ranges and viewport-relative coordinates. range.start.y -= beg; range.end.y -= beg; - range.end.x++; intervals.push_back(PointTree::interval(range.start, range.end, 0)); } while (uregex_findNext(re.get(), &status)); } diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 8ac499c97e..1459c39fc3 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -413,6 +413,7 @@ private: Microsoft::Console::Types::Viewport _mutableViewport; til::CoordType _scrollbackLines = 0; bool _detectURLs = false; + bool _clipboardOperationsAllowed = true; til::size _altBufferSize; std::optional _deferredResize; @@ -477,7 +478,7 @@ private: std::vector _GetSelectionSpans() const noexcept; std::pair _PivotSelection(const til::point targetPos, bool& targetStart) const noexcept; std::pair _ExpandSelectionAnchors(std::pair anchors) const; - til::point _ConvertToBufferCell(const til::point viewportPos) const; + til::point _ConvertToBufferCell(const til::point viewportPos, bool allowRightExclusive) const; void _ScrollToPoint(const til::point pos); void _MoveByChar(SelectionDirection direction, til::point& pos); void _MoveByWord(SelectionDirection direction, til::point& pos); diff --git a/src/cascadia/TerminalCore/TerminalApi.cpp b/src/cascadia/TerminalCore/TerminalApi.cpp index e6edec3ee9..7d8a706274 100644 --- a/src/cascadia/TerminalCore/TerminalApi.cpp +++ b/src/cascadia/TerminalCore/TerminalApi.cpp @@ -140,7 +140,10 @@ unsigned int Terminal::GetInputCodePage() const noexcept void Terminal::CopyToClipboard(wil::zwstring_view content) { - _pfnCopyToClipboard(content); + if (_clipboardOperationsAllowed) + { + _pfnCopyToClipboard(content); + } } // Method Description: diff --git a/src/cascadia/TerminalCore/TerminalSelection.cpp b/src/cascadia/TerminalCore/TerminalSelection.cpp index 6a800f329d..9501f64a85 100644 --- a/src/cascadia/TerminalCore/TerminalSelection.cpp +++ b/src/cascadia/TerminalCore/TerminalSelection.cpp @@ -93,14 +93,21 @@ const til::point Terminal::GetSelectionEnd() const noexcept til::point Terminal::SelectionStartForRendering() const { auto pos{ _selection->start }; - const auto bufferSize{ GetTextBuffer().GetSize() }; + const auto& buffer = GetTextBuffer(); + const auto bufferSize{ buffer.GetSize() }; + if (bufferSize.IsInBounds(pos) && buffer.GetCellDataAt(pos)->DbcsAttr() == DbcsAttribute::Trailing) + { + // if we're on a trailing byte, move off of it to include it + bufferSize.DecrementInExclusiveBounds(pos); + } + if (pos.x != bufferSize.Left()) { // In general, we need to draw the marker one before the // beginning of the selection. // When we're at the left boundary, we want to // flip the marker, so we skip this step. - bufferSize.DecrementInBounds(pos); + bufferSize.DecrementInExclusiveBounds(pos); } pos.y = base::ClampSub(pos.y, _VisibleStartIndex()); return til::point{ pos }; @@ -112,14 +119,21 @@ til::point Terminal::SelectionStartForRendering() const til::point Terminal::SelectionEndForRendering() const { auto pos{ _selection->end }; - const auto bufferSize{ GetTextBuffer().GetSize() }; - if (pos.x != bufferSize.RightInclusive()) + const auto& buffer = GetTextBuffer(); + const auto bufferSize{ buffer.GetSize() }; + if (bufferSize.IsInBounds(pos) && buffer.GetCellDataAt(pos)->DbcsAttr() == DbcsAttribute::Trailing) { - // In general, we need to draw the marker one after the - // end of the selection. + // if we're on a trailing byte, move off of it to include it + bufferSize.IncrementInExclusiveBounds(pos); + } + + if (pos.x == bufferSize.RightExclusive()) + { + // sln->end is exclusive + // In general, we need to draw the marker on the same cell. // When we're at the right boundary, we want to - // flip the marker, so we skip this step. - bufferSize.IncrementInBounds(pos); + // flip the marker, so we move one cell to the left. + bufferSize.DecrementInExclusiveBounds(pos); } pos.y = base::ClampSub(pos.y, _VisibleStartIndex()); return til::point{ pos }; @@ -157,7 +171,7 @@ void Terminal::MultiClickSelection(const til::point viewportPos, SelectionExpans auto selection{ _selection.write() }; wil::hide_name _selection; - selection->pivot = _ConvertToBufferCell(viewportPos); + selection->pivot = _ConvertToBufferCell(viewportPos, true); selection->active = true; _multiClickSelectionMode = expansionMode; @@ -179,7 +193,7 @@ void Terminal::SetSelectionAnchor(const til::point viewportPos) auto selection{ _selection.write() }; wil::hide_name _selection; - selection->pivot = _ConvertToBufferCell(viewportPos); + selection->pivot = _ConvertToBufferCell(viewportPos, true); selection->active = true; _multiClickSelectionMode = SelectionExpansion::Char; @@ -198,7 +212,7 @@ void Terminal::SetSelectionEnd(const til::point viewportPos, std::optional newExpansionMode) { wil::hide_name _selection; @@ -209,7 +223,12 @@ void Terminal::_SetSelectionEnd(SelectionInfo* selection, const til::point viewp return; } - const auto textBufferPos = _ConvertToBufferCell(viewportPos); + auto textBufferPos = _ConvertToBufferCell(viewportPos, true); + if (newExpansionMode && *newExpansionMode == SelectionExpansion::Char && textBufferPos >= selection->pivot) + { + // Shift+Click forwards should highlight the clicked space + _activeBuffer().GetSize().IncrementInExclusiveBounds(textBufferPos); + } // if this is a shiftClick action, we need to overwrite the _multiClickSelectionMode value (even if it's the same) // Otherwise, we may accidentally expand during other selection-based actions @@ -248,7 +267,7 @@ void Terminal::_SetSelectionEnd(SelectionInfo* selection, const til::point viewp // - the new start/end for a selection std::pair Terminal::_PivotSelection(const til::point targetPos, bool& targetStart) const noexcept { - if (targetStart = _activeBuffer().GetSize().CompareInBounds(targetPos, _selection->pivot) <= 0) + if (targetStart = targetPos <= _selection->pivot) { // target is before pivot // treat target as start @@ -273,17 +292,31 @@ std::pair Terminal::_ExpandSelectionAnchors(std::pair _selection->pivot) + { + bufferSize.DecrementInExclusiveBounds(end); + } + end = buffer.GetWordEnd2(end, _wordDelimiters, false); break; + } case SelectionExpansion::Char: default: // no expansion is necessary @@ -376,9 +409,9 @@ void Terminal::ExpandSelectionToWord() const auto& buffer = _activeBuffer(); auto selection{ _selection.write() }; wil::hide_name _selection; - selection->start = buffer.GetWordStart(selection->start, _wordDelimiters); + selection->start = buffer.GetWordStart2(selection->start, _wordDelimiters, false); selection->pivot = selection->start; - selection->end = buffer.GetWordEnd(selection->end, _wordDelimiters); + selection->end = buffer.GetWordEnd2(selection->end, _wordDelimiters, false); // if we're targeting both endpoints, instead just target "end" if (WI_IsFlagSet(_selectionEndpoint, SelectionEndpoint::Start) && WI_IsFlagSet(_selectionEndpoint, SelectionEndpoint::End)) @@ -529,7 +562,6 @@ void Terminal::SelectHyperlink(const SearchDirection dir) selection->start = result->first; selection->pivot = result->first; selection->end = result->second; - bufferSize.DecrementInBounds(selection->end); _selectionIsTargetingUrl = true; _selectionEndpoint = SelectionEndpoint::End; } @@ -625,7 +657,7 @@ void Terminal::UpdateSelection(SelectionDirection direction, SelectionExpansion } auto targetPos{ WI_IsFlagSet(_selectionEndpoint, SelectionEndpoint::Start) ? _selection->start : _selection->end }; - // 2 Perform the movement + // 2. Perform the movement switch (mode) { case SelectionExpansion::Char: @@ -695,12 +727,12 @@ void Terminal::_MoveByChar(SelectionDirection direction, til::point& pos) switch (direction) { case SelectionDirection::Left: - _activeBuffer().GetSize().DecrementInBounds(pos); - pos = _activeBuffer().GetGlyphStart(pos); + _activeBuffer().MoveToPreviousGlyph2(pos); break; case SelectionDirection::Right: - _activeBuffer().GetSize().IncrementInBounds(pos); - pos = _activeBuffer().GetGlyphEnd(pos); + // We need the limit to be the mutable viewport here, + // otherwise we're allowed to navigate by character past the mutable bottom + _activeBuffer().MoveToNextGlyph2(pos, _GetMutableViewport().BottomInclusiveRightExclusive()); break; case SelectionDirection::Up: { @@ -714,7 +746,7 @@ void Terminal::_MoveByChar(SelectionDirection direction, til::point& pos) const auto bufferSize{ _activeBuffer().GetSize() }; const auto mutableBottom{ _GetMutableViewport().BottomInclusive() }; const auto newY{ pos.y + 1 }; - pos = newY > mutableBottom ? til::point{ bufferSize.RightInclusive(), mutableBottom } : til::point{ pos.x, newY }; + pos = newY > mutableBottom ? til::point{ bufferSize.RightExclusive(), mutableBottom } : til::point{ pos.x, newY }; break; } } @@ -722,61 +754,45 @@ void Terminal::_MoveByChar(SelectionDirection direction, til::point& pos) void Terminal::_MoveByWord(SelectionDirection direction, til::point& pos) { + const auto& buffer = _activeBuffer(); switch (direction) { case SelectionDirection::Left: { - const auto wordStartPos{ _activeBuffer().GetWordStart(pos, _wordDelimiters) }; - if (_activeBuffer().GetSize().CompareInBounds(_selection->pivot, pos) < 0) + auto nextPos = pos; + nextPos = buffer.GetWordStart2(nextPos, _wordDelimiters, true); + if (nextPos == pos) { - // If we're moving towards the pivot, move one more cell - pos = wordStartPos; - _activeBuffer().GetSize().DecrementInBounds(pos); - } - else if (wordStartPos == pos) - { - // already at the beginning of the current word, - // move to the beginning of the previous word - _activeBuffer().GetSize().DecrementInBounds(pos); - pos = _activeBuffer().GetWordStart(pos, _wordDelimiters); - } - else - { - // move to the beginning of the current word - pos = wordStartPos; + // didn't move because we're already at the beginning of a word, + // so move to the beginning of the previous word + buffer.GetSize().DecrementInExclusiveBounds(nextPos); + nextPos = buffer.GetWordStart2(nextPos, _wordDelimiters, true); } + pos = nextPos; break; } case SelectionDirection::Right: { - const auto wordEndPos{ _activeBuffer().GetWordEnd(pos, _wordDelimiters) }; - if (_activeBuffer().GetSize().CompareInBounds(pos, _selection->pivot) < 0) + const auto mutableViewportEndExclusive = _GetMutableViewport().BottomInclusiveRightExclusive(); + auto nextPos = pos; + nextPos = buffer.GetWordEnd2(nextPos, _wordDelimiters, true, mutableViewportEndExclusive); + if (nextPos == pos) { - // If we're moving towards the pivot, move one more cell - pos = _activeBuffer().GetWordEnd(pos, _wordDelimiters); - _activeBuffer().GetSize().IncrementInBounds(pos); - } - else if (wordEndPos == pos) - { - // already at the end of the current word, - // move to the end of the next word - _activeBuffer().GetSize().IncrementInBounds(pos); - pos = _activeBuffer().GetWordEnd(pos, _wordDelimiters); - } - else - { - // move to the end of the current word - pos = wordEndPos; + // didn't move because we're already at the end of a word, + // so move to the end of the next word + buffer.GetSize().IncrementInExclusiveBounds(nextPos); + nextPos = buffer.GetWordEnd2(nextPos, _wordDelimiters, true, mutableViewportEndExclusive); } + pos = nextPos; break; } case SelectionDirection::Up: _MoveByChar(direction, pos); - pos = _activeBuffer().GetWordStart(pos, _wordDelimiters); + pos = buffer.GetWordStart2(pos, _wordDelimiters, true); break; case SelectionDirection::Down: _MoveByChar(direction, pos); - pos = _activeBuffer().GetWordEnd(pos, _wordDelimiters); + pos = buffer.GetWordEnd2(pos, _wordDelimiters, true); break; } } @@ -790,7 +806,7 @@ void Terminal::_MoveByViewport(SelectionDirection direction, til::point& pos) no pos = { bufferSize.Left(), pos.y }; break; case SelectionDirection::Right: - pos = { bufferSize.RightInclusive(), pos.y }; + pos = { bufferSize.RightExclusive(), pos.y }; break; case SelectionDirection::Up: { @@ -804,7 +820,7 @@ void Terminal::_MoveByViewport(SelectionDirection direction, til::point& pos) no const auto viewportHeight{ _GetMutableViewport().Height() }; const auto mutableBottom{ _GetMutableViewport().BottomInclusive() }; const auto newY{ pos.y + viewportHeight }; - pos = newY > mutableBottom ? til::point{ bufferSize.RightInclusive(), mutableBottom } : til::point{ pos.x, newY }; + pos = newY > mutableBottom ? til::point{ bufferSize.RightExclusive(), mutableBottom } : til::point{ pos.x, newY }; break; } } @@ -821,7 +837,7 @@ void Terminal::_MoveByBuffer(SelectionDirection direction, til::point& pos) noex break; case SelectionDirection::Right: case SelectionDirection::Down: - pos = { bufferSize.RightInclusive(), _GetMutableViewport().BottomInclusive() }; + pos = { bufferSize.RightExclusive(), _GetMutableViewport().BottomInclusive() }; break; } } @@ -901,13 +917,17 @@ Terminal::TextCopyData Terminal::RetrieveSelectedTextFromBuffer(const bool singl // - convert viewport position to the corresponding location on the buffer // Arguments: // - viewportPos: a coordinate on the viewport +// - allowRightExclusive: if true, clamp to the right exclusive boundary of the buffer. +// Careful! This position doesn't point to any data in the buffer! // Return Value: // - the corresponding location on the buffer -til::point Terminal::_ConvertToBufferCell(const til::point viewportPos) const +til::point Terminal::_ConvertToBufferCell(const til::point viewportPos, bool allowRightExclusive) const { const auto yPos = _VisibleStartIndex() + viewportPos.y; til::point bufferPos = { viewportPos.x, yPos }; - _activeBuffer().GetSize().Clamp(bufferPos); + const auto bufferSize = _activeBuffer().GetSize(); + bufferPos.x = std::clamp(bufferPos.x, bufferSize.Left(), allowRightExclusive ? bufferSize.RightExclusive() : bufferSize.RightInclusive()); + bufferPos.y = std::clamp(bufferPos.y, bufferSize.Top(), bufferSize.BottomInclusive()); return bufferPos; } @@ -917,7 +937,7 @@ til::point Terminal::_ConvertToBufferCell(const til::point viewportPos) const // - pos: a coordinate relative to the buffer (not viewport) void Terminal::_ScrollToPoint(const til::point pos) { - if (const auto visibleViewport = _GetVisibleViewport(); !visibleViewport.IsInBounds(pos)) + if (const auto visibleViewport = _GetVisibleViewport(); !visibleViewport.IsInExclusiveBounds(pos)) { if (const auto amtAboveView = visibleViewport.Top() - pos.y; amtAboveView > 0) { diff --git a/src/cascadia/TerminalCore/terminalrenderdata.cpp b/src/cascadia/TerminalCore/terminalrenderdata.cpp index 006d87aabe..d7bca1077c 100644 --- a/src/cascadia/TerminalCore/terminalrenderdata.cpp +++ b/src/cascadia/TerminalCore/terminalrenderdata.cpp @@ -201,6 +201,11 @@ til::CoordType Terminal::_ScrollToPoints(const til::point coordStart, const til: return _VisibleStartIndex(); } +// Method Description: +// - selects the region from coordStart to coordEnd +// Arguments: +// - coordStart - The start point (inclusive) +// - coordEnd - The end point (inclusive) void Terminal::SelectNewRegion(const til::point coordStart, const til::point coordEnd) { const auto newScrollOffset = _ScrollToPoints(coordStart, coordEnd); @@ -210,6 +215,7 @@ void Terminal::SelectNewRegion(const til::point coordStart, const til::point coo const auto newCoordEnd = til::point{ coordEnd.x, coordEnd.y - newScrollOffset }; SetSelectionAnchor(newCoordStart); SetSelectionEnd(newCoordEnd, SelectionExpansion::Char); + _activeBuffer().TriggerSelection(); } const std::wstring_view Terminal::GetConsoleTitle() const noexcept diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.cpp b/src/cascadia/TerminalSettingsEditor/Appearances.cpp index 4e6bc3b74f..536217cc6a 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.cpp +++ b/src/cascadia/TerminalSettingsEditor/Appearances.cpp @@ -221,6 +221,34 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation // box, prevent it from ever being changed again. _NotifyChanges(L"UseDesktopBGImage", L"BackgroundImageSettingsVisible"); } + else if (viewModelProperty == L"BackgroundImageAlignment") + { + _NotifyChanges(L"BackgroundImageAlignmentCurrentValue"); + } + else if (viewModelProperty == L"Foreground") + { + _NotifyChanges(L"ForegroundPreview"); + } + else if (viewModelProperty == L"Background") + { + _NotifyChanges(L"BackgroundPreview"); + } + else if (viewModelProperty == L"SelectionBackground") + { + _NotifyChanges(L"SelectionBackgroundPreview"); + } + else if (viewModelProperty == L"CursorColor") + { + _NotifyChanges(L"CursorColorPreview"); + } + else if (viewModelProperty == L"DarkColorSchemeName" || viewModelProperty == L"LightColorSchemeName") + { + _NotifyChanges(L"CurrentColorScheme"); + } + else if (viewModelProperty == L"CurrentColorScheme") + { + _NotifyChanges(L"ForegroundPreview", L"BackgroundPreview", L"SelectionBackgroundPreview", L"CursorColorPreview"); + } }); // Cache the original BG image path. If the user clicks "Use desktop @@ -888,6 +916,44 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation BackgroundImagePath(path); } + hstring AppearanceViewModel::BackgroundImageAlignmentCurrentValue() const + { + const auto alignment = BackgroundImageAlignment(); + hstring alignmentResourceKey = L"Profile_BackgroundImageAlignment"; + if (alignment == (ConvergedAlignment::Vertical_Center | ConvergedAlignment::Horizontal_Center)) + { + alignmentResourceKey = alignmentResourceKey + L"Center"; + } + else + { + // Append vertical alignment to the resource key + switch (alignment & static_cast(0xF0)) + { + case ConvergedAlignment::Vertical_Bottom: + alignmentResourceKey = alignmentResourceKey + L"Bottom"; + break; + case ConvergedAlignment::Vertical_Top: + alignmentResourceKey = alignmentResourceKey + L"Top"; + break; + } + + // Append horizontal alignment to the resource key + switch (alignment & static_cast(0x0F)) + { + case ConvergedAlignment::Horizontal_Left: + alignmentResourceKey = alignmentResourceKey + L"Left"; + break; + case ConvergedAlignment::Horizontal_Right: + alignmentResourceKey = alignmentResourceKey + L"Right"; + break; + } + } + alignmentResourceKey = alignmentResourceKey + L"/[using:Windows.UI.Xaml.Controls]ToolTipService/ToolTip"; + + // We can't use the RS_ macro here because the resource key is dynamic + return GetLibraryResourceString(alignmentResourceKey); + } + bool AppearanceViewModel::UseDesktopBGImage() { return BackgroundImagePath() == L"desktopWallpaper"; @@ -928,7 +994,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation _NotifyChanges(L"CurrentColorScheme"); } - Editor::ColorSchemeViewModel AppearanceViewModel::CurrentColorScheme() + Editor::ColorSchemeViewModel AppearanceViewModel::CurrentColorScheme() const { const auto schemeName{ DarkColorSchemeName() }; const auto allSchemes{ SchemesList() }; @@ -950,6 +1016,42 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation LightColorSchemeName(val.Name()); } + static inline Windows::UI::Color _getColorPreview(const IReference& modelVal, Windows::UI::Color deducedVal) + { + if (modelVal) + { + // user defined an override value + return Windows::UI::Color{ + .A = 255, + .R = modelVal.Value().R, + .G = modelVal.Value().G, + .B = modelVal.Value().B + }; + } + // set to null --> deduce value from color scheme + return deducedVal; + } + + Windows::UI::Color AppearanceViewModel::ForegroundPreview() const + { + return _getColorPreview(_appearance.Foreground(), CurrentColorScheme().ForegroundColor().Color()); + } + + Windows::UI::Color AppearanceViewModel::BackgroundPreview() const + { + return _getColorPreview(_appearance.Background(), CurrentColorScheme().BackgroundColor().Color()); + } + + Windows::UI::Color AppearanceViewModel::SelectionBackgroundPreview() const + { + return _getColorPreview(_appearance.SelectionBackground(), CurrentColorScheme().SelectionBackgroundColor().Color()); + } + + Windows::UI::Color AppearanceViewModel::CursorColorPreview() const + { + return _getColorPreview(_appearance.CursorColor(), CurrentColorScheme().CursorColor().Color()); + } + DependencyProperty Appearances::_AppearanceProperty{ nullptr }; Appearances::Appearances() diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.h b/src/cascadia/TerminalSettingsEditor/Appearances.h index aba3abd45f..989f278c56 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.h +++ b/src/cascadia/TerminalSettingsEditor/Appearances.h @@ -125,11 +125,17 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation bool BackgroundImageSettingsVisible(); void SetBackgroundImageOpacityFromPercentageValue(double percentageValue); void SetBackgroundImagePath(winrt::hstring path); + hstring BackgroundImageAlignmentCurrentValue() const; void ClearColorScheme(); - Editor::ColorSchemeViewModel CurrentColorScheme(); + Editor::ColorSchemeViewModel CurrentColorScheme() const; void CurrentColorScheme(const Editor::ColorSchemeViewModel& val); + Windows::UI::Color ForegroundPreview() const; + Windows::UI::Color BackgroundPreview() const; + Windows::UI::Color SelectionBackgroundPreview() const; + Windows::UI::Color CursorColorPreview() const; + WINRT_PROPERTY(bool, IsDefault, false); // These settings are not defined in AppearanceConfig, so we grab them @@ -153,6 +159,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation OBSERVABLE_PROJECTED_SETTING(_appearance, BackgroundImageAlignment); OBSERVABLE_PROJECTED_SETTING(_appearance, IntenseTextStyle); OBSERVABLE_PROJECTED_SETTING(_appearance, AdjustIndistinguishableColors); + OBSERVABLE_PROJECTED_SETTING(_appearance, Foreground); + OBSERVABLE_PROJECTED_SETTING(_appearance, Background); + OBSERVABLE_PROJECTED_SETTING(_appearance, SelectionBackground); + OBSERVABLE_PROJECTED_SETTING(_appearance, CursorColor); WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector, SchemesList, _propertyChangedHandlers, nullptr); private: diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.idl b/src/cascadia/TerminalSettingsEditor/Appearances.idl index 5a22a190d2..89096d857a 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.idl +++ b/src/cascadia/TerminalSettingsEditor/Appearances.idl @@ -40,11 +40,17 @@ namespace Microsoft.Terminal.Settings.Editor Boolean UseDesktopBGImage; Boolean BackgroundImageSettingsVisible { get; }; + String BackgroundImageAlignmentCurrentValue { get; }; void ClearColorScheme(); ColorSchemeViewModel CurrentColorScheme; IObservableVector SchemesList; + Windows.UI.Color ForegroundPreview { get; }; + Windows.UI.Color BackgroundPreview { get; }; + Windows.UI.Color SelectionBackgroundPreview { get; }; + Windows.UI.Color CursorColorPreview { get; }; + String MissingFontFaces { get; }; String ProportionalFontFaces { get; }; Boolean HasPowerlineCharacters { get; }; @@ -78,6 +84,11 @@ namespace Microsoft.Terminal.Settings.Editor OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Settings.Model.ConvergedAlignment, BackgroundImageAlignment); OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Settings.Model.IntenseStyle, IntenseTextStyle); OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Core.AdjustTextMode, AdjustIndistinguishableColors); + + OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.Foundation.IReference, Foreground); + OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.Foundation.IReference, Background); + OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.Foundation.IReference, SelectionBackground); + OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.Foundation.IReference, CursorColor); } [default_interface] runtimeclass Appearances : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.xaml b/src/cascadia/TerminalSettingsEditor/Appearances.xaml index 0ed87caa62..d4cff69560 100644 --- a/src/cascadia/TerminalSettingsEditor/Appearances.xaml +++ b/src/cascadia/TerminalSettingsEditor/Appearances.xaml @@ -69,138 +69,192 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + SettingOverrideSource="{x:Bind Appearance.DarkColorSchemeNameOverrideSource, Mode=OneWay}" + Style="{StaticResource ExpanderSettingContainerStyleWithComplexPreview}"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -503,6 +573,7 @@ @@ -60,6 +62,9 @@ + + + Firebrick 14.0 @@ -69,6 +74,32 @@ 1000 13,0,13,48 + + + + + + + + + + + + + + + + @@ -106,21 +124,68 @@ - - - - - - - - + SettingOverrideSource="{x:Bind Profile.PaddingOverrideSource, Mode=OneWay}" + Style="{StaticResource ExpanderSettingContainerStyle}"> + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/Profiles_Base.cpp b/src/cascadia/TerminalSettingsEditor/Profiles_Base.cpp index e685bdc64a..476c81e311 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles_Base.cpp +++ b/src/cascadia/TerminalSettingsEditor/Profiles_Base.cpp @@ -148,4 +148,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation _Profile.StartingDirectory(folder); } } + + Windows::UI::Xaml::Controls::IconSource Profiles_Base::BuiltInIconConverter(const IInspectable& iconVal) + { + return Microsoft::Terminal::UI::IconPathConverter::IconSourceWUX(unbox_value(iconVal)); + } } diff --git a/src/cascadia/TerminalSettingsEditor/Profiles_Base.h b/src/cascadia/TerminalSettingsEditor/Profiles_Base.h index 77b4f5f493..29ca4a0f69 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles_Base.h +++ b/src/cascadia/TerminalSettingsEditor/Profiles_Base.h @@ -25,6 +25,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation void Advanced_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e); void DeleteConfirmation_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e); + static Windows::UI::Xaml::Controls::IconSource BuiltInIconConverter(const Windows::Foundation::IInspectable& iconVal); + til::property_changed_event PropertyChanged; WINRT_PROPERTY(Editor::ProfileViewModel, Profile, nullptr); diff --git a/src/cascadia/TerminalSettingsEditor/Profiles_Base.idl b/src/cascadia/TerminalSettingsEditor/Profiles_Base.idl index b076fe75a3..0e85e04921 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles_Base.idl +++ b/src/cascadia/TerminalSettingsEditor/Profiles_Base.idl @@ -9,5 +9,7 @@ namespace Microsoft.Terminal.Settings.Editor { Profiles_Base(); ProfileViewModel Profile { get; }; + + static Windows.UI.Xaml.Controls.IconSource BuiltInIconConverter(IInspectable iconVal); } } diff --git a/src/cascadia/TerminalSettingsEditor/Profiles_Base.xaml b/src/cascadia/TerminalSettingsEditor/Profiles_Base.xaml index 4a92c48031..a048a8dba5 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles_Base.xaml +++ b/src/cascadia/TerminalSettingsEditor/Profiles_Base.xaml @@ -102,34 +102,106 @@ - - -