From 59248de1e44c6bd1714d4d17c93e100858c55a20 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 19 Sep 2023 15:03:24 -0500 Subject: [PATCH 01/12] Allow inheriting env vars from `wt` again and other env var changes too (#15897) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR is a few things: * part the first: Convert the `compatibility.reloadEnvironmentVariables` setting to a per-profile one. * The settings should migrate it from the user's old global place to the new one. * We also added it to "Profile>Advanced" while I was here. * Adds a new pair of commandline flags to `new-tab` and `split-pane`: `--inheritEnvironment` / `--reloadEnvironment` * On `wt` launch, bundle the entire environment that `wt` was spawned with, and put it into the `Remoting.CommandlineArgs`, and give them to the monarch (and ultimately, down to `TerminalPage` with the `AppCommandlineArgs`). DO THIS ALWAYS. * As a part of this, we’ll default to _reloading_ if there’s no explicit commandline set, and _inheriting_ if there is. * For example, `wt -- cmd` would inherit, and `wt -p “Command Prompt”` would reload.[^1] * This is a little wacky, but we’re trying to separate out the intentions here: * `wt -- cmd` feels like “I want to run cmd.exe (in a terminal tab)”. That feels like the user would _like_ environment variables from the calling process. They’re doing something more manual, so they get more refined control over it. * `wt` (or `wt -p “Command Prompt”`) is more like, “I want to run the Terminal (or, my Command Prompt profile) using whatever the Terminal would normally do”. So that feels more like a situation where it should just reload by default. (Of course, this will respect their settings here) ## References and Relevant Issues https://github.com/microsoft/terminal/issues/15496#issuecomment-1692450231 has more notes. ## Detailed Description of the Pull Request / Additional comments This is so VERY much plumbing. I'll try to leave comments in the interesting parts. ## PR Checklist - [x] This is not _all_ of #15496. We're also going to do a `-E foo=bar` arg on top of this. - [x] Tests added/passed - [x] Schema updated [^1]: In both these cases, plus the `environment` setting, of course. --- doc/cascadia/profiles.schema.json | 10 +- .../DeserializationTests.cpp | 38 ++++++ .../SerializationTests.cpp | 113 ++++++++++++++++++ src/cascadia/LocalTests_SettingsModel/pch.h | 1 + src/cascadia/Remoting/CommandlineArgs.h | 8 +- src/cascadia/Remoting/Monarch.h | 4 +- src/cascadia/Remoting/Monarch.idl | 1 + src/cascadia/Remoting/Peasant.idl | 3 +- src/cascadia/Remoting/WindowManager.cpp | 5 +- src/cascadia/Remoting/pch.h | 1 + .../TerminalApp/AppCommandlineArgs.cpp | 15 ++- src/cascadia/TerminalApp/AppCommandlineArgs.h | 2 + .../Resources/en-US/Resources.resw | 4 + src/cascadia/TerminalApp/TerminalPage.cpp | 24 +++- src/cascadia/TerminalApp/TerminalPage.h | 3 +- src/cascadia/TerminalApp/TerminalPage.idl | 1 + src/cascadia/TerminalApp/TerminalWindow.cpp | 10 +- src/cascadia/TerminalApp/TerminalWindow.h | 6 +- src/cascadia/TerminalApp/TerminalWindow.idl | 4 +- .../TerminalConnection/ConptyConnection.cpp | 82 ++++++++----- .../TerminalConnection/ConptyConnection.h | 8 +- .../TerminalConnection/ConptyConnection.idl | 4 +- .../TerminalSettingsEditor/ProfileViewModel.h | 3 +- .../ProfileViewModel.idl | 1 + .../Profiles_Advanced.xaml | 9 ++ .../Resources/en-US/Resources.resw | 8 ++ .../TerminalSettingsModel/ActionArgs.h | 7 ++ .../TerminalSettingsModel/ActionArgs.idl | 2 + .../CascadiaSettingsSerialization.cpp | 11 ++ .../GlobalAppSettings.cpp | 3 + .../TerminalSettingsModel/GlobalAppSettings.h | 3 + .../GlobalAppSettings.idl | 1 - .../TerminalSettingsModel/MTSMSettings.h | 4 +- .../TerminalSettingsModel/Profile.idl | 3 + .../TerminalSettings.cpp | 7 ++ .../TerminalSettingsModel/TerminalSettings.h | 2 + .../TerminalSettings.idl | 1 + src/cascadia/TerminalSettingsModel/pch.h | 1 + .../UnitTests_Remoting/RemotingTests.cpp | 34 +++--- src/cascadia/UnitTests_Remoting/pch.h | 1 + src/cascadia/WindowsTerminal/AppHost.cpp | 4 +- .../WindowsTerminal/WindowEmperor.cpp | 5 +- src/inc/til/env.h | 2 +- 43 files changed, 381 insertions(+), 78 deletions(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 74450b6704c..6f3d62fa297 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -2280,11 +2280,6 @@ "description": "When set to true, the background image for the currently focused profile is expanded to encompass the entire window, beneath other panes.", "type": "boolean" }, - "compatibility.reloadEnvironmentVariables": { - "default": true, - "description": "When set to true, when opening a new tab or pane it will get reloaded environment variables.", - "type": "boolean" - }, "initialCols": { "default": 120, "description": "The number of columns displayed in the window upon first load. If \"launchMode\" is set to \"maximized\" (or \"maximizedFocus\"), this property is ignored.", @@ -2533,6 +2528,11 @@ "null" ] }, + "compatibility.reloadEnvironmentVariables": { + "default": true, + "description": "When set to true, when opening a new tab or pane it will get reloaded environment variables.", + "type": "boolean" + }, "unfocusedAppearance": { "$ref": "#/$defs/AppearanceConfig", "description": "Sets the appearance of the terminal when it is unfocused.", diff --git a/src/cascadia/LocalTests_SettingsModel/DeserializationTests.cpp b/src/cascadia/LocalTests_SettingsModel/DeserializationTests.cpp index 5f02757084a..b5139a5263f 100644 --- a/src/cascadia/LocalTests_SettingsModel/DeserializationTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/DeserializationTests.cpp @@ -74,6 +74,8 @@ namespace SettingsModelLocalTests TEST_METHOD(TestInheritedCommand); TEST_METHOD(LoadFragmentsWithMultipleUpdates); + TEST_METHOD(MigrateReloadEnvVars); + private: static winrt::com_ptr createSettings(const std::string_view& userJSON) { @@ -2020,4 +2022,40 @@ namespace SettingsModelLocalTests // GH#12520: Fragments should be able to override the name of builtin profiles. VERIFY_ARE_EQUAL(L"NewName", loader.userSettings.profiles[0]->Name()); } + + void DeserializationTests::MigrateReloadEnvVars() + { + static constexpr std::string_view settings1Json{ R"( + { + "defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "compatibility.reloadEnvironmentVariables": false, + "profiles": [ + { + "name": "profile0", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "historySize": 1, + "commandline": "cmd.exe" + } + ], + "actions": [ + { + "name": "foo", + "command": "closePane", + "keys": "ctrl+shift+w" + } + ] + })" }; + + implementation::SettingsLoader loader{ settings1Json, DefaultJson }; + loader.MergeInboxIntoUserSettings(); + loader.FinalizeLayering(); + + VERIFY_IS_TRUE(loader.FixupUserSettings(), L"Validate that this will indicate we need to write them back to disk"); + + const auto settings = winrt::make_self(std::move(loader)); + + Log::Comment(L"Ensure that the profile defaults have the new setting added"); + VERIFY_IS_TRUE(settings->ProfileDefaults().HasReloadEnvironmentVariables()); + VERIFY_IS_FALSE(settings->ProfileDefaults().ReloadEnvironmentVariables()); + } } diff --git a/src/cascadia/LocalTests_SettingsModel/SerializationTests.cpp b/src/cascadia/LocalTests_SettingsModel/SerializationTests.cpp index ffc7dea07bd..2488f3f812d 100644 --- a/src/cascadia/LocalTests_SettingsModel/SerializationTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/SerializationTests.cpp @@ -42,6 +42,9 @@ namespace SettingsModelLocalTests TEST_METHOD(CascadiaSettings); TEST_METHOD(LegacyFontSettings); + TEST_METHOD(RoundtripReloadEnvVars); + TEST_METHOD(DontRoundtripNoReloadEnvVars); + private: // Method Description: // - deserializes and reserializes a json string representing a settings object model of type T @@ -513,4 +516,114 @@ namespace SettingsModelLocalTests VERIFY_ARE_EQUAL(toString(jsonOutput), toString(result)); } + + void SerializationTests::RoundtripReloadEnvVars() + { + static constexpr std::string_view oldSettingsJson{ R"( + { + "defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "compatibility.reloadEnvironmentVariables": false, + "profiles": [ + { + "name": "profile0", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "historySize": 1, + "commandline": "cmd.exe" + } + ], + "actions": [ + { + "name": "foo", + "command": "closePane", + "keys": "ctrl+shift+w" + } + ] + })" }; + + static constexpr std::string_view newSettingsJson{ R"( + { + "defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "profiles": + { + "defaults": + { + "compatibility.reloadEnvironmentVariables": false + }, + "list": + [ + { + "name": "profile0", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "historySize": 1, + "commandline": "cmd.exe" + } + ] + }, + "actions": [ + { + "name": "foo", + "command": "closePane", + "keys": "ctrl+shift+w" + } + ] + })" }; + + implementation::SettingsLoader oldLoader{ oldSettingsJson, DefaultJson }; + oldLoader.MergeInboxIntoUserSettings(); + oldLoader.FinalizeLayering(); + VERIFY_IS_TRUE(oldLoader.FixupUserSettings(), L"Validate that this will indicate we need to write them back to disk"); + const auto oldSettings = winrt::make_self(std::move(oldLoader)); + const auto oldResult{ oldSettings->ToJson() }; + + implementation::SettingsLoader newLoader{ newSettingsJson, DefaultJson }; + newLoader.MergeInboxIntoUserSettings(); + newLoader.FinalizeLayering(); + newLoader.FixupUserSettings(); + const auto newSettings = winrt::make_self(std::move(newLoader)); + const auto newResult{ newSettings->ToJson() }; + + VERIFY_ARE_EQUAL(toString(newResult), toString(oldResult)); + } + + void SerializationTests::DontRoundtripNoReloadEnvVars() + { + // Kinda like the above test, but confirming that _nothing_ happens if + // we don't have a setting to migrate. + + static constexpr std::string_view oldSettingsJson{ R"( + { + "defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "profiles": [ + { + "name": "profile0", + "guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}", + "historySize": 1, + "commandline": "cmd.exe" + } + ], + "actions": [ + { + "name": "foo", + "command": "closePane", + "keys": "ctrl+shift+w" + } + ] + })" }; + + implementation::SettingsLoader oldLoader{ oldSettingsJson, DefaultJson }; + oldLoader.MergeInboxIntoUserSettings(); + oldLoader.FinalizeLayering(); + oldLoader.FixupUserSettings(); + const auto oldSettings = winrt::make_self(std::move(oldLoader)); + const auto oldResult{ oldSettings->ToJson() }; + + Log::Comment(L"Now, create a _new_ settings object from the re-serialization of the first"); + implementation::SettingsLoader newLoader{ toString(oldResult), DefaultJson }; + newLoader.MergeInboxIntoUserSettings(); + newLoader.FinalizeLayering(); + newLoader.FixupUserSettings(); + const auto newSettings = winrt::make_self(std::move(newLoader)); + VERIFY_IS_FALSE(newSettings->ProfileDefaults().HasReloadEnvironmentVariables(), + L"Ensure that the new settings object didn't find a reloadEnvironmentVariables"); + } } diff --git a/src/cascadia/LocalTests_SettingsModel/pch.h b/src/cascadia/LocalTests_SettingsModel/pch.h index 96727252489..b077abab8be 100644 --- a/src/cascadia/LocalTests_SettingsModel/pch.h +++ b/src/cascadia/LocalTests_SettingsModel/pch.h @@ -64,6 +64,7 @@ Author(s): // Manually include til after we include Windows.Foundation to give it winrt superpowers #include "til.h" +#include // Common includes for most tests: #include "../../inc/conattrs.hpp" diff --git a/src/cascadia/Remoting/CommandlineArgs.h b/src/cascadia/Remoting/CommandlineArgs.h index 4d40c898a62..2f618e53efc 100644 --- a/src/cascadia/Remoting/CommandlineArgs.h +++ b/src/cascadia/Remoting/CommandlineArgs.h @@ -15,10 +15,12 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation CommandlineArgs(const winrt::array_view& args, winrt::hstring currentDirectory, - const uint32_t showWindowCommand) : + const uint32_t showWindowCommand, + winrt::hstring envString) : _args{ args.begin(), args.end() }, _cwd{ currentDirectory }, - _ShowWindowCommand{ showWindowCommand } + _ShowWindowCommand{ showWindowCommand }, + CurrentEnvironment{ envString } { } @@ -27,6 +29,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation 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: diff --git a/src/cascadia/Remoting/Monarch.h b/src/cascadia/Remoting/Monarch.h index 25c2cd1f8d2..203119a70ce 100644 --- a/src/cascadia/Remoting/Monarch.h +++ b/src/cascadia/Remoting/Monarch.h @@ -50,7 +50,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation _WindowName{ windowInfo.WindowName() }, _args{ command.Commandline() }, _CurrentDirectory{ command.CurrentDirectory() }, - _ShowWindowCommand{ command.ShowWindowCommand() } {}; + _ShowWindowCommand{ command.ShowWindowCommand() }, + _CurrentEnvironment{ command.CurrentEnvironment() } {}; WindowRequestedArgs(const winrt::hstring& window, const winrt::hstring& content, const Windows::Foundation::IReference& bounds) : _Id{ 0u }, @@ -68,6 +69,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation 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: diff --git a/src/cascadia/Remoting/Monarch.idl b/src/cascadia/Remoting/Monarch.idl index cc2c45f5426..f57bd6b59b2 100644 --- a/src/cascadia/Remoting/Monarch.idl +++ b/src/cascadia/Remoting/Monarch.idl @@ -27,6 +27,7 @@ namespace Microsoft.Terminal.Remoting String[] Commandline { get; }; String CurrentDirectory { get; }; UInt32 ShowWindowCommand { get; }; + String CurrentEnvironment { get; }; String Content { get; }; Windows.Foundation.IReference InitialBounds { get; }; diff --git a/src/cascadia/Remoting/Peasant.idl b/src/cascadia/Remoting/Peasant.idl index 64ff512a1b4..f02d22da9c4 100644 --- a/src/cascadia/Remoting/Peasant.idl +++ b/src/cascadia/Remoting/Peasant.idl @@ -7,11 +7,12 @@ namespace Microsoft.Terminal.Remoting runtimeclass CommandlineArgs { CommandlineArgs(); - CommandlineArgs(String[] args, String cwd, UInt32 showWindowCommand); + CommandlineArgs(String[] args, String cwd, UInt32 showWindowCommand, String env); String[] Commandline { get; set; }; String CurrentDirectory { get; }; UInt32 ShowWindowCommand { get; }; + String CurrentEnvironment { get; }; }; runtimeclass RenameRequestArgs diff --git a/src/cascadia/Remoting/WindowManager.cpp b/src/cascadia/Remoting/WindowManager.cpp index 5572c6eee95..aa9f67b0b3f 100644 --- a/src/cascadia/Remoting/WindowManager.cpp +++ b/src/cascadia/Remoting/WindowManager.cpp @@ -349,7 +349,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation // 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())); + p->ExecuteCommandline(*winrt::make_self(args.Commandline(), + args.CurrentDirectory(), + args.ShowWindowCommand(), + args.CurrentEnvironment())); _monarch.AddPeasant(*p); diff --git a/src/cascadia/Remoting/pch.h b/src/cascadia/Remoting/pch.h index 3e65fdf1038..4c4bcb1ac96 100644 --- a/src/cascadia/Remoting/pch.h +++ b/src/cascadia/Remoting/pch.h @@ -52,3 +52,4 @@ TRACELOGGING_DECLARE_PROVIDER(g_hRemotingProvider); #include "til.h" #include +#include diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index 2fa36a9711f..5060b4ff2f7 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -571,6 +571,11 @@ void AppCommandlineArgs::_addNewTerminalArgs(AppCommandlineArgs::NewTerminalSubc subcommand.appendCommandLineOption = subcommand.subcommand->add_flag("--appendCommandLine", _appendCommandLineOption, RS_A(L"CmdAppendCommandLineDesc")); + subcommand.inheritEnvOption = subcommand.subcommand->add_flag( + "--inheritEnvironment,!--reloadEnvironment", + _inheritEnvironment, + RS_A(L"CmdInheritEnvDesc")); + // Using positionals_at_end allows us to support "wt new-tab -d wsl -d Ubuntu" // without CLI11 thinking that we've specified -d twice. // There's an alternate construction where we make all subcommands "prefix commands", @@ -592,7 +597,8 @@ NewTerminalArgs AppCommandlineArgs::_getNewTerminalArgs(AppCommandlineArgs::NewT { NewTerminalArgs args{}; - if (!_commandline.empty()) + const auto hasCommandline{ !_commandline.empty() }; + if (hasCommandline) { std::ostringstream cmdlineBuffer; @@ -662,6 +668,13 @@ NewTerminalArgs AppCommandlineArgs::_getNewTerminalArgs(AppCommandlineArgs::NewT args.AppendCommandLine(_appendCommandLineOption); } + bool inheritEnv = hasCommandline; + if (*subcommand.inheritEnvOption) + { + inheritEnv = _inheritEnvironment; + } + args.ReloadEnvironmentVariables(!inheritEnv); + return args; } diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index 292a3500c42..9145697f453 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -68,6 +68,7 @@ class TerminalApp::AppCommandlineArgs final CLI::Option* suppressApplicationTitleOption; CLI::Option* colorSchemeOption; CLI::Option* appendCommandLineOption; + CLI::Option* inheritEnvOption; }; struct NewPaneSubcommand : public NewTerminalSubcommand @@ -100,6 +101,7 @@ class TerminalApp::AppCommandlineArgs final std::string _startingTabColor; std::string _startingColorScheme; bool _suppressApplicationTitle{ false }; + bool _inheritEnvironment{ false }; winrt::Microsoft::Terminal::Settings::Model::FocusDirection _moveFocusDirection{ winrt::Microsoft::Terminal::Settings::Model::FocusDirection::None }; winrt::Microsoft::Terminal::Settings::Model::FocusDirection _swapPaneDirection{ winrt::Microsoft::Terminal::Settings::Model::FocusDirection::None }; diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 71b0692708d..7cebf63ea09 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -371,6 +371,10 @@ Open the tab with tabTitle overriding default title and suppressing title change messages from the application {Locked="\"tabTitle\""} + + Inherit the terminal's own environment variables when creating the new tab or pane, rather than creating a fresh environment block. This defaults to set when a "command" is passed. + {Locked="\"command\""} + Open the tab with the specified color scheme, instead of the profile's set "colorScheme" {Locked="\"colorScheme\""} diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index a5a3860cae8..6d372513fb8 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -556,7 +556,8 @@ namespace winrt::TerminalApp::implementation // - winrt::fire_and_forget TerminalPage::ProcessStartupActions(Windows::Foundation::Collections::IVector actions, const bool initial, - const winrt::hstring cwd) + const winrt::hstring cwd, + const winrt::hstring env) { auto weakThis{ get_weak() }; @@ -576,6 +577,12 @@ namespace winrt::TerminalApp::implementation _WindowProperties.VirtualWorkingDirectory(originalVirtualCwd); }); + // Literally the same thing with env vars too + auto originalVirtualEnv{ _WindowProperties.VirtualEnvVars() }; + auto restoreEnv = wil::scope_exit([&originalVirtualEnv, this]() { + _WindowProperties.VirtualEnvVars(originalVirtualEnv); + }); + if (cwd.empty()) { // We didn't actually need to change the virtual CWD, so we don't @@ -587,6 +594,15 @@ namespace winrt::TerminalApp::implementation _WindowProperties.VirtualWorkingDirectory(cwd); } + if (env.empty()) + { + restoreEnv.release(); + } + else + { + _WindowProperties.VirtualEnvVars(env); + } + if (auto page{ weakThis.get() }) { for (const auto& action : actions) @@ -1213,6 +1229,8 @@ namespace winrt::TerminalApp::implementation auto valueSet = TerminalConnection::ConptyConnection::CreateSettings(azBridgePath.native(), L".", L"Azure", + false, + L"", nullptr, settings.InitialRows(), settings.InitialCols(), @@ -1253,6 +1271,8 @@ namespace winrt::TerminalApp::implementation auto valueSet = TerminalConnection::ConptyConnection::CreateSettings(settings.Commandline(), newWorkingDirectory, settings.StartingTitle(), + settings.ReloadEnvironmentVariables(), + _WindowProperties.VirtualEnvVars(), environment, settings.InitialRows(), settings.InitialCols(), @@ -1260,8 +1280,6 @@ namespace winrt::TerminalApp::implementation profile.Guid()); valueSet.Insert(L"passthroughMode", Windows::Foundation::PropertyValue::CreateBoolean(settings.VtPassthrough())); - valueSet.Insert(L"reloadEnvironmentVariables", - Windows::Foundation::PropertyValue::CreateBoolean(_settings.GlobalSettings().ReloadEnvironmentVariables())); if (inheritCursor) { diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index cb82efeaa8a..13d89198b05 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -154,7 +154,8 @@ namespace winrt::TerminalApp::implementation winrt::fire_and_forget ProcessStartupActions(Windows::Foundation::Collections::IVector actions, const bool initial, - const winrt::hstring cwd = L""); + const winrt::hstring cwd = L"", + const winrt::hstring env = L""); TerminalApp::WindowProperties WindowProperties() const noexcept { return _WindowProperties; }; diff --git a/src/cascadia/TerminalApp/TerminalPage.idl b/src/cascadia/TerminalApp/TerminalPage.idl index 4375c000738..76ee847fb80 100644 --- a/src/cascadia/TerminalApp/TerminalPage.idl +++ b/src/cascadia/TerminalApp/TerminalPage.idl @@ -52,6 +52,7 @@ namespace TerminalApp String WindowIdForDisplay { get; }; String VirtualWorkingDirectory { get; set; }; + String VirtualEnvVars { get; set; }; Boolean IsQuakeWindow(); }; diff --git a/src/cascadia/TerminalApp/TerminalWindow.cpp b/src/cascadia/TerminalApp/TerminalWindow.cpp index 7b60611db9b..3aa5e0bbaec 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.cpp +++ b/src/cascadia/TerminalApp/TerminalWindow.cpp @@ -1024,9 +1024,12 @@ 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) + int32_t TerminalWindow::SetStartupCommandline(array_view args, + winrt::hstring cwd, + winrt::hstring env) { _WindowProperties->SetInitialCwd(std::move(cwd)); + _WindowProperties->VirtualEnvVars(std::move(env)); // This is called in AppHost::ctor(), before we've created the window // (or called TerminalWindow::Initialize) @@ -1081,7 +1084,8 @@ namespace winrt::TerminalApp::implementation // - 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& cwd, + const winrt::hstring& env) { ::TerminalApp::AppCommandlineArgs appArgs; auto result = appArgs.ParseArgs(args); @@ -1089,7 +1093,7 @@ namespace winrt::TerminalApp::implementation { auto actions = winrt::single_threaded_vector(std::move(appArgs.GetStartupActions())); - _root->ProcessStartupActions(actions, false, cwd); + _root->ProcessStartupActions(actions, false, cwd, env); if (appArgs.IsHandoffListener()) { diff --git a/src/cascadia/TerminalApp/TerminalWindow.h b/src/cascadia/TerminalApp/TerminalWindow.h index a26b7c98bfb..f005ad0b0ba 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.h +++ b/src/cascadia/TerminalApp/TerminalWindow.h @@ -56,6 +56,8 @@ namespace winrt::TerminalApp::implementation // Used for setting the initial CWD, before we have XAML set up for property change notifications. void SetInitialCwd(winrt::hstring cwd) { _VirtualWorkingDirectory = std::move(cwd); }; + til::property VirtualEnvVars; + private: winrt::hstring _WindowName{}; uint64_t _WindowId{ 0 }; @@ -77,9 +79,9 @@ namespace winrt::TerminalApp::implementation bool HasCommandlineArguments() const noexcept; - int32_t SetStartupCommandline(array_view actions, winrt::hstring cwd); + int32_t SetStartupCommandline(array_view actions, winrt::hstring cwd, winrt::hstring env); void SetStartupContent(const winrt::hstring& content, const Windows::Foundation::IReference& contentBounds); - int32_t ExecuteCommandline(array_view actions, const winrt::hstring& cwd); + int32_t ExecuteCommandline(array_view actions, const winrt::hstring& cwd, const winrt::hstring& env); void SetSettingsStartupArgs(const std::vector& actions); winrt::hstring ParseCommandlineMessage(); bool ShouldExitEarly(); diff --git a/src/cascadia/TerminalApp/TerminalWindow.idl b/src/cascadia/TerminalApp/TerminalWindow.idl index 2ca487be544..a41cfb96c8e 100644 --- a/src/cascadia/TerminalApp/TerminalWindow.idl +++ b/src/cascadia/TerminalApp/TerminalWindow.idl @@ -53,9 +53,9 @@ namespace TerminalApp Boolean HasCommandlineArguments(); - Int32 SetStartupCommandline(String[] commands, String cwd); + Int32 SetStartupCommandline(String[] commands, String cwd, String env); void SetStartupContent(String json, Windows.Foundation.IReference bounds); - Int32 ExecuteCommandline(String[] commands, String cwd); + Int32 ExecuteCommandline(String[] commands, String cwd, String env); String ParseCommandlineMessage { get; }; Boolean ShouldExitEarly { get; }; diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index cecb5c7d759..e086c9b2cfc 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include "CTerminalHandoff.h" @@ -90,14 +89,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation }); // Populate the environment map with the current environment. - if (_reloadEnvironmentVariables) - { - environment.regenerate(); - } - else - { - environment = til::env::from_current_environment(); - } + environment = _initialEnv; { // Convert connection Guid to string and ignore the enclosing '{}'. @@ -235,7 +227,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation Windows::Foundation::Collections::ValueSet ConptyConnection::CreateSettings(const winrt::hstring& cmdline, const winrt::hstring& startingDirectory, const winrt::hstring& startingTitle, - const Windows::Foundation::Collections::IMapView& environment, + bool reloadEnvironmentVariables, + const winrt::hstring& initialEnvironment, + const Windows::Foundation::Collections::IMapView& environmentOverrides, uint32_t rows, uint32_t columns, const winrt::guid& guid, @@ -246,23 +240,35 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation vs.Insert(L"commandline", Windows::Foundation::PropertyValue::CreateString(cmdline)); vs.Insert(L"startingDirectory", Windows::Foundation::PropertyValue::CreateString(startingDirectory)); vs.Insert(L"startingTitle", Windows::Foundation::PropertyValue::CreateString(startingTitle)); + vs.Insert(L"reloadEnvironmentVariables", Windows::Foundation::PropertyValue::CreateBoolean(reloadEnvironmentVariables)); vs.Insert(L"initialRows", Windows::Foundation::PropertyValue::CreateUInt32(rows)); vs.Insert(L"initialCols", Windows::Foundation::PropertyValue::CreateUInt32(columns)); vs.Insert(L"guid", Windows::Foundation::PropertyValue::CreateGuid(guid)); vs.Insert(L"profileGuid", Windows::Foundation::PropertyValue::CreateGuid(profileGuid)); - if (environment) + if (environmentOverrides) { Windows::Foundation::Collections::ValueSet env{}; - for (const auto& [k, v] : environment) + for (const auto& [k, v] : environmentOverrides) { env.Insert(k, Windows::Foundation::PropertyValue::CreateString(v)); } vs.Insert(L"environment", env); } + + if (!initialEnvironment.empty()) + { + vs.Insert(L"initialEnvironment", Windows::Foundation::PropertyValue::CreateString(initialEnvironment)); + } return vs; } + template + T unbox_prop_or(const Windows::Foundation::Collections::ValueSet& blob, std::wstring_view key, T defaultValue) + { + return winrt::unbox_value_or(blob.TryLookup(key).try_as(), defaultValue); + } + void ConptyConnection::Initialize(const Windows::Foundation::Collections::ValueSet& settings) { if (settings) @@ -271,26 +277,47 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation // auto bad = unbox_value_or(settings.TryLookup(L"foo").try_as(), nullptr); // It'll just return null - _commandline = winrt::unbox_value_or(settings.TryLookup(L"commandline").try_as(), _commandline); - _startingDirectory = winrt::unbox_value_or(settings.TryLookup(L"startingDirectory").try_as(), _startingDirectory); - _startingTitle = winrt::unbox_value_or(settings.TryLookup(L"startingTitle").try_as(), _startingTitle); - _rows = winrt::unbox_value_or(settings.TryLookup(L"initialRows").try_as(), _rows); - _cols = winrt::unbox_value_or(settings.TryLookup(L"initialCols").try_as(), _cols); - _guid = winrt::unbox_value_or(settings.TryLookup(L"guid").try_as(), _guid); + _commandline = unbox_prop_or(settings, L"commandline", _commandline); + _startingDirectory = unbox_prop_or(settings, L"startingDirectory", _startingDirectory); + _startingTitle = unbox_prop_or(settings, L"startingTitle", _startingTitle); + _rows = unbox_prop_or(settings, L"initialRows", _rows); + _cols = unbox_prop_or(settings, L"initialCols", _cols); + _guid = unbox_prop_or(settings, L"guid", _guid); _environment = settings.TryLookup(L"environment").try_as(); if constexpr (Feature_VtPassthroughMode::IsEnabled()) { - _passthroughMode = winrt::unbox_value_or(settings.TryLookup(L"passthroughMode").try_as(), _passthroughMode); + _passthroughMode = unbox_prop_or(settings, L"passthroughMode", _passthroughMode); } - _inheritCursor = winrt::unbox_value_or(settings.TryLookup(L"inheritCursor").try_as(), _inheritCursor); - _reloadEnvironmentVariables = winrt::unbox_value_or(settings.TryLookup(L"reloadEnvironmentVariables").try_as(), - _reloadEnvironmentVariables); - _profileGuid = winrt::unbox_value_or(settings.TryLookup(L"profileGuid").try_as(), _profileGuid); - } + _inheritCursor = unbox_prop_or(settings, L"inheritCursor", _inheritCursor); + _profileGuid = unbox_prop_or(settings, L"profileGuid", _profileGuid); - if (_guid == guid{}) - { - _guid = Utils::CreateGuid(); + const auto& initialEnvironment{ unbox_prop_or(settings, L"initialEnvironment", L"") }; + + const bool reloadEnvironmentVariables = unbox_prop_or(settings, L"reloadEnvironmentVariables", false); + + if (reloadEnvironmentVariables) + { + _initialEnv.regenerate(); + } + else + { + if (!initialEnvironment.empty()) + { + _initialEnv = til::env{ initialEnvironment.c_str() }; + } + else + { + // If we were not explicitly provided an "initial" env block to + // treat as our original one, then just use our actual current + // env block. + _initialEnv = til::env::from_current_environment(); + } + } + + if (_guid == guid{}) + { + _guid = Utils::CreateGuid(); + } } } @@ -734,5 +761,4 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation co_await winrt::resume_background(); // move to background connection.reset(); // explicitly destruct } - } diff --git a/src/cascadia/TerminalConnection/ConptyConnection.h b/src/cascadia/TerminalConnection/ConptyConnection.h index 747434f6dba..0105104c130 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.h +++ b/src/cascadia/TerminalConnection/ConptyConnection.h @@ -7,6 +7,7 @@ #include "ConnectionStateHolder.h" #include "ITerminalHandoff.h" +#include namespace winrt::Microsoft::Terminal::TerminalConnection::implementation { @@ -49,7 +50,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation static Windows::Foundation::Collections::ValueSet CreateSettings(const winrt::hstring& cmdline, const winrt::hstring& startingDirectory, const winrt::hstring& startingTitle, - const Windows::Foundation::Collections::IMapView& environment, + bool reloadEnvironmentVariables, + const winrt::hstring& initialEnvironment, + const Windows::Foundation::Collections::IMapView& environmentOverrides, uint32_t rows, uint32_t columns, const winrt::guid& guid, @@ -91,7 +94,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation std::array _buffer{}; bool _passthroughMode{}; bool _inheritCursor{ false }; - bool _reloadEnvironmentVariables{}; + + til::env _initialEnv{}; guid _profileGuid{}; struct StartupInfoFromDefTerm diff --git a/src/cascadia/TerminalConnection/ConptyConnection.idl b/src/cascadia/TerminalConnection/ConptyConnection.idl index c9928d5c425..5cc0fb6f1d8 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.idl +++ b/src/cascadia/TerminalConnection/ConptyConnection.idl @@ -28,7 +28,9 @@ namespace Microsoft.Terminal.TerminalConnection static Windows.Foundation.Collections.ValueSet CreateSettings(String cmdline, String startingDirectory, String startingTitle, - IMapView environment, + Boolean reloadEnvironmentVariables, + String initialEnvironment, + IMapView environmentOverrides, UInt32 rows, UInt32 columns, Guid guid, diff --git a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.h b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.h index e752c8cffca..751645b79ba 100644 --- a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.h +++ b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.h @@ -104,7 +104,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation OBSERVABLE_PROJECTED_SETTING(_profile, BellStyle); OBSERVABLE_PROJECTED_SETTING(_profile, UseAtlasEngine); OBSERVABLE_PROJECTED_SETTING(_profile, Elevate); - OBSERVABLE_PROJECTED_SETTING(_profile, VtPassthrough) + OBSERVABLE_PROJECTED_SETTING(_profile, VtPassthrough); + OBSERVABLE_PROJECTED_SETTING(_profile, ReloadEnvironmentVariables); WINRT_PROPERTY(bool, IsBaseLayer, false); WINRT_PROPERTY(bool, FocusDeleteButton, false); diff --git a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl index ab0bcbf2ffb..e8517be3995 100644 --- a/src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl +++ b/src/cascadia/TerminalSettingsEditor/ProfileViewModel.idl @@ -106,5 +106,6 @@ namespace Microsoft.Terminal.Settings.Editor OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, UseAtlasEngine); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, Elevate); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, VtPassthrough); + OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, ReloadEnvironmentVariables); } } diff --git a/src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml b/src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml index b17296fe0ae..31a93782546 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml +++ b/src/cascadia/TerminalSettingsEditor/Profiles_Advanced.xaml @@ -136,6 +136,15 @@ + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index 85a19334d4f..630bcd87dd0 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -1142,6 +1142,14 @@ Use the new text renderer ("AtlasEngine") {Locked="AtlasEngine"} + + Launch this application with a new environment block + "environment variables" are user-definable values that can affect the way running processes will behave on a computer + + + When enabled, the Terminal will generate a new environment block when creating new tabs or panes with this profile. When disabled, the tab/pane will instead inherit the variables the Terminal was started with. + A description for what the "Reload environment variables" setting does. Presented near "Profile_ReloadEnvVars". + Enable experimental virtual terminal passthrough An option to enable experimental virtual terminal passthrough connectivity option with the underlying ConPTY diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.h b/src/cascadia/TerminalSettingsModel/ActionArgs.h index 5633c039469..6d83964cbbc 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.h @@ -313,6 +313,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation ACTION_ARG(Windows::Foundation::IReference, SuppressApplicationTitle, nullptr); ACTION_ARG(winrt::hstring, ColorScheme); ACTION_ARG(Windows::Foundation::IReference, Elevate, nullptr); + ACTION_ARG(Windows::Foundation::IReference, ReloadEnvironmentVariables, nullptr); ACTION_ARG(uint64_t, ContentId); static constexpr std::string_view CommandlineKey{ "commandline" }; @@ -325,6 +326,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation static constexpr std::string_view SuppressApplicationTitleKey{ "suppressApplicationTitle" }; static constexpr std::string_view ColorSchemeKey{ "colorScheme" }; static constexpr std::string_view ElevateKey{ "elevate" }; + static constexpr std::string_view ReloadEnvironmentVariablesKey{ "reloadEnvironmentVariables" }; static constexpr std::string_view ContentKey{ "__content" }; public: @@ -346,6 +348,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation otherAsUs->_SuppressApplicationTitle == _SuppressApplicationTitle && otherAsUs->_ColorScheme == _ColorScheme && otherAsUs->_Elevate == _Elevate && + otherAsUs->_ReloadEnvironmentVariables == _ReloadEnvironmentVariables && otherAsUs->_ContentId == _ContentId; } return false; @@ -363,6 +366,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation JsonUtils::GetValueForKey(json, SuppressApplicationTitleKey, args->_SuppressApplicationTitle); JsonUtils::GetValueForKey(json, ColorSchemeKey, args->_ColorScheme); JsonUtils::GetValueForKey(json, ElevateKey, args->_Elevate); + JsonUtils::GetValueForKey(json, ReloadEnvironmentVariablesKey, args->_ReloadEnvironmentVariables); JsonUtils::GetValueForKey(json, ContentKey, args->_ContentId); return *args; } @@ -383,6 +387,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation JsonUtils::SetValueForKey(json, SuppressApplicationTitleKey, args->_SuppressApplicationTitle); JsonUtils::SetValueForKey(json, ColorSchemeKey, args->_ColorScheme); JsonUtils::SetValueForKey(json, ElevateKey, args->_Elevate); + JsonUtils::SetValueForKey(json, ReloadEnvironmentVariablesKey, args->_ReloadEnvironmentVariables); JsonUtils::SetValueForKey(json, ContentKey, args->_ContentId); return json; } @@ -398,6 +403,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation copy->_SuppressApplicationTitle = _SuppressApplicationTitle; copy->_ColorScheme = _ColorScheme; copy->_Elevate = _Elevate; + copy->_ReloadEnvironmentVariables = _ReloadEnvironmentVariables; copy->_ContentId = _ContentId; return *copy; } @@ -418,6 +424,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation h.write(SuppressApplicationTitle()); h.write(ColorScheme()); h.write(Elevate()); + h.write(ReloadEnvironmentVariables()); h.write(ContentId()); } }; diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.idl b/src/cascadia/TerminalSettingsModel/ActionArgs.idl index 271c9d979d8..32f9005fdee 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.idl +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.idl @@ -147,6 +147,8 @@ namespace Microsoft.Terminal.Settings.Model // This needs to be an optional so that the default value (null) does // not modify whatever the profile's value is (either true or false) Windows.Foundation.IReference Elevate; + // Similarly with ReloadEnvironmentVariables + Windows.Foundation.IReference ReloadEnvironmentVariables; UInt64 ContentId{ get; set; }; diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp index 377e69a6c32..8964169f207 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettingsSerialization.cpp @@ -450,6 +450,17 @@ bool SettingsLoader::FixupUserSettings() } } + // Terminal 1.19: Migrate the global + // `compatibility.reloadEnvironmentVariables` to being a per-profile + // setting. If the user had it disabled in 1.18, then set the + // profiles.defaults value to false to match. + if (!userSettings.globals->LegacyReloadEnvironmentVariables()) + { + // migrate the user's opt-out to the profiles.defaults + userSettings.baseLayerProfile->ReloadEnvironmentVariables(false); + fixedUp = true; + } + return fixedUp; } diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp index dff11656140..1caef96b2cf 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp @@ -20,6 +20,7 @@ static constexpr std::string_view ActionsKey{ "actions" }; static constexpr std::string_view ThemeKey{ "theme" }; static constexpr std::string_view DefaultProfileKey{ "defaultProfile" }; static constexpr std::string_view LegacyUseTabSwitcherModeKey{ "useTabSwitcher" }; +static constexpr std::string_view LegacyReloadEnvironmentVariablesKey{ "compatibility.reloadEnvironmentVariables" }; // Method Description: // - Copies any extraneous data from the parent before completing a CreateChild call @@ -157,6 +158,8 @@ void GlobalAppSettings::LayerJson(const Json::Value& json) _keybindingsWarnings.insert(_keybindingsWarnings.end(), warnings.begin(), warnings.end()); } } + + JsonUtils::GetValueForKey(json, LegacyReloadEnvironmentVariablesKey, _legacyReloadEnvironmentVariables); } // Method Description: diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h index 8ef1a8a2f72..3ccc0972bea 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h @@ -67,6 +67,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation void ExpandCommands(const Windows::Foundation::Collections::IVectorView& profiles, const Windows::Foundation::Collections::IMapView& schemes); + bool LegacyReloadEnvironmentVariables() const noexcept { return _legacyReloadEnvironmentVariables; } + INHERITABLE_SETTING(Model::GlobalAppSettings, hstring, UnparsedDefaultProfile, L""); #define GLOBAL_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \ @@ -82,6 +84,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation #endif winrt::guid _defaultProfile; + bool _legacyReloadEnvironmentVariables{ true }; winrt::com_ptr _actionMap{ winrt::make_self() }; std::vector _keybindingsWarnings; diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl index a1847408fdf..20cb1d90528 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl @@ -79,7 +79,6 @@ namespace Microsoft.Terminal.Settings.Model INHERITABLE_SETTING(Boolean, ForceFullRepaintRendering); INHERITABLE_SETTING(Boolean, SoftwareRendering); INHERITABLE_SETTING(Boolean, UseBackgroundImageForWindow); - INHERITABLE_SETTING(Boolean, ReloadEnvironmentVariables); INHERITABLE_SETTING(Boolean, ForceVTInput); INHERITABLE_SETTING(Boolean, DebugFeaturesEnabled); INHERITABLE_SETTING(Boolean, StartOnUserLogin); diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h index 6c7b08649f9..794afa6a451 100644 --- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -27,7 +27,6 @@ Author(s): X(bool, ForceFullRepaintRendering, "experimental.rendering.forceFullRepaint", false) \ X(bool, SoftwareRendering, "experimental.rendering.software", false) \ X(bool, UseBackgroundImageForWindow, "experimental.useBackgroundImageForWindow", false) \ - X(bool, ReloadEnvironmentVariables, "compatibility.reloadEnvironmentVariables", true) \ X(bool, ForceVTInput, "experimental.input.forceVT", false) \ X(bool, TrimBlockSelection, "trimBlockSelection", true) \ X(bool, DetectURLs, "experimental.detectURLs", true) \ @@ -98,7 +97,8 @@ Author(s): X(bool, VtPassthrough, "experimental.connection.passthroughMode", false) \ X(bool, AutoMarkPrompts, "experimental.autoMarkPrompts", false) \ X(bool, ShowMarks, "experimental.showMarksOnScrollbar", false) \ - X(bool, RepositionCursorWithMouse, "experimental.repositionCursorWithMouse", false) + X(bool, RepositionCursorWithMouse, "experimental.repositionCursorWithMouse", false) \ + X(bool, ReloadEnvironmentVariables, "compatibility.reloadEnvironmentVariables", true) // Intentionally omitted Profile settings: // * Name diff --git a/src/cascadia/TerminalSettingsModel/Profile.idl b/src/cascadia/TerminalSettingsModel/Profile.idl index 86bce9beeb4..4aa9af3422a 100644 --- a/src/cascadia/TerminalSettingsModel/Profile.idl +++ b/src/cascadia/TerminalSettingsModel/Profile.idl @@ -94,5 +94,8 @@ namespace Microsoft.Terminal.Settings.Model INHERITABLE_PROFILE_SETTING(Boolean, RightClickContextMenu); INHERITABLE_PROFILE_SETTING(Boolean, RepositionCursorWithMouse); + + INHERITABLE_PROFILE_SETTING(Boolean, ReloadEnvironmentVariables); + } } diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp index 35881c8c715..617692691ee 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp @@ -185,6 +185,11 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { defaultSettings.Elevate(newTerminalArgs.Elevate().Value()); } + + if (newTerminalArgs.ReloadEnvironmentVariables()) + { + defaultSettings.ReloadEnvironmentVariables(newTerminalArgs.ReloadEnvironmentVariables().Value()); + } } return settingsPair; @@ -334,6 +339,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation _RightClickContextMenu = profile.RightClickContextMenu(); _RepositionCursorWithMouse = profile.RepositionCursorWithMouse(); + + _ReloadEnvironmentVariables = profile.ReloadEnvironmentVariables(); } // Method Description: diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.h b/src/cascadia/TerminalSettingsModel/TerminalSettings.h index daa895518e8..60c9b5fb2c2 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.h @@ -167,6 +167,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation INHERITABLE_SETTING(Model::TerminalSettings, bool, RightClickContextMenu, false); INHERITABLE_SETTING(Model::TerminalSettings, bool, RepositionCursorWithMouse, false); + INHERITABLE_SETTING(Model::TerminalSettings, bool, ReloadEnvironmentVariables, true); + private: std::optional> _ColorTable; std::span _getColorTableImpl(); diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.idl b/src/cascadia/TerminalSettingsModel/TerminalSettings.idl index 3bc2c72ed0e..23c305ee4e0 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.idl +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.idl @@ -45,5 +45,6 @@ namespace Microsoft.Terminal.Settings.Model String StartingDirectory { set; }; Boolean Elevate; + Boolean ReloadEnvironmentVariables; }; } diff --git a/src/cascadia/TerminalSettingsModel/pch.h b/src/cascadia/TerminalSettingsModel/pch.h index 75b789ed581..133786e5dae 100644 --- a/src/cascadia/TerminalSettingsModel/pch.h +++ b/src/cascadia/TerminalSettingsModel/pch.h @@ -58,6 +58,7 @@ TRACELOGGING_DECLARE_PROVIDER(g_hSettingsModelProvider); // Manually include til after we include Windows.Foundation to give it winrt superpowers #include "til.h" +#include #include #include diff --git a/src/cascadia/UnitTests_Remoting/RemotingTests.cpp b/src/cascadia/UnitTests_Remoting/RemotingTests.cpp index 0b8a07ddfe1..7dec3c052e6 100644 --- a/src/cascadia/UnitTests_Remoting/RemotingTests.cpp +++ b/src/cascadia/UnitTests_Remoting/RemotingTests.cpp @@ -431,7 +431,7 @@ namespace RemotingUnitTests m0->FindTargetWindowRequested(&RemotingTests::_findTargetWindowHelper); std::vector args{}; - Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow()); @@ -468,7 +468,7 @@ namespace RemotingUnitTests }); std::vector args{ L"1", L"arg[1]" }; - Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow()); @@ -489,7 +489,7 @@ namespace RemotingUnitTests { std::vector args{ L"-1" }; - Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow()); @@ -497,7 +497,7 @@ namespace RemotingUnitTests } { std::vector args{ L"-2" }; - Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow()); @@ -534,7 +534,7 @@ namespace RemotingUnitTests winrt::clock().now() }; p1->ActivateWindow(activatedArgs); - Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow()); @@ -559,7 +559,7 @@ namespace RemotingUnitTests p2->ActivateWindow(activatedArgs); Log::Comment(L"Send a commandline to the current window, which should be p2"); - Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow()); VERIFY_ARE_EQUAL(false, (bool)result.Id()); @@ -572,7 +572,7 @@ namespace RemotingUnitTests p1->ActivateWindow(activatedArgs); Log::Comment(L"Send a commandline to the current window, which should be p1 again"); - Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow()); VERIFY_ARE_EQUAL(false, (bool)result.Id()); @@ -593,7 +593,7 @@ namespace RemotingUnitTests { std::vector args{ L"2" }; - Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow()); @@ -602,7 +602,7 @@ namespace RemotingUnitTests } { std::vector args{ L"10" }; - Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow()); @@ -648,7 +648,7 @@ namespace RemotingUnitTests { Log::Comment(L"Send a commandline to p2, who is still alive. We won't create a new window."); - Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow()); @@ -656,7 +656,7 @@ namespace RemotingUnitTests } { Log::Comment(L"Send a commandline to p1, who is dead. We will create a new window."); - Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow()); @@ -1359,7 +1359,7 @@ namespace RemotingUnitTests std::vector p2Args{ L"two", L"this is for p2" }; { - Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { p1Args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow()); VERIFY_ARE_EQUAL(false, (bool)result.Id()); // Casting to (bool) checks if the reference has a value @@ -1368,7 +1368,7 @@ namespace RemotingUnitTests { Log::Comment(L"Send a commandline to \"two\", which should be p2"); - Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(false, result.ShouldCreateWindow()); VERIFY_ARE_EQUAL(false, (bool)result.Id()); // Casting to (bool) checks if the reference has a value @@ -1380,7 +1380,7 @@ namespace RemotingUnitTests { Log::Comment(L"Send a commandline to \"two\", who is now dead."); - Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { p2Args }, { L"" }, SW_NORMAL, L"" }; auto result = m0->ProposeCommandline(eventArgs); VERIFY_ARE_EQUAL(true, result.ShouldCreateWindow()); VERIFY_ARE_EQUAL(false, (bool)result.Id()); // Casting to (bool) checks if the reference has a value @@ -2392,7 +2392,7 @@ namespace RemotingUnitTests VERIFY_ARE_EQUAL(p1->GetID(), m0->_mruPeasants[1].PeasantID()); std::vector commandlineArgs{ L"0", L"arg[1]" }; - Remoting::CommandlineArgs eventArgs{ { commandlineArgs }, { L"" }, SW_NORMAL }; + Remoting::CommandlineArgs eventArgs{ { commandlineArgs }, { L"" }, SW_NORMAL, L"" }; Log::Comment(L"When we attempt to send a commandline to the MRU window," L" we should find peasant 1 (who's name is \"one\"), not 2" @@ -2577,7 +2577,7 @@ namespace RemotingUnitTests auto m0 = make_private(monarch0PID); { - Remoting::CommandlineArgs args{ { L"wt.exe" }, { L"-Embedding" }, SW_NORMAL }; + Remoting::CommandlineArgs args{ { L"wt.exe" }, { L"-Embedding" }, SW_NORMAL, L"" }; const auto result = m0->ProposeCommandline(args); auto shouldCreateWindow = result.ShouldCreateWindow(); VERIFY_IS_TRUE(shouldCreateWindow); @@ -2585,7 +2585,7 @@ namespace RemotingUnitTests auto m1 = make_self(); { - Remoting::CommandlineArgs args{ { L"wt.exe" }, { L"-Embedding" }, SW_NORMAL }; + Remoting::CommandlineArgs args{ { L"wt.exe" }, { L"-Embedding" }, SW_NORMAL, L"" }; try { diff --git a/src/cascadia/UnitTests_Remoting/pch.h b/src/cascadia/UnitTests_Remoting/pch.h index 4ad6732bf6b..523f6305c3b 100644 --- a/src/cascadia/UnitTests_Remoting/pch.h +++ b/src/cascadia/UnitTests_Remoting/pch.h @@ -49,3 +49,4 @@ Licensed under the MIT license. #include "../../inc/DefaultSettings.h" #include +#include diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 1de5441ab94..81218dbf4c9 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -158,7 +158,7 @@ void AppHost::_HandleCommandlineArgs(const Remoting::WindowRequestedArgs& window } else if (args) { - const auto result = _windowLogic.SetStartupCommandline(args.Commandline(), args.CurrentDirectory()); + const auto result = _windowLogic.SetStartupCommandline(args.Commandline(), args.CurrentDirectory(), args.CurrentEnvironment()); const auto message = _windowLogic.ParseCommandlineMessage(); if (!message.empty()) { @@ -912,7 +912,7 @@ void AppHost::_DispatchCommandline(winrt::Windows::Foundation::IInspectable send // Summon the window whenever we dispatch a commandline to it. This will // make it obvious when a new tab/pane is created in a window. _HandleSummon(sender, summonArgs); - _windowLogic.ExecuteCommandline(args.Commandline(), args.CurrentDirectory()); + _windowLogic.ExecuteCommandline(args.Commandline(), args.CurrentDirectory(), args.CurrentEnvironment()); } void AppHost::_WindowActivated(bool activated) diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.cpp b/src/cascadia/WindowsTerminal/WindowEmperor.cpp index 23aba3d683e..47a11bba38e 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.cpp +++ b/src/cascadia/WindowsTerminal/WindowEmperor.cpp @@ -12,6 +12,7 @@ #include "resource.h" #include "NotificationIcon.h" +#include using namespace winrt; using namespace winrt::Microsoft::Terminal; @@ -105,7 +106,9 @@ bool WindowEmperor::HandleCommandlineArgs() GetStartupInfoW(&si); const uint32_t showWindow = WI_IsFlagSet(si.dwFlags, STARTF_USESHOWWINDOW) ? si.wShowWindow : SW_SHOW; - Remoting::CommandlineArgs eventArgs{ { args }, { cwd }, showWindow }; + const auto currentEnv{ til::env::from_current_environment() }; + + Remoting::CommandlineArgs eventArgs{ { args }, { cwd }, showWindow, winrt::hstring{ currentEnv.to_string() } }; const auto isolatedMode{ _app.Logic().IsolatedMode() }; diff --git a/src/inc/til/env.h b/src/inc/til/env.h index 36b682cfbd3..4d95f9f2f98 100644 --- a/src/inc/til/env.h +++ b/src/inc/til/env.h @@ -559,7 +559,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" get_vars_from_registry(HKEY_CURRENT_USER, fmt::format(til::details::vars::reg::user_volatile_session_env_var_root_pattern, NtCurrentTeb()->ProcessEnvironmentBlock->SessionId)); } - std::wstring to_string() + std::wstring to_string() const { std::wstring result; for (const auto& [name, value] : _envMap) From 394b942a565378fb1aeee227763fae07efdca9e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=84=A2=EF=B8=8F?= Date: Tue, 19 Sep 2023 22:13:21 +0200 Subject: [PATCH 02/12] Option to default to show icon in tab, hide tabicon or make icon in tab monochrome. (#15948) Adding enum iconstyle for hiding the icon in the tab #8157 ## Summary of the Pull Request Please confirm if I am on the right track. ## References and Relevant Issues ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed ## PR Checklist - [ ] Closes #8157 - [x] Tests added/passed - [ ] Documentation updated - If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx - [ ] Schema updated (if necessary) --- .../LocalTests_SettingsModel/ThemeTests.cpp | 3 ++- src/cascadia/TerminalApp/SettingsTab.cpp | 2 +- src/cascadia/TerminalApp/TabManagement.cpp | 4 +-- src/cascadia/TerminalApp/TerminalTab.cpp | 25 +++++++++++++------ src/cascadia/TerminalApp/TerminalTab.h | 3 ++- .../IconPathConverter.cpp | 21 ++++++++-------- .../TerminalSettingsModel/IconPathConverter.h | 2 +- .../IconPathConverter.idl | 2 +- .../TerminalSettingsModel/MTSMSettings.h | 7 +++--- .../TerminalSettingsSerializationHelpers.h | 9 +++++++ src/cascadia/TerminalSettingsModel/Theme.idl | 8 ++++++ 11 files changed, 58 insertions(+), 28 deletions(-) diff --git a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp index 4e3bdacc254..c7bf11326af 100644 --- a/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/ThemeTests.cpp @@ -60,7 +60,8 @@ namespace SettingsModelLocalTests "tabRow": { "background": "#FFFF8800", - "unfocusedBackground": "#FF8844" + "unfocusedBackground": "#FF8844", + "iconStyle": "default" }, "window": { diff --git a/src/cascadia/TerminalApp/SettingsTab.cpp b/src/cascadia/TerminalApp/SettingsTab.cpp index 107bbb45732..1c9c4049f66 100644 --- a/src/cascadia/TerminalApp/SettingsTab.cpp +++ b/src/cascadia/TerminalApp/SettingsTab.cpp @@ -114,7 +114,7 @@ namespace winrt::TerminalApp::implementation // The TabViewItem Icon needs MUX while the IconSourceElement in the CommandPalette needs WUX... Icon(winrt::hstring{ glyph }); - TabViewItem().IconSource(IconPathConverter::IconSourceMUX(glyph)); + TabViewItem().IconSource(IconPathConverter::IconSourceMUX(glyph, false)); } winrt::Windows::UI::Xaml::Media::Brush SettingsTab::_BackgroundBrush() diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index 9e4ddbe9996..d727989162d 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -176,7 +176,7 @@ namespace winrt::TerminalApp::implementation { if (!profile.Icon().empty()) { - newTabImpl->UpdateIcon(profile.Icon()); + newTabImpl->UpdateIcon(profile.Icon(), _settings.GlobalSettings().CurrentTheme().Tab().IconStyle()); } } @@ -241,7 +241,7 @@ namespace winrt::TerminalApp::implementation { if (const auto profile = tab.GetFocusedProfile()) { - tab.UpdateIcon(profile.Icon()); + tab.UpdateIcon(profile.Icon(), _settings.GlobalSettings().CurrentTheme().Tab().IconStyle()); } } diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index e8b7a595af3..8e3dadaa650 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -280,17 +280,17 @@ namespace winrt::TerminalApp::implementation // - iconPath: The new path string to use as the IconPath for our TabViewItem // Return Value: // - - void TerminalTab::UpdateIcon(const winrt::hstring iconPath) + void TerminalTab::UpdateIcon(const winrt::hstring iconPath, const winrt::Microsoft::Terminal::Settings::Model::IconStyle iconStyle) { ASSERT_UI_THREAD(); - // Don't reload our icon if it hasn't changed. - if (iconPath == _lastIconPath) + // Don't reload our icon and iconStyle hasn't changed. + if (iconPath == _lastIconPath && iconStyle == _lastIconStyle) { return; } - _lastIconPath = iconPath; + _lastIconStyle = iconStyle; // If the icon is currently hidden, just return here (but only after setting _lastIconPath to the new path // for when we show the icon again) @@ -299,9 +299,18 @@ namespace winrt::TerminalApp::implementation return; } - // The TabViewItem Icon needs MUX while the IconSourceElement in the CommandPalette needs WUX... - Icon(_lastIconPath); - TabViewItem().IconSource(IconPathConverter::IconSourceMUX(_lastIconPath)); + if (iconStyle == IconStyle::Hidden) + { + // The TabViewItem Icon needs MUX while the IconSourceElement in the CommandPalette needs WUX... + Icon({}); + TabViewItem().IconSource(IconSource{ nullptr }); + } + else + { + Icon(_lastIconPath); + bool isMonochrome = iconStyle == IconStyle::Monochrome; + TabViewItem().IconSource(IconPathConverter::IconSourceMUX(_lastIconPath, isMonochrome)); + } } // Method Description: @@ -323,7 +332,7 @@ namespace winrt::TerminalApp::implementation else { Icon(_lastIconPath); - TabViewItem().IconSource(IconPathConverter::IconSourceMUX(_lastIconPath)); + TabViewItem().IconSource(IconPathConverter::IconSourceMUX(_lastIconPath, _lastIconStyle == IconStyle::Monochrome)); } _iconHidden = hide; } diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index 12c4f79a643..9c0284d55aa 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -41,7 +41,7 @@ namespace winrt::TerminalApp::implementation std::shared_ptr newPane); void ToggleSplitOrientation(); - void UpdateIcon(const winrt::hstring iconPath); + void UpdateIcon(const winrt::hstring iconPath, const winrt::Microsoft::Terminal::Settings::Model::IconStyle iconStyle); void HideIcon(const bool hide); void ShowBellIndicator(const bool show); @@ -111,6 +111,7 @@ namespace winrt::TerminalApp::implementation Windows::UI::Xaml::Controls::MenuFlyoutItem _closePaneMenuItem; Windows::UI::Xaml::Controls::MenuFlyoutItem _restartConnectionMenuItem; + winrt::Microsoft::Terminal::Settings::Model::IconStyle _lastIconStyle; winrt::hstring _lastIconPath{}; std::optional _runtimeTabColor{}; winrt::TerminalApp::TabHeaderControl _headerControl{}; diff --git a/src/cascadia/TerminalSettingsModel/IconPathConverter.cpp b/src/cascadia/TerminalSettingsModel/IconPathConverter.cpp index 4b2239a9ad7..a51ead61899 100644 --- a/src/cascadia/TerminalSettingsModel/IconPathConverter.cpp +++ b/src/cascadia/TerminalSettingsModel/IconPathConverter.cpp @@ -72,7 +72,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation // Return Value: // - An IconElement with its IconSource set, if possible. template - TIconSource _getColoredBitmapIcon(const winrt::hstring& path) + TIconSource _getColoredBitmapIcon(const winrt::hstring& path, bool monochrome) { // FontIcon uses glyphs in the private use area, whereas valid URIs only contain ASCII characters. // To skip throwing on Uri construction, we can quickly check if the first character is ASCII. @@ -85,7 +85,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation // Make sure to set this to false, so we keep the RGB data of the // image. Otherwise, the icon will be white for all the // non-transparent pixels in the image. - iconSource.ShowAsMonochrome(false); + iconSource.ShowAsMonochrome(monochrome); iconSource.UriSource(iconUri); return iconSource; } @@ -121,14 +121,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation // Return Value: // - An IconElement with its IconSource set, if possible. template - TIconSource _getIconSource(const winrt::hstring& iconPath) + TIconSource _getIconSource(const winrt::hstring& iconPath, bool monochrome) { TIconSource iconSource{ nullptr }; if (iconPath.size() != 0) { const auto expandedIconPath{ _expandIconPath(iconPath) }; - iconSource = _getColoredBitmapIcon(expandedIconPath); + iconSource = _getColoredBitmapIcon(expandedIconPath, monochrome); // If we fail to set the icon source using the "icon" as a path, // let's try it as a symbol/emoji. @@ -197,7 +197,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation const hstring& /* language */) { const auto& iconPath = winrt::unbox_value_or(value, L""); - return _getIconSource(iconPath); + return _getIconSource(iconPath, false); } // unused for one-way bindings @@ -211,12 +211,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation Windows::UI::Xaml::Controls::IconSource _IconSourceWUX(hstring path) { - return _getIconSource(path); + return _getIconSource(path, false); } - Microsoft::UI::Xaml::Controls::IconSource _IconSourceMUX(hstring path) + Microsoft::UI::Xaml::Controls::IconSource _IconSourceMUX(hstring path, bool monochrome) { - return _getIconSource(path); + return _getIconSource(path, monochrome); } SoftwareBitmap _convertToSoftwareBitmap(HICON hicon, @@ -329,13 +329,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation return bitmapSource; } - MUX::Controls::IconSource IconPathConverter::IconSourceMUX(const winrt::hstring& iconPath) + MUX::Controls::IconSource IconPathConverter::IconSourceMUX(const winrt::hstring& iconPath, + const bool monochrome) { std::wstring_view iconPathWithoutIndex; const auto indexOpt = _getIconIndex(iconPath, iconPathWithoutIndex); if (!indexOpt.has_value()) { - return _IconSourceMUX(iconPath); + return _IconSourceMUX(iconPath, monochrome); } const auto bitmapSource = _getImageIconSourceForBinary(iconPathWithoutIndex, indexOpt.value()); diff --git a/src/cascadia/TerminalSettingsModel/IconPathConverter.h b/src/cascadia/TerminalSettingsModel/IconPathConverter.h index a9eee104b94..f91fdcad7bd 100644 --- a/src/cascadia/TerminalSettingsModel/IconPathConverter.h +++ b/src/cascadia/TerminalSettingsModel/IconPathConverter.h @@ -19,7 +19,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation const hstring& language); static Windows::UI::Xaml::Controls::IconElement IconWUX(const winrt::hstring& iconPath); - static Microsoft::UI::Xaml::Controls::IconSource IconSourceMUX(const winrt::hstring& iconPath); + static Microsoft::UI::Xaml::Controls::IconSource IconSourceMUX(const winrt::hstring& iconPath, const bool convertToGrayscale); }; } diff --git a/src/cascadia/TerminalSettingsModel/IconPathConverter.idl b/src/cascadia/TerminalSettingsModel/IconPathConverter.idl index bbe1e055b8c..b52367b6c34 100644 --- a/src/cascadia/TerminalSettingsModel/IconPathConverter.idl +++ b/src/cascadia/TerminalSettingsModel/IconPathConverter.idl @@ -16,7 +16,7 @@ namespace Microsoft.Terminal.Settings.Model IconPathConverter(); static Windows.UI.Xaml.Controls.IconElement IconWUX(String path); - static Microsoft.UI.Xaml.Controls.IconSource IconSourceMUX(String path); + static Microsoft.UI.Xaml.Controls.IconSource IconSourceMUX(String path, Boolean convertToGrayscale); }; } diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h index 794afa6a451..15e91a1d7ae 100644 --- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -151,7 +151,8 @@ Author(s): X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Background, "background", nullptr) \ X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, UnfocusedBackground, "unfocusedBackground", nullptr) -#define MTSM_THEME_TAB_SETTINGS(X) \ - X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Background, "background", nullptr) \ - X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, UnfocusedBackground, "unfocusedBackground", nullptr) \ +#define MTSM_THEME_TAB_SETTINGS(X) \ + X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Background, "background", nullptr) \ + X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, UnfocusedBackground, "unfocusedBackground", nullptr) \ + X(winrt::Microsoft::Terminal::Settings::Model::IconStyle, IconStyle, "iconStyle", winrt::Microsoft::Terminal::Settings::Model::IconStyle::Default) \ X(winrt::Microsoft::Terminal::Settings::Model::TabCloseButtonVisibility, ShowCloseButton, "showCloseButton", winrt::Microsoft::Terminal::Settings::Model::TabCloseButtonVisibility::Always) diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h index 0dc91e30b11..f5431aabf3d 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalSettingsModel/TerminalSettingsSerializationHelpers.h @@ -652,6 +652,15 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::TabCloseButtonVi }; }; +JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::IconStyle) +{ + JSON_MAPPINGS(3) = { + pair_type{ "default", ValueType::Default }, + pair_type{ "hidden", ValueType::Hidden }, + pair_type{ "monochrome", ValueType::Monochrome }, + }; +}; + // Possible ScrollToMarkDirection values JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::ScrollToMarkDirection) { diff --git a/src/cascadia/TerminalSettingsModel/Theme.idl b/src/cascadia/TerminalSettingsModel/Theme.idl index f7f041a9dda..830bafef2a2 100644 --- a/src/cascadia/TerminalSettingsModel/Theme.idl +++ b/src/cascadia/TerminalSettingsModel/Theme.idl @@ -4,6 +4,13 @@ namespace Microsoft.Terminal.Settings.Model { + enum IconStyle + { + Default, + Hidden, + Monochrome + }; + enum ThemeColorType { Accent, @@ -63,6 +70,7 @@ namespace Microsoft.Terminal.Settings.Model ThemeColor Background { get; }; ThemeColor UnfocusedBackground { get; }; TabCloseButtonVisibility ShowCloseButton { get; }; + IconStyle IconStyle { get; }; } [default_interface] runtimeclass Theme : Windows.Foundation.IStringable { From 523edd7941c93dbeb11755fcfad2fa1b55f56766 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 20 Sep 2023 06:35:53 -0500 Subject: [PATCH 03/12] Don't crash when the checking for updates without a network (#16002) You can't catch an A/V. Closes #15459 --- src/cascadia/TerminalApp/AboutDialog.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/cascadia/TerminalApp/AboutDialog.cpp b/src/cascadia/TerminalApp/AboutDialog.cpp index 3fc9715dfa2..764f7b6dcaf 100644 --- a/src/cascadia/TerminalApp/AboutDialog.cpp +++ b/src/cascadia/TerminalApp/AboutDialog.cpp @@ -90,10 +90,13 @@ namespace winrt::TerminalApp::implementation { const auto updates = co_await storeContext.GetAppAndOptionalStorePackageUpdatesAsync(); co_await wil::resume_foreground(strongThis->Dispatcher()); - const auto numUpdates = updates.Size(); - if (numUpdates > 0) + if (updates) { - UpdatesAvailable(true); + const auto numUpdates = updates.Size(); + if (numUpdates > 0) + { + UpdatesAvailable(true); + } } } #endif From b5333f64e5b447aab97944fa465fc34f8f1c2e23 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Wed, 20 Sep 2023 17:03:53 +0200 Subject: [PATCH 04/12] Improve performance of scrollbar marks (#16006) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This replaces the use of a `` with an `` for drawing scrollbar marks. Otherwise, WinUI struggles with the up to ~9000 UI elements as they get dirtied every time the scrollbar moves. (FWIW 9000 is not a lot and it should not struggle with that.) The `` element has the benefit that we can get hold of a CPU-side bitmap which we can manually draw our marks into and then swap them into the UI tree. It draws the same 9000 elements, but now WinUI doesn't struggle anymore because only 1 element gets invalidated every time. Closes #15955 ## Validation Steps Performed * Fill the buffer with "e" * Searching for "e" fills the entire thumb range with white ✅ * ...doesn't lag when scrolling around ✅ * ...updates quickly when adding newlines at the end ✅ * Marks sort of align with their scroll position ✅ --- src/cascadia/TerminalControl/ControlCore.cpp | 1 + src/cascadia/TerminalControl/TermControl.cpp | 129 ++++++++++++------ src/cascadia/TerminalControl/TermControl.xaml | 30 ++-- 3 files changed, 97 insertions(+), 63 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 31462753ff0..b4a9571d075 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1380,6 +1380,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation til::color ControlCore::ForegroundColor() const { + const auto lock = _terminal->LockForReading(); return _terminal->GetRenderSettings().GetColorAlias(ColorAlias::DefaultForeground); } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 1fdbde88d7f..78896c46600 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -296,56 +296,102 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (_showMarksInScrollbar) { - // Update scrollbar marks - ScrollBarCanvas().Children().Clear(); - const auto marks{ _core.ScrollMarks() }; - const auto fullHeight{ ScrollBarCanvas().ActualHeight() }; - const auto totalBufferRows{ update.newMaximum + update.newViewportSize }; - - auto drawPip = [&](const auto row, const auto rightAlign, const auto& brush) { - Windows::UI::Xaml::Shapes::Rectangle r; - r.Fill(brush); - r.Width(16.0f / 3.0f); // pip width - 1/3rd of the scrollbar width. - r.Height(2); - const auto fractionalHeight = row / totalBufferRows; - const auto relativePos = fractionalHeight * fullHeight; - ScrollBarCanvas().Children().Append(r); - Windows::UI::Xaml::Controls::Canvas::SetTop(r, relativePos); - if (rightAlign) + const auto scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel(); + const auto scrollBarWidthInDIP = scrollBar.ActualWidth(); + const auto scrollBarHeightInDIP = scrollBar.ActualHeight(); + const auto scrollBarWidthInPx = gsl::narrow_cast(lrint(scrollBarWidthInDIP * scaleFactor)); + const auto scrollBarHeightInPx = gsl::narrow_cast(lrint(scrollBarHeightInDIP * scaleFactor)); + + const auto canvas = FindName(L"ScrollBarCanvas").as(); + auto source = canvas.Source().try_as(); + + if (!source || scrollBarWidthInPx != source.PixelWidth() || scrollBarHeightInPx != source.PixelHeight()) + { + source = Media::Imaging::WriteableBitmap{ scrollBarWidthInPx, scrollBarHeightInPx }; + canvas.Source(source); + canvas.Width(scrollBarWidthInDIP); + canvas.Height(scrollBarHeightInDIP); + } + + const auto buffer = source.PixelBuffer(); + const auto data = buffer.data(); + const auto stride = scrollBarWidthInPx * sizeof(til::color); + + // The bitmap has the size of the entire scrollbar, but we want the marks to only show in the range the "thumb" + // (the scroll indicator) can move. That's why we need to add an offset to the start of the drawable bitmap area + // (to offset the decrease button) and subtract twice that (to offset the increase button as well). + // + // The WinUI standard scrollbar defines a Margin="2,0,2,0" for the "VerticalPanningThumb" and a Padding="0,4,0,0" + // for the "VerticalDecrementTemplate" (and similar for the increment), but it seems neither of those is correct, + // because a padding for 3 DIPs seem to be the exact right amount to add. + const auto increaseDecreaseButtonHeight = scrollBarWidthInPx + lround(3 * scaleFactor); + const auto drawableDataStart = data + stride * increaseDecreaseButtonHeight; + const auto drawableRange = scrollBarHeightInPx - 2 * increaseDecreaseButtonHeight; + + // Protect the remaining code against negative offsets. This normally can't happen + // and this code just exists so it doesn't crash if I'm ever wrong about this. + // (The window has a min. size that ensures that there's always a scrollbar thumb.) + if (drawableRange < 0) + { + assert(false); + return; + } + + // The scrollbar bitmap is divided into 3 evenly sized stripes: + // Left: Regular marks + // Center: nothing + // Right: Search marks + const auto pipWidth = (scrollBarWidthInPx + 1) / 3; + const auto pipHeight = lround(1 * scaleFactor); + + const auto maxOffsetY = drawableRange - pipHeight; + const auto offsetScale = maxOffsetY / gsl::narrow_cast(update.newMaximum + update.newViewportSize); + // A helper to turn a TextBuffer row offset into a bitmap offset. + const auto dataAt = [&](til::CoordType row) [[msvc::forceinline]] { + const auto y = std::clamp(lrintf(row * offsetScale), 0, maxOffsetY); + return drawableDataStart + stride * y; + }; + // A helper to draw a single pip (mark) at the given location. + const auto drawPip = [&](uint8_t* beg, til::color color) [[msvc::forceinline]] { + const auto end = beg + pipHeight * stride; + for (; beg < end; beg += stride) { - Windows::UI::Xaml::Controls::Canvas::SetLeft(r, 16.0f * .66f); + // Coincidentally a til::color has the same RGBA format as the bitmap. +#pragma warning(suppress : 26490) // Don't use reinterpret_cast (type.1). + std::fill_n(reinterpret_cast(beg), pipWidth, color); } }; - for (const auto m : marks) + memset(data, 0, buffer.Length()); + + if (const auto marks = _core.ScrollMarks()) { - Windows::UI::Xaml::Shapes::Rectangle r; - Media::SolidColorBrush brush{}; - // Sneaky: technically, a mark doesn't need to have a color set, - // it might want to just use the color from the palette for that - // kind of mark. Fortunately, ControlCore is kind enough to - // pre-evaluate that for us, and shove the real value into the - // Color member, regardless if the mark has a literal value set. - brush.Color(static_cast(m.Color.Color)); - drawPip(m.Start.Y, false, brush); + for (const auto& m : marks) + { + const auto row = m.Start.Y; + const til::color color{ m.Color.Color }; + const auto base = dataAt(row); + drawPip(base, color); + } } - if (_searchBox) + if (_searchBox && _searchBox->Visibility() == Visibility::Visible) { - const auto searchMatches{ _core.SearchResultRows() }; - if (searchMatches && - searchMatches.Size() > 0 && - _searchBox->Visibility() == Visibility::Visible) + if (const auto searchMatches = _core.SearchResultRows()) { - const til::color fgColor{ _core.ForegroundColor() }; - Media::SolidColorBrush searchMarkBrush{}; - searchMarkBrush.Color(fgColor); - for (const auto m : searchMatches) + const til::color color{ _core.ForegroundColor() }; + const auto rightAlignedOffset = (scrollBarWidthInPx - pipWidth) * sizeof(til::color); + + for (const auto row : searchMatches) { - drawPip(m, true, searchMarkBrush); + const auto base = dataAt(row) + rightAlignedOffset; + drawPip(base, color); } } } + + source.Invalidate(); + canvas.Visibility(Visibility::Visible); } } @@ -620,14 +666,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation // achieve the intended effect. ScrollBar().IndicatorMode(Controls::Primitives::ScrollingIndicatorMode::None); ScrollBar().Visibility(Visibility::Collapsed); - ScrollMarksGrid().Visibility(Visibility::Collapsed); } else // (default or Visible) { // Default behavior ScrollBar().IndicatorMode(Controls::Primitives::ScrollingIndicatorMode::MouseIndicator); ScrollBar().Visibility(Visibility::Visible); - ScrollMarksGrid().Visibility(Visibility::Visible); } _interactivity.UpdateSettings(); @@ -640,8 +684,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation } _showMarksInScrollbar = settings.ShowMarks(); - // Clear out all the current marks - ScrollBarCanvas().Children().Clear(); + // Hide all scrollbar marks since they might be disabled now. + if (const auto canvas = ScrollBarCanvas()) + { + canvas.Visibility(Visibility::Collapsed); + } // When we hot reload the settings, the core will send us a scrollbar // update. If we enabled scrollbar marks, then great, when we handle // that message, we'll redraw them. diff --git a/src/cascadia/TerminalControl/TermControl.xaml b/src/cascadia/TerminalControl/TermControl.xaml index 9f1c9dc83a5..57bc4fa9308 100644 --- a/src/cascadia/TerminalControl/TermControl.xaml +++ b/src/cascadia/TerminalControl/TermControl.xaml @@ -1322,28 +1322,14 @@ ValueChanged="_ScrollbarChangeHandler" ViewportSize="10" /> - - - - - - - - - - - - + From 059f7701f241a314a049eb5d2c62cf7f4c3b803f Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Wed, 20 Sep 2023 10:21:55 -0500 Subject: [PATCH 05/12] Merge PublicTerminalCore into TermControl (#15992) This pull request moves HwndTerminal into Microsoft.Terminal.Control.Lib and removes PublicTerminalCore completely. Microsoft.Terminal.Control.dll now exports the C API from HwndTerminal. This adds ~100kb to Microsoft.Terminal.Control.dll and ~1400kb to the WPF package (per architecture) but with the coming interactivity platform merge it's going to benefit us big time. --- OpenConsole.sln | 33 +--------- build/config/esrp.build.batch.wpf.json | 2 +- .../templates-v2/job-build-project.yml | 2 +- doc/ORGANIZATION.md | 1 - .../PublicTerminalCore.vcxproj | 64 ------------------- .../PublicTerminalCore.vcxproj.filters | 42 ------------ src/cascadia/PublicTerminalCore/pch.cpp | 4 -- src/cascadia/PublicTerminalCore/pch.h | 12 ---- .../HwndTerminal.cpp | 0 .../HwndTerminal.hpp | 0 .../HwndTerminalAutomationPeer.cpp | 0 .../HwndTerminalAutomationPeer.hpp | 0 .../TerminalControlLib.vcxproj | 4 ++ .../dll/Microsoft.Terminal.Control.def | 27 +++++++- .../dll/TerminalControl.vcxproj | 3 +- src/cascadia/TerminalControl/pch.h | 1 + src/cascadia/WinRTUtils/WinRTUtils.vcxproj | 1 + .../WpfTerminalControl/NativeMethods.cs | 54 +++++++--------- .../WpfTerminalControl/TerminalContainer.cs | 29 --------- .../WpfTerminalControl.csproj | 12 ++-- .../WpfTerminalTestNetCore.csproj | 4 +- 21 files changed, 68 insertions(+), 227 deletions(-) delete mode 100644 src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj delete mode 100644 src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj.filters delete mode 100644 src/cascadia/PublicTerminalCore/pch.cpp delete mode 100644 src/cascadia/PublicTerminalCore/pch.h rename src/cascadia/{PublicTerminalCore => TerminalControl}/HwndTerminal.cpp (100%) rename src/cascadia/{PublicTerminalCore => TerminalControl}/HwndTerminal.hpp (100%) rename src/cascadia/{PublicTerminalCore => TerminalControl}/HwndTerminalAutomationPeer.cpp (100%) rename src/cascadia/{PublicTerminalCore => TerminalControl}/HwndTerminalAutomationPeer.hpp (100%) diff --git a/OpenConsole.sln b/OpenConsole.sln index 1a48fa2a001..5c2b55ccd4b 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -239,8 +239,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{89CDCC EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Types.Unit.Tests", "src\types\ut_types\Types.Unit.Tests.vcxproj", "{34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PublicTerminalCore", "src\cascadia\PublicTerminalCore\PublicTerminalCore.vcxproj", "{84848BFA-931D-42CE-9ADF-01EE54DE7890}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTerminalControl", "src\cascadia\WpfTerminalControl\WpfTerminalControl.csproj", "{376FE273-6B84-4EB5-8B30-8DE9D21B022C}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_TerminalApp", "src\cascadia\ut_app\TerminalApp.UnitTests.vcxproj", "{CA5CAD1A-9333-4D05-B12A-1905CBF112F9}" @@ -334,7 +332,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmt", "src\dep\fmt\fmt.vcxp EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTerminalTestNetCore", "src\cascadia\WpfTerminalTestNetCore\WpfTerminalTestNetCore.csproj", "{1588FD7C-241E-4E7D-9113-43735F3E6BAD}" ProjectSection(ProjectDependencies) = postProject - {84848BFA-931D-42CE-9ADF-01EE54DE7890} = {84848BFA-931D-42CE-9ADF-01EE54DE7890} + {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} {A22EC5F6-7851-4B88-AC52-47249D437A52} = {A22EC5F6-7851-4B88-AC52-47249D437A52} EndProjectSection EndProject @@ -1711,34 +1709,6 @@ Global {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Release|x64.Build.0 = Release|x64 {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Release|x86.ActiveCfg = Release|Win32 {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Release|x86.Build.0 = Release|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|x64.ActiveCfg = AuditMode|x64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|x64.Build.0 = AuditMode|x64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|x86.ActiveCfg = AuditMode|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.AuditMode|x86.Build.0 = AuditMode|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|ARM.ActiveCfg = Debug|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|ARM64.Build.0 = Debug|ARM64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|x64.ActiveCfg = Debug|x64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|x64.Build.0 = Debug|x64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|x86.ActiveCfg = Debug|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|x86.Build.0 = Debug|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|Any CPU.ActiveCfg = Release|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|ARM.ActiveCfg = Release|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|ARM64.ActiveCfg = Release|ARM64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|ARM64.Build.0 = Release|ARM64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|x64.ActiveCfg = Release|x64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|x64.Build.0 = Release|x64 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|x86.ActiveCfg = Release|Win32 - {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|x86.Build.0 = Release|Win32 {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.AuditMode|Any CPU.ActiveCfg = Release|Any CPU {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.AuditMode|ARM.ActiveCfg = Debug|Any CPU {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.AuditMode|ARM.Build.0 = Debug|Any CPU @@ -2894,7 +2864,6 @@ Global {05500DEF-2294-41E3-AF9A-24E580B82836} = {89CDCC5C-9F53-4054-97A4-639D99F169CD} {1E4A062E-293B-4817-B20D-BF16B979E350} = {89CDCC5C-9F53-4054-97A4-639D99F169CD} {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73} = {89CDCC5C-9F53-4054-97A4-639D99F169CD} - {84848BFA-931D-42CE-9ADF-01EE54DE7890} = {4DAF0299-495E-4CD1-A982-9BAC16A45932} {376FE273-6B84-4EB5-8B30-8DE9D21B022C} = {4DAF0299-495E-4CD1-A982-9BAC16A45932} {CA5CAD1A-9333-4D05-B12A-1905CBF112F9} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E} {CA5CAD1A-9A12-429C-B551-8562EC954746} = {59840756-302F-44DF-AA47-441A9D673202} diff --git a/build/config/esrp.build.batch.wpf.json b/build/config/esrp.build.batch.wpf.json index e9c9af87891..62432046664 100644 --- a/build/config/esrp.build.batch.wpf.json +++ b/build/config/esrp.build.batch.wpf.json @@ -1,7 +1,7 @@ [ { "MatchedPath": [ - "PublicTerminalCore.dll" + "Microsoft.Terminal.Control/Microsoft.Terminal.Control.dll" ], "SigningInfo": { "Operations": [ diff --git a/build/pipelines/templates-v2/job-build-project.yml b/build/pipelines/templates-v2/job-build-project.yml index eda45842bbe..39d5020c5c3 100644 --- a/build/pipelines/templates-v2/job-build-project.yml +++ b/build/pipelines/templates-v2/job-build-project.yml @@ -114,7 +114,7 @@ jobs: $SignFragments += "wpfdotnet" } If ([bool]::Parse("${{ parameters.buildWPF }}")) { - $BuildTargets += "Terminal\wpf\PublicTerminalCore" + $BuildTargets += "Terminal\Control\Microsoft_Terminal_Control" $SignFragments += "wpf" } If ([bool]::Parse("${{ parameters.buildConPTY }}")) { diff --git a/doc/ORGANIZATION.md b/doc/ORGANIZATION.md index d220c9034e4..07a6e41ee7e 100644 --- a/doc/ORGANIZATION.md +++ b/doc/ORGANIZATION.md @@ -32,7 +32,6 @@ * `/src/cascadia/TerminalApp` - This DLL represents the implementation of the Windows Terminal application. This includes parsing settings, hosting tabs & panes with Terminals in them, and displaying other UI elements. This DLL is almost entirely UWP-like code, and shouldn't be doing any Win32-like UI work. * `/src/cascadia/WindowsTerminal` - This EXE provides Win32 hosting for the TerminalApp. It will set up XAML islands, and is responsible for drawing the window, either as a standard window or with content in the titlebar (non-client area). * `/src/cascadia/CascadiaPackage` - This is a project for packaging the Windows Terminal and its dependencies into an .appx/.msix for deploying to the machine. - * `/src/cascadia/PublicTerminalCore` - This is a DLL wrapper for the TerminalCore and Renderer, similar to `TermControl`, which exposes some exported functions that so the Terminal can be used from C#. * `/src/cascadia/WpfTerminalControl` - A DLL implementing a WPF version of the Terminal Control. * `/src/host` – The meat of the windows console host. This includes buffer, input, output, windowing, server management, clipboard, and most interactions with the console host window that aren’t stated anywhere else. We’re trying to pull things out that are reusable into other libraries, but it’s a work in progress * `/src/host/lib` – Builds the reusable LIB copy of the host diff --git a/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj b/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj deleted file mode 100644 index f8db236b21f..00000000000 --- a/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj +++ /dev/null @@ -1,64 +0,0 @@ - - - - 16.0 - {84848BFA-931D-42CE-9ADF-01EE54DE7890} - Win32Proj - PublicTerminalCore - PublicTerminalCore - DynamicLibrary - - - - - - Create - - - - - - - - - - - - {1cf55140-ef6a-4736-a403-957e4f7430bb} - - - {ca5cad1a-abcd-429c-b551-8562ec954746} - - - {18D09A24-8240-42D6-8CB6-236EEE820263} - - - {8222900C-8B6C-452A-91AC-BE95DB04B95F} - - - {af0a096a-8b3a-4949-81ef-7df8f0fee91f} - - - {48d21369-3d7b-4431-9967-24e81292cf62} - - - {48d21369-3d7b-4431-9967-24e81292cf63} - - - - - pch.h - - - - - - - - - delayimp.lib;Uiautomationcore.lib;onecoreuap.lib;%(AdditionalDependencies) - uiautomationcore.dll;%(DelayLoadDLLs) - - - diff --git a/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj.filters b/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj.filters deleted file mode 100644 index 6865448d4a3..00000000000 --- a/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj.filters +++ /dev/null @@ -1,42 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/src/cascadia/PublicTerminalCore/pch.cpp b/src/cascadia/PublicTerminalCore/pch.cpp deleted file mode 100644 index 398a99f6653..00000000000 --- a/src/cascadia/PublicTerminalCore/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/PublicTerminalCore/pch.h b/src/cascadia/PublicTerminalCore/pch.h deleted file mode 100644 index 3834f83cdee..00000000000 --- a/src/cascadia/PublicTerminalCore/pch.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN // If this is not defined, windows.h includes commdlg.h which defines FindText globally and conflicts with UIAutomation ITextRangeProvider. -#define NOMCX -#define NOHELP -#define NOCOMM -#endif - -#include -#include \ No newline at end of file diff --git a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp b/src/cascadia/TerminalControl/HwndTerminal.cpp similarity index 100% rename from src/cascadia/PublicTerminalCore/HwndTerminal.cpp rename to src/cascadia/TerminalControl/HwndTerminal.cpp diff --git a/src/cascadia/PublicTerminalCore/HwndTerminal.hpp b/src/cascadia/TerminalControl/HwndTerminal.hpp similarity index 100% rename from src/cascadia/PublicTerminalCore/HwndTerminal.hpp rename to src/cascadia/TerminalControl/HwndTerminal.hpp diff --git a/src/cascadia/PublicTerminalCore/HwndTerminalAutomationPeer.cpp b/src/cascadia/TerminalControl/HwndTerminalAutomationPeer.cpp similarity index 100% rename from src/cascadia/PublicTerminalCore/HwndTerminalAutomationPeer.cpp rename to src/cascadia/TerminalControl/HwndTerminalAutomationPeer.cpp diff --git a/src/cascadia/PublicTerminalCore/HwndTerminalAutomationPeer.hpp b/src/cascadia/TerminalControl/HwndTerminalAutomationPeer.hpp similarity index 100% rename from src/cascadia/PublicTerminalCore/HwndTerminalAutomationPeer.hpp rename to src/cascadia/TerminalControl/HwndTerminalAutomationPeer.hpp diff --git a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj index d4560ea14a6..151fe35932d 100644 --- a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj +++ b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj @@ -69,6 +69,8 @@ TSFInputControl.xaml + + @@ -111,6 +113,8 @@ InteractivityAutomationPeer.idl + + diff --git a/src/cascadia/TerminalControl/dll/Microsoft.Terminal.Control.def b/src/cascadia/TerminalControl/dll/Microsoft.Terminal.Control.def index ba15818ddb1..8500c457d68 100644 --- a/src/cascadia/TerminalControl/dll/Microsoft.Terminal.Control.def +++ b/src/cascadia/TerminalControl/dll/Microsoft.Terminal.Control.def @@ -1,3 +1,26 @@ EXPORTS -DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE -DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE + ; WinRT ABI + DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE + DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE + + ; Flat C ABI + CreateTerminal + DestroyTerminal + TerminalBlinkCursor + TerminalCalculateResize + TerminalClearSelection + TerminalDpiChanged + TerminalGetSelection + TerminalIsSelectionActive + TerminalKillFocus + TerminalRegisterScrollCallback + TerminalRegisterWriteCallback + TerminalSendCharEvent + TerminalSendKeyEvent + TerminalSendOutput + TerminalSetCursorVisible + TerminalSetFocus + TerminalSetTheme + TerminalTriggerResize + TerminalTriggerResizeWithDimension + TerminalUserScroll diff --git a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj index 82ef3b91658..4116d986ea5 100644 --- a/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj +++ b/src/cascadia/TerminalControl/dll/TerminalControl.vcxproj @@ -89,7 +89,8 @@ - dwrite.lib;dxgi.lib;d2d1.lib;d3d11.lib;shcore.lib;winmm.lib;pathcch.lib;propsys.lib;uiautomationcore.lib;Shlwapi.lib;ntdll.lib;user32.lib;shell32.lib;kernel32.lib;%(AdditionalDependencies) + delayimp.lib;Uiautomationcore.lib;onecoreuap.lib;%(AdditionalDependencies) + uiautomationcore.dll;%(DelayLoadDLLs)