From ebf75edab1b5272bd5341cb78716d19b1d507e47 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 20 Aug 2020 10:46:40 -0500 Subject: [PATCH 01/17] Move the dll project to /dll and move the lib project up --- OpenConsole.sln | 4 +- .../TerminalApp.LocalTests.vcxproj | 4 +- .../TestHostApp/TestHostApp.vcxproj | 2 +- src/cascadia/TerminalApp/App.idl | 2 +- src/cascadia/TerminalApp/AppKeyBindings.idl | 4 +- src/cascadia/TerminalApp/AppLogic.idl | 6 +- src/cascadia/TerminalApp/Command.idl | 2 +- src/cascadia/TerminalApp/CommandPalette.idl | 2 +- .../TerminalApp/MinMaxCloseControl.idl | 2 +- .../TerminalApp/ShortcutActionDispatch.idl | 2 +- .../{lib => }/TerminalAppLib.vcxproj | 314 +++++++++--------- .../{lib => }/TerminalAppLib.vcxproj.filters | 0 .../{ => dll}/FixVisualStudioBug.targets | 0 .../TerminalApp/{ => dll}/TerminalApp.def | 0 .../TerminalApp/{ => dll}/TerminalApp.vcxproj | 26 +- src/cascadia/TerminalApp/{lib => dll}/pch.cpp | 0 src/cascadia/TerminalApp/dll/pch.h | 12 + src/cascadia/TerminalApp/lib/pch.h | 75 ----- src/cascadia/TerminalApp/pch.h | 69 +++- .../WindowsTerminal/WindowsTerminal.vcxproj | 2 +- .../ut_app/TerminalApp.UnitTests.vcxproj | 14 +- 21 files changed, 275 insertions(+), 267 deletions(-) rename src/cascadia/TerminalApp/{lib => }/TerminalAppLib.vcxproj (52%) rename src/cascadia/TerminalApp/{lib => }/TerminalAppLib.vcxproj.filters (100%) rename src/cascadia/TerminalApp/{ => dll}/FixVisualStudioBug.targets (100%) rename src/cascadia/TerminalApp/{ => dll}/TerminalApp.def (100%) rename src/cascadia/TerminalApp/{ => dll}/TerminalApp.vcxproj (78%) rename src/cascadia/TerminalApp/{lib => dll}/pch.cpp (100%) create mode 100644 src/cascadia/TerminalApp/dll/pch.h delete mode 100644 src/cascadia/TerminalApp/lib/pch.h diff --git a/OpenConsole.sln b/OpenConsole.sln index 935e252c3f5..82ab30fdc5a 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -177,7 +177,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminal", "src\casc {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalApp", "src\cascadia\TerminalApp\TerminalApp.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalApp", "src\cascadia\TerminalApp\dll\TerminalApp.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-9A12-429C-B551-8562EC954746} = {CA5CAD1A-9A12-429C-B551-8562EC954746} {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} @@ -227,7 +227,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_TerminalApp", "sr {CA5CAD1A-9A12-429C-B551-8562EC954746} = {CA5CAD1A-9A12-429C-B551-8562EC954746} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAppLib", "src\cascadia\TerminalApp\lib\TerminalAppLib.vcxproj", "{CA5CAD1A-9A12-429C-B551-8562EC954746}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAppLib", "src\cascadia\TerminalApp\TerminalAppLib.vcxproj", "{CA5CAD1A-9A12-429C-B551-8562EC954746}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} EndProjectSection diff --git a/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj b/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj index b99a6146693..150004c2f74 100644 --- a/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj +++ b/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj @@ -74,7 +74,7 @@ - + - ..;$(OpenConsoleDir)\dep;$(OpenConsoleDir)\dep\jsoncpp\json;$(OpenConsoleDir)src\inc;$(OpenConsoleDir)src\inc\test;$(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)\src\cascadia\TerminalApp\lib\Generated Files";%(AdditionalIncludeDirectories) + ..;$(OpenConsoleDir)\dep;$(OpenConsoleDir)\dep\jsoncpp\json;$(OpenConsoleDir)src\inc;$(OpenConsoleDir)src\inc\test;$(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)\src\cascadia\TerminalApp\Generated Files";%(AdditionalIncludeDirectories) pch.h diff --git a/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj b/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj index f035d8a74d1..b6d85e9ae04 100644 --- a/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj +++ b/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj @@ -96,7 +96,7 @@ - + {ca5cad1a-44bd-4ac7-ac72-f16e576fdd12} diff --git a/src/cascadia/TerminalApp/App.idl b/src/cascadia/TerminalApp/App.idl index 018c495b805..5e000c5a182 100644 --- a/src/cascadia/TerminalApp/App.idl +++ b/src/cascadia/TerminalApp/App.idl @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import "../AppLogic.idl"; +import "AppLogic.idl"; namespace TerminalApp { diff --git a/src/cascadia/TerminalApp/AppKeyBindings.idl b/src/cascadia/TerminalApp/AppKeyBindings.idl index 0dcba935591..ab670a33908 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.idl +++ b/src/cascadia/TerminalApp/AppKeyBindings.idl @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import "../ActionArgs.idl"; -import "../ShortcutActionDispatch.idl"; +import "ActionArgs.idl"; +import "ShortcutActionDispatch.idl"; namespace TerminalApp { diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index 00006608ef1..73b77b54413 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import "../TerminalPage.idl"; -import "../ShortcutActionDispatch.idl"; -import "../IDirectKeyListener.idl"; +import "TerminalPage.idl"; +import "ShortcutActionDispatch.idl"; +import "IDirectKeyListener.idl"; namespace TerminalApp { diff --git a/src/cascadia/TerminalApp/Command.idl b/src/cascadia/TerminalApp/Command.idl index beb0a43f10c..eea4c9bac73 100644 --- a/src/cascadia/TerminalApp/Command.idl +++ b/src/cascadia/TerminalApp/Command.idl @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import "../ShortcutActionDispatch.idl"; +import "ShortcutActionDispatch.idl"; namespace TerminalApp { diff --git a/src/cascadia/TerminalApp/CommandPalette.idl b/src/cascadia/TerminalApp/CommandPalette.idl index 93d5851f60d..793ac8334e4 100644 --- a/src/cascadia/TerminalApp/CommandPalette.idl +++ b/src/cascadia/TerminalApp/CommandPalette.idl @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import "../Command.idl"; +import "Command.idl"; namespace TerminalApp { diff --git a/src/cascadia/TerminalApp/MinMaxCloseControl.idl b/src/cascadia/TerminalApp/MinMaxCloseControl.idl index c0ccb370f21..eb8fbd16e37 100644 --- a/src/cascadia/TerminalApp/MinMaxCloseControl.idl +++ b/src/cascadia/TerminalApp/MinMaxCloseControl.idl @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import "..\TitlebarControl.idl"; +import "TitlebarControl.idl"; namespace TerminalApp { diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl index e13c0433565..f34256f3a6b 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl @@ -1,6 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import "../ActionArgs.idl"; +import "ActionArgs.idl"; namespace TerminalApp { diff --git a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj similarity index 52% rename from src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj rename to src/cascadia/TerminalApp/TerminalAppLib.vcxproj index abb49e21e58..807f9464445 100644 --- a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj +++ b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj @@ -24,9 +24,9 @@ false nested - + - + @@ -42,190 +42,190 @@ For any types that use XAML information, if their .idl and .h aren't marked DependentUpon the corresponding .xaml file, XamlTypeInfo.g.h won't pick it up correctly. --> - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer - + Designer - - - - - ../MinMaxCloseControl.xaml + + + + + MinMaxCloseControl.xaml - - ../TerminalPage.xaml + + TerminalPage.xaml Code - - ../TitlebarControl.xaml + + TitlebarControl.xaml - - ../TabRowControl.xaml + + TabRowControl.xaml - - ../ColorPickupFlyout.xaml + + ColorPickupFlyout.xaml - - ../CommandPalette.xaml + + CommandPalette.xaml - - ../Command.idl + + Command.idl - - ../EmptyStringVisibilityConverter.idl + + EmptyStringVisibilityConverter.idl - - ../HasNestedCommandsVisibilityConverter.idl + + HasNestedCommandsVisibilityConverter.idl - - ../Tab.idl + + Tab.idl - - - ../ColorScheme.idl + + + ColorScheme.idl - - - - - - - - - - - - - - - - - ../TerminalSettings.idl + + + + + + + + + + + + + + + + + TerminalSettings.idl - - ../ShortcutActionDispatch.idl + + ShortcutActionDispatch.idl - - ../ActionArgs.idl + + ActionArgs.idl - - ../ActionArgs.idl + + ActionArgs.idl - - - ../AppKeyBindings.idl + + + AppKeyBindings.idl - - ../App.xaml + + App.xaml - - ../AppLogic.idl + + AppLogic.idl - - - - - ../MinMaxCloseControl.xaml + + + + + MinMaxCloseControl.xaml - - ../TerminalPage.xaml + + TerminalPage.xaml Code - - ../TitlebarControl.xaml + + TitlebarControl.xaml - - ../TabRowControl.xaml + + TabRowControl.xaml - - ../ColorPickupFlyout.xaml + + ColorPickupFlyout.xaml - - ../CommandPalette.xaml + + CommandPalette.xaml - - ../Command.idl + + Command.idl - - ../EmptyStringVisibilityConverter.idl + + EmptyStringVisibilityConverter.idl - - ../HasNestedCommandsVisibilityConverter.idl + + HasNestedCommandsVisibilityConverter.idl - - ../Tab.idl + + Tab.idl - - - ../ColorScheme.idl + + + ColorScheme.idl - - - - - - - - - - - - - - - - ../TerminalSettings.idl + + + + + + + + + + + + + + + + TerminalSettings.idl Create - - ../AppKeyBindings.idl + + AppKeyBindings.idl - - ../ShortcutActionDispatch.idl + + ShortcutActionDispatch.idl - - ../ActionArgs.idl + + ActionArgs.idl - - ../ActionArgs.idl + + ActionArgs.idl - - ../App.xaml + + App.xaml - - ../App.xaml + + App.xaml - - ../AppLogic.idl + + AppLogic.idl @@ -238,50 +238,50 @@ - - - ../App.xaml + + + App.xaml - - - - - - ../MinMaxCloseControl.xaml + + + + + + MinMaxCloseControl.xaml Code - - ../TerminalPage.xaml + + TerminalPage.xaml Code - - ../TitlebarControl.xaml + + TitlebarControl.xaml Code - - ../TabRowControl.xaml + + TabRowControl.xaml Code - - ../ColorPickupFlyout.xaml + + ColorPickupFlyout.xaml Code - - ../CommandPalette.xaml + + CommandPalette.xaml Code - - - - - - + + + + + + - - - + + + @@ -343,8 +343,8 @@ - - + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. @@ -375,16 +375,16 @@ - - + + - - + + - - + + diff --git a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters similarity index 100% rename from src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters rename to src/cascadia/TerminalApp/TerminalAppLib.vcxproj.filters diff --git a/src/cascadia/TerminalApp/FixVisualStudioBug.targets b/src/cascadia/TerminalApp/dll/FixVisualStudioBug.targets similarity index 100% rename from src/cascadia/TerminalApp/FixVisualStudioBug.targets rename to src/cascadia/TerminalApp/dll/FixVisualStudioBug.targets diff --git a/src/cascadia/TerminalApp/TerminalApp.def b/src/cascadia/TerminalApp/dll/TerminalApp.def similarity index 100% rename from src/cascadia/TerminalApp/TerminalApp.def rename to src/cascadia/TerminalApp/dll/TerminalApp.def diff --git a/src/cascadia/TerminalApp/TerminalApp.vcxproj b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj similarity index 78% rename from src/cascadia/TerminalApp/TerminalApp.vcxproj rename to src/cascadia/TerminalApp/dll/TerminalApp.vcxproj index a19fa271c79..8d8962cca79 100644 --- a/src/cascadia/TerminalApp/TerminalApp.vcxproj +++ b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj @@ -17,9 +17,9 @@ --> true - + - + @@ -28,15 +28,15 @@ - + - - - - - - - + + + + + + + @@ -72,14 +72,14 @@ - + true true - - + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. diff --git a/src/cascadia/TerminalApp/lib/pch.cpp b/src/cascadia/TerminalApp/dll/pch.cpp similarity index 100% rename from src/cascadia/TerminalApp/lib/pch.cpp rename to src/cascadia/TerminalApp/dll/pch.cpp diff --git a/src/cascadia/TerminalApp/dll/pch.h b/src/cascadia/TerminalApp/dll/pch.h new file mode 100644 index 00000000000..465827b00d6 --- /dev/null +++ b/src/cascadia/TerminalApp/dll/pch.h @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +// pch.h +// Header for platform projection include files +// + +#pragma once + +// This file can be empty - the pch.h in TerminalApp/lib does the heavy lifting +// of including all the headers we need. As this project is just a dll wrapper, +// we don't actually need anything in here. diff --git a/src/cascadia/TerminalApp/lib/pch.h b/src/cascadia/TerminalApp/lib/pch.h deleted file mode 100644 index dcac6c4e1ab..00000000000 --- a/src/cascadia/TerminalApp/lib/pch.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -// -// pch.h -// Header for platform projection include files -// - -#pragma once - -#define WIN32_LEAN_AND_MEAN - -// Manually include til after we include Windows.Foundation to give it winrt superpowers -#define BLOCK_TIL -#include -// This is inexplicable, but for whatever reason, cppwinrt conflicts with the -// SDK definition of this function, so the only fix is to undef it. -// from WinBase.h -// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime -#ifdef GetCurrentTime -#undef GetCurrentTime -#endif - -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "winrt/Windows.UI.Xaml.Markup.h" -#include "winrt/Windows.UI.Xaml.Documents.h" -#include "winrt/Windows.UI.Xaml.Automation.h" -#include -#include - -#include -#include -#include -#include - -#include - -#include - -// Including TraceLogging essentials for the binary -#include -#include -TRACELOGGING_DECLARE_PROVIDER(g_hTerminalAppProvider); -#include -#include - -// JsonCpp -#include - -#include - -#include -#include - -#include - -// Manually include til after we include Windows.Foundation to give it winrt superpowers -#include "til.h" diff --git a/src/cascadia/TerminalApp/pch.h b/src/cascadia/TerminalApp/pch.h index 465827b00d6..dcac6c4e1ab 100644 --- a/src/cascadia/TerminalApp/pch.h +++ b/src/cascadia/TerminalApp/pch.h @@ -7,6 +7,69 @@ #pragma once -// This file can be empty - the pch.h in TerminalApp/lib does the heavy lifting -// of including all the headers we need. As this project is just a dll wrapper, -// we don't actually need anything in here. +#define WIN32_LEAN_AND_MEAN + +// Manually include til after we include Windows.Foundation to give it winrt superpowers +#define BLOCK_TIL +#include +// This is inexplicable, but for whatever reason, cppwinrt conflicts with the +// SDK definition of this function, so the only fix is to undef it. +// from WinBase.h +// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime +#ifdef GetCurrentTime +#undef GetCurrentTime +#endif + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "winrt/Windows.UI.Xaml.Markup.h" +#include "winrt/Windows.UI.Xaml.Documents.h" +#include "winrt/Windows.UI.Xaml.Automation.h" +#include +#include + +#include +#include +#include +#include + +#include + +#include + +// Including TraceLogging essentials for the binary +#include +#include +TRACELOGGING_DECLARE_PROVIDER(g_hTerminalAppProvider); +#include +#include + +// JsonCpp +#include + +#include + +#include +#include + +#include + +// Manually include til after we include Windows.Foundation to give it winrt superpowers +#include "til.h" diff --git a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj index b940f569e23..395c76d9e8e 100644 --- a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj +++ b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj @@ -75,7 +75,7 @@ - + diff --git a/src/cascadia/ut_app/TerminalApp.UnitTests.vcxproj b/src/cascadia/ut_app/TerminalApp.UnitTests.vcxproj index 280cd1c3bed..868002a5fd2 100644 --- a/src/cascadia/ut_app/TerminalApp.UnitTests.vcxproj +++ b/src/cascadia/ut_app/TerminalApp.UnitTests.vcxproj @@ -27,6 +27,14 @@ + + + + true + + + @@ -53,7 +61,7 @@ - + @@ -62,7 +70,7 @@ - ..;$(OpenConsoleDir)\dep\jsoncpp\json;$(OpenConsoleDir)src\inc;$(OpenConsoleDir)src\inc\test;$(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)\src\cascadia\TerminalApp\lib\Generated Files";%(AdditionalIncludeDirectories) + ..;$(OpenConsoleDir)\dep\jsoncpp\json;$(OpenConsoleDir)src\inc;$(OpenConsoleDir)src\inc\test;$(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)\src\cascadia\TerminalApp\Generated Files";%(AdditionalIncludeDirectories) precomp.h @@ -124,6 +132,6 @@ - + From cb468e66c761ee7fb9f988462dfdbb0973b4790a Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 20 Aug 2020 11:25:01 -0500 Subject: [PATCH 02/17] Huh, this definitely creates an animation, but it's got HORRIFYING performance. Let's do _better_ --- src/cascadia/TerminalApp/Pane.cpp | 15 +++++++++++++++ src/cascadia/TerminalApp/pch.h | 1 + 2 files changed, 16 insertions(+) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 180100f4a97..a9cca49fcf1 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -1177,6 +1177,21 @@ std::pair, std::shared_ptr> Pane::_Split(SplitState _lastActive = false; + + winrt::Windows::UI::Xaml::Media::Animation::DoubleAnimation d{}; + d.Duration(winrt::Windows::UI::Xaml::Duration{ std::chrono::milliseconds{ 3000 } }); + d.From(0.0); + d.To(400.0); + d.EnableDependentAnimation(true); + winrt::Windows::UI::Xaml::Media::Animation::Storyboard s; + s.Duration(winrt::Windows::UI::Xaml::Duration{ std::chrono::milliseconds{ 3000 } }); + s.Children().Append(d); + s.SetTarget(d, control); + s.SetTargetProperty(d, L"Width"); + _root.Resources().Insert(winrt::box_value(L"paneAnimation"), s); + s.Begin(); + control.HorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment::Left); + return { _firstChild, _secondChild }; } diff --git a/src/cascadia/TerminalApp/pch.h b/src/cascadia/TerminalApp/pch.h index dcac6c4e1ab..6dd99796713 100644 --- a/src/cascadia/TerminalApp/pch.h +++ b/src/cascadia/TerminalApp/pch.h @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include "winrt/Windows.UI.Xaml.Markup.h" From 22a8b4db5217dbc0f7b9681e2e8551c5a67f1835 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 20 Aug 2020 12:43:15 -0500 Subject: [PATCH 03/17] animating one split > animating 0 splits --- src/cascadia/TerminalApp/Pane.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index a9cca49fcf1..28a80ed4dbf 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -1177,20 +1177,34 @@ std::pair, std::shared_ptr> Pane::_Split(SplitState _lastActive = false; - + const auto firstPercent = _desiredSplitPosition; + const auto secondPercent = 1.0f - firstPercent; + auto secondWidth = secondPercent * _root.ActualWidth(); + auto childGrid = _secondChild->_root; winrt::Windows::UI::Xaml::Media::Animation::DoubleAnimation d{}; - d.Duration(winrt::Windows::UI::Xaml::Duration{ std::chrono::milliseconds{ 3000 } }); + d.Duration(winrt::Windows::UI::Xaml::Duration{ std::chrono::milliseconds{ 300 } }); d.From(0.0); d.To(400.0); + // d.EasingFunction(Media::Animation::SineEase{}); + // d.EasingFunction(Media::Animation::QuadraticEase{}); + d.EasingFunction(Media::Animation::CubicEase{}); d.EnableDependentAnimation(true); winrt::Windows::UI::Xaml::Media::Animation::Storyboard s; - s.Duration(winrt::Windows::UI::Xaml::Duration{ std::chrono::milliseconds{ 3000 } }); + s.Duration(winrt::Windows::UI::Xaml::Duration{ std::chrono::milliseconds{ 300 } }); s.Children().Append(d); - s.SetTarget(d, control); + s.SetTarget(d, childGrid); s.SetTargetProperty(d, L"Width"); _root.Resources().Insert(winrt::box_value(L"paneAnimation"), s); s.Begin(); + childGrid.HorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment::Right); control.HorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment::Left); + control.Width(secondWidth); + d.Completed([control, childGrid](auto&&, auto&&) { + control.Width(NAN); + childGrid.Width(NAN); + childGrid.HorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment::Stretch); + control.HorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment::Stretch); + }); return { _firstChild, _secondChild }; } From d7e872cb604a27797fdfcfc5a6f85b0dcc15832e Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 20 Aug 2020 14:57:50 -0500 Subject: [PATCH 04/17] hot damn this is so C R I S P --- src/cascadia/TerminalApp/Pane.cpp | 72 +++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 28a80ed4dbf..785bf6206fa 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -42,6 +42,8 @@ Pane::Pane(const GUID& profile, const TermControl& control, const bool lastFocus _SetupResources(); } + _root.Background(s_unfocusedBorderBrush); + // Register an event with the control to have it inform us when it gains focus. _gotFocusRevoker = control.GotFocus(winrt::auto_revoke, { this, &Pane::_ControlGotFocusHandler }); @@ -1177,33 +1179,57 @@ std::pair, std::shared_ptr> Pane::_Split(SplitState _lastActive = false; - const auto firstPercent = _desiredSplitPosition; - const auto secondPercent = 1.0f - firstPercent; - auto secondWidth = secondPercent * _root.ActualWidth(); + // const auto firstPercent = _desiredSplitPosition; + // const auto secondPercent = 1.0f - firstPercent; + // auto secondWidth = secondPercent * _root.ActualWidth(); + const bool splitWidth = _splitState == SplitState::Vertical; + auto [firstSize, secondSize] = _CalcChildrenSizes(::base::saturated_cast(splitWidth ? _root.ActualWidth() : _root.ActualHeight())); + auto childGrid = _secondChild->_root; - winrt::Windows::UI::Xaml::Media::Animation::DoubleAnimation d{}; - d.Duration(winrt::Windows::UI::Xaml::Duration{ std::chrono::milliseconds{ 300 } }); - d.From(0.0); - d.To(400.0); + Duration duration{ std::chrono::milliseconds{ 166 } }; + Duration d2 = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(300))); + Media::Animation::DoubleAnimation animation{}; + animation.Duration(d2); + animation.From(0.0); + animation.To(secondSize); // d.EasingFunction(Media::Animation::SineEase{}); - // d.EasingFunction(Media::Animation::QuadraticEase{}); - d.EasingFunction(Media::Animation::CubicEase{}); - d.EnableDependentAnimation(true); - winrt::Windows::UI::Xaml::Media::Animation::Storyboard s; - s.Duration(winrt::Windows::UI::Xaml::Duration{ std::chrono::milliseconds{ 300 } }); - s.Children().Append(d); - s.SetTarget(d, childGrid); - s.SetTargetProperty(d, L"Width"); + animation.EasingFunction(Media::Animation::QuadraticEase{}); + // animation.EasingFunction(Media::Animation::CubicEase{}); + animation.EnableDependentAnimation(true); + Media::Animation::Storyboard s; + s.Duration(d2); + s.Children().Append(animation); + s.SetTarget(animation, childGrid); + s.SetTargetProperty(animation, splitWidth ? L"Width" : L"Height"); _root.Resources().Insert(winrt::box_value(L"paneAnimation"), s); s.Begin(); - childGrid.HorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment::Right); - control.HorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment::Left); - control.Width(secondWidth); - d.Completed([control, childGrid](auto&&, auto&&) { - control.Width(NAN); - childGrid.Width(NAN); - childGrid.HorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment::Stretch); - control.HorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment::Stretch); + if (splitWidth) + { + childGrid.HorizontalAlignment(HorizontalAlignment::Right); + control.HorizontalAlignment(HorizontalAlignment::Left); + control.Width(secondSize); + } + else + { + childGrid.VerticalAlignment(VerticalAlignment::Bottom); + control.VerticalAlignment(VerticalAlignment::Top); + control.Height(secondSize); + } + animation.Completed([control, childGrid, splitWidth](auto&&, auto&&) { + if (splitWidth) + { + control.Width(NAN); + childGrid.Width(NAN); + childGrid.HorizontalAlignment(HorizontalAlignment::Stretch); + control.HorizontalAlignment(HorizontalAlignment::Stretch); + } + else + { + control.Height(NAN); + childGrid.Height(NAN); + childGrid.VerticalAlignment(VerticalAlignment::Stretch); + control.VerticalAlignment(VerticalAlignment::Stretch); + } }); return { _firstChild, _secondChild }; From d472fe5c5f0e34b806edf3b261f320494769e312 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 20 Aug 2020 16:40:06 -0500 Subject: [PATCH 05/17] Add a bunch of code cleanup --- src/cascadia/TerminalApp/Pane.cpp | 148 +++++++++++++++++++----------- src/cascadia/TerminalApp/Pane.h | 1 + 2 files changed, 97 insertions(+), 52 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 785bf6206fa..acf0a400d66 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -905,6 +905,101 @@ void Pane::_ApplySplitDefinitions() } } +void Pane::_SetupEntranceAnimation() +{ + const bool splitWidth = _splitState == SplitState::Vertical; + const auto totalSize = splitWidth ? _root.ActualWidth() : _root.ActualHeight(); + if (totalSize <= 0) + { + return; + } + + const auto [firstSize, secondSize] = _CalcChildrenSizes(::base::saturated_cast(totalSize)); + + auto childGrid = _secondChild->_root; + auto control = _secondChild->_control; + // WARNING: Don't do this! This won't work + // Duration duration{ std::chrono::milliseconds{ 166 } }; + // Instead, make a duration from a timespan from the time in millis + // + // 300ms was chosen because it's quick enough that it doesn't break your + // flow, but not too quick to see + Duration duration = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(200))); + + // Build up our animation: + // * it'll take as long as our duration (300ms) + // * it'll change the value of our property from 0 to secondSize + // * it'll animate that value using a quadratic function (like f(t) = t^2) + // * IMPORTANT! We'll manually tell the animation that "yes we know what + // we're doing, we want an animation here." + Media::Animation::DoubleAnimation animation{}; + animation.Duration(duration); + animation.From(0.0); + animation.To(secondSize); + animation.EasingFunction(Media::Animation::QuadraticEase{}); + animation.EnableDependentAnimation(true); + + // Now we're going to set up the Storyboard. This is a unit that uses the + // Animation from above, and actually applies it to a property. + // * we'll set it up for the same duration as the animation we have + // * Apply the animation to the grid of the new pane we're adding to the tree. + // * apply the animation to the Width or Height property. + // * add the storyboard to our resources. TODO: I don't know if this is necessary. + Media::Animation::Storyboard s; + s.Duration(duration); + s.Children().Append(animation); + s.SetTarget(animation, childGrid); + s.SetTargetProperty(animation, splitWidth ? L"Width" : L"Height"); + _root.Resources().Insert(winrt::box_value(L"paneAnimation"), s); + + // BE TRICKY: + // We're animating the width or height of our child pane's grid. + // + // We DON'T want to change the size of the control itself, because the + // terminal has to reflow the buffer every time the control changes size. So + // what we're going to do there is manually set the control's size to how + // big we _actually know_ the control will be. + // + // We're also going to be changing alignment of our child pane and the + // control. This way, we'll be able to have the control stick to the inside + // of the child pane's grid (the side that's moving), while we also have the + // pane's grid stick to "outside" of the grid (the side that's not moving) + if (splitWidth) + { + childGrid.HorizontalAlignment(HorizontalAlignment::Right); + control.HorizontalAlignment(HorizontalAlignment::Left); + control.Width(secondSize); + } + else + { + childGrid.VerticalAlignment(VerticalAlignment::Bottom); + control.VerticalAlignment(VerticalAlignment::Top); + control.Height(secondSize); + } + + // Start the animation. + s.Begin(); + + // When the animation is completed, undo the trickiness from before, to + // restore the controls to the behavior they'd usually have. + animation.Completed([control, childGrid, splitWidth](auto&&, auto&&) { + if (splitWidth) + { + control.Width(NAN); + childGrid.Width(NAN); + childGrid.HorizontalAlignment(HorizontalAlignment::Stretch); + control.HorizontalAlignment(HorizontalAlignment::Stretch); + } + else + { + control.Height(NAN); + childGrid.Height(NAN); + childGrid.VerticalAlignment(VerticalAlignment::Stretch); + control.VerticalAlignment(VerticalAlignment::Stretch); + } + }); +} + // Method Description: // - Determines whether the pane can be split // Arguments: @@ -1179,58 +1274,7 @@ std::pair, std::shared_ptr> Pane::_Split(SplitState _lastActive = false; - // const auto firstPercent = _desiredSplitPosition; - // const auto secondPercent = 1.0f - firstPercent; - // auto secondWidth = secondPercent * _root.ActualWidth(); - const bool splitWidth = _splitState == SplitState::Vertical; - auto [firstSize, secondSize] = _CalcChildrenSizes(::base::saturated_cast(splitWidth ? _root.ActualWidth() : _root.ActualHeight())); - - auto childGrid = _secondChild->_root; - Duration duration{ std::chrono::milliseconds{ 166 } }; - Duration d2 = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(300))); - Media::Animation::DoubleAnimation animation{}; - animation.Duration(d2); - animation.From(0.0); - animation.To(secondSize); - // d.EasingFunction(Media::Animation::SineEase{}); - animation.EasingFunction(Media::Animation::QuadraticEase{}); - // animation.EasingFunction(Media::Animation::CubicEase{}); - animation.EnableDependentAnimation(true); - Media::Animation::Storyboard s; - s.Duration(d2); - s.Children().Append(animation); - s.SetTarget(animation, childGrid); - s.SetTargetProperty(animation, splitWidth ? L"Width" : L"Height"); - _root.Resources().Insert(winrt::box_value(L"paneAnimation"), s); - s.Begin(); - if (splitWidth) - { - childGrid.HorizontalAlignment(HorizontalAlignment::Right); - control.HorizontalAlignment(HorizontalAlignment::Left); - control.Width(secondSize); - } - else - { - childGrid.VerticalAlignment(VerticalAlignment::Bottom); - control.VerticalAlignment(VerticalAlignment::Top); - control.Height(secondSize); - } - animation.Completed([control, childGrid, splitWidth](auto&&, auto&&) { - if (splitWidth) - { - control.Width(NAN); - childGrid.Width(NAN); - childGrid.HorizontalAlignment(HorizontalAlignment::Stretch); - control.HorizontalAlignment(HorizontalAlignment::Stretch); - } - else - { - control.Height(NAN); - childGrid.Height(NAN); - childGrid.VerticalAlignment(VerticalAlignment::Stretch); - control.VerticalAlignment(VerticalAlignment::Stretch); - } - }); + _SetupEntranceAnimation(); return { _firstChild, _secondChild }; } diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h index 6d1ffa133f1..8ed4062eac0 100644 --- a/src/cascadia/TerminalApp/Pane.h +++ b/src/cascadia/TerminalApp/Pane.h @@ -119,6 +119,7 @@ class Pane : public std::enable_shared_from_this void _CreateRowColDefinitions(); void _ApplySplitDefinitions(); + void _SetupEntranceAnimation(); void _UpdateBorders(); bool _Resize(const winrt::TerminalApp::Direction& direction); From dcbba94b62558291e446ece9282a905790390a92 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 21 Aug 2020 08:18:02 -0500 Subject: [PATCH 06/17] Try animating both the first and second panes This doesn't work, so I'm reverting it. The grid layout is created first and foremost, so the first pane is already clipped to the smaller size, no matter what. So let's just not. --- src/cascadia/TerminalApp/Pane.cpp | 152 +++++++++++++++++------------- 1 file changed, 84 insertions(+), 68 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index acf0a400d66..909d82735c7 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -916,8 +916,9 @@ void Pane::_SetupEntranceAnimation() const auto [firstSize, secondSize] = _CalcChildrenSizes(::base::saturated_cast(totalSize)); - auto childGrid = _secondChild->_root; - auto control = _secondChild->_control; + // auto childGrid = _secondChild->_root; + // auto control = _secondChild->_control; + // WARNING: Don't do this! This won't work // Duration duration{ std::chrono::milliseconds{ 166 } }; // Instead, make a duration from a timespan from the time in millis @@ -926,78 +927,93 @@ void Pane::_SetupEntranceAnimation() // flow, but not too quick to see Duration duration = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(200))); - // Build up our animation: - // * it'll take as long as our duration (300ms) - // * it'll change the value of our property from 0 to secondSize - // * it'll animate that value using a quadratic function (like f(t) = t^2) - // * IMPORTANT! We'll manually tell the animation that "yes we know what - // we're doing, we want an animation here." - Media::Animation::DoubleAnimation animation{}; - animation.Duration(duration); - animation.From(0.0); - animation.To(secondSize); - animation.EasingFunction(Media::Animation::QuadraticEase{}); - animation.EnableDependentAnimation(true); - - // Now we're going to set up the Storyboard. This is a unit that uses the - // Animation from above, and actually applies it to a property. - // * we'll set it up for the same duration as the animation we have - // * Apply the animation to the grid of the new pane we're adding to the tree. - // * apply the animation to the Width or Height property. - // * add the storyboard to our resources. TODO: I don't know if this is necessary. - Media::Animation::Storyboard s; - s.Duration(duration); - s.Children().Append(animation); - s.SetTarget(animation, childGrid); - s.SetTargetProperty(animation, splitWidth ? L"Width" : L"Height"); - _root.Resources().Insert(winrt::box_value(L"paneAnimation"), s); - - // BE TRICKY: - // We're animating the width or height of our child pane's grid. - // - // We DON'T want to change the size of the control itself, because the - // terminal has to reflow the buffer every time the control changes size. So - // what we're going to do there is manually set the control's size to how - // big we _actually know_ the control will be. - // - // We're also going to be changing alignment of our child pane and the - // control. This way, we'll be able to have the control stick to the inside - // of the child pane's grid (the side that's moving), while we also have the - // pane's grid stick to "outside" of the grid (the side that's not moving) - if (splitWidth) - { - childGrid.HorizontalAlignment(HorizontalAlignment::Right); - control.HorizontalAlignment(HorizontalAlignment::Left); - control.Width(secondSize); - } - else - { - childGrid.VerticalAlignment(VerticalAlignment::Bottom); - control.VerticalAlignment(VerticalAlignment::Top); - control.Height(secondSize); - } - - // Start the animation. - s.Begin(); - - // When the animation is completed, undo the trickiness from before, to - // restore the controls to the behavior they'd usually have. - animation.Completed([control, childGrid, splitWidth](auto&&, auto&&) { + auto setupAnimation = [&duration, &totalSize, &splitWidth](auto child, const auto& size, const bool isFirstChild) { + auto childGrid = child->_root; + auto control = child->_control; + // Build up our animation: + // * it'll take as long as our duration (300ms) + // * it'll change the value of our property from 0 to secondSize + // * it'll animate that value using a quadratic function (like f(t) = t^2) + // * IMPORTANT! We'll manually tell the animation that "yes we know what + // we're doing, we want an animation here." + Media::Animation::DoubleAnimation animation{}; + animation.Duration(duration); + if (isFirstChild) + { + animation.From(totalSize); + animation.To(size); + } + else + { + animation.From(0.0); + animation.To(size); + } + animation.EasingFunction(Media::Animation::QuadraticEase{}); + animation.EnableDependentAnimation(true); + + // Now we're going to set up the Storyboard. This is a unit that uses the + // Animation from above, and actually applies it to a property. + // * we'll set it up for the same duration as the animation we have + // * Apply the animation to the grid of the new pane we're adding to the tree. + // * apply the animation to the Width or Height property. + // * add the storyboard to our resources. TODO: I don't know if this is necessary. + Media::Animation::Storyboard s; + s.Duration(duration); + s.Children().Append(animation); + s.SetTarget(animation, childGrid); + s.SetTargetProperty(animation, splitWidth ? L"Width" : L"Height"); + // _root.Resources().Insert(winrt::box_value(L"paneAnimation"), s); + + // BE TRICKY: + // We're animating the width or height of our child pane's grid. + // + // We DON'T want to change the size of the control itself, because the + // terminal has to reflow the buffer every time the control changes size. So + // what we're going to do there is manually set the control's size to how + // big we _actually know_ the control will be. + // + // We're also going to be changing alignment of our child pane and the + // control. This way, we'll be able to have the control stick to the inside + // of the child pane's grid (the side that's moving), while we also have the + // pane's grid stick to "outside" of the grid (the side that's not moving) if (splitWidth) { - control.Width(NAN); - childGrid.Width(NAN); - childGrid.HorizontalAlignment(HorizontalAlignment::Stretch); - control.HorizontalAlignment(HorizontalAlignment::Stretch); + childGrid.HorizontalAlignment(isFirstChild ? HorizontalAlignment::Left : HorizontalAlignment::Right); + control.HorizontalAlignment(HorizontalAlignment::Left); + control.Width(isFirstChild ? totalSize : size); } else { - control.Height(NAN); - childGrid.Height(NAN); - childGrid.VerticalAlignment(VerticalAlignment::Stretch); - control.VerticalAlignment(VerticalAlignment::Stretch); + childGrid.VerticalAlignment(isFirstChild ? VerticalAlignment::Top : VerticalAlignment::Bottom); + control.VerticalAlignment(VerticalAlignment::Top); + control.Height(isFirstChild ? totalSize : size); } - }); + + // Start the animation. + s.Begin(); + + // When the animation is completed, undo the trickiness from before, to + // restore the controls to the behavior they'd usually have. + animation.Completed([control, childGrid, splitWidth](auto&&, auto&&) { + if (splitWidth) + { + control.Width(NAN); + childGrid.Width(NAN); + childGrid.HorizontalAlignment(HorizontalAlignment::Stretch); + control.HorizontalAlignment(HorizontalAlignment::Stretch); + } + else + { + control.Height(NAN); + childGrid.Height(NAN); + childGrid.VerticalAlignment(VerticalAlignment::Stretch); + control.VerticalAlignment(VerticalAlignment::Stretch); + } + }); + }; + + // setupAnimation(_firstChild, firstSize, true); + setupAnimation(_secondChild, secondSize, false); } // Method Description: From a09ec805832d331d26ef90bf58f834c4ad6831f4 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 21 Aug 2020 09:06:21 -0500 Subject: [PATCH 07/17] Pane.cpp is ready for review, just gotta add the setting now --- src/cascadia/TerminalApp/Pane.cpp | 75 +++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 24 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 909d82735c7..d0ced3c3630 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -42,6 +42,8 @@ Pane::Pane(const GUID& profile, const TermControl& control, const bool lastFocus _SetupResources(); } + // Use the unfocused border color as the pane background, so an actual color + // appears behind panes as we animate them sliding in. _root.Background(s_unfocusedBorderBrush); // Register an event with the control to have it inform us when it gains focus. @@ -905,10 +907,17 @@ void Pane::_ApplySplitDefinitions() } } +// Method Description: +// - Create a pair of animations when a new control enters this pane. This +// should _ONLY_ be called in _Split, AFTER the first and second child panes +// have been set up. void Pane::_SetupEntranceAnimation() { const bool splitWidth = _splitState == SplitState::Vertical; const auto totalSize = splitWidth ? _root.ActualWidth() : _root.ActualHeight(); + // If we don't have a size yet, it's likely that we're in startup, or we're + // being executed as a sequence of actions. In that case, just skip the + // animation. if (totalSize <= 0) { return; @@ -916,22 +925,22 @@ void Pane::_SetupEntranceAnimation() const auto [firstSize, secondSize] = _CalcChildrenSizes(::base::saturated_cast(totalSize)); - // auto childGrid = _secondChild->_root; - // auto control = _secondChild->_control; - // WARNING: Don't do this! This won't work - // Duration duration{ std::chrono::milliseconds{ 166 } }; + // Duration duration{ std::chrono::milliseconds{ 200 } }; // Instead, make a duration from a timespan from the time in millis // - // 300ms was chosen because it's quick enough that it doesn't break your + // 100ms was chosen because it's quick enough that it doesn't break your // flow, but not too quick to see Duration duration = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(200))); - auto setupAnimation = [&duration, &totalSize, &splitWidth](auto child, const auto& size, const bool isFirstChild) { + // This is safe to capture this, because it's only being called in the + // context of this method (not on another thread) + auto setupAnimation = [&](const auto& size, const bool isFirstChild) { + auto child = isFirstChild ? _firstChild : _secondChild; auto childGrid = child->_root; auto control = child->_control; // Build up our animation: - // * it'll take as long as our duration (300ms) + // * it'll take as long as our duration (200ms) // * it'll change the value of our property from 0 to secondSize // * it'll animate that value using a quadratic function (like f(t) = t^2) // * IMPORTANT! We'll manually tell the animation that "yes we know what @@ -940,11 +949,15 @@ void Pane::_SetupEntranceAnimation() animation.Duration(duration); if (isFirstChild) { + // If we're animating the first pane, the size should decrease, form the + // full size down to the given size. animation.From(totalSize); animation.To(size); } else { + // Otherwise, we want to show the pane getting larger, so animate + // from 0 to the requested size. animation.From(0.0); animation.To(size); } @@ -956,13 +969,11 @@ void Pane::_SetupEntranceAnimation() // * we'll set it up for the same duration as the animation we have // * Apply the animation to the grid of the new pane we're adding to the tree. // * apply the animation to the Width or Height property. - // * add the storyboard to our resources. TODO: I don't know if this is necessary. Media::Animation::Storyboard s; s.Duration(duration); s.Children().Append(animation); s.SetTarget(animation, childGrid); s.SetTargetProperty(animation, splitWidth ? L"Width" : L"Height"); - // _root.Resources().Insert(winrt::box_value(L"paneAnimation"), s); // BE TRICKY: // We're animating the width or height of our child pane's grid. @@ -978,12 +989,18 @@ void Pane::_SetupEntranceAnimation() // pane's grid stick to "outside" of the grid (the side that's not moving) if (splitWidth) { + // If we're animating the first child, then stick to the top/left of + // the parent pane, otherwise use the bottom/right. This is always + // the "outside" of the parent pane. childGrid.HorizontalAlignment(isFirstChild ? HorizontalAlignment::Left : HorizontalAlignment::Right); control.HorizontalAlignment(HorizontalAlignment::Left); control.Width(isFirstChild ? totalSize : size); } else { + // If we're animating the first child, then stick to the top/left of + // the parent pane, otherwise use the bottom/right. This is always + // the "outside" of the parent pane. childGrid.VerticalAlignment(isFirstChild ? VerticalAlignment::Top : VerticalAlignment::Bottom); control.VerticalAlignment(VerticalAlignment::Top); control.Height(isFirstChild ? totalSize : size); @@ -992,28 +1009,38 @@ void Pane::_SetupEntranceAnimation() // Start the animation. s.Begin(); + std::weak_ptr weakThis{ shared_from_this() }; // When the animation is completed, undo the trickiness from before, to // restore the controls to the behavior they'd usually have. - animation.Completed([control, childGrid, splitWidth](auto&&, auto&&) { - if (splitWidth) - { - control.Width(NAN); - childGrid.Width(NAN); - childGrid.HorizontalAlignment(HorizontalAlignment::Stretch); - control.HorizontalAlignment(HorizontalAlignment::Stretch); - } - else + animation.Completed([weakThis, isFirstChild, splitWidth](auto&&, auto&&) { + if (auto pane{ weakThis.lock() }) { - control.Height(NAN); - childGrid.Height(NAN); - childGrid.VerticalAlignment(VerticalAlignment::Stretch); - control.VerticalAlignment(VerticalAlignment::Stretch); + auto child = isFirstChild ? pane->_firstChild : pane->_secondChild; + auto childGrid = child->_root; + auto control = child->_control; + + if (splitWidth) + { + control.Width(NAN); + childGrid.Width(NAN); + childGrid.HorizontalAlignment(HorizontalAlignment::Stretch); + control.HorizontalAlignment(HorizontalAlignment::Stretch); + } + else + { + control.Height(NAN); + childGrid.Height(NAN); + childGrid.VerticalAlignment(VerticalAlignment::Stretch); + control.VerticalAlignment(VerticalAlignment::Stretch); + } } }); }; - // setupAnimation(_firstChild, firstSize, true); - setupAnimation(_secondChild, secondSize, false); + // TODO: GH#TODO - animating the first child right now doesn't _really_ do + // anything. We could do better though. + setupAnimation(firstSize, true); + setupAnimation(secondSize, false); } // Method Description: From 522ab15d922ab14fdf0540fea439bd3f59745967 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 21 Aug 2020 09:40:23 -0500 Subject: [PATCH 08/17] add a setting to disable animations, ready for review --- doc/cascadia/profiles.schema.json | 5 ++++ .../TerminalApp/GlobalAppSettings.cpp | 3 ++ src/cascadia/TerminalApp/GlobalAppSettings.h | 1 + src/cascadia/TerminalApp/Pane.cpp | 29 ++++++++++--------- src/cascadia/TerminalApp/TerminalPage.cpp | 5 ++++ src/cascadia/TerminalApp/defaults.json | 1 + 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 1f28228137a..312b11870c3 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -510,6 +510,11 @@ "description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. An array of specific formats can also be used. Supported array values include `html` and `rtf`. Plain text is always copied.", "$ref": "#/definitions/CopyFormat" }, + "disableAnimations": { + "default": false, + "description": "When set to `true`, visual animations will be disabled across the application.", + "type": "boolean" + }, "largePasteWarning": { "default": true, "description": "When set to true, trying to paste text with more than 5 KiB of characters will display a warning asking you whether to continue or not with the paste.", diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.cpp b/src/cascadia/TerminalApp/GlobalAppSettings.cpp index 449502509cd..4f86b6349b5 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalApp/GlobalAppSettings.cpp @@ -36,6 +36,7 @@ static constexpr std::string_view ConfirmCloseAllKey{ "confirmCloseAllTabs" }; static constexpr std::string_view SnapToGridOnResizeKey{ "snapToGridOnResize" }; static constexpr std::string_view EnableStartupTaskKey{ "startOnUserLogin" }; static constexpr std::string_view AlwaysOnTopKey{ "alwaysOnTop" }; +static constexpr std::string_view DisableAnimationsKey{ "disableAnimations" }; static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" }; @@ -180,6 +181,8 @@ void GlobalAppSettings::LayerJson(const Json::Value& json) JsonUtils::GetValueForKey(json, AlwaysOnTopKey, _AlwaysOnTop); + JsonUtils::GetValueForKey(json, DisableAnimationsKey, _DisableAnimations); + // This is a helper lambda to get the keybindings and commands out of both // and array of objects. We'll use this twice, once on the legacy // `keybindings` key, and again on the newer `bindings` key. diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.h b/src/cascadia/TerminalApp/GlobalAppSettings.h index bc00276f8d4..74d532bd624 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.h +++ b/src/cascadia/TerminalApp/GlobalAppSettings.h @@ -82,6 +82,7 @@ class TerminalApp::GlobalAppSettings final GETSET_PROPERTY(bool, DebugFeaturesEnabled); // default value set in constructor GETSET_PROPERTY(bool, StartOnUserLogin, false); GETSET_PROPERTY(bool, AlwaysOnTop, false); + GETSET_PROPERTY(bool, DisableAnimations, false); private: std::optional _unparsedDefaultProfile; diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index d0ced3c3630..48cb35ffe74 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -1017,21 +1017,22 @@ void Pane::_SetupEntranceAnimation() { auto child = isFirstChild ? pane->_firstChild : pane->_secondChild; auto childGrid = child->_root; - auto control = child->_control; - - if (splitWidth) - { - control.Width(NAN); - childGrid.Width(NAN); - childGrid.HorizontalAlignment(HorizontalAlignment::Stretch); - control.HorizontalAlignment(HorizontalAlignment::Stretch); - } - else + if (auto control = child->_control) { - control.Height(NAN); - childGrid.Height(NAN); - childGrid.VerticalAlignment(VerticalAlignment::Stretch); - control.VerticalAlignment(VerticalAlignment::Stretch); + if (splitWidth) + { + control.Width(NAN); + childGrid.Width(NAN); + childGrid.HorizontalAlignment(HorizontalAlignment::Stretch); + control.HorizontalAlignment(HorizontalAlignment::Stretch); + } + else + { + control.Height(NAN); + childGrid.Height(NAN); + childGrid.VerticalAlignment(VerticalAlignment::Stretch); + control.VerticalAlignment(VerticalAlignment::Stretch); + } } } }); diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 7049dcf2841..11c40bb56f2 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2044,6 +2044,11 @@ namespace winrt::TerminalApp::implementation // the alwaysOnTop setting will be lost. _isAlwaysOnTop = _settings->GlobalSettings().AlwaysOnTop(); _alwaysOnTopChangedHandlers(*this, nullptr); + + // 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. + WUX::Media::Animation::Timeline::AllowDependentAnimations(!_settings->GlobalSettings().DisableAnimations()); } // This is a helper to aid in sorting commands by their `Name`s, alphabetically. diff --git a/src/cascadia/TerminalApp/defaults.json b/src/cascadia/TerminalApp/defaults.json index bab95d13a85..e7140ea1190 100644 --- a/src/cascadia/TerminalApp/defaults.json +++ b/src/cascadia/TerminalApp/defaults.json @@ -24,6 +24,7 @@ "startOnUserLogin": false, "theme": "system", "snapToGridOnResize": true, + "disableAnimations": false, "profiles": [ From 188c9690bd334ea1aab129e78837a37894350307 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 21 Aug 2020 09:52:58 -0500 Subject: [PATCH 09/17] okay bot --- src/cascadia/TerminalApp/Pane.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 48cb35ffe74..bebd09d042a 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -927,7 +927,7 @@ void Pane::_SetupEntranceAnimation() // WARNING: Don't do this! This won't work // Duration duration{ std::chrono::milliseconds{ 200 } }; - // Instead, make a duration from a timespan from the time in millis + // Instead, make a duration from a TimeSpan from the time in millis // // 100ms was chosen because it's quick enough that it doesn't break your // flow, but not too quick to see @@ -1038,7 +1038,7 @@ void Pane::_SetupEntranceAnimation() }); }; - // TODO: GH#TODO - animating the first child right now doesn't _really_ do + // TODO: GH#7365 - animating the first child right now doesn't _really_ do // anything. We could do better though. setupAnimation(firstSize, true); setupAnimation(secondSize, false); From fde5dca2b048f3a9873758a7ba2326c69d934453 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 27 Aug 2020 10:19:35 -0500 Subject: [PATCH 10/17] holy shit it finally worked --- src/cascadia/TerminalApp/Pane.cpp | 140 +++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index bebd09d042a..34b2567e5a8 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -331,7 +331,8 @@ void Pane::_ControlConnectionStateChangedHandler(const TermControl& /*sender*/, if ((mode == CloseOnExitMode::Always) || (mode == CloseOnExitMode::Graceful && newConnectionState == ConnectionState::Closed)) { - _ClosedHandlers(nullptr, nullptr); + // _ClosedHandlers(nullptr, nullptr); + Close(); } } } @@ -765,7 +766,142 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst) if (auto pane{ weakThis.get() }) { - _CloseChild(closeFirst); + auto removedChild = closeFirst ? _firstChild : _secondChild; + auto remainingChild = closeFirst ? _secondChild : _firstChild; + const bool splitWidth = _splitState == SplitState::Vertical; + const auto totalSize = splitWidth ? _root.ActualWidth() : _root.ActualHeight(); + + Size removedOriginalSize{ + ::base::saturated_cast(removedChild->_root.ActualWidth()), + ::base::saturated_cast(removedChild->_root.ActualHeight()) + }; + Size remainingOriginalSize{ + ::base::saturated_cast(remainingChild->_root.ActualWidth()), + ::base::saturated_cast(remainingChild->_root.ActualHeight()) + }; + + // Remove both children from the grid + _root.Children().Clear(); + // Add the remaining child back to the grid + _root.Children().Append(remainingChild->GetRootElement()); + if (_splitState == SplitState::Vertical) + { + Controls::Grid::SetColumn(remainingChild->GetRootElement(), closeFirst ? 1 : 0); + } + else if (_splitState == SplitState::Horizontal) + { + Controls::Grid::SetRow(remainingChild->GetRootElement(), closeFirst ? 1 : 0); + } + + // Create the dummy grid + Controls::Grid dummyGrid; + Color magenta = ColorHelper::FromArgb(255, 255, 0, 255); + SolidColorBrush b; + b.Color(magenta); + dummyGrid.Background(b); + dummyGrid.Width(removedOriginalSize.Width); + dummyGrid.Height(removedOriginalSize.Height); + // Put it where the removed child is + if (_splitState == SplitState::Vertical) + { + Controls::Grid::SetColumn(dummyGrid, closeFirst ? 0 : 1); + } + else if (_splitState == SplitState::Horizontal) + { + Controls::Grid::SetRow(dummyGrid, closeFirst ? 0 : 1); + } + // Add it to the tree + _root.Children().Append(dummyGrid); + + // Set up the rows/cols as auto/auto, so they'll only use the size of + // the elements in the grid. + _root.ColumnDefinitions().Clear(); + _root.RowDefinitions().Clear(); + if (_splitState == SplitState::Vertical) + { + auto firstColDef = Controls::ColumnDefinition(); + auto secondColDef = Controls::ColumnDefinition(); + firstColDef.Width(!closeFirst ? GridLengthHelper::FromValueAndType(1, GridUnitType::Star) : GridLengthHelper::Auto()); + secondColDef.Width(closeFirst ? GridLengthHelper::FromValueAndType(1, GridUnitType::Star) : GridLengthHelper::Auto()); + _root.ColumnDefinitions().Append(firstColDef); + _root.ColumnDefinitions().Append(secondColDef); + } + else if (_splitState == SplitState::Horizontal) + { + auto firstRowDef = Controls::RowDefinition(); + auto secondRowDef = Controls::RowDefinition(); + firstRowDef.Height(!closeFirst ? GridLengthHelper::FromValueAndType(1, GridUnitType::Star) : GridLengthHelper::Auto()); + secondRowDef.Height(closeFirst ? GridLengthHelper::FromValueAndType(1, GridUnitType::Star) : GridLengthHelper::Auto()); + _root.RowDefinitions().Append(firstRowDef); + _root.RowDefinitions().Append(secondRowDef); + } + + // TODO: + // If the remaining child isn't a leaf, then pre-size it's children to + // the space they'll use in when they take up this full space. + // + // const auto [firstSize, secondSize] = remainingChild->_CalcChildrenSizes(::base::saturated_cast(totalSize)); + + // Set the remaining grid to manually be the size of us + if (splitWidth) + { + // remainingChild->_root.Width(totalSize); + // remainingChild->_root.Width(remainingOriginalSize.Width); + // remainingChild->_root.HorizontalAlignment(HorizontalAlignment::Left); + } + else + { + // remainingChild->_root.Height(totalSize); + // remainingChild->_root.Height(remainingOriginalSize.Height); + // remainingChild->_root.VerticalAlignment(VerticalAlignment::Top); + } + + // Animate the dummy grid from it's current size down to 0 + + Duration duration = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(1000))); + + Media::Animation::DoubleAnimation animation{}; + animation.Duration(duration); + animation.From(splitWidth ? removedOriginalSize.Width : removedOriginalSize.Height); + animation.To(0.0); + animation.EasingFunction(Media::Animation::QuadraticEase{}); + animation.EnableDependentAnimation(true); + + Media::Animation::Storyboard s; + s.Duration(duration); + s.Children().Append(animation); + s.SetTarget(animation, dummyGrid); + s.SetTargetProperty(animation, splitWidth ? L"Width" : L"Height"); + + // Start the animation. + s.Begin(); + + std::weak_ptr weakThis{ shared_from_this() }; + // When the animation is completed, undo the trickiness from before, to + // restore the controls to the behavior they'd usually have. + animation.Completed([weakThis, closeFirst, splitWidth](auto&&, auto&&) { + if (auto pane{ weakThis.lock() }) + { + auto remainingChild = closeFirst ? pane->_secondChild : pane->_firstChild; + // Remove both children from the grid + pane->_root.Children().Clear(); + // Add the remaining child back to the grid + pane->_root.Children().Append(remainingChild->GetRootElement()); + + if (splitWidth) + { + remainingChild->_root.Width(NAN); + remainingChild->_root.HorizontalAlignment(HorizontalAlignment::Stretch); + } + else + { + remainingChild->_root.Height(NAN); + remainingChild->_root.VerticalAlignment(VerticalAlignment::Stretch); + } + + pane->_CloseChild(closeFirst); + } + }); } } From 38ddc35aa1cf72c8e95c4d578ddc2a14fb5567e6 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 27 Aug 2020 11:19:02 -0500 Subject: [PATCH 11/17] Update this to look more crisp --- src/cascadia/TerminalApp/Pane.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 34b2567e5a8..53435c51987 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -795,10 +795,11 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst) // Create the dummy grid Controls::Grid dummyGrid; - Color magenta = ColorHelper::FromArgb(255, 255, 0, 255); - SolidColorBrush b; - b.Color(magenta); - dummyGrid.Background(b); + // Color magenta = ColorHelper::FromArgb(255, 255, 0, 255); + // SolidColorBrush b; + // b.Color(magenta); + // dummyGrid.Background(b); + dummyGrid.Background(s_unfocusedBorderBrush); dummyGrid.Width(removedOriginalSize.Width); dummyGrid.Height(removedOriginalSize.Height); // Put it where the removed child is @@ -858,7 +859,7 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst) // Animate the dummy grid from it's current size down to 0 - Duration duration = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(1000))); + Duration duration = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(200))); Media::Animation::DoubleAnimation animation{}; animation.Duration(duration); From ae04952653f38ba79aa1bb48da43cd07150fbe03 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 27 Aug 2020 11:56:54 -0500 Subject: [PATCH 12/17] Clean up this code for review --- src/cascadia/TerminalApp/Pane.cpp | 84 +++++++++-------------- src/cascadia/TerminalApp/TerminalPage.cpp | 5 ++ 2 files changed, 38 insertions(+), 51 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 53435c51987..05beaeb0ec7 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -20,6 +20,8 @@ using namespace TerminalApp; static const int PaneBorderSize = 2; static const int CombinedPaneBorderSize = 2 * PaneBorderSize; static const float Half = 0.50f; +static const int AnimationDurationInMilliseconds = 200; +static const Duration AnimationDuration = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(AnimationDurationInMilliseconds))); winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_focusedBorderBrush = { nullptr }; winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_unfocusedBorderBrush = { nullptr }; @@ -766,6 +768,18 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst) if (auto pane{ weakThis.get() }) { + // If animations are disabled, just skip this and go straight to + // _CloseChild. Curiously, the pane opening animation doesn't need this, + // and will skip straight to Completed when animations are disabled, but + // this one doesn't seem to. + if (!Media::Animation::Timeline::AllowDependentAnimations()) + { + pane->_CloseChild(closeFirst); + return; + } + + // Setup the animation + auto removedChild = closeFirst ? _firstChild : _secondChild; auto remainingChild = closeFirst ? _secondChild : _firstChild; const bool splitWidth = _splitState == SplitState::Vertical; @@ -782,7 +796,7 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst) // Remove both children from the grid _root.Children().Clear(); - // Add the remaining child back to the grid + // Add the remaining child back to the grid, in the right place. _root.Children().Append(remainingChild->GetRootElement()); if (_splitState == SplitState::Vertical) { @@ -793,13 +807,11 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst) Controls::Grid::SetRow(remainingChild->GetRootElement(), closeFirst ? 1 : 0); } - // Create the dummy grid + // Create the dummy grid. This grid will be the one we actually animate, + // in the place of the closed pane. Controls::Grid dummyGrid; - // Color magenta = ColorHelper::FromArgb(255, 255, 0, 255); - // SolidColorBrush b; - // b.Color(magenta); - // dummyGrid.Background(b); dummyGrid.Background(s_unfocusedBorderBrush); + // It should be the size of the closed pane. dummyGrid.Width(removedOriginalSize.Width); dummyGrid.Height(removedOriginalSize.Height); // Put it where the removed child is @@ -816,6 +828,12 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst) // Set up the rows/cols as auto/auto, so they'll only use the size of // the elements in the grid. + // + // * For the closed pane, we want to make that row/col "auto" sized, so + // it takes up as much space as is available. + // * For the remaining pane, we'll make that row/col "*" sized, so it + // takes all the remaining space. As the dummy grid is resized down, + // the remaining pane will expand to take the rest of the space. _root.ColumnDefinitions().Clear(); _root.RowDefinitions().Clear(); if (_splitState == SplitState::Vertical) @@ -837,39 +855,17 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst) _root.RowDefinitions().Append(secondRowDef); } - // TODO: - // If the remaining child isn't a leaf, then pre-size it's children to - // the space they'll use in when they take up this full space. - // - // const auto [firstSize, secondSize] = remainingChild->_CalcChildrenSizes(::base::saturated_cast(totalSize)); - - // Set the remaining grid to manually be the size of us - if (splitWidth) - { - // remainingChild->_root.Width(totalSize); - // remainingChild->_root.Width(remainingOriginalSize.Width); - // remainingChild->_root.HorizontalAlignment(HorizontalAlignment::Left); - } - else - { - // remainingChild->_root.Height(totalSize); - // remainingChild->_root.Height(remainingOriginalSize.Height); - // remainingChild->_root.VerticalAlignment(VerticalAlignment::Top); - } - // Animate the dummy grid from it's current size down to 0 - - Duration duration = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(200))); - Media::Animation::DoubleAnimation animation{}; - animation.Duration(duration); + animation.Duration(AnimationDuration); animation.From(splitWidth ? removedOriginalSize.Width : removedOriginalSize.Height); animation.To(0.0); + // This easing is the same as the entrance animation. animation.EasingFunction(Media::Animation::QuadraticEase{}); animation.EnableDependentAnimation(true); Media::Animation::Storyboard s; - s.Duration(duration); + s.Duration(AnimationDuration); s.Children().Append(animation); s.SetTarget(animation, dummyGrid); s.SetTargetProperty(animation, splitWidth ? L"Width" : L"Height"); @@ -878,28 +874,14 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst) s.Begin(); std::weak_ptr weakThis{ shared_from_this() }; - // When the animation is completed, undo the trickiness from before, to - // restore the controls to the behavior they'd usually have. - animation.Completed([weakThis, closeFirst, splitWidth](auto&&, auto&&) { + + // When the animation is completed, reparent the child's content up to + // us, and remove the child nodes from the tree. + animation.Completed([weakThis, closeFirst](auto&&, auto&&) { if (auto pane{ weakThis.lock() }) { - auto remainingChild = closeFirst ? pane->_secondChild : pane->_firstChild; - // Remove both children from the grid - pane->_root.Children().Clear(); - // Add the remaining child back to the grid - pane->_root.Children().Append(remainingChild->GetRootElement()); - - if (splitWidth) - { - remainingChild->_root.Width(NAN); - remainingChild->_root.HorizontalAlignment(HorizontalAlignment::Stretch); - } - else - { - remainingChild->_root.Height(NAN); - remainingChild->_root.VerticalAlignment(VerticalAlignment::Stretch); - } - + // We don't need to manually undo any of the above trickiness. + // We're going to re-parent the child's content into us anyways pane->_CloseChild(closeFirst); } }); diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index dc425f05c8b..0c707eeb51b 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -251,6 +251,11 @@ namespace winrt::TerminalApp::implementation } }); + // 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. + WUX::Media::Animation::Timeline::AllowDependentAnimations(!_settings->GlobalSettings().DisableAnimations()); + // Once the page is actually laid out on the screen, trigger all our // startup actions. Things like Panes need to know at least how big the // window will be, so they can subdivide that space. From bcb675fcda541172aa0b170456c6d7877a6450de Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 27 Aug 2020 15:11:22 -0500 Subject: [PATCH 13/17] gottem --- src/cascadia/TerminalApp/Pane.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 05beaeb0ec7..6e430d68dc5 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -333,7 +333,6 @@ void Pane::_ControlConnectionStateChangedHandler(const TermControl& /*sender*/, if ((mode == CloseOnExitMode::Always) || (mode == CloseOnExitMode::Graceful && newConnectionState == ConnectionState::Closed)) { - // _ClosedHandlers(nullptr, nullptr); Close(); } } From cddf16c6f0705c146aff6f4509da80397d2e6fbf Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 28 Aug 2020 12:11:06 -0500 Subject: [PATCH 14/17] disable this animation when animations are disabled in the OS --- .../TerminalApp/GlobalAppSettings.idl | 1 + src/cascadia/TerminalApp/Pane.cpp | 36 ++++++++++++------- src/cascadia/TerminalApp/pch.h | 1 + 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.idl b/src/cascadia/TerminalApp/GlobalAppSettings.idl index 6b0de0440ab..9dcf9eb90a5 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.idl +++ b/src/cascadia/TerminalApp/GlobalAppSettings.idl @@ -46,6 +46,7 @@ namespace TerminalApp Boolean StartOnUserLogin; Boolean AlwaysOnTop; Boolean UseTabSwitcher; + Boolean DisableAnimations; Windows.Foundation.Collections.IMapView GetColorSchemes(); void AddColorScheme(ColorScheme scheme); diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 19319d8acf2..bb3ca8c0c75 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -20,6 +20,13 @@ using namespace TerminalApp; static const int PaneBorderSize = 2; static const int CombinedPaneBorderSize = 2 * PaneBorderSize; static const float Half = 0.50f; + +// WARNING: Don't do this! This won't work +// Duration duration{ std::chrono::milliseconds{ 200 } }; +// Instead, make a duration from a TimeSpan from the time in millis +// +// 200ms was chosen because it's quick enough that it doesn't break your +// flow, but not too quick to see static const int AnimationDurationInMilliseconds = 200; static const Duration AnimationDuration = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(AnimationDurationInMilliseconds))); @@ -767,14 +774,20 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst) if (auto pane{ weakThis.get() }) { + // This will query if animations are enabled via the "Show animations in + // Windows" setting in the OS + winrt::Windows::UI::ViewManagement::UISettings uiSettings; + const auto animationsEnabledInOS = uiSettings.AnimationsEnabled(); + const auto animationsEnabledInApp = Media::Animation::Timeline::AllowDependentAnimations(); + // If animations are disabled, just skip this and go straight to // _CloseChild. Curiously, the pane opening animation doesn't need this, // and will skip straight to Completed when animations are disabled, but // this one doesn't seem to. - if (!Media::Animation::Timeline::AllowDependentAnimations()) + if (!animationsEnabledInOS || !animationsEnabledInApp) { pane->_CloseChild(closeFirst); - return; + co_return; } // Setup the animation @@ -1031,26 +1044,23 @@ void Pane::_ApplySplitDefinitions() // have been set up. void Pane::_SetupEntranceAnimation() { + // This will query if animations are enabled via the "Show animations in + // Windows" setting in the OS + winrt::Windows::UI::ViewManagement::UISettings uiSettings; + const auto animationsEnabledInOS = uiSettings.AnimationsEnabled(); + const bool splitWidth = _splitState == SplitState::Vertical; const auto totalSize = splitWidth ? _root.ActualWidth() : _root.ActualHeight(); // If we don't have a size yet, it's likely that we're in startup, or we're // being executed as a sequence of actions. In that case, just skip the // animation. - if (totalSize <= 0) + if (totalSize <= 0 || !animationsEnabledInOS) { return; } const auto [firstSize, secondSize] = _CalcChildrenSizes(::base::saturated_cast(totalSize)); - // WARNING: Don't do this! This won't work - // Duration duration{ std::chrono::milliseconds{ 200 } }; - // Instead, make a duration from a TimeSpan from the time in millis - // - // 100ms was chosen because it's quick enough that it doesn't break your - // flow, but not too quick to see - Duration duration = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(200))); - // This is safe to capture this, because it's only being called in the // context of this method (not on another thread) auto setupAnimation = [&](const auto& size, const bool isFirstChild) { @@ -1064,7 +1074,7 @@ void Pane::_SetupEntranceAnimation() // * IMPORTANT! We'll manually tell the animation that "yes we know what // we're doing, we want an animation here." Media::Animation::DoubleAnimation animation{}; - animation.Duration(duration); + animation.Duration(AnimationDuration); if (isFirstChild) { // If we're animating the first pane, the size should decrease, form the @@ -1088,7 +1098,7 @@ void Pane::_SetupEntranceAnimation() // * Apply the animation to the grid of the new pane we're adding to the tree. // * apply the animation to the Width or Height property. Media::Animation::Storyboard s; - s.Duration(duration); + s.Duration(AnimationDuration); s.Children().Append(animation); s.SetTarget(animation, childGrid); s.SetTargetProperty(animation, splitWidth ? L"Width" : L"Height"); diff --git a/src/cascadia/TerminalApp/pch.h b/src/cascadia/TerminalApp/pch.h index 6dd99796713..449921aee5c 100644 --- a/src/cascadia/TerminalApp/pch.h +++ b/src/cascadia/TerminalApp/pch.h @@ -43,6 +43,7 @@ #include "winrt/Windows.UI.Xaml.Markup.h" #include "winrt/Windows.UI.Xaml.Documents.h" #include "winrt/Windows.UI.Xaml.Automation.h" +#include "winrt/Windows.UI.ViewManagement.h" #include #include From 994d7e04073706f7228b3843c76cf2cedb21f6dd Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 29 Sep 2020 07:02:26 -0500 Subject: [PATCH 15/17] spellcheck nits --- src/cascadia/TerminalApp/Pane.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index bb3ca8c0c75..be6f824b241 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -867,7 +867,7 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst) _root.RowDefinitions().Append(secondRowDef); } - // Animate the dummy grid from it's current size down to 0 + // Animate the dummy grid from its current size down to 0 Media::Animation::DoubleAnimation animation{}; animation.Duration(AnimationDuration); animation.From(splitWidth ? removedOriginalSize.Width : removedOriginalSize.Height); @@ -1077,8 +1077,8 @@ void Pane::_SetupEntranceAnimation() animation.Duration(AnimationDuration); if (isFirstChild) { - // If we're animating the first pane, the size should decrease, form the - // full size down to the given size. + // If we're animating the first pane, the size should decrease, from + // the full size down to the given size. animation.From(totalSize); animation.To(size); } From 1653fa3af9287fb57738624e3b2589a87f72e29f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 5 Oct 2020 08:58:44 -0500 Subject: [PATCH 16/17] Some merge conflicts fromt the month I was awaty --- src/cascadia/TerminalApp/TerminalPage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 78deb2d4885..1e6795ec014 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -255,7 +255,7 @@ namespace winrt::TerminalApp::implementation // 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. - WUX::Media::Animation::Timeline::AllowDependentAnimations(!_settings->GlobalSettings().DisableAnimations()); + WUX::Media::Animation::Timeline::AllowDependentAnimations(!_settings.GlobalSettings().DisableAnimations()); // Once the page is actually laid out on the screen, trigger all our // startup actions. Things like Panes need to know at least how big the @@ -2125,7 +2125,7 @@ namespace winrt::TerminalApp::implementation // 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. - WUX::Media::Animation::Timeline::AllowDependentAnimations(!_settings->GlobalSettings().DisableAnimations()); + WUX::Media::Animation::Timeline::AllowDependentAnimations(!_settings.GlobalSettings().DisableAnimations()); } // This is a helper to aid in sorting commands by their `Name`s, alphabetically. From 082be75ab1d331d7d0ffd64667b4f51af56e8d43 Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Fri, 9 Oct 2020 14:55:24 -0700 Subject: [PATCH 17/17] do something to make the azp run