From b617c434a171f0349395038a532d1f6630fb441d Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Thu, 6 Aug 2020 03:03:58 +0200 Subject: [PATCH 01/22] Fix #7064: Ignore key events without scan code (#7145) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Up until #4999 we deferred all key events to the character event handler for which `ToUnicodeEx` returned a valid character and alternatively those who aren't a special key combination as listed in `TerminalInput`'s implementation. Since #4999 we started acknowledging/handling all key events no matter whether they're actually a known key combination. Given non-ASCII inputs the Win32 `SendInput()` method generates certain sequences that aren't recognizable combinations though and if they're handled by the key event handler no follow up character event is sent containing the unicode character. This PR adds another condition and defers all key events without scan code (i.e. those not representable by the current keyboard layout) to the character event handler. I'm absolutely not certain that this PR doesn't have a negative effect on other kinds of inputs. Is it common for key events to not contain a scan code? I personally haven't seen it happen before AutoHotKey/SendInput. Before this PR is merged it'd be nice to have a good testing plan in place in order to ensure nothing breaks. ## Validation Steps Performed Remapped `AltGr+8` to `»` using AutoHotKey using `<^>!8::SendInput {Raw}»`. Ensured `»` is printed if `AltGr+8` is pressed. Closes #7064 Closes #7120 --- src/cascadia/TerminalCore/Terminal.cpp | 13 +++++++++++++ src/cascadia/UnitTests_TerminalCore/InputTest.cpp | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index b71471fc7ef..7f106ba1f90 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -430,6 +430,19 @@ bool Terminal::SendKeyEvent(const WORD vkey, _StoreKeyEvent(vkey, scanCode); + // As a Terminal we're mostly interested in getting key events from physical hardware (mouse & keyboard). + // We're thus ignoring events whose values are outside the valid range and unlikely to be generated by the current keyboard. + // It's very likely that a proper followup character event will be sent to us. + // This prominently happens using AutoHotKey's keyboard remapping feature, + // which sends input events whose vkey is 0xff and scanCode is 0. + // We need to check for this early, as _CharacterFromKeyEvent() always returns 0 for such invalid values, + // making us believe that this is an actual non-character input, while it usually isn't. + // GH#7064 + if (vkey == 0 || vkey >= 0xff || scanCode == 0) + { + return false; + } + const auto isAltOnlyPressed = states.IsAltPressed() && !states.IsCtrlPressed(); const auto isSuppressedAltGrAlias = !_altGrAliasing && states.IsAltPressed() && states.IsCtrlPressed(); diff --git a/src/cascadia/UnitTests_TerminalCore/InputTest.cpp b/src/cascadia/UnitTests_TerminalCore/InputTest.cpp index 037c81db45b..9745b0e6b2d 100644 --- a/src/cascadia/UnitTests_TerminalCore/InputTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/InputTest.cpp @@ -30,6 +30,7 @@ namespace TerminalCoreUnitTests TEST_METHOD(AltShiftKey); TEST_METHOD(AltSpace); + TEST_METHOD(InvalidKeyEvent); void _VerifyExpectedInput(std::wstring& actualInput) { @@ -65,4 +66,14 @@ namespace TerminalCoreUnitTests VERIFY_IS_FALSE(term.SendKeyEvent(L' ', 0, ControlKeyStates::LeftAltPressed, false)); VERIFY_IS_FALSE(term.SendCharEvent(L' ', 0, ControlKeyStates::LeftAltPressed)); } + + void InputTest::InvalidKeyEvent() + { + // Certain applications like AutoHotKey and its keyboard remapping feature, + // send us key events using SendInput() whose values are outside of the valid range. + // We don't want to handle those events as we're probably going to get a proper followup character event. + VERIFY_IS_FALSE(term.SendKeyEvent(0, 123, {}, true)); + VERIFY_IS_FALSE(term.SendKeyEvent(255, 123, {}, true)); + VERIFY_IS_FALSE(term.SendKeyEvent(123, 0, {}, true)); + } } From f215b56ca3344cfd5fdec72d8c73a664c31ece46 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 6 Aug 2020 16:23:54 -0500 Subject: [PATCH 02/22] Add a "shell vs terminal" section to Niksa.md (#7202) I've typed this up way too many times now. I'm sticking this comment in Niksa.md, and if it's ever an insufficient explanation of the differences, we can elaborate. --- doc/Niksa.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/doc/Niksa.md b/doc/Niksa.md index 4ad72148cf6..e543191a6c7 100644 --- a/doc/Niksa.md +++ b/doc/Niksa.md @@ -9,6 +9,8 @@ This document serves as a storage point for those posts. - [Output Processing between "Far East" and "Western"](#fesb) - [Why do we not backport things?](#backport) - [Why can't we have mixed elevated and non-elevated tabs in the Terminal?](#elevation) +- [What's the difference between a shell and a terminal?](#shell-vs-terminal) + ## Why do we avoid changing CMD.exe? `setlocal` doesn't behave the same way as an environment variable. It's a thing that would have to be put in at the top of the batch script that is `somefile.cmd` as one of its first commands to adjust the way that one specific batch file is processed by the `cmd.exe` engine. That's probably not suitable for your needs, but that's the way we have to go. @@ -179,3 +181,20 @@ Other platforms have accepted that risk in preference for user convenience. They Original Source: https://github.com/microsoft/terminal/issues/632#issuecomment-519375707 +## What's the difference between a shell and a terminal? + +_guest speaker @zadjii-msft_ + +I think there might be a bit of a misunderstanding here - there are two different kinds of applications we're talking about here: +* shell applications, like `cmd.exe`, `powershell`, `zsh`, etc. These are text-only applications that emit streams of characters. They don't care at all about how they're eventually rendered to the user. These are also sometimes referred to as "commandline client" applications. +* terminal applications, like the Windows Terminal, gnome-terminal, xterm, iterm2, hyper. These are graphical applications that can be used to render the output of commandline clients. + +On Windows, if you just run `cmd.exe` directly, the OS will create an instance of `conhost.exe` as the _terminal_ for `cmd.exe`. The same thing happens for `powershell.exe`, the system will creates a new conhost window for any client that's not already connected to a terminal of some sort. This has lead to an enormous amount of confusion for people thinking that a conhost window is actually a "`cmd` window". `cmd` can't have a window, it's just a commandline application. Its window is always some other terminal. + +Any terminal can run any commandline client application. So you can use the Windows Terminal to run whatever shell you want. I use mine for both `cmd` and `powershell`, and also WSL: + +![image](https://user-images.githubusercontent.com/18356694/89556758-79d27e80-d7d7-11ea-84e2-10710e09ef4a.png) + +It's not the Terminal's responsibility to remember the commands executed by a commandline client. That's the responsibility of the _shell_. How would the terminal remember commands executed by something like `emacs` or `vim`? Those are both applications where the user is typing input and hitting enter, like they would at a cmd prompt, but without something that resembles a command history. + +Original Source: https://github.com/microsoft/terminal/issues/6500#issuecomment-670035468 From 0a30b856a98cc6383fb125f21c8ac6b137fbd4ee Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 6 Aug 2020 16:47:50 -0500 Subject: [PATCH 03/22] Add `closeOtherTabs`, `closeTabsAfter` actions (#7176) ## Summary of the Pull Request Adds support for two actions, `closeOtherTabs` and `closeTabsAfter`. Both these actions accept an `index` parameter. * `closeOtherTabs`: Close tabs other than `index` * `closeTabsAfter`: Close tabs after `index` (This is also "Close tabs to the right") ## References * This PR is being made to unblock @RahulRavishankar in #1912 ## PR Checklist * [x] I work here * [ ] Tests added/passed * [x] Requires documentation to be updated * [ ] We should file an issue for "add an `index` param to `closeTab`" to add similar support to the close tab action * [ ] We should file an issue for "make the `index` param to `closeOtherTabs`, `closeTabsAfter` optional" to make them both work on the _active_ tab when there's no `index` provided ## Validation Steps Performed * _Verified that_ closing all tabs when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing all tabs when I have a tab other than the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have a tab other than the `index`'th tab selected _works as expected_ - This one has one caveat: for whatever reason, if you run this action when the tab that's currently focused is _before_ the `index` param, then the tabs will expand to fill the entire width of the tab row, until you mouse over them. Probably has something to do with tabs not resizing down until there's a mouse exit event. --- doc/cascadia/profiles.schema.json | 38 ++++++++++++ src/cascadia/TerminalApp/ActionAndArgs.cpp | 10 ++++ src/cascadia/TerminalApp/ActionArgs.cpp | 17 ++++++ src/cascadia/TerminalApp/ActionArgs.h | 58 +++++++++++++++++++ src/cascadia/TerminalApp/ActionArgs.idl | 10 ++++ .../TerminalApp/AppActionHandlers.cpp | 45 ++++++++++++++ .../Resources/en-US/Resources.resw | 12 +++- .../TerminalApp/ShortcutActionDispatch.cpp | 11 ++++ .../TerminalApp/ShortcutActionDispatch.h | 2 + .../TerminalApp/ShortcutActionDispatch.idl | 6 +- src/cascadia/TerminalApp/TerminalPage.cpp | 2 + src/cascadia/TerminalApp/TerminalPage.h | 2 + 12 files changed, 210 insertions(+), 3 deletions(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 0ca40b685bd..a4dbd3d806d 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -64,6 +64,8 @@ "renameTab", "commandPalette", "wt", + "closeOtherTabs", + "closeTabsAfter", "unbound" ], "type": "string" @@ -298,6 +300,40 @@ ], "required": [ "commandline" ] }, + "CloseOtherTabsAction": { + "description": "Arguments for a closeOtherTabs action", + "allOf": [ + { "$ref": "#/definitions/ShortcutAction" }, + { + "properties": { + "action": { "type": "string", "pattern": "closeOtherTabs" }, + "index": { + "type": "integer", + "default": "", + "description": "close the tabs following the tab at this index" + } + } + } + ], + "required": [ "index" ] + }, + "CloseTabsAfterAction": { + "description": "Arguments for a closeTabsAfter action", + "allOf": [ + { "$ref": "#/definitions/ShortcutAction" }, + { + "properties": { + "action": { "type": "string", "pattern": "closeTabsAfter" }, + "index": { + "type": "integer", + "default": "", + "description": "close the tabs other than the one at this index" + } + } + } + ], + "required": [ "index" ] + }, "Keybinding": { "additionalProperties": false, "properties": { @@ -315,6 +351,8 @@ { "$ref": "#/definitions/OpenSettingsAction" }, { "$ref": "#/definitions/SetTabColorAction" }, { "$ref": "#/definitions/WtAction" }, + { "$ref": "#/definitions/CloseOtherTabsAction" }, + { "$ref": "#/definitions/CloseTabsAfterAction" }, { "type": "null" } ] }, diff --git a/src/cascadia/TerminalApp/ActionAndArgs.cpp b/src/cascadia/TerminalApp/ActionAndArgs.cpp index f28bfcca8a6..2f8966810fe 100644 --- a/src/cascadia/TerminalApp/ActionAndArgs.cpp +++ b/src/cascadia/TerminalApp/ActionAndArgs.cpp @@ -40,6 +40,8 @@ static constexpr std::string_view OpenTabColorPickerKey{ "openTabColorPicker" }; static constexpr std::string_view RenameTabKey{ "renameTab" }; static constexpr std::string_view ExecuteCommandlineKey{ "wt" }; static constexpr std::string_view ToggleCommandPaletteKey{ "commandPalette" }; +static constexpr std::string_view CloseOtherTabsKey{ "closeOtherTabs" }; +static constexpr std::string_view CloseTabsAfterKey{ "closeTabsAfter" }; static constexpr std::string_view ActionKey{ "action" }; @@ -92,6 +94,8 @@ namespace winrt::TerminalApp::implementation { RenameTabKey, ShortcutAction::RenameTab }, { ExecuteCommandlineKey, ShortcutAction::ExecuteCommandline }, { ToggleCommandPaletteKey, ShortcutAction::ToggleCommandPalette }, + { CloseOtherTabsKey, ShortcutAction::CloseOtherTabs }, + { CloseTabsAfterKey, ShortcutAction::CloseTabsAfter }, }; using ParseResult = std::tuple>; @@ -125,6 +129,10 @@ namespace winrt::TerminalApp::implementation { ShortcutAction::ExecuteCommandline, winrt::TerminalApp::implementation::ExecuteCommandlineArgs::FromJson }, + { ShortcutAction::CloseOtherTabs, winrt::TerminalApp::implementation::CloseOtherTabsArgs::FromJson }, + + { ShortcutAction::CloseTabsAfter, winrt::TerminalApp::implementation::CloseTabsAfterArgs::FromJson }, + { ShortcutAction::Invalid, nullptr }, }; @@ -274,6 +282,8 @@ namespace winrt::TerminalApp::implementation { ShortcutAction::RenameTab, RS_(L"ResetTabNameCommandKey") }, { ShortcutAction::ExecuteCommandline, RS_(L"ExecuteCommandlineCommandKey") }, { ShortcutAction::ToggleCommandPalette, RS_(L"ToggleCommandPaletteCommandKey") }, + { ShortcutAction::CloseOtherTabs, L"" }, // Intentionally omitted, must be generated by GenerateName + { ShortcutAction::CloseTabsAfter, L"" }, // Intentionally omitted, must be generated by GenerateName }; }(); diff --git a/src/cascadia/TerminalApp/ActionArgs.cpp b/src/cascadia/TerminalApp/ActionArgs.cpp index a5a83203afa..27425c58fc7 100644 --- a/src/cascadia/TerminalApp/ActionArgs.cpp +++ b/src/cascadia/TerminalApp/ActionArgs.cpp @@ -272,4 +272,21 @@ namespace winrt::TerminalApp::implementation return L""; } + winrt::hstring CloseOtherTabsArgs::GenerateName() const + { + // "Close tabs other than index {0}" + return winrt::hstring{ + fmt::format(std::wstring_view(RS_(L"CloseOtherTabsCommandKey")), + _Index) + }; + } + + winrt::hstring CloseTabsAfterArgs::GenerateName() const + { + // "Close tabs after index {0}" + return winrt::hstring{ + fmt::format(std::wstring_view(RS_(L"CloseTabsAfterCommandKey")), + _Index) + }; + } } diff --git a/src/cascadia/TerminalApp/ActionArgs.h b/src/cascadia/TerminalApp/ActionArgs.h index 091774230d1..941b4716a8f 100644 --- a/src/cascadia/TerminalApp/ActionArgs.h +++ b/src/cascadia/TerminalApp/ActionArgs.h @@ -18,6 +18,8 @@ #include "SetTabColorArgs.g.h" #include "RenameTabArgs.g.h" #include "ExecuteCommandlineArgs.g.h" +#include "CloseOtherTabsArgs.g.h" +#include "CloseTabsAfterArgs.g.h" #include "../../cascadia/inc/cppwinrt_utils.h" #include "Utils.h" @@ -421,6 +423,62 @@ namespace winrt::TerminalApp::implementation } }; + struct CloseOtherTabsArgs : public CloseOtherTabsArgsT + { + CloseOtherTabsArgs() = default; + GETSET_PROPERTY(uint32_t, Index, 0); + + static constexpr std::string_view IndexKey{ "index" }; + + public: + hstring GenerateName() const; + + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_Index == _Index; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + JsonUtils::GetValueForKey(json, IndexKey, args->_Index); + return { *args, {} }; + } + }; + + struct CloseTabsAfterArgs : public CloseTabsAfterArgsT + { + CloseTabsAfterArgs() = default; + GETSET_PROPERTY(uint32_t, Index, 0); + + static constexpr std::string_view IndexKey{ "index" }; + + public: + hstring GenerateName() const; + + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_Index == _Index; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + JsonUtils::GetValueForKey(json, IndexKey, args->_Index); + return { *args, {} }; + } + }; + } namespace winrt::TerminalApp::factory_implementation diff --git a/src/cascadia/TerminalApp/ActionArgs.idl b/src/cascadia/TerminalApp/ActionArgs.idl index 84e5588bf2d..bfeee27d3f6 100644 --- a/src/cascadia/TerminalApp/ActionArgs.idl +++ b/src/cascadia/TerminalApp/ActionArgs.idl @@ -120,4 +120,14 @@ namespace TerminalApp { String Commandline; }; + + [default_interface] runtimeclass CloseOtherTabsArgs : IActionArgs + { + UInt32 Index { get; }; + }; + + [default_interface] runtimeclass CloseTabsAfterArgs : IActionArgs + { + UInt32 Index { get; }; + }; } diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 63a2743d80b..afb72b94506 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -351,4 +351,49 @@ namespace winrt::TerminalApp::implementation } } } + + void TerminalPage::_HandleCloseOtherTabs(const IInspectable& /*sender*/, + const TerminalApp::ActionEventArgs& actionArgs) + { + if (const auto& realArgs = actionArgs.ActionArgs().try_as()) + { + uint32_t index = realArgs.Index(); + + // Remove tabs after the current one + while (_tabs.Size() > index + 1) + { + _RemoveTabViewItemByIndex(_tabs.Size() - 1); + } + + // Remove all of them leading up to the selected tab + while (_tabs.Size() > 1) + { + _RemoveTabViewItemByIndex(0); + } + + actionArgs.Handled(true); + } + } + void TerminalPage::_HandleCloseTabsAfter(const IInspectable& /*sender*/, + const TerminalApp::ActionEventArgs& actionArgs) + { + if (const auto& realArgs = actionArgs.ActionArgs().try_as()) + { + uint32_t index = realArgs.Index(); + + // Remove tabs after the current one + while (_tabs.Size() > index + 1) + { + _RemoveTabViewItemByIndex(_tabs.Size() - 1); + } + + // TODO:GH#7182 For whatever reason, if you run this action + // when the tab that's currently focused is _before_ the `index` + // param, then the tabs will expand to fill the entire width of the + // tab row, until you mouse over them. Probably has something to do + // with tabs not resizing down until there's a mouse exit event. + + actionArgs.Handled(true); + } + } } diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 6ca22a39ff0..d1cb5606c07 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -538,14 +538,22 @@ Rename tab to "{0}" - {0} will be replaced with user-defined string + {0} will be replaced with a user-defined string Reset tab title Run commandline "{0}" in this window - {0} will be replaced with user-defined commandline + {0} will be replaced with a user-defined commandline + + + Close tabs other than index {0} + {0} will be replaced with a number + + + Close tabs after index {0} + {0} will be replaced with a number Crimson diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index 571b4589516..1ea1bb7fae2 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -197,6 +197,17 @@ namespace winrt::TerminalApp::implementation case ShortcutAction::ExecuteCommandline: { _ExecuteCommandlineHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::CloseOtherTabs: + { + _CloseOtherTabsHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::CloseTabsAfter: + { + _CloseTabsAfterHandlers(*this, *eventArgs); + break; } default: return false; diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.h b/src/cascadia/TerminalApp/ShortcutActionDispatch.h index 9c1dff1575c..7ed978d9b80 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.h +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.h @@ -55,6 +55,8 @@ namespace winrt::TerminalApp::implementation TYPED_EVENT(OpenTabColorPicker, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(RenameTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(ExecuteCommandline, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(CloseOtherTabs, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(CloseTabsAfter, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); // clang-format on private: diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl index 8306c04fc46..026fa4aa2ba 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl @@ -40,7 +40,9 @@ namespace TerminalApp OpenTabColorPicker, RenameTab, ExecuteCommandline, - ToggleCommandPalette + ToggleCommandPalette, + CloseOtherTabs, + CloseTabsAfter }; [default_interface] runtimeclass ActionAndArgs { @@ -86,5 +88,7 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler OpenTabColorPicker; event Windows.Foundation.TypedEventHandler RenameTab; event Windows.Foundation.TypedEventHandler ExecuteCommandline; + event Windows.Foundation.TypedEventHandler CloseOtherTabs; + event Windows.Foundation.TypedEventHandler CloseTabsAfter; } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 30689891f04..201eeda0854 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -893,6 +893,8 @@ namespace winrt::TerminalApp::implementation _actionDispatch->OpenTabColorPicker({ this, &TerminalPage::_HandleOpenTabColorPicker }); _actionDispatch->RenameTab({ this, &TerminalPage::_HandleRenameTab }); _actionDispatch->ExecuteCommandline({ this, &TerminalPage::_HandleExecuteCommandline }); + _actionDispatch->CloseOtherTabs({ this, &TerminalPage::_HandleCloseOtherTabs }); + _actionDispatch->CloseTabsAfter({ this, &TerminalPage::_HandleCloseTabsAfter }); } // Method Description: diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 021be7a3e16..174ee77d597 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -224,6 +224,8 @@ namespace winrt::TerminalApp::implementation void _HandleRenameTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleExecuteCommandline(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleToggleCommandPalette(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); + void _HandleCloseOtherTabs(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); + void _HandleCloseTabsAfter(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); // Make sure to hook new actions up in _RegisterActionCallbacks! #pragma endregion From 858905f4925f045fc33b47654b14bf22f6448715 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Thu, 6 Aug 2020 16:55:07 -0700 Subject: [PATCH 04/22] Disable MinimalCoreWin when OpenConsoleUniversalApp is false (#7203) This fixes the build the rest of the way in VS 16.7. Something about the way we were using the Store/Container flags caused some of our projects to end up linking kernel32.lib only (MinimalCoreWin==KernelOnly). The best way to solve it once and for all is to make sure MinimalCoreWin is always set. References 313568d0e5c. --- src/cppwinrt.build.pre.props | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/cppwinrt.build.pre.props b/src/cppwinrt.build.pre.props index cd89880fdd6..c7ac9550f61 100644 --- a/src/cppwinrt.build.pre.props +++ b/src/cppwinrt.build.pre.props @@ -22,12 +22,20 @@ at the winmd we build to generate type info. In general, cppwinrt projects all want this. --> - + true true true Windows Store + + + false + - diff --git a/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj b/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj index c1745442044..f035d8a74d1 100644 --- a/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj +++ b/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj @@ -45,11 +45,11 @@ "taef.png" is actually in the package. taef.png will get copied to the OutputPath when taef is run, but if this isn't set to false, then the CI will try and make sure taef.png is in the OutputPath at build time.--> - + false - + 4453;%(DisableSpecificWarnings) @@ -94,7 +94,6 @@ {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} - diff --git a/src/cascadia/LocalTests_TerminalApp/TestUtils.h b/src/cascadia/LocalTests_TerminalApp/TestUtils.h index ea1df508e1f..c34552b019a 100644 --- a/src/cascadia/LocalTests_TerminalApp/TestUtils.h +++ b/src/cascadia/LocalTests_TerminalApp/TestUtils.h @@ -24,18 +24,18 @@ class TerminalAppLocalTests::TestUtils // Return Value: // - The ActionAndArgs bound to the given key, or nullptr if nothing is bound to it. static const winrt::TerminalApp::ActionAndArgs GetActionAndArgs(const winrt::TerminalApp::implementation::AppKeyBindings& bindings, - const winrt::Microsoft::Terminal::Settings::KeyChord& kc) + const winrt::Microsoft::Terminal::TerminalControl::KeyChord& kc) { std::wstring buffer{ L"" }; - if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::Settings::KeyModifiers::Ctrl)) + if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::TerminalControl::KeyModifiers::Ctrl)) { buffer += L"Ctrl+"; } - if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::Settings::KeyModifiers::Shift)) + if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::TerminalControl::KeyModifiers::Shift)) { buffer += L"Shift+"; } - if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::Settings::KeyModifiers::Alt)) + if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::TerminalControl::KeyModifiers::Alt)) { buffer += L"Alt+"; } diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index afb72b94506..5d260ef94c4 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -14,7 +14,6 @@ using namespace winrt::Windows::UI::Core; using namespace winrt::Windows::Foundation::Collections; using namespace winrt::Windows::System; using namespace winrt::Microsoft::Terminal; -using namespace winrt::Microsoft::Terminal::Settings; using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace winrt::Microsoft::Terminal::TerminalConnection; using namespace ::TerminalApp; diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index 58821ac5a6a..4ac3f012c2c 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -9,12 +9,12 @@ using namespace winrt::Microsoft::Terminal; using namespace winrt::TerminalApp; -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::Microsoft::Terminal::TerminalControl; namespace winrt::TerminalApp::implementation { void AppKeyBindings::SetKeyBinding(const TerminalApp::ActionAndArgs& actionAndArgs, - const Settings::KeyChord& chord) + const KeyChord& chord) { _keyShortcuts[chord] = actionAndArgs; } @@ -25,7 +25,7 @@ namespace winrt::TerminalApp::implementation // - chord: the keystroke to remove the action for. // Return Value: // - - void AppKeyBindings::ClearKeyBinding(const Settings::KeyChord& chord) + void AppKeyBindings::ClearKeyBinding(const KeyChord& chord) { _keyShortcuts.erase(chord); } @@ -67,7 +67,7 @@ namespace winrt::TerminalApp::implementation return { nullptr }; } - bool AppKeyBindings::TryKeyChord(const Settings::KeyChord& kc) + bool AppKeyBindings::TryKeyChord(const KeyChord& kc) { const auto keyIter = _keyShortcuts.find(kc); if (keyIter != _keyShortcuts.end()) @@ -87,19 +87,19 @@ namespace winrt::TerminalApp::implementation // - Takes the KeyModifier flags from Terminal and maps them to the WinRT types which are used by XAML // Return Value: // - a Windows::System::VirtualKeyModifiers object with the flags of which modifiers used. - Windows::System::VirtualKeyModifiers AppKeyBindings::ConvertVKModifiers(Settings::KeyModifiers modifiers) + Windows::System::VirtualKeyModifiers AppKeyBindings::ConvertVKModifiers(KeyModifiers modifiers) { Windows::System::VirtualKeyModifiers keyModifiers = Windows::System::VirtualKeyModifiers::None; - if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Ctrl)) + if (WI_IsFlagSet(modifiers, KeyModifiers::Ctrl)) { keyModifiers |= Windows::System::VirtualKeyModifiers::Control; } - if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Shift)) + if (WI_IsFlagSet(modifiers, KeyModifiers::Shift)) { keyModifiers |= Windows::System::VirtualKeyModifiers::Shift; } - if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Alt)) + if (WI_IsFlagSet(modifiers, KeyModifiers::Alt)) { // note: Menu is the Alt VK_MENU keyModifiers |= Windows::System::VirtualKeyModifiers::Menu; diff --git a/src/cascadia/TerminalApp/AppKeyBindings.h b/src/cascadia/TerminalApp/AppKeyBindings.h index 63df542a75a..4feb7e8968a 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.h +++ b/src/cascadia/TerminalApp/AppKeyBindings.h @@ -20,10 +20,10 @@ namespace winrt::TerminalApp::implementation { struct KeyChordHash { - std::size_t operator()(const winrt::Microsoft::Terminal::Settings::KeyChord& key) const + std::size_t operator()(const winrt::Microsoft::Terminal::TerminalControl::KeyChord& key) const { std::hash keyHash; - std::hash modifiersHash; + std::hash modifiersHash; std::size_t hashedKey = keyHash(key.Vkey()); std::size_t hashedMods = modifiersHash(key.Modifiers()); return hashedKey ^ hashedMods; @@ -32,7 +32,7 @@ namespace winrt::TerminalApp::implementation struct KeyChordEquality { - bool operator()(const winrt::Microsoft::Terminal::Settings::KeyChord& lhs, const winrt::Microsoft::Terminal::Settings::KeyChord& rhs) const + bool operator()(const winrt::Microsoft::Terminal::TerminalControl::KeyChord& lhs, const winrt::Microsoft::Terminal::TerminalControl::KeyChord& rhs) const { return lhs.Modifiers() == rhs.Modifiers() && lhs.Vkey() == rhs.Vkey(); } @@ -42,15 +42,15 @@ namespace winrt::TerminalApp::implementation { AppKeyBindings() = default; - bool TryKeyChord(winrt::Microsoft::Terminal::Settings::KeyChord const& kc); + bool TryKeyChord(winrt::Microsoft::Terminal::TerminalControl::KeyChord const& kc); void SetKeyBinding(TerminalApp::ActionAndArgs const& actionAndArgs, - winrt::Microsoft::Terminal::Settings::KeyChord const& chord); - void ClearKeyBinding(winrt::Microsoft::Terminal::Settings::KeyChord const& chord); - Microsoft::Terminal::Settings::KeyChord GetKeyBindingForAction(TerminalApp::ShortcutAction const& action); - Microsoft::Terminal::Settings::KeyChord GetKeyBindingForActionWithArgs(TerminalApp::ActionAndArgs const& actionAndArgs); + winrt::Microsoft::Terminal::TerminalControl::KeyChord const& chord); + void ClearKeyBinding(winrt::Microsoft::Terminal::TerminalControl::KeyChord const& chord); + Microsoft::Terminal::TerminalControl::KeyChord GetKeyBindingForAction(TerminalApp::ShortcutAction const& action); + Microsoft::Terminal::TerminalControl::KeyChord GetKeyBindingForActionWithArgs(TerminalApp::ActionAndArgs const& actionAndArgs); - static Windows::System::VirtualKeyModifiers ConvertVKModifiers(winrt::Microsoft::Terminal::Settings::KeyModifiers modifiers); + static Windows::System::VirtualKeyModifiers ConvertVKModifiers(winrt::Microsoft::Terminal::TerminalControl::KeyModifiers modifiers); // Defined in AppKeyBindingsSerialization.cpp std::vector<::TerminalApp::SettingsLoadWarnings> LayerJson(const Json::Value& json); @@ -59,7 +59,7 @@ namespace winrt::TerminalApp::implementation void SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch); private: - std::unordered_map _keyShortcuts; + std::unordered_map _keyShortcuts; winrt::TerminalApp::ShortcutActionDispatch _dispatch{ nullptr }; diff --git a/src/cascadia/TerminalApp/AppKeyBindings.idl b/src/cascadia/TerminalApp/AppKeyBindings.idl index db287b79267..0dcba935591 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.idl +++ b/src/cascadia/TerminalApp/AppKeyBindings.idl @@ -5,15 +5,15 @@ import "../ShortcutActionDispatch.idl"; namespace TerminalApp { - [default_interface] runtimeclass AppKeyBindings : Microsoft.Terminal.Settings.IKeyBindings + [default_interface] runtimeclass AppKeyBindings : Microsoft.Terminal.TerminalControl.IKeyBindings { AppKeyBindings(); - void SetKeyBinding(ActionAndArgs actionAndArgs, Microsoft.Terminal.Settings.KeyChord chord); - void ClearKeyBinding(Microsoft.Terminal.Settings.KeyChord chord); + void SetKeyBinding(ActionAndArgs actionAndArgs, Microsoft.Terminal.TerminalControl.KeyChord chord); + void ClearKeyBinding(Microsoft.Terminal.TerminalControl.KeyChord chord); - Microsoft.Terminal.Settings.KeyChord GetKeyBindingForAction(ShortcutAction action); - Microsoft.Terminal.Settings.KeyChord GetKeyBindingForActionWithArgs(ActionAndArgs actionAndArgs); + Microsoft.Terminal.TerminalControl.KeyChord GetKeyBindingForAction(ShortcutAction action); + Microsoft.Terminal.TerminalControl.KeyChord GetKeyBindingForActionWithArgs(ActionAndArgs actionAndArgs); void SetDispatch(ShortcutActionDispatch dispatch); } diff --git a/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp b/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp index 6be18ca683e..2bb507ec86f 100644 --- a/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp @@ -12,9 +12,8 @@ #include "KeyChordSerialization.h" #include "Utils.h" #include "JsonUtils.h" -#include -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace winrt::TerminalApp; static constexpr std::string_view KeysKey{ "keys" }; diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 5a6ec188703..b0257b431a6 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -15,7 +15,6 @@ using namespace winrt::Windows::UI::Xaml::Controls; using namespace winrt::Windows::UI::Core; using namespace winrt::Windows::System; using namespace winrt::Microsoft::Terminal; -using namespace winrt::Microsoft::Terminal::Settings; using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace ::TerminalApp; diff --git a/src/cascadia/TerminalApp/CascadiaSettings.cpp b/src/cascadia/TerminalApp/CascadiaSettings.cpp index 96e947e952d..29c8d750d02 100644 --- a/src/cascadia/TerminalApp/CascadiaSettings.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettings.cpp @@ -17,7 +17,6 @@ #include "WslDistroGenerator.h" #include "AzureCloudShellGenerator.h" -using namespace winrt::Microsoft::Terminal::Settings; using namespace ::TerminalApp; using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace winrt::TerminalApp; diff --git a/src/cascadia/TerminalApp/ColorScheme.cpp b/src/cascadia/TerminalApp/ColorScheme.cpp index 1659013809c..b04090b6e03 100644 --- a/src/cascadia/TerminalApp/ColorScheme.cpp +++ b/src/cascadia/TerminalApp/ColorScheme.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include #include "ColorScheme.h" #include "DefaultSettings.h" #include "../../types/inc/Utils.hpp" diff --git a/src/cascadia/TerminalApp/ColorScheme.h b/src/cascadia/TerminalApp/ColorScheme.h index dca0f53759a..4eafdc75b7c 100644 --- a/src/cascadia/TerminalApp/ColorScheme.h +++ b/src/cascadia/TerminalApp/ColorScheme.h @@ -15,7 +15,6 @@ Author(s): --*/ #pragma once -#include #include "TerminalSettings.h" #include "../../inc/conattrs.hpp" diff --git a/src/cascadia/TerminalApp/Command.cpp b/src/cascadia/TerminalApp/Command.cpp index f3fe1219126..6d164bc7445 100644 --- a/src/cascadia/TerminalApp/Command.cpp +++ b/src/cascadia/TerminalApp/Command.cpp @@ -10,7 +10,6 @@ #include "JsonUtils.h" #include -using namespace winrt::Microsoft::Terminal::Settings; using namespace winrt::TerminalApp; using namespace ::TerminalApp; diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index fd0a139281b..f6fdfa9567b 100644 --- a/src/cascadia/TerminalApp/CommandPalette.cpp +++ b/src/cascadia/TerminalApp/CommandPalette.cpp @@ -5,7 +5,6 @@ #include "CommandPalette.h" #include "CommandPalette.g.cpp" -#include using namespace winrt; using namespace winrt::TerminalApp; diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.cpp b/src/cascadia/TerminalApp/GlobalAppSettings.cpp index dd3b17ae723..00ce2cc3310 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalApp/GlobalAppSettings.cpp @@ -10,7 +10,6 @@ #include "TerminalSettingsSerializationHelpers.h" using namespace TerminalApp; -using namespace winrt::Microsoft::Terminal::Settings; using namespace winrt::TerminalApp; using namespace winrt::Windows::UI::Xaml; using namespace ::Microsoft::Console; diff --git a/src/cascadia/TerminalApp/KeyChordSerialization.cpp b/src/cascadia/TerminalApp/KeyChordSerialization.cpp index b825c251047..69625004d14 100644 --- a/src/cascadia/TerminalApp/KeyChordSerialization.cpp +++ b/src/cascadia/TerminalApp/KeyChordSerialization.cpp @@ -4,7 +4,7 @@ #include "pch.h" #include "KeyChordSerialization.h" -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::Microsoft::Terminal::TerminalControl; static constexpr std::wstring_view CTRL_KEY{ L"ctrl" }; static constexpr std::wstring_view SHIFT_KEY{ L"shift" }; @@ -99,7 +99,7 @@ static const std::unordered_map vkeyNamePairs { // - hstr: the string to parse into a keychord. // Return Value: // - a newly constructed KeyChord -winrt::Microsoft::Terminal::Settings::KeyChord KeyChordSerialization::FromString(const winrt::hstring& hstr) +KeyChord KeyChordSerialization::FromString(const winrt::hstring& hstr) { std::wstring wstr{ hstr }; @@ -201,7 +201,7 @@ winrt::Microsoft::Terminal::Settings::KeyChord KeyChordSerialization::FromString } } - return winrt::Microsoft::Terminal::Settings::KeyChord{ modifiers, vkey }; + return KeyChord{ modifiers, vkey }; } // Function Description: diff --git a/src/cascadia/TerminalApp/KeyChordSerialization.h b/src/cascadia/TerminalApp/KeyChordSerialization.h index 8f9cf4f26ee..4da2f0020a7 100644 --- a/src/cascadia/TerminalApp/KeyChordSerialization.h +++ b/src/cascadia/TerminalApp/KeyChordSerialization.h @@ -2,11 +2,11 @@ // Licensed under the MIT license. #pragma once -#include +#include class KeyChordSerialization final { public: - static winrt::Microsoft::Terminal::Settings::KeyChord FromString(const winrt::hstring& str); - static winrt::hstring ToString(const winrt::Microsoft::Terminal::Settings::KeyChord& chord); + static winrt::Microsoft::Terminal::TerminalControl::KeyChord FromString(const winrt::hstring& str); + static winrt::hstring ToString(const winrt::Microsoft::Terminal::TerminalControl::KeyChord& chord); }; diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index f8e61ae8379..40438f81f51 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -12,7 +12,6 @@ using namespace winrt::Windows::UI; using namespace winrt::Windows::UI::Xaml; using namespace winrt::Windows::UI::Core; using namespace winrt::Windows::UI::Xaml::Media; -using namespace winrt::Microsoft::Terminal::Settings; using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace winrt::Microsoft::Terminal::TerminalConnection; using namespace winrt::TerminalApp; diff --git a/src/cascadia/TerminalApp/Profile.cpp b/src/cascadia/TerminalApp/Profile.cpp index b98efb9f691..9829474297a 100644 --- a/src/cascadia/TerminalApp/Profile.cpp +++ b/src/cascadia/TerminalApp/Profile.cpp @@ -13,7 +13,7 @@ using namespace TerminalApp; using namespace winrt::TerminalApp; -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace winrt::Windows::UI::Xaml; using namespace ::Microsoft::Console; diff --git a/src/cascadia/TerminalApp/Profile.h b/src/cascadia/TerminalApp/Profile.h index 1e145e669c7..422b139883e 100644 --- a/src/cascadia/TerminalApp/Profile.h +++ b/src/cascadia/TerminalApp/Profile.h @@ -122,7 +122,7 @@ class TerminalApp::Profile final bool _snapOnInput; bool _altGrAliasing; uint32_t _cursorHeight; - winrt::Microsoft::Terminal::Settings::CursorStyle _cursorShape; + winrt::Microsoft::Terminal::TerminalControl::CursorStyle _cursorShape; std::wstring _commandline; std::wstring _fontFace; @@ -137,13 +137,13 @@ class TerminalApp::Profile final std::optional _backgroundImageStretchMode; std::optional> _backgroundImageAlignment; - std::optional<::winrt::Microsoft::Terminal::Settings::ScrollbarState> _scrollbarState; + std::optional<::winrt::Microsoft::Terminal::TerminalControl::ScrollbarState> _scrollbarState; CloseOnExitMode _closeOnExitMode; std::wstring _padding; std::optional _icon; - winrt::Microsoft::Terminal::Settings::TextAntialiasingMode _antialiasingMode; + winrt::Microsoft::Terminal::TerminalControl::TextAntialiasingMode _antialiasingMode; friend class TerminalAppLocalTests::SettingsTests; friend class TerminalAppLocalTests::ProfileTests; diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index 51e54be09ee..5e7521bbdfe 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -12,7 +12,6 @@ using namespace winrt; using namespace winrt::Windows::UI::Xaml; using namespace winrt::Windows::UI::Core; -using namespace winrt::Microsoft::Terminal::Settings; using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace winrt::Windows::System; diff --git a/src/cascadia/TerminalApp/TerminalApp.vcxproj b/src/cascadia/TerminalApp/TerminalApp.vcxproj index 320c20a299a..a19fa271c79 100644 --- a/src/cascadia/TerminalApp/TerminalApp.vcxproj +++ b/src/cascadia/TerminalApp/TerminalApp.vcxproj @@ -67,7 +67,6 @@ - - - $(_BinRoot)TerminalSettings\Microsoft.Terminal.Settings.winmd - true - false - false - $(_BinRoot)TerminalConnection\Microsoft.Terminal.TerminalConnection.winmd true diff --git a/src/cascadia/TerminalSettings/IControlSettings.idl b/src/cascadia/TerminalControl/IControlSettings.idl similarity index 85% rename from src/cascadia/TerminalSettings/IControlSettings.idl rename to src/cascadia/TerminalControl/IControlSettings.idl index 47484d99b4a..2f140a0a3f8 100644 --- a/src/cascadia/TerminalSettings/IControlSettings.idl +++ b/src/cascadia/TerminalControl/IControlSettings.idl @@ -2,9 +2,8 @@ // Licensed under the MIT license. import "IKeyBindings.idl"; -import "ICoreSettings.idl"; -namespace Microsoft.Terminal.Settings +namespace Microsoft.Terminal.TerminalControl { enum ScrollbarState { @@ -24,7 +23,7 @@ namespace Microsoft.Terminal.Settings // TermControl's behavior. In these settings there is both the entirety // of the Core ITerminalSettings interface, and any additional settings // for specifically the control. - interface IControlSettings requires Microsoft.Terminal.Settings.ICoreSettings + interface IControlSettings requires ICoreSettings { String ProfileName; @@ -37,7 +36,7 @@ namespace Microsoft.Terminal.Settings Windows.UI.Text.FontWeight FontWeight; String Padding; - IKeyBindings KeyBindings; + Microsoft.Terminal.TerminalControl.IKeyBindings KeyBindings; Boolean CopyOnSelect; diff --git a/src/cascadia/TerminalSettings/IKeyBindings.idl b/src/cascadia/TerminalControl/IKeyBindings.idl similarity index 78% rename from src/cascadia/TerminalSettings/IKeyBindings.idl rename to src/cascadia/TerminalControl/IKeyBindings.idl index 5c43e6dd376..6d3992c5d0a 100644 --- a/src/cascadia/TerminalSettings/IKeyBindings.idl +++ b/src/cascadia/TerminalControl/IKeyBindings.idl @@ -3,7 +3,7 @@ import "KeyChord.idl"; -namespace Microsoft.Terminal.Settings +namespace Microsoft.Terminal.TerminalControl { // [default_interface] interface IKeyBindings diff --git a/src/cascadia/TerminalSettings/KeyChord.cpp b/src/cascadia/TerminalControl/KeyChord.cpp similarity index 51% rename from src/cascadia/TerminalSettings/KeyChord.cpp rename to src/cascadia/TerminalControl/KeyChord.cpp index 6c3523497e0..c265b061312 100644 --- a/src/cascadia/TerminalSettings/KeyChord.cpp +++ b/src/cascadia/TerminalControl/KeyChord.cpp @@ -6,7 +6,7 @@ #include "KeyChord.g.cpp" -namespace winrt::Microsoft::Terminal::Settings::implementation +namespace winrt::Microsoft::Terminal::TerminalControl::implementation { KeyChord::KeyChord() noexcept : _modifiers{ 0 }, @@ -15,25 +15,25 @@ namespace winrt::Microsoft::Terminal::Settings::implementation } KeyChord::KeyChord(bool ctrl, bool alt, bool shift, int32_t vkey) noexcept : - _modifiers{ (ctrl ? Settings::KeyModifiers::Ctrl : Settings::KeyModifiers::None) | - (alt ? Settings::KeyModifiers::Alt : Settings::KeyModifiers::None) | - (shift ? Settings::KeyModifiers::Shift : Settings::KeyModifiers::None) }, + _modifiers{ (ctrl ? TerminalControl::KeyModifiers::Ctrl : TerminalControl::KeyModifiers::None) | + (alt ? TerminalControl::KeyModifiers::Alt : TerminalControl::KeyModifiers::None) | + (shift ? TerminalControl::KeyModifiers::Shift : TerminalControl::KeyModifiers::None) }, _vkey{ vkey } { } - KeyChord::KeyChord(Settings::KeyModifiers const& modifiers, int32_t vkey) noexcept : + KeyChord::KeyChord(TerminalControl::KeyModifiers const& modifiers, int32_t vkey) noexcept : _modifiers{ modifiers }, _vkey{ vkey } { } - Settings::KeyModifiers KeyChord::Modifiers() noexcept + TerminalControl::KeyModifiers KeyChord::Modifiers() noexcept { return _modifiers; } - void KeyChord::Modifiers(Settings::KeyModifiers const& value) noexcept + void KeyChord::Modifiers(TerminalControl::KeyModifiers const& value) noexcept { _modifiers = value; } diff --git a/src/cascadia/TerminalSettings/KeyChord.h b/src/cascadia/TerminalControl/KeyChord.h similarity index 53% rename from src/cascadia/TerminalSettings/KeyChord.h rename to src/cascadia/TerminalControl/KeyChord.h index e948c1afcd9..910eb6ca15f 100644 --- a/src/cascadia/TerminalSettings/KeyChord.h +++ b/src/cascadia/TerminalControl/KeyChord.h @@ -5,26 +5,26 @@ #include "KeyChord.g.h" -namespace winrt::Microsoft::Terminal::Settings::implementation +namespace winrt::Microsoft::Terminal::TerminalControl::implementation { struct KeyChord : KeyChordT { KeyChord() noexcept; - KeyChord(Settings::KeyModifiers const& modifiers, int32_t vkey) noexcept; + KeyChord(TerminalControl::KeyModifiers const& modifiers, int32_t vkey) noexcept; KeyChord(bool ctrl, bool alt, bool shift, int32_t vkey) noexcept; - Settings::KeyModifiers Modifiers() noexcept; - void Modifiers(Settings::KeyModifiers const& value) noexcept; + TerminalControl::KeyModifiers Modifiers() noexcept; + void Modifiers(TerminalControl::KeyModifiers const& value) noexcept; int32_t Vkey() noexcept; void Vkey(int32_t value) noexcept; private: - Settings::KeyModifiers _modifiers; + TerminalControl::KeyModifiers _modifiers; int32_t _vkey; }; } -namespace winrt::Microsoft::Terminal::Settings::factory_implementation +namespace winrt::Microsoft::Terminal::TerminalControl::factory_implementation { struct KeyChord : KeyChordT { diff --git a/src/cascadia/TerminalSettings/KeyChord.idl b/src/cascadia/TerminalControl/KeyChord.idl similarity index 87% rename from src/cascadia/TerminalSettings/KeyChord.idl rename to src/cascadia/TerminalControl/KeyChord.idl index c02459144b3..4952688a602 100644 --- a/src/cascadia/TerminalSettings/KeyChord.idl +++ b/src/cascadia/TerminalControl/KeyChord.idl @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -namespace Microsoft.Terminal.Settings +namespace Microsoft.Terminal.TerminalControl { [flags] enum KeyModifiers diff --git a/src/cascadia/TerminalControl/TSFInputControl.cpp b/src/cascadia/TerminalControl/TSFInputControl.cpp index 1eb56878c8a..23bd9bcbec2 100644 --- a/src/cascadia/TerminalControl/TSFInputControl.cpp +++ b/src/cascadia/TerminalControl/TSFInputControl.cpp @@ -31,14 +31,14 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation InitializeComponent(); // Create a CoreTextEditingContext for since we are acting like a custom edit control - auto manager = Core::CoreTextServicesManager::GetForCurrentView(); + auto manager = CoreTextServicesManager::GetForCurrentView(); _editContext = manager.CreateEditContext(); // InputPane is manually shown inside of TermControl. - _editContext.InputPaneDisplayPolicy(Core::CoreTextInputPaneDisplayPolicy::Manual); + _editContext.InputPaneDisplayPolicy(CoreTextInputPaneDisplayPolicy::Manual); // set the input scope to Text because this control is for any text. - _editContext.InputScope(Core::CoreTextInputScope::Text); + _editContext.InputScope(CoreTextInputScope::Text); _textRequestedRevoker = _editContext.TextRequested(winrt::auto_revoke, { this, &TSFInputControl::_textRequestedHandler }); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 62bc7a948e2..e99e0d2153d 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -25,7 +25,6 @@ using namespace winrt::Windows::UI::Core; using namespace winrt::Windows::UI::ViewManagement; using namespace winrt::Windows::UI::Input; using namespace winrt::Windows::System; -using namespace winrt::Microsoft::Terminal::Settings; using namespace winrt::Windows::ApplicationModel::DataTransfer; // The minimum delay between updates to the scroll bar's values. @@ -56,7 +55,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return initialized; } - TermControl::TermControl(Settings::IControlSettings settings, TerminalConnection::ITerminalConnection connection) : + TermControl::TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection) : _connection{ connection }, _initializedTerminal{ false }, _settings{ settings }, @@ -237,7 +236,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - newSettings: New settings values for the profile in this terminal. // Return Value: // - - winrt::fire_and_forget TermControl::UpdateSettings(Settings::IControlSettings newSettings) + winrt::fire_and_forget TermControl::UpdateSettings(IControlSettings newSettings) { _settings = newSettings; auto weakThis{ get_weak() }; @@ -2320,7 +2319,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const int32_t& fontHeight, const winrt::Windows::UI::Text::FontWeight& fontWeight, const winrt::hstring& fontFace, - const Microsoft::Terminal::Settings::ScrollbarState& scrollState, + const ScrollbarState& scrollState, const winrt::hstring& padding, const uint32_t dpi) { diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 4499c589efc..ce9a8a49d2d 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -7,7 +7,6 @@ #include "CopyToClipboardEventArgs.g.h" #include "PasteFromClipboardEventArgs.g.h" #include -#include #include "../../renderer/base/Renderer.hpp" #include "../../renderer/dx/DxRenderer.hpp" #include "../../renderer/uia/UiaRenderer.hpp" @@ -56,9 +55,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation struct TermControl : TermControlT { - TermControl(Settings::IControlSettings settings, TerminalConnection::ITerminalConnection connection); + TermControl(IControlSettings settings, TerminalConnection::ITerminalConnection connection); - winrt::fire_and_forget UpdateSettings(Settings::IControlSettings newSettings); + winrt::fire_and_forget UpdateSettings(IControlSettings newSettings); hstring Title(); hstring GetProfileName() const; @@ -99,12 +98,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation TerminalConnection::ConnectionState ConnectionState() const; - static Windows::Foundation::Size GetProposedDimensions(Microsoft::Terminal::Settings::IControlSettings const& settings, const uint32_t dpi); + static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi); static Windows::Foundation::Size GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars, const int32_t& fontSize, const winrt::Windows::UI::Text::FontWeight& fontWeight, const winrt::hstring& fontFace, - const Microsoft::Terminal::Settings::ScrollbarState& scrollState, + const ScrollbarState& scrollState, const winrt::hstring& padding, const uint32_t dpi); @@ -137,7 +136,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine; std::unique_ptr<::Microsoft::Console::Render::UiaEngine> _uiaEngine; - Settings::IControlSettings _settings; + IControlSettings _settings; bool _focused; std::atomic _closing; diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index d9a2ac5cdff..e729c38659c 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -2,6 +2,7 @@ // Licensed under the MIT license. import "IMouseWheelListener.idl"; +import "IControlSettings.idl"; namespace Microsoft.Terminal.TerminalControl { @@ -32,11 +33,11 @@ namespace Microsoft.Terminal.TerminalControl [default_interface] runtimeclass TermControl : Windows.UI.Xaml.Controls.UserControl, IDirectKeyListener, IMouseWheelListener { - TermControl(Microsoft.Terminal.Settings.IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); + TermControl(Microsoft.Terminal.TerminalControl.IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection); - static Windows.Foundation.Size GetProposedDimensions(Microsoft.Terminal.Settings.IControlSettings settings, UInt32 dpi); + static Windows.Foundation.Size GetProposedDimensions(Microsoft.Terminal.TerminalControl.IControlSettings settings, UInt32 dpi); - void UpdateSettings(Microsoft.Terminal.Settings.IControlSettings newSettings); + void UpdateSettings(Microsoft.Terminal.TerminalControl.IControlSettings newSettings); event TitleChangedEventArgs TitleChanged; event FontSizeChangedEventArgs FontSizeChanged; diff --git a/src/cascadia/TerminalControl/TerminalControl.vcxproj b/src/cascadia/TerminalControl/TerminalControl.vcxproj index bdad948d0b4..14992abab81 100644 --- a/src/cascadia/TerminalControl/TerminalControl.vcxproj +++ b/src/cascadia/TerminalControl/TerminalControl.vcxproj @@ -19,7 +19,6 @@ projects compile properly when they depend on this "Microsoft.winmd." --> 3 - + + $(MarkupCompilePass1DependsOn);OpenConsoleStripDuplicateWinmdFromReferencesBeforePass1 + $(MarkupCompilePass2DependsOn);OpenConsoleStripDuplicateWinmdFromReferencesBeforePass2 + + + + + + + + + + + + + + + + + + + + diff --git a/src/cascadia/TerminalControl/TerminalControl.vcxproj.filters b/src/cascadia/TerminalControl/TerminalControl.vcxproj.filters index f4bdeb33de2..d9eaaf778d3 100644 --- a/src/cascadia/TerminalControl/TerminalControl.vcxproj.filters +++ b/src/cascadia/TerminalControl/TerminalControl.vcxproj.filters @@ -15,8 +15,6 @@ - - @@ -26,15 +24,15 @@ - - + + @@ -42,6 +40,8 @@ + + @@ -51,4 +51,4 @@ Resources - + \ No newline at end of file diff --git a/src/cascadia/TerminalSettings/ICoreSettings.idl b/src/cascadia/TerminalCore/ICoreSettings.idl similarity index 91% rename from src/cascadia/TerminalSettings/ICoreSettings.idl rename to src/cascadia/TerminalCore/ICoreSettings.idl index 3bc4834592d..99fe24e7930 100644 --- a/src/cascadia/TerminalSettings/ICoreSettings.idl +++ b/src/cascadia/TerminalCore/ICoreSettings.idl @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -namespace Microsoft.Terminal.Settings +namespace Microsoft.Terminal.TerminalControl { enum CursorStyle { diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 7f106ba1f90..6d4a4208567 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -10,9 +10,9 @@ #include "../../inc/argb.h" #include "../../types/inc/utils.hpp" -#include "winrt/Microsoft.Terminal.Settings.h" +#include -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace Microsoft::Terminal::Core; using namespace Microsoft::Console; using namespace Microsoft::Console::Render; @@ -84,8 +84,8 @@ void Terminal::Create(COORD viewportSize, SHORT scrollbackLines, IRenderTarget& // Arguments: // - settings: the set of CoreSettings we need to use to initialize the terminal // - renderTarget: A render target the terminal can use for paint invalidation. -void Terminal::CreateFromSettings(winrt::Microsoft::Terminal::Settings::ICoreSettings settings, - Microsoft::Console::Render::IRenderTarget& renderTarget) +void Terminal::CreateFromSettings(ICoreSettings settings, + IRenderTarget& renderTarget) { const COORD viewportSize{ Utils::ClampToShortMax(settings.InitialCols(), 1), Utils::ClampToShortMax(settings.InitialRows(), 1) }; @@ -101,7 +101,7 @@ void Terminal::CreateFromSettings(winrt::Microsoft::Terminal::Settings::ICoreSet // CoreSettings object. // Arguments: // - settings: an ICoreSettings with new settings values for us to use. -void Terminal::UpdateSettings(winrt::Microsoft::Terminal::Settings::ICoreSettings settings) +void Terminal::UpdateSettings(ICoreSettings settings) { _defaultFg = settings.DefaultForeground(); _defaultBg = settings.DefaultBackground(); @@ -344,7 +344,7 @@ void Terminal::UpdateSettings(winrt::Microsoft::Terminal::Settings::ICoreSetting // If the old scrolloffset was 0, then we weren't scrolled back at all // before, and shouldn't be now either. - _scrollOffset = originalOffsetWasZero ? 0 : ::base::ClampSub(_mutableViewport.Top(), newVisibleTop); + _scrollOffset = originalOffsetWasZero ? 0 : static_cast(::base::ClampSub(_mutableViewport.Top(), newVisibleTop)); // GH#5029 - make sure to InvalidateAll here, so that we'll paint the entire visible viewport. try diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index ac8d59d3e02..351b7c7f8a5 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -19,7 +19,7 @@ // You have to forward decl the ICoreSettings here, instead of including the header. // If you include the header, there will be compilation errors with other // headers that include Terminal.hpp -namespace winrt::Microsoft::Terminal::Settings +namespace winrt::Microsoft::Terminal::TerminalControl { struct ICoreSettings; } @@ -58,10 +58,10 @@ class Microsoft::Terminal::Core::Terminal final : SHORT scrollbackLines, Microsoft::Console::Render::IRenderTarget& renderTarget); - void CreateFromSettings(winrt::Microsoft::Terminal::Settings::ICoreSettings settings, + void CreateFromSettings(winrt::Microsoft::Terminal::TerminalControl::ICoreSettings settings, Microsoft::Console::Render::IRenderTarget& renderTarget); - void UpdateSettings(winrt::Microsoft::Terminal::Settings::ICoreSettings settings); + void UpdateSettings(winrt::Microsoft::Terminal::TerminalControl::ICoreSettings settings); // Write goes through the parser void Write(std::wstring_view stringView); diff --git a/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj b/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj index 1acf771a692..42006cbda86 100644 --- a/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj +++ b/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj @@ -7,16 +7,22 @@ TerminalCore StaticLibrary 10.0.17763.0 - Microsoft.Terminal.Core + Microsoft.Terminal.TerminalControl + + true - "$(SolutionDir)\src\cascadia\TerminalSettings\Generated Files\winrt";$(SolutionDir)src\cascadia\TerminalSettings;$(CAExcludePath) + "$(SolutionDir)\src\cascadia\TerminalCore\Generated Files\winrt";$(SolutionDir)src\cascadia\TerminalCore;$(CAExcludePath) - + - + @@ -40,20 +46,23 @@ + + + pch.h - $(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)src\cascadia\TerminalSettings\Generated Files";%(AdditionalIncludeDirectories); + $(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)src\cascadia\TerminalCore\Generated Files";%(AdditionalIncludeDirectories); - - + + diff --git a/src/cascadia/TerminalSettings/TerminalSettings.def b/src/cascadia/TerminalSettings/TerminalSettings.def deleted file mode 100644 index 8c1a02932d0..00000000000 --- a/src/cascadia/TerminalSettings/TerminalSettings.def +++ /dev/null @@ -1,3 +0,0 @@ -EXPORTS -DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE -DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/src/cascadia/TerminalSettings/TerminalSettings.vcxproj b/src/cascadia/TerminalSettings/TerminalSettings.vcxproj deleted file mode 100644 index eef3fe672f4..00000000000 --- a/src/cascadia/TerminalSettings/TerminalSettings.vcxproj +++ /dev/null @@ -1,48 +0,0 @@ - - - - {CA5CAD1A-d7ec-4107-b7c6-79cb77ae2907} - TerminalSettings - Microsoft.Terminal.Settings - - - DynamicLibrary - Console - - true - - true - - - - - - - KeyChord.idl - - - - - Create - - - KeyChord.idl - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/cascadia/TerminalSettings/packages.config b/src/cascadia/TerminalSettings/packages.config deleted file mode 100644 index 8db4233e6a9..00000000000 --- a/src/cascadia/TerminalSettings/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/cascadia/TerminalSettings/pch.h b/src/cascadia/TerminalSettings/pch.h deleted file mode 100644 index 012b411e47d..00000000000 --- a/src/cascadia/TerminalSettings/pch.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -// -// pch.h -// Header for platform projection include files -// - -#pragma once - -#define WIN32_LEAN_AND_MEAN - -#include -// This is inexplicable, but for whatever reason, cppwinrt conflicts with the -// SDK definition of this function, so the only fix is to undef it. -// from WinBase.h -// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime -#ifdef GetCurrentTime -#undef GetCurrentTime -#endif - -#include -#include -#include diff --git a/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp b/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp index f4cc7a24063..95812c957a8 100644 --- a/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp +++ b/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp @@ -8,7 +8,7 @@ // `renderer.PaintFrame()` is called, the tests will validate the expected // output, and then flush the output of the VtEngine straight to the Terminal. -#include "precomp.h" +#include "pch.h" #include #include "../../inc/consoletaeftemplates.hpp" #include "../../types/inc/Viewport.hpp" diff --git a/src/cascadia/UnitTests_TerminalCore/InputTest.cpp b/src/cascadia/UnitTests_TerminalCore/InputTest.cpp index 9745b0e6b2d..27b114793f7 100644 --- a/src/cascadia/UnitTests_TerminalCore/InputTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/InputTest.cpp @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -#include "precomp.h" +#include "pch.h" #include #include "../cascadia/TerminalCore/Terminal.hpp" diff --git a/src/cascadia/UnitTests_TerminalCore/MockTermSettings.h b/src/cascadia/UnitTests_TerminalCore/MockTermSettings.h index 9d91488075c..8ddc223ee36 100644 --- a/src/cascadia/UnitTests_TerminalCore/MockTermSettings.h +++ b/src/cascadia/UnitTests_TerminalCore/MockTermSettings.h @@ -1,13 +1,13 @@ #pragma once -#include "precomp.h" +#include "pch.h" #include #include "DefaultSettings.h" -#include "winrt/Microsoft.Terminal.Settings.h" +#include -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::Microsoft::Terminal::TerminalControl; namespace TerminalCoreUnitTests { diff --git a/src/cascadia/UnitTests_TerminalCore/ScreenSizeLimitsTest.cpp b/src/cascadia/UnitTests_TerminalCore/ScreenSizeLimitsTest.cpp index aa7f28365ff..11a6d1021b3 100644 --- a/src/cascadia/UnitTests_TerminalCore/ScreenSizeLimitsTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/ScreenSizeLimitsTest.cpp @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -#include "precomp.h" +#include "pch.h" #include #include "../cascadia/TerminalCore/Terminal.hpp" @@ -9,7 +9,7 @@ #include "../renderer/inc/DummyRenderTarget.hpp" #include "consoletaeftemplates.hpp" -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace Microsoft::Terminal::Core; using namespace WEX::Logging; using namespace WEX::TestExecution; diff --git a/src/cascadia/UnitTests_TerminalCore/ScrollTest.cpp b/src/cascadia/UnitTests_TerminalCore/ScrollTest.cpp index bf786ea6ca2..5e0aa4e86e5 100644 --- a/src/cascadia/UnitTests_TerminalCore/ScrollTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/ScrollTest.cpp @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -#include "precomp.h" +#include "pch.h" #include #include @@ -16,7 +16,7 @@ #include "consoletaeftemplates.hpp" #include "TestUtils.h" -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace Microsoft::Terminal::Core; using namespace ::Microsoft::Console::Types; diff --git a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp index 39f78b0b41c..325cb073972 100644 --- a/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/SelectionTest.cpp @@ -5,7 +5,7 @@ * This File was generated using the VisualTAEF C++ Project Wizard. * Class Name: SelectionTest */ -#include "precomp.h" +#include "pch.h" #include #include "../cascadia/TerminalCore/Terminal.hpp" @@ -17,7 +17,7 @@ using namespace WEX::Logging; using namespace WEX::TestExecution; using namespace Microsoft::Terminal::Core; -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::Microsoft::Terminal::TerminalControl; namespace TerminalCoreUnitTests { diff --git a/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp b/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp index b236765bb43..c3c4d1bcdd9 100644 --- a/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp +++ b/src/cascadia/UnitTests_TerminalCore/TerminalApiTest.cpp @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -#include "precomp.h" +#include "pch.h" #include #include "../cascadia/TerminalCore/Terminal.hpp" @@ -9,7 +9,7 @@ #include "../renderer/inc/DummyRenderTarget.hpp" #include "consoletaeftemplates.hpp" -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace Microsoft::Terminal::Core; using namespace WEX::Logging; diff --git a/src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp b/src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp index c3bca20d903..5fbc2d7403d 100644 --- a/src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp +++ b/src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -#include "precomp.h" +#include "pch.h" #include #include "../renderer/inc/DummyRenderTarget.hpp" @@ -10,7 +10,7 @@ #include "consoletaeftemplates.hpp" #include "TestUtils.h" -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::Microsoft::Terminal::TerminalControl; using namespace Microsoft::Terminal::Core; using namespace WEX::Common; diff --git a/src/cascadia/UnitTests_TerminalCore/UnitTests.vcxproj b/src/cascadia/UnitTests_TerminalCore/UnitTests.vcxproj index 48734244141..59a1b747b3e 100644 --- a/src/cascadia/UnitTests_TerminalCore/UnitTests.vcxproj +++ b/src/cascadia/UnitTests_TerminalCore/UnitTests.vcxproj @@ -7,14 +7,15 @@ UnitTests_TerminalCore Terminal.Core.Unit.Tests DynamicLibrary + false - + - + Create @@ -83,18 +84,18 @@ - + - ..;$(SolutionDir)src\inc;$(SolutionDir)src\inc\test;$(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)\src\cascadia\TerminalSettings\Generated Files";$(OpenConsoleDir)\src\host;%(AdditionalIncludeDirectories) - precomp.h + ..;$(SolutionDir)src\inc;$(SolutionDir)src\inc\test;$(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)\src\cascadia\TerminalControl\Generated Files";$(OpenConsoleDir)\src\host;%(AdditionalIncludeDirectories) + pch.h WindowsApp.lib;%(AdditionalDependencies) - + diff --git a/src/cascadia/TerminalSettings/pch.cpp b/src/cascadia/UnitTests_TerminalCore/pch.cpp similarity index 100% rename from src/cascadia/TerminalSettings/pch.cpp rename to src/cascadia/UnitTests_TerminalCore/pch.cpp diff --git a/src/cascadia/UnitTests_TerminalCore/precomp.h b/src/cascadia/UnitTests_TerminalCore/pch.h similarity index 95% rename from src/cascadia/UnitTests_TerminalCore/precomp.h rename to src/cascadia/UnitTests_TerminalCore/pch.h index 53dbb752420..b63aeadb8a0 100644 --- a/src/cascadia/UnitTests_TerminalCore/precomp.h +++ b/src/cascadia/UnitTests_TerminalCore/pch.h @@ -3,7 +3,7 @@ Copyright (c) Microsoft Corporation Licensed under the MIT license. Module Name: -- precomp.h +- pch.h Abstract: - Contains external headers to include in the precompile phase of console build diff --git a/src/cascadia/UnitTests_TerminalCore/precomp.cpp b/src/cascadia/UnitTests_TerminalCore/precomp.cpp deleted file mode 100644 index 6a6fa8e5af1..00000000000 --- a/src/cascadia/UnitTests_TerminalCore/precomp.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "precomp.h" \ No newline at end of file diff --git a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj index 782d9703990..b940f569e23 100644 --- a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj +++ b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj @@ -33,12 +33,6 @@ $(OpenConsoleDir)\src\inc;$(OpenConsoleDir)\dep;$(OpenConsoleDir)\dep\Console;$(OpenConsoleDir)\dep\Win32K;$(OpenConsoleDir)\dep\gsl\include;%(AdditionalIncludeDirectories); - - - "$(OpenConsoleDir)src\cascadia\TerminalCore\lib\Generated Files";%(AdditionalIncludeDirectories); - gdi32.lib;dwmapi.lib;Shcore.lib;UxTheme.lib;%(AdditionalDependencies) @@ -78,7 +72,6 @@ - diff --git a/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj b/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj index 84e99be6046..f001359816c 100644 --- a/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj +++ b/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj @@ -89,12 +89,6 @@ $(OpenConsoleDir)\src\inc;$(OpenConsoleDir)\dep;$(OpenConsoleDir)\dep\Console;$(OpenConsoleDir)\dep\Win32K;$(OpenConsoleDir)\dep\gsl\include;$(OpenConsoleDir)\dep\wil\include;$(SolutionDir)\oss\chromium;$(SolutionDir)\oss\fmt\include;$(SolutionDir)\oss\dynamic_bitset;$(SolutionDir)\oss\libpopcnt;%(AdditionalIncludeDirectories); - - - "$(OpenConsoleDir)src\cascadia\TerminalCore\lib\Generated Files";"$(OpenConsoleDir)src\cascadia\TerminalApp\lib\Generated Files";%(AdditionalIncludeDirectories); - gdi32.lib;dwmapi.lib;Shcore.lib;%(AdditionalDependencies) @@ -149,7 +143,6 @@ - diff --git a/src/cascadia/ut_app/JsonTests.cpp b/src/cascadia/ut_app/JsonTests.cpp index 1afbeaeddff..f18579b1d0d 100644 --- a/src/cascadia/ut_app/JsonTests.cpp +++ b/src/cascadia/ut_app/JsonTests.cpp @@ -14,7 +14,7 @@ using namespace WEX::Logging; using namespace WEX::TestExecution; using namespace WEX::Common; using namespace winrt::TerminalApp; -using namespace winrt::Microsoft::Terminal::Settings; +using namespace winrt::Microsoft::Terminal::TerminalControl; namespace TerminalAppUnitTests { diff --git a/src/cppwinrt.build.pre.props b/src/cppwinrt.build.pre.props index c7ac9550f61..835797a2d6b 100644 --- a/src/cppwinrt.build.pre.props +++ b/src/cppwinrt.build.pre.props @@ -97,7 +97,7 @@ _WINRT_DLL;%(PreprocessorDefinitions) - $(ProjectName).def + $(ProjectName).def diff --git a/src/inc/test/CommonState.hpp b/src/inc/test/CommonState.hpp index b493babe4e4..2a4ddeab47e 100644 --- a/src/inc/test/CommonState.hpp +++ b/src/inc/test/CommonState.hpp @@ -303,7 +303,7 @@ class CommonState const CONSOLE_INFORMATION& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation(); // length 80 string of text with bisecting characters at the beginning and end. // positions of き(\x304d) are at 0, 27-28, 39-40, 67-68, 79 - PWCHAR pwszText = + auto pwszText = L"\x304d" L"ABCDEFGHIJKLMNOPQRSTUVWXYZ" L"\x304d\x304d" From 60b44c856ef0d1a95d6611c5be53d0f7efd6166b Mon Sep 17 00:00:00 2001 From: Moshe Schorr Date: Fri, 7 Aug 2020 22:04:53 +0300 Subject: [PATCH 06/22] Batch RTL runs to ensure proper draw order (#7190) Consecutive RTL GlyphRuns are drawn from the last to the first. References #538, #7149, all those issues asking for RTL closed as dupes. As @miniksa suggested in a comment on #7149 -- handle the thingy on the render side. If we have GlyphRuns abcdEFGh, where EFG are RTL, we draw them now in order abcdGFEh. This has ransom-noting, because I didn't touch the font scaling at all. This should fix the majority of RTL issues, except it *doesn't* fix issues with colors, because those get split in the TextBuffer phase in the renderer I think, so they show up separately by the GlyphRun phase. --- ...1ff90dc512c83c902762b02f284c1c61603b4a.txt | 10 ++ .github/actions/spell-check/expect/expect.txt | 33 ----- src/renderer/dx/CustomTextLayout.cpp | 140 ++++++++++++------ src/renderer/dx/CustomTextLayout.h | 4 + 4 files changed, 112 insertions(+), 75 deletions(-) create mode 100644 .github/actions/spell-check/expect/af1ff90dc512c83c902762b02f284c1c61603b4a.txt diff --git a/.github/actions/spell-check/expect/af1ff90dc512c83c902762b02f284c1c61603b4a.txt b/.github/actions/spell-check/expect/af1ff90dc512c83c902762b02f284c1c61603b4a.txt new file mode 100644 index 00000000000..66fb99de72d --- /dev/null +++ b/.github/actions/spell-check/expect/af1ff90dc512c83c902762b02f284c1c61603b4a.txt @@ -0,0 +1,10 @@ +abcd +dst +EFG +EFGh +EMPTYBOX +GFEh +nrcs +Remoting +Scs +Shobjidl diff --git a/.github/actions/spell-check/expect/expect.txt b/.github/actions/spell-check/expect/expect.txt index 01b64c42d78..5a74915444a 100644 --- a/.github/actions/spell-check/expect/expect.txt +++ b/.github/actions/spell-check/expect/expect.txt @@ -99,7 +99,6 @@ AStomps ASYNCWINDOWPOS atch ATest -atg attr ATTRCOLOR aumid @@ -160,7 +159,6 @@ bitsavers bitset BKCOLOR BKGND -BKMK Bksp blog Blt @@ -295,7 +293,6 @@ codepage codepoint codeproject COINIT -colo colorizing colororacle colorref @@ -352,7 +349,6 @@ conpty conptylib consecteturadipiscingelit conserv -consoleaccessibility consoleapi CONSOLECONTROL CONSOLEENDTASK @@ -640,7 +636,6 @@ DROPDOWNLIST DROPFILES drv dsm -Dst DSwap DTest dtor @@ -683,7 +678,6 @@ Elems elif elseif emacs -emptybox enabledelayedexpansion endian endif @@ -752,7 +746,6 @@ fdw fea fesb FFDE -FFF FFrom FGCOLOR fgetc @@ -769,7 +762,6 @@ FILETYPE FILEW FILLATTR FILLCONSOLEOUTPUT -Filledbox FILTERONPASTE finalizer FINDCASE @@ -821,7 +813,6 @@ fsproj fstream fte Ftm -fullcolor fullscreen fullwidth func @@ -1011,7 +1002,6 @@ hwheel hwnd HWNDPARENT hxx -hyperlink IAccessibility IAction IApi @@ -1034,7 +1024,6 @@ ICore IData IDCANCEL IDD -IDefault IDesktop IDictionary IDISHWND @@ -1384,7 +1373,6 @@ mincore mindbogglingly mingw minkernel -minmax minwin minwindef Mip @@ -1545,7 +1533,6 @@ NOYIELD NOZORDER NPM npos -NRCS NSTATUS ntapi ntcon @@ -1722,7 +1709,6 @@ pguid pgup PHANDLE phhook -phsl phwnd pid pidl @@ -1752,7 +1738,6 @@ POBJECT Podcast POINTSLIST POLYTEXTW -popclip popd POPF poppack @@ -1935,7 +1920,6 @@ REGSTR reingest Relayout RELBINPATH -remoting renderengine rendersize reparent @@ -1943,7 +1927,6 @@ reparenting replatformed Replymessage repositorypath -rerendered rescap Resequence Reserialize @@ -1989,7 +1972,6 @@ RMENU roadmap robomac roundtrip -ROWSTOSCROLL rparen RRF RRRGGGBB @@ -2051,7 +2033,6 @@ SCROLLSCALE SCROLLSCREENBUFFER Scrollup Scrolluppage -SCS scursor sddl sdeleted @@ -2121,7 +2102,6 @@ Shl shlguid shlobj shlwapi -shobjidl SHORTPATH SHOWCURSOR SHOWMAXIMIZED @@ -2194,14 +2174,11 @@ STARTWPARMSW Statusline stdafx STDAPI -stdarg stdcall -stddef stderr stdexcept stdin stdio -stdlib STDMETHODCALLTYPE STDMETHODIMP stdout @@ -2295,7 +2272,6 @@ telnetd telnetpp templated terminalcore -terminalnuget TERMINALSCROLLING terminfo TEs @@ -2351,7 +2327,6 @@ TMult tmultiple tmux todo -Tofill tofrom tokenhelpers tokenized @@ -2447,7 +2422,6 @@ undef Unescape unexpand Unfocus -unfocuses unhighlighting unhosted unicode @@ -2753,33 +2727,26 @@ WWith wx wxh xa -xab xact xamarin xaml Xamlmeta xargs xaz -xb -xbc xbf xbutton XBUTTONDBLCLK XBUTTONDOWN XBUTTONUP -xca XCast -xce XCENTER XColors xcopy XCount -xdd xdy xe XEncoding xff -xffff XFile xlang XManifest diff --git a/src/renderer/dx/CustomTextLayout.cpp b/src/renderer/dx/CustomTextLayout.cpp index c9f30c039a7..43b491cb54e 100644 --- a/src/renderer/dx/CustomTextLayout.cpp +++ b/src/renderer/dx/CustomTextLayout.cpp @@ -847,57 +847,113 @@ CATCH_RETURN(); auto mutableOrigin = origin; // Draw each run separately. - for (UINT32 runIndex = 0; runIndex < _runs.size(); ++runIndex) + for (INT32 runIndex = 0; runIndex < gsl::narrow(_runs.size()); ++runIndex) { // Get the run const Run& run = _runs.at(runIndex); - // Prepare the glyph run and description objects by converting our - // internal storage representation into something that matches DWrite's structures. - DWRITE_GLYPH_RUN glyphRun; - glyphRun.bidiLevel = run.bidiLevel; - glyphRun.fontEmSize = _format->GetFontSize() * run.fontScale; - glyphRun.fontFace = run.fontFace.Get(); - glyphRun.glyphAdvances = &_glyphAdvances.at(run.glyphStart); - glyphRun.glyphCount = run.glyphCount; - glyphRun.glyphIndices = &_glyphIndices.at(run.glyphStart); - glyphRun.glyphOffsets = &_glyphOffsets.at(run.glyphStart); - glyphRun.isSideways = false; - - DWRITE_GLYPH_RUN_DESCRIPTION glyphRunDescription; - glyphRunDescription.clusterMap = _glyphClusters.data(); - glyphRunDescription.localeName = _localeName.data(); - glyphRunDescription.string = _text.data(); - glyphRunDescription.stringLength = run.textLength; - glyphRunDescription.textPosition = run.textStart; - - // Calculate the origin for the next run based on the amount of space - // that would be consumed. We are doing this calculation now, not after, - // because if the text is RTL then we need to advance immediately, before the - // write call since DirectX expects the origin to the RIGHT of the text for RTL. - const auto postOriginX = std::accumulate(_glyphAdvances.begin() + run.glyphStart, - _glyphAdvances.begin() + run.glyphStart + run.glyphCount, - mutableOrigin.x); - - // Check for RTL, if it is, apply space adjustment. - if (WI_IsFlagSet(glyphRun.bidiLevel, 1)) + if (!WI_IsFlagSet(run.bidiLevel, 1)) { - mutableOrigin.x = postOriginX; + RETURN_IF_FAILED(_DrawGlyphRun(clientDrawingContext, renderer, mutableOrigin, run)); } + // This is the RTL behavior. We will advance to the last contiguous RTL run, draw that, + // and then keep on going backwards from there, and then move runIndex beyond. + // Let's say we have runs abcdEFGh, where runs EFG are RTL. + // Then we will draw them in the order abcdGFEh + else + { + const INT32 originalRunIndex = runIndex; + INT32 lastIndexRTL = runIndex; + + // Step 1: Get to the last contiguous RTL run from here + while (lastIndexRTL < gsl::narrow(_runs.size()) - 1) // only could ever advance if there's something left + { + const Run& nextRun = _runs.at(gsl::narrow_cast(lastIndexRTL + 1)); + if (WI_IsFlagSet(nextRun.bidiLevel, 1)) + { + lastIndexRTL++; + } + else + { + break; + } + } + + // Go from the last to the first and draw + for (runIndex = lastIndexRTL; runIndex >= originalRunIndex; runIndex--) + { + const Run& currentRun = _runs.at(runIndex); + RETURN_IF_FAILED(_DrawGlyphRun(clientDrawingContext, renderer, mutableOrigin, currentRun)); + } + runIndex = lastIndexRTL; // and the for loop will take the increment to the last one + } + } + } + CATCH_RETURN(); + return S_OK; +} - // Try to draw it - RETURN_IF_FAILED(renderer->DrawGlyphRun(clientDrawingContext, - mutableOrigin.x, - mutableOrigin.y, - DWRITE_MEASURING_MODE_NATURAL, - &glyphRun, - &glyphRunDescription, - run.drawingEffect.Get())); - - // Either way, we should be at this point by the end of writing this sequence, - // whether it was LTR or RTL. +// Routine Description: +// - Draw the given run +// - The origin is updated to be after the run. +// Arguments: +// - clientDrawingContext - Optional pointer to information that the renderer might need +// while attempting to graphically place the text onto the screen +// - renderer - The interface to be used for actually putting text onto the screen +// - origin - pixel point of top left corner on final surface for drawing +// - run - the run to be drawn +[[nodiscard]] HRESULT CustomTextLayout::_DrawGlyphRun(_In_opt_ void* clientDrawingContext, + gsl::not_null renderer, + D2D_POINT_2F& mutableOrigin, + const Run& run) noexcept +{ + try + { + // Prepare the glyph run and description objects by converting our + // internal storage representation into something that matches DWrite's structures. + DWRITE_GLYPH_RUN glyphRun; + glyphRun.bidiLevel = run.bidiLevel; + glyphRun.fontEmSize = _format->GetFontSize() * run.fontScale; + glyphRun.fontFace = run.fontFace.Get(); + glyphRun.glyphAdvances = &_glyphAdvances.at(run.glyphStart); + glyphRun.glyphCount = run.glyphCount; + glyphRun.glyphIndices = &_glyphIndices.at(run.glyphStart); + glyphRun.glyphOffsets = &_glyphOffsets.at(run.glyphStart); + glyphRun.isSideways = false; + + DWRITE_GLYPH_RUN_DESCRIPTION glyphRunDescription; + glyphRunDescription.clusterMap = _glyphClusters.data(); + glyphRunDescription.localeName = _localeName.data(); + glyphRunDescription.string = _text.data(); + glyphRunDescription.stringLength = run.textLength; + glyphRunDescription.textPosition = run.textStart; + + // Calculate the origin for the next run based on the amount of space + // that would be consumed. We are doing this calculation now, not after, + // because if the text is RTL then we need to advance immediately, before the + // write call since DirectX expects the origin to the RIGHT of the text for RTL. + const auto postOriginX = std::accumulate(_glyphAdvances.begin() + run.glyphStart, + _glyphAdvances.begin() + run.glyphStart + run.glyphCount, + mutableOrigin.x); + + // Check for RTL, if it is, apply space adjustment. + if (WI_IsFlagSet(glyphRun.bidiLevel, 1)) + { mutableOrigin.x = postOriginX; } + + // Try to draw it + RETURN_IF_FAILED(renderer->DrawGlyphRun(clientDrawingContext, + mutableOrigin.x, + mutableOrigin.y, + DWRITE_MEASURING_MODE_NATURAL, + &glyphRun, + &glyphRunDescription, + run.drawingEffect.Get())); + + // Either way, we should be at this point by the end of writing this sequence, + // whether it was LTR or RTL. + mutableOrigin.x = postOriginX; } CATCH_RETURN(); return S_OK; diff --git a/src/renderer/dx/CustomTextLayout.h b/src/renderer/dx/CustomTextLayout.h index cf2a63b574b..fe197425794 100644 --- a/src/renderer/dx/CustomTextLayout.h +++ b/src/renderer/dx/CustomTextLayout.h @@ -147,6 +147,10 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT _DrawGlyphRuns(_In_opt_ void* clientDrawingContext, IDWriteTextRenderer* renderer, const D2D_POINT_2F origin) noexcept; + [[nodiscard]] HRESULT _DrawGlyphRun(_In_opt_ void* clientDrawingContext, + gsl::not_null renderer, + D2D_POINT_2F& mutableOrigin, + const Run& run) noexcept; [[nodiscard]] static constexpr UINT32 _EstimateGlyphCount(const UINT32 textLength) noexcept; From 4e0f31337d9514ba4743c3ab195715ef50e3c83d Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 7 Aug 2020 18:07:42 -0500 Subject: [PATCH 07/22] Add support for per-profile tab colors (#7162) This PR adds support for per-profile tab colors, in accordance with #7134. This adds a single `tabColor` property, that when set, specifies the background color for profile's tab. This color can be overridden by the color picker, and clearing the color with the color picker will revert to this default color set for the tab. * Full theming is covered in #3327 & #5772 Validation: Played with setting this color, both on launch and via hot-reload Specified in #7134 Closes #1337 --- .../TerminalApp/AppActionHandlers.cpp | 4 +- src/cascadia/TerminalApp/CascadiaSettings.cpp | 4 +- src/cascadia/TerminalApp/Profile.cpp | 9 + src/cascadia/TerminalApp/Profile.h | 1 + src/cascadia/TerminalApp/Tab.cpp | 225 ++++++++++++------ src/cascadia/TerminalApp/Tab.h | 11 +- src/cascadia/TerminalApp/TerminalPage.cpp | 11 - src/cascadia/TerminalApp/TerminalSettings.h | 2 + src/cascadia/TerminalControl/TermControl.cpp | 13 + src/cascadia/TerminalControl/TermControl.h | 4 + src/cascadia/TerminalControl/TermControl.idl | 3 + src/cascadia/TerminalCore/ICoreSettings.idl | 2 + src/cascadia/TerminalCore/Terminal.cpp | 23 ++ src/cascadia/TerminalCore/Terminal.hpp | 5 + src/cascadia/TerminalCore/pch.h | 1 + .../ConptyRoundtripTests.cpp | 2 - .../UnitTests_TerminalCore/MockTermSettings.h | 3 + src/cascadia/UnitTests_TerminalCore/pch.h | 53 +++-- src/inc/test/CommonState.hpp | 1 - src/inc/til.h | 1 + src/inc/til/coalesce.h | 61 +++++ src/til/ut_til/CoalesceTests.cpp | 84 +++++++ src/til/ut_til/til.unit.tests.vcxproj | 3 +- src/types/inc/utils.hpp | 28 --- 24 files changed, 408 insertions(+), 146 deletions(-) create mode 100644 src/inc/til/coalesce.h create mode 100644 src/til/ut_til/CoalesceTests.cpp diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 5d260ef94c4..71bea71051f 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -289,11 +289,11 @@ namespace winrt::TerminalApp::implementation { if (tabColor.has_value()) { - activeTab->SetTabColor(tabColor.value()); + activeTab->SetRuntimeTabColor(tabColor.value()); } else { - activeTab->ResetTabColor(); + activeTab->ResetRuntimeTabColor(); } } args.Handled(true); diff --git a/src/cascadia/TerminalApp/CascadiaSettings.cpp b/src/cascadia/TerminalApp/CascadiaSettings.cpp index 29c8d750d02..1206437256f 100644 --- a/src/cascadia/TerminalApp/CascadiaSettings.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettings.cpp @@ -226,7 +226,7 @@ void CascadiaSettings::_ResolveDefaultProfile() { const auto unparsedDefaultProfile{ GlobalSettings().UnparsedDefaultProfile() }; auto maybeParsedDefaultProfile{ _GetProfileGuidByName(unparsedDefaultProfile) }; - auto defaultProfileGuid{ Utils::CoalesceOptionals(maybeParsedDefaultProfile, GUID{}) }; + auto defaultProfileGuid{ til::coalesce_value(maybeParsedDefaultProfile, GUID{}) }; GlobalSettings().DefaultProfile(defaultProfileGuid); } @@ -565,7 +565,7 @@ GUID CascadiaSettings::_GetProfileForArgs(const NewTerminalArgs& newTerminalArgs profileByName = _GetProfileGuidByName(newTerminalArgs.Profile()); } - return Utils::CoalesceOptionals(profileByName, profileByIndex, _globals.DefaultProfile()); + return til::coalesce_value(profileByName, profileByIndex, _globals.DefaultProfile()); } // Method Description: diff --git a/src/cascadia/TerminalApp/Profile.cpp b/src/cascadia/TerminalApp/Profile.cpp index 9829474297a..22e627ad896 100644 --- a/src/cascadia/TerminalApp/Profile.cpp +++ b/src/cascadia/TerminalApp/Profile.cpp @@ -53,6 +53,7 @@ static constexpr std::string_view BackgroundImageStretchModeKey{ "backgroundImag static constexpr std::string_view BackgroundImageAlignmentKey{ "backgroundImageAlignment" }; static constexpr std::string_view RetroTerminalEffectKey{ "experimental.retroTerminalEffect" }; static constexpr std::string_view AntialiasingModeKey{ "antialiasingMode" }; +static constexpr std::string_view TabColorKey{ "tabColor" }; Profile::Profile() : Profile(std::nullopt) @@ -232,6 +233,12 @@ TerminalSettings Profile::CreateTerminalSettings(const std::unordered_map colorRef{ _tabColor.value() }; + terminalSettings.TabColor(colorRef); + } + return terminalSettings; } @@ -405,6 +412,8 @@ void Profile::LayerJson(const Json::Value& json) JsonUtils::GetValueForKey(json, BackgroundImageAlignmentKey, _backgroundImageAlignment); JsonUtils::GetValueForKey(json, RetroTerminalEffectKey, _retroTerminalEffect); JsonUtils::GetValueForKey(json, AntialiasingModeKey, _antialiasingMode); + + JsonUtils::GetValueForKey(json, TabColorKey, _tabColor); } void Profile::SetFontFace(std::wstring fontFace) noexcept diff --git a/src/cascadia/TerminalApp/Profile.h b/src/cascadia/TerminalApp/Profile.h index 422b139883e..a6794bbcc07 100644 --- a/src/cascadia/TerminalApp/Profile.h +++ b/src/cascadia/TerminalApp/Profile.h @@ -117,6 +117,7 @@ class TerminalApp::Profile final std::optional _selectionBackground; std::optional _cursorColor; std::optional _tabTitle; + std::optional _tabColor; bool _suppressApplicationTitle; int32_t _historySize; bool _snapOnInput; diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index 5e7521bbdfe..77e3371104f 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -54,6 +54,7 @@ namespace winrt::TerminalApp::implementation }); _UpdateTitle(); + _RecalculateAndApplyTabColor(); } // Method Description: @@ -435,6 +436,16 @@ namespace winrt::TerminalApp::implementation _rootPane->Relayout(); } }); + + control.TabColorChanged([weakThis](auto&&, auto&&) { + if (auto tab{ weakThis.get() }) + { + // The control's tabColor changed, but it is not necessarily the + // active control in this tab. We'll just recalculate the + // current color anyways. + tab->_RecalculateAndApplyTabColor(); + } + }); } // Method Description: @@ -479,6 +490,7 @@ namespace winrt::TerminalApp::implementation if (tab && sender != tab->_activePane) { tab->_UpdateActivePane(sender); + tab->_RecalculateAndApplyTabColor(); } }); } @@ -529,14 +541,14 @@ namespace winrt::TerminalApp::implementation _tabColorPickup.ColorSelected([weakThis](auto newTabColor) { if (auto tab{ weakThis.get() }) { - tab->SetTabColor(newTabColor); + tab->SetRuntimeTabColor(newTabColor); } }); _tabColorPickup.ColorCleared([weakThis]() { if (auto tab{ weakThis.get() }) { - tab->ResetTabColor(); + tab->ResetRuntimeTabColor(); } }); @@ -706,114 +718,179 @@ namespace winrt::TerminalApp::implementation // - The tab's color, if any std::optional Tab::GetTabColor() { - return _tabColor; + const auto currControlColor{ GetActiveTerminalControl().TabColor() }; + std::optional controlTabColor; + if (currControlColor != nullptr) + { + controlTabColor = currControlColor.Value(); + } + + // A Tab's color will be the result of layering a variety of sources, + // from the bottom up: + // + // Color | | Set by + // -------------------- | -- | -- + // Runtime Color | _optional_ | Color Picker / `setTabColor` action + // Control Tab Color | _optional_ | Profile's `tabColor`, or a color set by VT + // Theme Tab Background | _optional_ | `tab.backgroundColor` in the theme + // Tab Default Color | **default** | TabView in XAML + // + // coalesce will get us the first of these values that's + // actually set, with nullopt being our sentinel for "use the default + // tabview color" (and clear out any colors we've set). + + return til::coalesce(_runtimeTabColor, + controlTabColor, + _themeTabColor, + std::optional(std::nullopt)); } // Method Description: - // - Sets the tab background color to the color chosen by the user + // - Sets the runtime tab background color to the color chosen by the user // - Sets the tab foreground color depending on the luminance of // the background color // Arguments: - // - color: the shiny color the user picked for their tab + // - color: the color the user picked for their tab // Return Value: // - - void Tab::SetTabColor(const winrt::Windows::UI::Color& color) + void Tab::SetRuntimeTabColor(const winrt::Windows::UI::Color& color) + { + _runtimeTabColor.emplace(color); + _RecalculateAndApplyTabColor(); + } + + // Method Description: + // - This function dispatches a function to the UI thread to recalculate + // what this tab's current background color should be. If a color is set, + // it will apply the given color to the tab's background. Otherwise, it + // will clear the tab's background color. + // Arguments: + // - + // Return Value: + // - + void Tab::_RecalculateAndApplyTabColor() { auto weakThis{ get_weak() }; - _tabViewItem.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [weakThis, color]() { + _tabViewItem.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [weakThis]() { auto ptrTab = weakThis.get(); if (!ptrTab) return; auto tab{ ptrTab }; - Media::SolidColorBrush selectedTabBrush{}; - Media::SolidColorBrush deselectedTabBrush{}; - Media::SolidColorBrush fontBrush{}; - Media::SolidColorBrush hoverTabBrush{}; - // calculate the luminance of the current color and select a font - // color based on that - // see https://www.w3.org/TR/WCAG20/#relativeluminancedef - if (TerminalApp::ColorHelper::IsBrightColor(color)) + + std::optional currentColor = tab->GetTabColor(); + if (currentColor.has_value()) { - fontBrush.Color(winrt::Windows::UI::Colors::Black()); + tab->_ApplyTabColor(currentColor.value()); } else { - fontBrush.Color(winrt::Windows::UI::Colors::White()); + tab->_ClearTabBackgroundColor(); } - - hoverTabBrush.Color(TerminalApp::ColorHelper::GetAccentColor(color)); - selectedTabBrush.Color(color); - - // currently if a tab has a custom color, a deselected state is - // signified by using the same color with a bit ot transparency - auto deselectedTabColor = color; - deselectedTabColor.A = 64; - deselectedTabBrush.Color(deselectedTabColor); - - // currently if a tab has a custom color, a deselected state is - // signified by using the same color with a bit ot transparency - tab->_tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundSelected"), selectedTabBrush); - tab->_tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackground"), deselectedTabBrush); - tab->_tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPointerOver"), hoverTabBrush); - tab->_tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPressed"), selectedTabBrush); - tab->_tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderForeground"), fontBrush); - tab->_tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundSelected"), fontBrush); - tab->_tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundPointerOver"), fontBrush); - tab->_tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundPressed"), fontBrush); - tab->_tabViewItem.Resources().Insert(winrt::box_value(L"TabViewButtonForegroundActiveTab"), fontBrush); - - tab->_RefreshVisualState(); - - tab->_tabColor.emplace(color); - tab->_colorSelected(color); }); } // Method Description: - // Clear the custom color of the tab, if any + // - Applies the given color to the background of this tab's TabViewItem. + // - Sets the tab foreground color depending on the luminance of // the background color + // - This method should only be called on the UI thread. + // Arguments: + // - color: the color the user picked for their tab + // Return Value: + // - + void Tab::_ApplyTabColor(const winrt::Windows::UI::Color& color) + { + Media::SolidColorBrush selectedTabBrush{}; + Media::SolidColorBrush deselectedTabBrush{}; + Media::SolidColorBrush fontBrush{}; + Media::SolidColorBrush hoverTabBrush{}; + // calculate the luminance of the current color and select a font + // color based on that + // see https://www.w3.org/TR/WCAG20/#relativeluminancedef + if (TerminalApp::ColorHelper::IsBrightColor(color)) + { + fontBrush.Color(winrt::Windows::UI::Colors::Black()); + } + else + { + fontBrush.Color(winrt::Windows::UI::Colors::White()); + } + + hoverTabBrush.Color(TerminalApp::ColorHelper::GetAccentColor(color)); + selectedTabBrush.Color(color); + + // currently if a tab has a custom color, a deselected state is + // signified by using the same color with a bit ot transparency + auto deselectedTabColor = color; + deselectedTabColor.A = 64; + deselectedTabBrush.Color(deselectedTabColor); + + // currently if a tab has a custom color, a deselected state is + // signified by using the same color with a bit ot transparency + _tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundSelected"), selectedTabBrush); + _tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackground"), deselectedTabBrush); + _tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPointerOver"), hoverTabBrush); + _tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPressed"), selectedTabBrush); + _tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderForeground"), fontBrush); + _tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundSelected"), fontBrush); + _tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundPointerOver"), fontBrush); + _tabViewItem.Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundPressed"), fontBrush); + _tabViewItem.Resources().Insert(winrt::box_value(L"TabViewButtonForegroundActiveTab"), fontBrush); + + _RefreshVisualState(); + + _colorSelected(color); + } + + // Method Description: + // - Clear the custom runtime color of the tab, if any color is set. This + // will re-apply whatever the tab's base color should be (either the color + // from the control, the theme, or the default tab color.) // Arguments: // - // Return Value: // - - void Tab::ResetTabColor() + void Tab::ResetRuntimeTabColor() { - auto weakThis{ get_weak() }; + _runtimeTabColor.reset(); + _RecalculateAndApplyTabColor(); + } - _tabViewItem.Dispatcher().RunAsync(CoreDispatcherPriority::Normal, [weakThis]() { - auto ptrTab = weakThis.get(); - if (!ptrTab) - return; + // Method Description: + // - Clear out any color we've set for the TabViewItem. + // - This method should only be called on the UI thread. + // Arguments: + // - + // Return Value: + // - + void Tab::_ClearTabBackgroundColor() + { + winrt::hstring keys[] = { + L"TabViewItemHeaderBackground", + L"TabViewItemHeaderBackgroundSelected", + L"TabViewItemHeaderBackgroundPointerOver", + L"TabViewItemHeaderForeground", + L"TabViewItemHeaderForegroundSelected", + L"TabViewItemHeaderForegroundPointerOver", + L"TabViewItemHeaderBackgroundPressed", + L"TabViewItemHeaderForegroundPressed", + L"TabViewButtonForegroundActiveTab" + }; - auto tab{ ptrTab }; - winrt::hstring keys[] = { - L"TabViewItemHeaderBackground", - L"TabViewItemHeaderBackgroundSelected", - L"TabViewItemHeaderBackgroundPointerOver", - L"TabViewItemHeaderForeground", - L"TabViewItemHeaderForegroundSelected", - L"TabViewItemHeaderForegroundPointerOver", - L"TabViewItemHeaderBackgroundPressed", - L"TabViewItemHeaderForegroundPressed", - L"TabViewButtonForegroundActiveTab" - }; - - // simply clear any of the colors in the tab's dict - for (auto keyString : keys) + // simply clear any of the colors in the tab's dict + for (auto keyString : keys) + { + auto key = winrt::box_value(keyString); + if (_tabViewItem.Resources().HasKey(key)) { - auto key = winrt::box_value(keyString); - if (tab->_tabViewItem.Resources().HasKey(key)) - { - tab->_tabViewItem.Resources().Remove(key); - } + _tabViewItem.Resources().Remove(key); } + } - tab->_RefreshVisualState(); - tab->_tabColor.reset(); - tab->_colorCleared(); - }); + _RefreshVisualState(); + _colorCleared(); } // Method Description: diff --git a/src/cascadia/TerminalApp/Tab.h b/src/cascadia/TerminalApp/Tab.h index 055d631c421..a53326b04f6 100644 --- a/src/cascadia/TerminalApp/Tab.h +++ b/src/cascadia/TerminalApp/Tab.h @@ -57,8 +57,8 @@ namespace winrt::TerminalApp::implementation std::optional GetTabColor(); - void SetTabColor(const winrt::Windows::UI::Color& color); - void ResetTabColor(); + void SetRuntimeTabColor(const winrt::Windows::UI::Color& color); + void ResetRuntimeTabColor(); void ActivateColorPicker(); WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler); @@ -75,7 +75,8 @@ namespace winrt::TerminalApp::implementation std::shared_ptr _activePane{ nullptr }; winrt::hstring _lastIconPath{}; winrt::TerminalApp::ColorPickupFlyout _tabColorPickup{}; - std::optional _tabColor{}; + std::optional _themeTabColor{}; + std::optional _runtimeTabColor{}; bool _focused{ false }; winrt::Microsoft::UI::Xaml::Controls::TabViewItem _tabViewItem{ nullptr }; @@ -102,6 +103,10 @@ namespace winrt::TerminalApp::implementation winrt::fire_and_forget _UpdateTitle(); void _ConstructTabRenameBox(const winrt::hstring& tabText); + void _RecalculateAndApplyTabColor(); + void _ApplyTabColor(const winrt::Windows::UI::Color& color); + void _ClearTabBackgroundColor(); + friend class ::TerminalAppLocalTests::TabTests; }; } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index b2c859f3218..b19710a8194 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -1818,17 +1818,6 @@ namespace winrt::TerminalApp::implementation // Raise an event that our title changed _titleChangeHandlers(*this, tab->GetActiveTitle()); - - // Raise an event that our titlebar color changed - std::optional color = tab->GetTabColor(); - if (color.has_value()) - { - _SetNonClientAreaColors(color.value()); - } - else - { - _ClearNonClientAreaColors(); - } } CATCH_LOG(); } diff --git a/src/cascadia/TerminalApp/TerminalSettings.h b/src/cascadia/TerminalApp/TerminalSettings.h index e3e2aec0bfc..53a4ab3201d 100644 --- a/src/cascadia/TerminalApp/TerminalSettings.h +++ b/src/cascadia/TerminalApp/TerminalSettings.h @@ -54,6 +54,8 @@ namespace winrt::TerminalApp::implementation GETSET_PROPERTY(hstring, WordDelimiters, DEFAULT_WORD_DELIMITERS); GETSET_PROPERTY(bool, CopyOnSelect, false); + GETSET_PROPERTY(Windows::Foundation::IReference, TabColor, nullptr); + // ------------------------ End of Core Settings ----------------------- GETSET_PROPERTY(hstring, ProfileName); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index e99e0d2153d..4b7b64a7b15 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -82,6 +82,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation auto pfnTitleChanged = std::bind(&TermControl::_TerminalTitleChanged, this, std::placeholders::_1); _terminal->SetTitleChangedCallback(pfnTitleChanged); + auto pfnTabColorChanged = std::bind(&TermControl::_TerminalTabColorChanged, this, std::placeholders::_1); + _terminal->SetTabColorChangedCallback(pfnTabColorChanged); + auto pfnBackgroundColorChanged = std::bind(&TermControl::_BackgroundColorChanged, this, std::placeholders::_1); _terminal->SetBackgroundCallback(pfnBackgroundColorChanged); @@ -2051,6 +2054,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation { _titleChangedHandlers(winrt::hstring{ wstr }); } + void TermControl::_TerminalTabColorChanged(const std::optional /*color*/) + { + _TabColorChangedHandlers(*this, nullptr); + } void TermControl::_CopyToClipboard(const std::wstring_view& wstr) { @@ -2821,6 +2828,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _renderer->ResetErrorStateAndResume(); } + Windows::Foundation::IReference TermControl::TabColor() noexcept + { + auto coreColor = _terminal->GetTabColor(); + return coreColor.has_value() ? Windows::Foundation::IReference(coreColor.value()) : nullptr; + } + // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. // These macros will define them both for you. diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index ce9a8a49d2d..5b159fea38e 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -107,6 +107,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const winrt::hstring& padding, const uint32_t dpi); + Windows::Foundation::IReference TabColor() noexcept; + // clang-format off // -------------------------------- WinRT Events --------------------------------- DECLARE_EVENT(TitleChanged, _titleChangedHandlers, TerminalControl::TitleChangedEventArgs); @@ -118,6 +120,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation TYPED_EVENT(ConnectionStateChanged, TerminalControl::TermControl, IInspectable); TYPED_EVENT(Initialized, TerminalControl::TermControl, Windows::UI::Xaml::RoutedEventArgs); + TYPED_EVENT(TabColorChanged, IInspectable, IInspectable); // clang-format on private: @@ -219,6 +222,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _DoResizeUnderLock(const double newWidth, const double newHeight); void _RefreshSizeUnderLock(); void _TerminalTitleChanged(const std::wstring_view& wstr); + void _TerminalTabColorChanged(const std::optional color); void _CopyToClipboard(const std::wstring_view& wstr); void _TerminalScrollPositionChanged(const int viewTop, const int viewHeight, const int bufferSize); void _TerminalCursorPositionChanged(); diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index e729c38659c..89e4634e968 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -70,5 +70,8 @@ namespace Microsoft.Terminal.TerminalControl void ResetFontSize(); void ToggleRetroEffect(); + + Windows.Foundation.IReference TabColor { get; }; + event Windows.Foundation.TypedEventHandler TabColorChanged; } } diff --git a/src/cascadia/TerminalCore/ICoreSettings.idl b/src/cascadia/TerminalCore/ICoreSettings.idl index 99fe24e7930..de11ec04b05 100644 --- a/src/cascadia/TerminalCore/ICoreSettings.idl +++ b/src/cascadia/TerminalCore/ICoreSettings.idl @@ -34,6 +34,8 @@ namespace Microsoft.Terminal.TerminalControl String WordDelimiters; Boolean ForceVTInput; + + Windows.Foundation.IReference TabColor; }; } diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 6d4a4208567..f4a847cc884 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -147,6 +147,19 @@ void Terminal::UpdateSettings(ICoreSettings settings) _terminalInput->ForceDisableWin32InputMode(settings.ForceVTInput()); + if (settings.TabColor() == nullptr) + { + _tabColor = std::nullopt; + } + else + { + _tabColor = til::color(settings.TabColor().Value() | 0xff000000); + } + if (_pfnTabColorChanged) + { + _pfnTabColorChanged(_tabColor); + } + // TODO:MSFT:21327402 - if HistorySize has changed, resize the buffer so we // have a smaller scrollback. We should do this carefully - if the new buffer // size is smaller than where the mutable viewport currently is, we'll want @@ -913,6 +926,11 @@ void Terminal::SetTitleChangedCallback(std::function)> pfn) noexcept +{ + _pfnTabColorChanged.swap(pfn); +} + void Terminal::SetCopyToClipboardCallback(std::function pfn) noexcept { _pfnCopyToClipboard.swap(pfn); @@ -969,3 +987,8 @@ bool Terminal::IsCursorBlinkingAllowed() const noexcept const auto& cursor = _buffer->GetCursor(); return cursor.IsBlinkingAllowed(); } + +const std::optional Terminal::GetTabColor() const noexcept +{ + return _tabColor; +} diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 351b7c7f8a5..78e0ead8952 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -168,6 +168,7 @@ class Microsoft::Terminal::Core::Terminal final : void SetWriteInputCallback(std::function pfn) noexcept; void SetTitleChangedCallback(std::function pfn) noexcept; + void SetTabColorChangedCallback(std::function)> pfn) noexcept; void SetCopyToClipboardCallback(std::function pfn) noexcept; void SetScrollPositionChangedCallback(std::function pfn) noexcept; void SetCursorPositionChangedCallback(std::function pfn) noexcept; @@ -176,6 +177,8 @@ class Microsoft::Terminal::Core::Terminal final : void SetCursorOn(const bool isOn); bool IsCursorBlinkingAllowed() const noexcept; + const std::optional GetTabColor() const noexcept; + #pragma region TextSelection // These methods are defined in TerminalSelection.cpp enum class SelectionExpansionMode @@ -199,12 +202,14 @@ class Microsoft::Terminal::Core::Terminal final : std::function _pfnScrollPositionChanged; std::function _pfnBackgroundColorChanged; std::function _pfnCursorPositionChanged; + std::function)> _pfnTabColorChanged; std::unique_ptr<::Microsoft::Console::VirtualTerminal::StateMachine> _stateMachine; std::unique_ptr<::Microsoft::Console::VirtualTerminal::TerminalInput> _terminalInput; std::optional _title; std::wstring _startingTitle; + std::optional _tabColor; std::array _colorTable; COLORREF _defaultFg; diff --git a/src/cascadia/TerminalCore/pch.h b/src/cascadia/TerminalCore/pch.h index e03399daf91..58fe68df1da 100644 --- a/src/cascadia/TerminalCore/pch.h +++ b/src/cascadia/TerminalCore/pch.h @@ -4,3 +4,4 @@ #pragma once #include +#include "winrt/Windows.Foundation.h" diff --git a/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp b/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp index 95812c957a8..a68aa213db1 100644 --- a/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp +++ b/src/cascadia/UnitTests_TerminalCore/ConptyRoundtripTests.cpp @@ -9,8 +9,6 @@ // output, and then flush the output of the VtEngine straight to the Terminal. #include "pch.h" -#include -#include "../../inc/consoletaeftemplates.hpp" #include "../../types/inc/Viewport.hpp" #include "../../types/inc/convert.hpp" diff --git a/src/cascadia/UnitTests_TerminalCore/MockTermSettings.h b/src/cascadia/UnitTests_TerminalCore/MockTermSettings.h index 8ddc223ee36..1a328c9d015 100644 --- a/src/cascadia/UnitTests_TerminalCore/MockTermSettings.h +++ b/src/cascadia/UnitTests_TerminalCore/MockTermSettings.h @@ -6,6 +6,7 @@ #include "DefaultSettings.h" #include +#include "../inc/cppwinrt_utils.h" using namespace winrt::Microsoft::Terminal::TerminalControl; @@ -63,6 +64,8 @@ namespace TerminalCoreUnitTests // other unimplemented methods void SetColorTableEntry(int32_t /* index */, uint32_t /* value */) {} + GETSET_PROPERTY(winrt::Windows::Foundation::IReference, TabColor, nullptr); + private: int32_t _historySize; int32_t _initialRows; diff --git a/src/cascadia/UnitTests_TerminalCore/pch.h b/src/cascadia/UnitTests_TerminalCore/pch.h index b63aeadb8a0..c33ba50c236 100644 --- a/src/cascadia/UnitTests_TerminalCore/pch.h +++ b/src/cascadia/UnitTests_TerminalCore/pch.h @@ -17,31 +17,40 @@ Author(s): #pragma once -// -// This header and define are needed so that the console host code can build in -// this test binary. - -// Block minwindef.h min/max macros to prevent conflict -#define NOMINMAX - -// This includes a lot of common headers needed by both the host and the propsheet -// including: windows.h, winuser, ntstatus, assert, and the DDK -#include "HostAndPropsheetIncludes.h" -// - +#define BLOCK_TIL // This includes support libraries from the CRT, STL, WIL, and GSL #include "LibraryIncludes.h" - -#ifdef BUILDING_INSIDE_WINIDE -#define DbgRaiseAssertionFailure() __int2c() +// This is inexplicable, but for whatever reason, cppwinrt conflicts with the +// SDK definition of this function, so the only fix is to undef it. +// from WinBase.h +// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime +#ifdef GetCurrentTime +#undef GetCurrentTime #endif -#include +#include +#include +#include -// Comment to build against the private SDK. -#define CON_BUILD_PUBLIC +#include +#include "consoletaeftemplates.hpp" -#ifdef CON_BUILD_PUBLIC -#define CON_USERPRIVAPI_INDIRECT -#define CON_DPIAPI_INDIRECT -#endif +#include +#include +#include + +// Manually include til after we include Windows.Foundation to give it winrt superpowers +#include "til.h" + +// +// These are needed because the roundtrip tests included in this library also +// re-use some conhost code that depends on these. + +#include "conddkrefs.h" +// From ntdef.h, but that can't be included or it'll fight over PROBE_ALIGNMENT and other such arch specific defs +typedef _Return_type_success_(return >= 0) LONG NTSTATUS; +/*lint -save -e624 */ // Don't complain about different typedefs. +typedef NTSTATUS* PNTSTATUS; +/*lint -restore */ // Resume checking for different typedefs. +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +// diff --git a/src/inc/test/CommonState.hpp b/src/inc/test/CommonState.hpp index 2a4ddeab47e..03abae9a221 100644 --- a/src/inc/test/CommonState.hpp +++ b/src/inc/test/CommonState.hpp @@ -22,7 +22,6 @@ unit testing projects in the codebase without a bunch of overhead. #define VERIFY_SUCCESS_NTSTATUS(x) VERIFY_IS_TRUE(NT_SUCCESS(x)) -#include "precomp.h" #include "../host/globals.h" #include "../host/inputReadHandleData.h" #include "../buffer/out/CharRow.hpp" diff --git a/src/inc/til.h b/src/inc/til.h index e9504535708..36e10ad0e6f 100644 --- a/src/inc/til.h +++ b/src/inc/til.h @@ -16,6 +16,7 @@ #include "til/bitmap.h" #include "til/u8u16convert.h" #include "til/spsc.h" +#include "til/coalesce.h" namespace til // Terminal Implementation Library. Also: "Today I Learned" { diff --git a/src/inc/til/coalesce.h b/src/inc/til/coalesce.h new file mode 100644 index 00000000000..24153869a67 --- /dev/null +++ b/src/inc/til/coalesce.h @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +namespace til +{ + // Method Description: + // - Base case provided to handle the last argument to coalesce_value() + template + T coalesce_value(const T& base) + { + return base; + } + + // Method Description: + // - Base case provided to throw an assertion if you call coalesce_value(opt, opt, opt) + template + T coalesce_value(const std::optional& base) + { + static_assert(false, "coalesce_value must be passed a base non-optional value to be used if all optionals are empty"); + return T{}; + } + + // Method Description: + // - Returns the value from the first populated optional, or a base value if none were populated. + template + T coalesce_value(const std::optional& t1, Ts&&... t2) + { + // Initially, I wanted to check "has_value" and short-circuit out so that we didn't + // evaluate value_or for every single optional, but has_value/value emits exception handling + // code that value_or doesn't. Less exception handling is cheaper than calling value_or a + // few more times. + return t1.value_or(coalesce_value(std::forward(t2)...)); + } + + // Method Description: + // - Base case provided to handle the last argument to coalesce_value() + template + std::optional coalesce(const std::optional& base) + { + return base; + } + + // Method Description: + // - Base case provided to handle the last argument to coalesce_value(..., nullopt) + template + std::optional coalesce(const std::nullopt_t& base) + { + return base; + } + + // Method Description: + // - Returns the value from the first populated optional, or the last one (if none of the previous had a value) + template + std::optional coalesce(const std::optional& t1, Ts&&... t2) + { + return t1.has_value() ? t1 : coalesce(std::forward(t2)...); + } + +} diff --git a/src/til/ut_til/CoalesceTests.cpp b/src/til/ut_til/CoalesceTests.cpp new file mode 100644 index 00000000000..76c2e9c31ab --- /dev/null +++ b/src/til/ut_til/CoalesceTests.cpp @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "precomp.h" +#include "WexTestClass.h" + +using namespace WEX::Common; +using namespace WEX::Logging; +using namespace WEX::TestExecution; + +class CoalesceTests +{ + TEST_CLASS(CoalesceTests); + + TEST_METHOD(CoalesceFirstValue); + TEST_METHOD(CoalesceMiddleValue); + TEST_METHOD(CoalesceDefaultValue); + + TEST_METHOD(CoalesceOrNotFirstValue); + TEST_METHOD(CoalesceOrNotMiddleValue); + TEST_METHOD(CoalesceOrNotDefaultValue); + TEST_METHOD(CoalesceOrNotDefaultIsNullopt); +}; + +void CoalesceTests::CoalesceFirstValue() +{ + int result = til::coalesce_value(std::optional(1), + std::optional(2), + std::optional(3), + 4); + VERIFY_ARE_EQUAL(1, result); +} +void CoalesceTests::CoalesceMiddleValue() +{ + int result = til::coalesce_value(std::optional(std::nullopt), + std::optional(2), + std::optional(3), + 4); + VERIFY_ARE_EQUAL(2, result); +} +void CoalesceTests::CoalesceDefaultValue() +{ + int result = til::coalesce_value(std::optional(std::nullopt), + std::optional(std::nullopt), + std::optional(std::nullopt), + 4); + VERIFY_ARE_EQUAL(4, result); +} + +void CoalesceTests::CoalesceOrNotFirstValue() +{ + std::optional result = til::coalesce(std::optional(1), + std::optional(2), + std::optional(3), + std::optional(4)); + VERIFY_IS_TRUE(result.has_value()); + VERIFY_ARE_EQUAL(1, result.value()); +} +void CoalesceTests::CoalesceOrNotMiddleValue() +{ + std::optional result = til::coalesce(std::optional(std::nullopt), + std::optional(2), + std::optional(3), + std::optional(4)); + VERIFY_IS_TRUE(result.has_value()); + VERIFY_ARE_EQUAL(2, result.value()); +} +void CoalesceTests::CoalesceOrNotDefaultValue() +{ + std::optional result = til::coalesce(std::optional(std::nullopt), + std::optional(std::nullopt), + std::optional(std::nullopt), + std::optional(4)); + VERIFY_IS_TRUE(result.has_value()); + VERIFY_ARE_EQUAL(4, result.value()); +} +void CoalesceTests::CoalesceOrNotDefaultIsNullopt() +{ + std::optional result = til::coalesce(std::optional(std::nullopt), + std::optional(std::nullopt), + std::optional(std::nullopt), + std::optional(std::nullopt)); + VERIFY_IS_FALSE(result.has_value()); +} diff --git a/src/til/ut_til/til.unit.tests.vcxproj b/src/til/ut_til/til.unit.tests.vcxproj index 82b7908bb7c..52a07246b81 100644 --- a/src/til/ut_til/til.unit.tests.vcxproj +++ b/src/til/ut_til/til.unit.tests.vcxproj @@ -18,6 +18,7 @@ + Create @@ -36,4 +37,4 @@ - \ No newline at end of file + diff --git a/src/types/inc/utils.hpp b/src/types/inc/utils.hpp index 5e22a25127e..05ba610e9d5 100644 --- a/src/types/inc/utils.hpp +++ b/src/types/inc/utils.hpp @@ -96,32 +96,4 @@ namespace Microsoft::Console::Utils GUID CreateV5Uuid(const GUID& namespaceGuid, const gsl::span name); - // Method Description: - // - Base case provided to handle the last argument to CoalesceOptionals() - template - T CoalesceOptionals(const T& base) - { - return base; - } - - // Method Description: - // - Base case provided to throw an assertion if you call CoalesceOptionals(opt, opt, opt) - template - T CoalesceOptionals(const std::optional& base) - { - static_assert(false, "CoalesceOptionals must be passed a base non-optional value to be used if all optionals are empty"); - return T{}; - } - - // Method Description: - // - Returns the value from the first populated optional, or a base value if none were populated. - template - T CoalesceOptionals(const std::optional& t1, Ts&&... t2) - { - // Initially, I wanted to check "has_value" and short-circuit out so that we didn't - // evaluate value_or for every single optional, but has_value/value emits exception handling - // code that value_or doesn't. Less exception handling is cheaper than calling value_or a - // few more times. - return t1.value_or(CoalesceOptionals(std::forward(t2)...)); - } } From 70fd03f247f03b6cc38502ab024c78e11a279c4e Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 7 Aug 2020 18:11:44 -0500 Subject: [PATCH 08/22] Add a `togglePaneZoom` action for zooming a pane (#6989) This PR adds the `togglePaneZoom` action, which can be used to make a pane expand to fill the entire contents of the window. A tab that contains a zoomed pane will have a magnifying glass icon prepended to its title. Any attempts to manage panes with one zoomed will force the zoomed pane back to normal size. VALIDATION Zoomed in and out a bunch. Tried closing panes while zoomed. Tried splitting panes while zoomed. Etc. Closes #996 --- src/cascadia/TerminalApp/ActionAndArgs.cpp | 3 + .../TerminalApp/AppActionHandlers.cpp | 20 ++++ src/cascadia/TerminalApp/Pane.cpp | 102 +++++++++++++++--- src/cascadia/TerminalApp/Pane.h | 5 + .../Resources/en-US/Resources.resw | 3 + .../TerminalApp/ShortcutActionDispatch.cpp | 6 ++ .../TerminalApp/ShortcutActionDispatch.h | 1 + .../TerminalApp/ShortcutActionDispatch.idl | 2 + src/cascadia/TerminalApp/Tab.cpp | 75 ++++++++++++- src/cascadia/TerminalApp/Tab.h | 6 ++ src/cascadia/TerminalApp/TerminalPage.cpp | 33 ++++++ src/cascadia/TerminalApp/TerminalPage.h | 3 + 12 files changed, 244 insertions(+), 15 deletions(-) diff --git a/src/cascadia/TerminalApp/ActionAndArgs.cpp b/src/cascadia/TerminalApp/ActionAndArgs.cpp index 2f8966810fe..f784345ba5a 100644 --- a/src/cascadia/TerminalApp/ActionAndArgs.cpp +++ b/src/cascadia/TerminalApp/ActionAndArgs.cpp @@ -28,6 +28,7 @@ static constexpr std::string_view ScrolldownpageKey{ "scrollDownPage" }; static constexpr std::string_view SwitchToTabKey{ "switchToTab" }; static constexpr std::string_view OpenSettingsKey{ "openSettings" }; // TODO GH#2557: Add args for OpenSettings static constexpr std::string_view SplitPaneKey{ "splitPane" }; +static constexpr std::string_view TogglePaneZoomKey{ "togglePaneZoom" }; static constexpr std::string_view ResizePaneKey{ "resizePane" }; static constexpr std::string_view MoveFocusKey{ "moveFocus" }; static constexpr std::string_view FindKey{ "find" }; @@ -87,6 +88,7 @@ namespace winrt::TerminalApp::implementation { ToggleFullscreenKey, ShortcutAction::ToggleFullscreen }, { ToggleAlwaysOnTopKey, ShortcutAction::ToggleAlwaysOnTop }, { SplitPaneKey, ShortcutAction::SplitPane }, + { TogglePaneZoomKey, ShortcutAction::TogglePaneZoom }, { SetTabColorKey, ShortcutAction::SetTabColor }, { OpenTabColorPickerKey, ShortcutAction::OpenTabColorPicker }, { UnboundKey, ShortcutAction::Invalid }, @@ -275,6 +277,7 @@ namespace winrt::TerminalApp::implementation { ShortcutAction::ToggleFullscreen, RS_(L"ToggleFullscreenCommandKey") }, { ShortcutAction::ToggleAlwaysOnTop, RS_(L"ToggleAlwaysOnTopCommandKey") }, { ShortcutAction::SplitPane, RS_(L"SplitPaneCommandKey") }, + { ShortcutAction::TogglePaneZoom, RS_(L"TogglePaneZoomCommandKey") }, { ShortcutAction::Invalid, L"" }, { ShortcutAction::Find, RS_(L"FindCommandKey") }, { ShortcutAction::SetTabColor, RS_(L"ResetTabColorCommandKey") }, diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 71bea71051f..c58a95b248c 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -103,6 +103,26 @@ namespace winrt::TerminalApp::implementation } } + void TerminalPage::_HandleTogglePaneZoom(const IInspectable& /*sender*/, + const TerminalApp::ActionEventArgs& args) + { + auto activeTab = _GetFocusedTab(); + if (activeTab) + { + // First thing's first, remove the current content from the UI + // tree. This is important, because we might be leaving zoom, and if + // a pane is zoomed, then it's currently in the UI tree, and should + // be removed before it's re-added in Pane::Restore + _tabContent.Children().Clear(); + + activeTab->ToggleZoom(); + + // Update the selected tab, to trigger us to re-add the tab's GetRootElement to the UI tree + _UpdatedSelectedTab(_tabView.SelectedIndex()); + } + args.Handled(true); + } + void TerminalPage::_HandleScrollUpPage(const IInspectable& /*sender*/, const TerminalApp::ActionEventArgs& args) { diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 40438f81f51..180100f4a97 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -840,21 +840,29 @@ void Pane::_UpdateBorders() double top = 0, bottom = 0, left = 0, right = 0; Thickness newBorders{ 0 }; - if (WI_IsFlagSet(_borders, Borders::Top)) + if (_zoomed) { - top = PaneBorderSize; + // When the pane is zoomed, manually show all the borders around the window. + top = bottom = right = left = PaneBorderSize; } - if (WI_IsFlagSet(_borders, Borders::Bottom)) - { - bottom = PaneBorderSize; - } - if (WI_IsFlagSet(_borders, Borders::Left)) - { - left = PaneBorderSize; - } - if (WI_IsFlagSet(_borders, Borders::Right)) + else { - right = PaneBorderSize; + if (WI_IsFlagSet(_borders, Borders::Top)) + { + top = PaneBorderSize; + } + if (WI_IsFlagSet(_borders, Borders::Bottom)) + { + bottom = PaneBorderSize; + } + if (WI_IsFlagSet(_borders, Borders::Left)) + { + left = PaneBorderSize; + } + if (WI_IsFlagSet(_borders, Borders::Right)) + { + right = PaneBorderSize; + } } _border.BorderThickness(ThicknessHelper::FromLengths(left, top, right, bottom)); } @@ -1172,6 +1180,76 @@ std::pair, std::shared_ptr> Pane::_Split(SplitState return { _firstChild, _secondChild }; } +// Method Description: +// - Recursively attempt to "zoom" the given pane. When the pane is zoomed, it +// won't be displayed as part of the tab tree, instead it'll take up the full +// content of the tab. When we find the given pane, we'll need to remove it +// from the UI tree, so that the caller can re-add it. We'll also set some +// internal state, so the pane can display all of its borders. +// Arguments: +// - zoomedPane: This is the pane which we're attempting to zoom on. +// Return Value: +// - +void Pane::Maximize(std::shared_ptr zoomedPane) +{ + if (_IsLeaf()) + { + _zoomed = (zoomedPane == shared_from_this()); + _UpdateBorders(); + } + else + { + if (zoomedPane == _firstChild || zoomedPane == _secondChild) + { + // When we're zooming the pane, we'll need to remove it from our UI + // tree. Easy way: just remove both children. We'll re-attach both + // when we un-zoom. + _root.Children().Clear(); + } + + // Always recurse into both children. If the (un)zoomed pane was one of + // our direct children, we'll still want to update it's borders. + _firstChild->Maximize(zoomedPane); + _secondChild->Maximize(zoomedPane); + } +} + +// Method Description: +// - Recursively attempt to "un-zoom" the given pane. This does the opposite of +// Pane::Maximize. When we find the given pane, we should return the pane to our +// UI tree. We'll also clear the internal state, so the pane can display its +// borders correctly. +// - The caller should make sure to have removed the zoomed pane from the UI +// tree _before_ calling this. +// Arguments: +// - zoomedPane: This is the pane which we're attempting to un-zoom. +// Return Value: +// - +void Pane::Restore(std::shared_ptr zoomedPane) +{ + if (_IsLeaf()) + { + _zoomed = false; + _UpdateBorders(); + } + else + { + if (zoomedPane == _firstChild || zoomedPane == _secondChild) + { + // When we're un-zooming the pane, we'll need to re-add it to our UI + // tree where it originally belonged. easy way: just re-add both. + _root.Children().Clear(); + _root.Children().Append(_firstChild->GetRootElement()); + _root.Children().Append(_secondChild->GetRootElement()); + } + + // Always recurse into both children. If the (un)zoomed pane was one of + // our direct children, we'll still want to update it's borders. + _firstChild->Restore(zoomedPane); + _secondChild->Restore(zoomedPane); + } +} + // Method Description: // - Gets the size in pixels of each of our children, given the full size they // should fill. Since these children own their own separators (borders), this diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h index dfbcf1e7bc2..6d1ffa133f1 100644 --- a/src/cascadia/TerminalApp/Pane.h +++ b/src/cascadia/TerminalApp/Pane.h @@ -72,6 +72,9 @@ class Pane : public std::enable_shared_from_this int GetLeafPaneCount() const noexcept; + void Maximize(std::shared_ptr zoomedPane); + void Restore(std::shared_ptr zoomedPane); + WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler); DECLARE_EVENT(GotFocus, _GotFocusHandlers, winrt::delegate>); @@ -103,6 +106,8 @@ class Pane : public std::enable_shared_from_this Borders _borders{ Borders::None }; + bool _zoomed{ false }; + bool _IsLeaf() const noexcept; bool _HasFocusedChild() const noexcept; void _SetupChildCloseHandlers(); diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index d1cb5606c07..25fc712d10f 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -452,6 +452,9 @@ Split pane + + Toggle pane zoom + New window diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index 1ea1bb7fae2..2f6a1a280c6 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -121,6 +121,12 @@ namespace winrt::TerminalApp::implementation break; } + case ShortcutAction::TogglePaneZoom: + { + _TogglePaneZoomHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::SwitchToTab: { _SwitchToTabHandlers(*this, *eventArgs); diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.h b/src/cascadia/TerminalApp/ShortcutActionDispatch.h index 7ed978d9b80..963bfbea447 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.h +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.h @@ -36,6 +36,7 @@ namespace winrt::TerminalApp::implementation TYPED_EVENT(NextTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(PrevTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(SplitPane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(TogglePaneZoom, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(AdjustFontSize, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(ResetFontSize, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(ScrollUp, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl index 026fa4aa2ba..4136e44a97e 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl @@ -21,6 +21,7 @@ namespace TerminalApp SplitVertical, SplitHorizontal, SplitPane, + TogglePaneZoom, SwitchToTab, AdjustFontSize, ResetFontSize, @@ -69,6 +70,7 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler NextTab; event Windows.Foundation.TypedEventHandler PrevTab; event Windows.Foundation.TypedEventHandler SplitPane; + event Windows.Foundation.TypedEventHandler TogglePaneZoom; event Windows.Foundation.TypedEventHandler AdjustFontSize; event Windows.Foundation.TypedEventHandler ResetFontSize; event Windows.Foundation.TypedEventHandler ScrollUp; diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index 77e3371104f..eb396275303 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -65,7 +65,14 @@ namespace winrt::TerminalApp::implementation // - The UIElement acting as root of the Tab's root pane. UIElement Tab::GetRootElement() { - return _rootPane->GetRootElement(); + if (_zoomedPane) + { + return _zoomedPane->GetRootElement(); + } + else + { + return _rootPane->GetRootElement(); + } } // Method Description: @@ -598,8 +605,28 @@ namespace winrt::TerminalApp::implementation if (!_inRename) { - // If we're not currently in the process of renaming the tab, then just set the tab's text to whatever our active title is. - _tabViewItem.Header(winrt::box_value(tabText)); + if (_zoomedPane) + { + Controls::StackPanel sp; + sp.Orientation(Controls::Orientation::Horizontal); + Controls::FontIcon ico; + ico.FontFamily(Media::FontFamily{ L"Segoe MDL2 Assets" }); + ico.Glyph(L"\xE8A3"); // "ZoomIn", a magnifying glass with a '+' in it. + ico.FontSize(12); + ico.Margin(ThicknessHelper::FromLengths(0, 0, 8, 0)); + sp.Children().Append(ico); + Controls::TextBlock tb; + tb.Text(tabText); + sp.Children().Append(tb); + + _tabViewItem.Header(sp); + } + else + { + // If we're not currently in the process of renaming the tab, + // then just set the tab's text to whatever our active title is. + _tabViewItem.Header(winrt::box_value(tabText)); + } } else { @@ -955,6 +982,48 @@ namespace winrt::TerminalApp::implementation { return _rootPane->PreCalculateCanSplit(_activePane, splitType, availableSpace).value_or(false); } + + // Method Description: + // - Toggle our zoom state. + // * If we're not zoomed, then zoom the active pane, making it take the + // full size of the tab. We'll achieve this by changing our response to + // Tab::GetRootElement, so that it'll return the zoomed pane only. + // * If we're currently zoomed on a pane, un-zoom that pane. + // Arguments: + // - + // Return Value: + // - + void Tab::ToggleZoom() + { + if (_zoomedPane) + { + ExitZoom(); + } + else + { + EnterZoom(); + } + } + void Tab::EnterZoom() + { + _zoomedPane = _activePane; + _rootPane->Maximize(_zoomedPane); + // Update the tab header to show the magnifying glass + _UpdateTabHeader(); + } + void Tab::ExitZoom() + { + _rootPane->Restore(_zoomedPane); + _zoomedPane = nullptr; + // Update the tab header to hide the magnifying glass + _UpdateTabHeader(); + } + + bool Tab::IsZoomed() + { + return _zoomedPane != nullptr; + } + DEFINE_EVENT(Tab, ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>); DEFINE_EVENT(Tab, ColorSelected, _colorSelected, winrt::delegate); DEFINE_EVENT(Tab, ColorCleared, _colorCleared, winrt::delegate<>); diff --git a/src/cascadia/TerminalApp/Tab.h b/src/cascadia/TerminalApp/Tab.h index a53326b04f6..6e3e5cc5b95 100644 --- a/src/cascadia/TerminalApp/Tab.h +++ b/src/cascadia/TerminalApp/Tab.h @@ -61,6 +61,11 @@ namespace winrt::TerminalApp::implementation void ResetRuntimeTabColor(); void ActivateColorPicker(); + void ToggleZoom(); + bool IsZoomed(); + void EnterZoom(); + void ExitZoom(); + WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler); WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); DECLARE_EVENT(ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>); @@ -73,6 +78,7 @@ namespace winrt::TerminalApp::implementation private: std::shared_ptr _rootPane{ nullptr }; std::shared_ptr _activePane{ nullptr }; + std::shared_ptr _zoomedPane{ nullptr }; winrt::hstring _lastIconPath{}; winrt::TerminalApp::ColorPickupFlyout _tabColorPickup{}; std::optional _themeTabColor{}; diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index b19710a8194..309fb12fe09 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -872,6 +872,7 @@ namespace winrt::TerminalApp::implementation _actionDispatch->NextTab({ this, &TerminalPage::_HandleNextTab }); _actionDispatch->PrevTab({ this, &TerminalPage::_HandlePrevTab }); _actionDispatch->SplitPane({ this, &TerminalPage::_HandleSplitPane }); + _actionDispatch->TogglePaneZoom({ this, &TerminalPage::_HandleTogglePaneZoom }); _actionDispatch->ScrollUpPage({ this, &TerminalPage::_HandleScrollUpPage }); _actionDispatch->ScrollDownPage({ this, &TerminalPage::_HandleScrollDownPage }); _actionDispatch->OpenSettings({ this, &TerminalPage::_HandleOpenSettings }); @@ -1189,6 +1190,33 @@ namespace winrt::TerminalApp::implementation return false; } + // Method Description: + // - Helper to manually exit "zoom" when certain actions take place. + // Anything that modifies the state of the pane tree should probably + // un-zoom the focused pane first, so that the user can see the full pane + // tree again. These actions include: + // * Splitting a new pane + // * Closing a pane + // * Moving focus between panes + // * Resizing a pane + // Arguments: + // - + // Return Value: + // - + void TerminalPage::_UnZoomIfNeeded() + { + auto activeTab = _GetFocusedTab(); + if (activeTab && activeTab->IsZoomed()) + { + // Remove the content from the tab first, so Pane::UnZoom can + // re-attach the content to the tree w/in the pane + _tabContent.Children().Clear(); + activeTab->ExitZoom(); + // Re-attach the tab's content to the UI tree. + _tabContent.Children().Append(activeTab->GetRootElement()); + } + } + // Method Description: // - Attempt to move focus between panes, as to focus the child on // the other side of the separator. See Pane::NavigateFocus for details. @@ -1202,6 +1230,7 @@ namespace winrt::TerminalApp::implementation if (auto index{ _GetFocusedTabIndex() }) { auto focusedTab{ _GetStrongTabImpl(*index) }; + _UnZoomIfNeeded(); focusedTab->NavigateFocus(direction); } } @@ -1292,6 +1321,7 @@ namespace winrt::TerminalApp::implementation if (auto index{ _GetFocusedTabIndex() }) { auto focusedTab{ _GetStrongTabImpl(*index) }; + _UnZoomIfNeeded(); focusedTab->ClosePane(); } } @@ -1423,6 +1453,8 @@ namespace winrt::TerminalApp::implementation // Hookup our event handlers to the new terminal _RegisterTerminalEvents(newControl, *focusedTab); + _UnZoomIfNeeded(); + focusedTab->SplitPane(realSplitType, realGuid, newControl); } CATCH_LOG(); @@ -1441,6 +1473,7 @@ namespace winrt::TerminalApp::implementation if (auto index{ _GetFocusedTabIndex() }) { auto focusedTab{ _GetStrongTabImpl(*index) }; + _UnZoomIfNeeded(); focusedTab->ResizePane(direction); } } diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 8eb8e5752a3..1228226f6c1 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -191,6 +191,8 @@ namespace winrt::TerminalApp::implementation void _CommandPaletteClosed(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs); + void _UnZoomIfNeeded(); + #pragma region ActionHandlers // These are all defined in AppActionHandlers.cpp void _HandleOpenNewTabDropdown(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); @@ -202,6 +204,7 @@ namespace winrt::TerminalApp::implementation void _HandleNextTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandlePrevTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleSplitPane(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); + void _HandleTogglePaneZoom(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleScrollUpPage(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleScrollDownPage(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleOpenSettings(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); From 20a288020e26d48efab309b843e41498e7bc8684 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Fri, 7 Aug 2020 16:21:09 -0700 Subject: [PATCH 09/22] Pass mouse button state into HandleMouse instead of asking win32 (#6765) MouseInput was directly asking user32 about the state of the mouse buttons, which was somewhat of a layering violation. This commit makes all callers have to pass the mouse state in themselves. Closes #4869 --- .../PublicTerminalCore/HwndTerminal.cpp | 12 +++- .../TerminalControl/IMouseWheelListener.idl | 2 +- src/cascadia/TerminalControl/TermControl.cpp | 24 +++++--- src/cascadia/TerminalControl/TermControl.h | 9 ++- src/cascadia/TerminalCore/ITerminalInput.hpp | 2 +- src/cascadia/TerminalCore/Terminal.cpp | 4 +- src/cascadia/TerminalCore/Terminal.hpp | 2 +- src/cascadia/WindowsTerminal/AppHost.cpp | 10 +++- src/interactivity/win32/windowio.cpp | 13 ++++- .../adapter/ut_adapter/MouseInputTest.cpp | 55 +++++++++++-------- src/terminal/input/mouseInput.cpp | 24 ++++---- src/terminal/input/terminalInput.hpp | 13 ++++- 12 files changed, 116 insertions(+), 54 deletions(-) diff --git a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp b/src/cascadia/PublicTerminalCore/HwndTerminal.cpp index bb7112efb1b..c194e5d77a8 100644 --- a/src/cascadia/PublicTerminalCore/HwndTerminal.cpp +++ b/src/cascadia/PublicTerminalCore/HwndTerminal.cpp @@ -16,6 +16,10 @@ using namespace ::Microsoft::Terminal::Core; static LPCWSTR term_window_class = L"HwndTerminalClass"; +// This magic flag is "documented" at https://msdn.microsoft.com/en-us/library/windows/desktop/ms646301(v=vs.85).aspx +// "If the high-order bit is 1, the key is down; otherwise, it is up." +static constexpr short KeyPressed{ gsl::narrow_cast(0x8000) }; + static constexpr bool _IsMouseMessage(UINT uMsg) { return uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_LBUTTONDBLCLK || @@ -645,7 +649,13 @@ try cursorPosition = coordsToTransform; } - return _terminal->SendMouseEvent(cursorPosition / fontSize, uMsg, getControlKeyState(), wheelDelta); + const TerminalInput::MouseButtonState state{ + WI_IsFlagSet(GetKeyState(VK_LBUTTON), KeyPressed), + WI_IsFlagSet(GetKeyState(VK_MBUTTON), KeyPressed), + WI_IsFlagSet(GetKeyState(VK_RBUTTON), KeyPressed) + }; + + return _terminal->SendMouseEvent(cursorPosition / fontSize, uMsg, getControlKeyState(), wheelDelta, state); } catch (...) { diff --git a/src/cascadia/TerminalControl/IMouseWheelListener.idl b/src/cascadia/TerminalControl/IMouseWheelListener.idl index 63089552683..8ba8284b5d4 100644 --- a/src/cascadia/TerminalControl/IMouseWheelListener.idl +++ b/src/cascadia/TerminalControl/IMouseWheelListener.idl @@ -11,6 +11,6 @@ namespace Microsoft.Terminal.TerminalControl [uuid("65b8b8c5-988f-43ff-aba9-e89368da1598")] interface IMouseWheelListener { - Boolean OnMouseWheel(Windows.Foundation.Point coord, Int32 delta); + Boolean OnMouseWheel(Windows.Foundation.Point coord, Int32 delta, Boolean leftButtonDown, Boolean midButtonDown, Boolean rightButtonDown); } } diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 4b7b64a7b15..d14fb9c9061 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -16,6 +16,7 @@ #include "TermControlAutomationPeer.h" using namespace ::Microsoft::Console::Types; +using namespace ::Microsoft::Console::VirtualTerminal; using namespace ::Microsoft::Terminal::Core; using namespace winrt::Windows::Graphics::Display; using namespace winrt::Windows::UI::Xaml; @@ -1007,7 +1008,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } const auto modifiers = _GetPressedModifierKeys(); - return _terminal->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta); + const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), props.IsMiddleButtonPressed(), props.IsRightButtonPressed() }; + return _terminal->SendMouseEvent(terminalPosition, uiButton, modifiers, sWheelDelta, state); } // Method Description: @@ -1331,10 +1333,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } const auto point = args.GetCurrentPoint(*this); + const auto props = point.Properties(); + const TerminalInput::MouseButtonState state{ props.IsLeftButtonPressed(), props.IsMiddleButtonPressed(), props.IsRightButtonPressed() }; auto result = _DoMouseWheel(point.Position(), ControlKeyStates{ args.KeyModifiers() }, point.Properties().MouseWheelDelta(), - point.Properties().IsLeftButtonPressed()); + state); if (result) { args.Handled(true); @@ -1357,7 +1361,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation bool TermControl::_DoMouseWheel(const Windows::Foundation::Point point, const ControlKeyStates modifiers, const int32_t delta, - const bool isLeftButtonPressed) + const TerminalInput::MouseButtonState state) { if (_CanSendVTMouseInput()) { @@ -1369,7 +1373,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation return _terminal->SendMouseEvent(_GetTerminalPosition(point), WM_MOUSEWHEEL, _GetPressedModifierKeys(), - ::base::saturated_cast(delta)); + ::base::saturated_cast(delta), + state); } const auto ctrlPressed = modifiers.IsCtrlPressed(); @@ -1385,7 +1390,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } else { - _MouseScrollHandler(delta, point, isLeftButtonPressed); + _MouseScrollHandler(delta, point, state.isLeftButtonDown); } return false; } @@ -1399,11 +1404,16 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // - location: the location of the mouse during this event. This location is // relative to the origin of the control // - delta: the mouse wheel delta that triggered this event. + // - state: the state for each of the mouse buttons individually (pressed/unpressed) bool TermControl::OnMouseWheel(const Windows::Foundation::Point location, - const int32_t delta) + const int32_t delta, + const bool leftButtonDown, + const bool midButtonDown, + const bool rightButtonDown) { const auto modifiers = _GetPressedModifierKeys(); - return _DoMouseWheel(location, modifiers, delta, false); + TerminalInput::MouseButtonState state{ leftButtonDown, midButtonDown, rightButtonDown }; + return _DoMouseWheel(location, modifiers, delta, state); } // Method Description: diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 5b159fea38e..f3d91c5c0b3 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -16,6 +16,11 @@ #include "SearchBoxControl.h" #include "ThrottledFunc.h" +namespace Microsoft::Console::VirtualTerminal +{ + struct MouseButtonState; +} + namespace winrt::Microsoft::Terminal::TerminalControl::implementation { struct CopyToClipboardEventArgs : @@ -87,7 +92,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation bool OnDirectKeyEvent(const uint32_t vkey, const bool down); - bool OnMouseWheel(const Windows::Foundation::Point location, const int32_t delta); + bool OnMouseWheel(const Windows::Foundation::Point location, const int32_t delta, const bool leftButtonDown, const bool midButtonDown, const bool rightButtonDown); ~TermControl(); @@ -230,7 +235,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _MouseScrollHandler(const double mouseDelta, const Windows::Foundation::Point point, const bool isLeftButtonPressed); void _MouseZoomHandler(const double delta); void _MouseTransparencyHandler(const double delta); - bool _DoMouseWheel(const Windows::Foundation::Point point, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta, const bool isLeftButtonPressed); + bool _DoMouseWheel(const Windows::Foundation::Point point, const ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const int32_t delta, const ::Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state); bool _CapturePointer(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); bool _ReleasePointerCapture(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); diff --git a/src/cascadia/TerminalCore/ITerminalInput.hpp b/src/cascadia/TerminalCore/ITerminalInput.hpp index 1d9785e4ee6..307f03b1165 100644 --- a/src/cascadia/TerminalCore/ITerminalInput.hpp +++ b/src/cascadia/TerminalCore/ITerminalInput.hpp @@ -17,7 +17,7 @@ namespace Microsoft::Terminal::Core ITerminalInput& operator=(ITerminalInput&&) = default; virtual bool SendKeyEvent(const WORD vkey, const WORD scanCode, const ControlKeyStates states, const bool keyDown) = 0; - virtual bool SendMouseEvent(const COORD viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta) = 0; + virtual bool SendMouseEvent(const COORD viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state) = 0; virtual bool SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) = 0; // void SendMouseEvent(uint row, uint col, KeyModifiers modifiers); diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index f4a847cc884..4709eeaf0e8 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -510,7 +510,7 @@ bool Terminal::SendKeyEvent(const WORD vkey, // Return Value: // - true if we translated the key event, and it should not be processed any further. // - false if we did not translate the key, and it should be processed into a character. -bool Terminal::SendMouseEvent(const COORD viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta) +bool Terminal::SendMouseEvent(const COORD viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const TerminalInput::MouseButtonState state) { // GH#6401: VT applications should be able to receive mouse events from outside the // terminal buffer. This is likely to happen when the user drags the cursor offscreen. @@ -519,7 +519,7 @@ bool Terminal::SendMouseEvent(const COORD viewportPos, const unsigned int uiButt #pragma warning(suppress : 26496) // analysis can't tell we're assigning through a reference below auto clampedPos{ viewportPos }; _mutableViewport.ToOrigin().Clamp(clampedPos); - return _terminalInput->HandleMouse(clampedPos, uiButton, GET_KEYSTATE_WPARAM(states.Value()), wheelDelta); + return _terminalInput->HandleMouse(clampedPos, uiButton, GET_KEYSTATE_WPARAM(states.Value()), wheelDelta, state); } // Method Description: diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index 78e0ead8952..df70bc0184c 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -116,7 +116,7 @@ class Microsoft::Terminal::Core::Terminal final : #pragma region ITerminalInput // These methods are defined in Terminal.cpp bool SendKeyEvent(const WORD vkey, const WORD scanCode, const Microsoft::Terminal::Core::ControlKeyStates states, const bool keyDown) override; - bool SendMouseEvent(const COORD viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta) override; + bool SendMouseEvent(const COORD viewportPos, const unsigned int uiButton, const ControlKeyStates states, const short wheelDelta, const Microsoft::Console::VirtualTerminal::TerminalInput::MouseButtonState state) override; bool SendCharEvent(const wchar_t ch, const WORD scanCode, const ControlKeyStates states) override; [[nodiscard]] HRESULT UserResize(const COORD viewportSize) noexcept override; diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 36ec74db1a7..1f0fb413e26 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -17,6 +17,10 @@ using namespace winrt::Windows::Foundation::Numerics; using namespace ::Microsoft::Console; using namespace ::Microsoft::Console::Types; +// This magic flag is "documented" at https://msdn.microsoft.com/en-us/library/windows/desktop/ms646301(v=vs.85).aspx +// "If the high-order bit is 1, the key is down; otherwise, it is up." +static constexpr short KeyPressed{ gsl::narrow_cast(0x8000) }; + AppHost::AppHost() noexcept : _app{}, _logic{ nullptr }, // don't make one, we're going to take a ref on app's @@ -405,7 +409,11 @@ void AppHost::_WindowMouseWheeled(const til::point coord, const int32_t delta) const til::point offsetPoint = coord - controlOrigin; - if (control.OnMouseWheel(offsetPoint, delta)) + const auto lButtonDown = WI_IsFlagSet(GetKeyState(VK_LBUTTON), KeyPressed); + const auto mButtonDown = WI_IsFlagSet(GetKeyState(VK_MBUTTON), KeyPressed); + const auto rButtonDown = WI_IsFlagSet(GetKeyState(VK_RBUTTON), KeyPressed); + + if (control.OnMouseWheel(offsetPoint, delta, lButtonDown, mButtonDown, rButtonDown)) { // If the element handled the mouse wheel event, don't // continue to iterate over the remaining controls. diff --git a/src/interactivity/win32/windowio.cpp b/src/interactivity/win32/windowio.cpp index 2b65f515047..19542281c7d 100644 --- a/src/interactivity/win32/windowio.cpp +++ b/src/interactivity/win32/windowio.cpp @@ -23,12 +23,17 @@ #pragma hdrstop using namespace Microsoft::Console::Interactivity::Win32; +using namespace Microsoft::Console::VirtualTerminal; using Microsoft::Console::Interactivity::ServiceLocator; // For usage with WM_SYSKEYDOWN message processing. // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms646286(v=vs.85).aspx // Bit 29 is whether ALT was held when the message was posted. #define WM_SYSKEYDOWN_ALT_PRESSED (0x20000000) +// This magic flag is "documented" at https://msdn.microsoft.com/en-us/library/windows/desktop/ms646301(v=vs.85).aspx +// "If the high-order bit is 1, the key is down; otherwise, it is up." +static constexpr short KeyPressed{ gsl::narrow_cast(0x8000) }; + // ---------------------------- // Helpers // ---------------------------- @@ -123,6 +128,12 @@ bool HandleTerminalMouseEvent(const COORD cMousePosition, // Virtual terminal input mode if (IsInVirtualTerminalInputMode()) { + const TerminalInput::MouseButtonState state{ + WI_IsFlagSet(GetKeyState(VK_LBUTTON), KeyPressed), + WI_IsFlagSet(GetKeyState(VK_MBUTTON), KeyPressed), + WI_IsFlagSet(GetKeyState(VK_RBUTTON), KeyPressed) + }; + // GH#6401: VT applications should be able to receive mouse events from outside the // terminal buffer. This is likely to happen when the user drags the cursor offscreen. // We shouldn't throw away perfectly good events when they're offscreen, so we just @@ -130,7 +141,7 @@ bool HandleTerminalMouseEvent(const COORD cMousePosition, auto clampedPosition{ cMousePosition }; const auto clampViewport{ gci.GetActiveOutputBuffer().GetViewport().ToOrigin() }; clampViewport.Clamp(clampedPosition); - fWasHandled = gci.GetActiveInputBuffer()->GetTerminalInput().HandleMouse(clampedPosition, uiButton, sModifierKeystate, sWheelDelta); + fWasHandled = gci.GetActiveInputBuffer()->GetTerminalInput().HandleMouse(clampedPosition, uiButton, sModifierKeystate, sWheelDelta, state); } return fWasHandled; diff --git a/src/terminal/adapter/ut_adapter/MouseInputTest.cpp b/src/terminal/adapter/ut_adapter/MouseInputTest.cpp index c064c330dd0..a5e28356ae3 100644 --- a/src/terminal/adapter/ut_adapter/MouseInputTest.cpp +++ b/src/terminal/adapter/ut_adapter/MouseInputTest.cpp @@ -292,7 +292,7 @@ class MouseInputTest bool fExpectedKeyHandled = false; s_pwszInputExpected = L"\x0"; - VERIFY_ARE_EQUAL(fExpectedKeyHandled, mouseInput->HandleMouse({ 0, 0 }, uiButton, sModifierKeystate, sScrollDelta)); + VERIFY_ARE_EQUAL(fExpectedKeyHandled, mouseInput->HandleMouse({ 0, 0 }, uiButton, sModifierKeystate, sScrollDelta, {})); mouseInput->EnableDefaultTracking(true); @@ -309,7 +309,8 @@ class MouseInputTest mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, - sScrollDelta), + sScrollDelta, + {}), NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y)); } @@ -327,7 +328,8 @@ class MouseInputTest mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, - sScrollDelta), + sScrollDelta, + {}), NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y)); } @@ -345,7 +347,8 @@ class MouseInputTest mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, - sScrollDelta), + sScrollDelta, + {}), NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y)); } } @@ -371,7 +374,7 @@ class MouseInputTest bool fExpectedKeyHandled = false; s_pwszInputExpected = L"\x0"; - VERIFY_ARE_EQUAL(fExpectedKeyHandled, mouseInput->HandleMouse({ 0, 0 }, uiButton, sModifierKeystate, sScrollDelta)); + VERIFY_ARE_EQUAL(fExpectedKeyHandled, mouseInput->HandleMouse({ 0, 0 }, uiButton, sModifierKeystate, sScrollDelta, {})); mouseInput->SetUtf8ExtendedMode(true); @@ -391,7 +394,8 @@ class MouseInputTest mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, - sScrollDelta), + sScrollDelta, + {}), NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y)); } @@ -409,7 +413,8 @@ class MouseInputTest mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, - sScrollDelta), + sScrollDelta, + {}), NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y)); } @@ -427,7 +432,8 @@ class MouseInputTest mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, - sScrollDelta), + sScrollDelta, + {}), NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y)); } } @@ -453,7 +459,7 @@ class MouseInputTest bool fExpectedKeyHandled = false; s_pwszInputExpected = L"\x0"; - VERIFY_ARE_EQUAL(fExpectedKeyHandled, mouseInput->HandleMouse({ 0, 0 }, uiButton, sModifierKeystate, sScrollDelta)); + VERIFY_ARE_EQUAL(fExpectedKeyHandled, mouseInput->HandleMouse({ 0, 0 }, uiButton, sModifierKeystate, sScrollDelta, {})); mouseInput->SetSGRExtendedMode(true); @@ -471,7 +477,7 @@ class MouseInputTest // validate translation VERIFY_ARE_EQUAL(fExpectedKeyHandled, - mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, sScrollDelta), + mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, sScrollDelta, {}), NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y)); } @@ -488,7 +494,8 @@ class MouseInputTest mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, - sScrollDelta), + sScrollDelta, + {}), NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y)); } @@ -506,7 +513,8 @@ class MouseInputTest mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, - sScrollDelta), + sScrollDelta, + {}), NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y)); } } @@ -532,7 +540,7 @@ class MouseInputTest bool fExpectedKeyHandled = false; s_pwszInputExpected = L"\x0"; - VERIFY_ARE_EQUAL(fExpectedKeyHandled, mouseInput->HandleMouse({ 0, 0 }, uiButton, sModifierKeystate, sScrollDelta)); + VERIFY_ARE_EQUAL(fExpectedKeyHandled, mouseInput->HandleMouse({ 0, 0 }, uiButton, sModifierKeystate, sScrollDelta, {})); // Default Tracking, Default Encoding mouseInput->EnableDefaultTracking(true); @@ -550,7 +558,8 @@ class MouseInputTest mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, - sScrollDelta), + sScrollDelta, + {}), NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y)); } @@ -570,7 +579,8 @@ class MouseInputTest mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, - sScrollDelta), + sScrollDelta, + {}), NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y)); } @@ -589,7 +599,8 @@ class MouseInputTest mouseInput->HandleMouse(Coord, uiButton, sModifierKeystate, - sScrollDelta), + sScrollDelta, + {}), NoThrowString().Format(L"(x,y)=(%d,%d)", Coord.X, Coord.Y)); } } @@ -606,31 +617,31 @@ class MouseInputTest Log::Comment(L"Test mouse wheel scrolling up"); s_pwszInputExpected = L"\x1B[A"; - VERIFY_IS_TRUE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, WHEEL_DELTA)); + VERIFY_IS_TRUE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, WHEEL_DELTA, {})); Log::Comment(L"Test mouse wheel scrolling down"); s_pwszInputExpected = L"\x1B[B"; - VERIFY_IS_TRUE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, -WHEEL_DELTA)); + VERIFY_IS_TRUE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, -WHEEL_DELTA, {})); Log::Comment(L"Enable cursor keys mode"); mouseInput->ChangeCursorKeysMode(true); Log::Comment(L"Test mouse wheel scrolling up"); s_pwszInputExpected = L"\x1BOA"; - VERIFY_IS_TRUE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, WHEEL_DELTA)); + VERIFY_IS_TRUE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, WHEEL_DELTA, {})); Log::Comment(L"Test mouse wheel scrolling down"); s_pwszInputExpected = L"\x1BOB"; - VERIFY_IS_TRUE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, -WHEEL_DELTA)); + VERIFY_IS_TRUE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, -WHEEL_DELTA, {})); Log::Comment(L"Confirm no effect when scroll mode is disabled"); mouseInput->UseAlternateScreenBuffer(); mouseInput->EnableAlternateScroll(false); - VERIFY_IS_FALSE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, WHEEL_DELTA)); + VERIFY_IS_FALSE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, WHEEL_DELTA, {})); Log::Comment(L"Confirm no effect when using the main buffer"); mouseInput->UseMainScreenBuffer(); mouseInput->EnableAlternateScroll(true); - VERIFY_IS_FALSE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, WHEEL_DELTA)); + VERIFY_IS_FALSE(mouseInput->HandleMouse({ 0, 0 }, WM_MOUSEWHEEL, noModifierKeys, WHEEL_DELTA, {})); } }; diff --git a/src/terminal/input/mouseInput.cpp b/src/terminal/input/mouseInput.cpp index 70694d26dff..152ab4f4958 100644 --- a/src/terminal/input/mouseInput.cpp +++ b/src/terminal/input/mouseInput.cpp @@ -13,10 +13,6 @@ using namespace Microsoft::Console::VirtualTerminal; #endif static const int s_MaxDefaultCoordinate = 94; -// This magic flag is "documented" at https://msdn.microsoft.com/en-us/library/windows/desktop/ms646301(v=vs.85).aspx -// "If the high-order bit is 1, the key is down; otherwise, it is up." -static constexpr short KeyPressed{ gsl::narrow_cast(0x8000) }; - // Alternate scroll sequences static constexpr std::wstring_view CursorUpSequence{ L"\x1b[A" }; static constexpr std::wstring_view CursorDownSequence{ L"\x1b[B" }; @@ -105,22 +101,22 @@ static constexpr bool _isButtonDown(const unsigned int button) noexcept // - Retrieves which mouse button is currently pressed. This is needed because // MOUSEMOVE events do not also tell us if any mouse buttons are pressed during the move. // Parameters: -// +// - state - the current state of which mouse buttons are pressed // Return value: // - a button corresponding to any pressed mouse buttons, else WM_LBUTTONUP if none are pressed. -unsigned int TerminalInput::s_GetPressedButton() noexcept +constexpr unsigned int TerminalInput::s_GetPressedButton(const MouseButtonState state) noexcept { - // TODO GH#4869: Have the caller pass the mouse button state into HandleMouse - unsigned int button = WM_LBUTTONUP; // Will be treated as a release, or no button pressed. - if (WI_IsFlagSet(GetKeyState(VK_LBUTTON), KeyPressed)) + // Will be treated as a release, or no button pressed. + unsigned int button = WM_LBUTTONUP; + if (state.isLeftButtonDown) { button = WM_LBUTTONDOWN; } - else if (WI_IsFlagSet(GetKeyState(VK_MBUTTON), KeyPressed)) + else if (state.isMiddleButtonDown) { button = WM_MBUTTONDOWN; } - else if (WI_IsFlagSet(GetKeyState(VK_RBUTTON), KeyPressed)) + else if (state.isRightButtonDown) { button = WM_RBUTTONDOWN; } @@ -298,12 +294,14 @@ bool TerminalInput::IsTrackingMouseInput() const noexcept // - button - the message to decode. // - modifierKeyState - the modifier keys pressed with this button // - delta - the amount that the scroll wheel changed (should be 0 unless button is a WM_MOUSE*WHEEL) +// - state - the state of the mouse buttons at this moment // Return value: // - true if the event was handled and we should stop event propagation to the default window handler. bool TerminalInput::HandleMouse(const COORD position, const unsigned int button, const short modifierKeyState, - const short delta) + const short delta, + const MouseButtonState state) { if (Utils::Sign(delta) != Utils::Sign(_mouseInputState.accumulatedDelta)) { @@ -354,7 +352,7 @@ bool TerminalInput::HandleMouse(const COORD position, // _GetPressedButton will return the first pressed mouse button. // If it returns WM_LBUTTONUP, then we can assume that the mouse // moved without a button being pressed. - const unsigned int realButton = isHover ? s_GetPressedButton() : button; + const unsigned int realButton = isHover ? s_GetPressedButton(state) : button; // In default mode, only button presses/releases are sent // In ButtonEvent mode, changing coord hovers WITH A BUTTON PRESSED diff --git a/src/terminal/input/terminalInput.hpp b/src/terminal/input/terminalInput.hpp index 167e0f68370..0405ecca36b 100644 --- a/src/terminal/input/terminalInput.hpp +++ b/src/terminal/input/terminalInput.hpp @@ -43,10 +43,19 @@ namespace Microsoft::Console::VirtualTerminal #pragma region MouseInput // These methods are defined in mouseInput.cpp + + struct MouseButtonState + { + bool isLeftButtonDown; + bool isMiddleButtonDown; + bool isRightButtonDown; + }; + bool HandleMouse(const COORD position, const unsigned int button, const short modifierKeyState, - const short delta); + const short delta, + const MouseButtonState state); bool IsTrackingMouseInput() const noexcept; #pragma endregion @@ -136,7 +145,7 @@ namespace Microsoft::Console::VirtualTerminal bool _ShouldSendAlternateScroll(const unsigned int button, const short delta) const noexcept; bool _SendAlternateScroll(const short delta) const noexcept; - static unsigned int s_GetPressedButton() noexcept; + static constexpr unsigned int s_GetPressedButton(const MouseButtonState state) noexcept; #pragma endregion }; } From aee803e694a876ff89fef786dad4ae0198dc461f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 10 Aug 2020 11:21:56 -0500 Subject: [PATCH 10/22] Add support for changing the active color scheme with an action (#6993) ## Summary of the Pull Request Adds the `setColorScheme` action, to change the color scheme of the active control to one given by the `name` parameter. `name` is required. If `name` is not the name of a color scheme, the action does nothing. ## References * Being done as a stepping stone to #6689 ## PR Checklist * [x] Closes #5401 * [x] I work here * [ ] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments Technically, the action is being done by changing the settings of the current `TerminalSettings` of the `TermControl`. Frankly, it should be operating on a copy of the `TermControl`'s `IControlSettings`, then updating the control's settings, or the Control should just listen for changes to it's setting's properties, and update in real time (without a manual call to `UpdateSettings`. However, both those paths are somewhere unknowable beyond #6904, so we'll just do this for now. ## Validation Steps Performed * tested manually with a scheme that exists * tested manually with a scheme that doesn't exist --- doc/cascadia/profiles.schema.json | 19 +++++++++++ src/cascadia/TerminalApp/ActionAndArgs.cpp | 5 +++ src/cascadia/TerminalApp/ActionArgs.cpp | 14 ++++++++ src/cascadia/TerminalApp/ActionArgs.h | 33 +++++++++++++++++++ src/cascadia/TerminalApp/ActionArgs.idl | 5 +++ .../TerminalApp/AppActionHandlers.cpp | 21 ++++++++++++ src/cascadia/TerminalApp/CascadiaSettings.cpp | 23 +++++++++++++ src/cascadia/TerminalApp/CascadiaSettings.h | 2 ++ src/cascadia/TerminalApp/ColorScheme.cpp | 2 +- src/cascadia/TerminalApp/ColorScheme.h | 2 +- .../Resources/en-US/Resources.resw | 4 +++ .../TerminalApp/ShortcutActionDispatch.cpp | 5 +++ .../TerminalApp/ShortcutActionDispatch.h | 1 + .../TerminalApp/ShortcutActionDispatch.idl | 2 ++ src/cascadia/TerminalApp/TerminalPage.cpp | 1 + src/cascadia/TerminalApp/TerminalPage.h | 1 + src/cascadia/TerminalControl/TermControl.cpp | 5 +++ src/cascadia/TerminalControl/TermControl.h | 1 + src/cascadia/TerminalControl/TermControl.idl | 2 ++ 19 files changed, 146 insertions(+), 2 deletions(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index a4dbd3d806d..38bdd5352ab 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -59,6 +59,7 @@ "toggleAlwaysOnTop", "toggleRetroEffect", "find", + "setColorScheme", "setTabColor", "openTabColorPicker", "renameTab", @@ -283,6 +284,23 @@ } ] }, + "SetColorSchemeAction": { + "description": "Arguments corresponding to a Set Color Scheme Action", + "allOf": [ + { "$ref": "#/definitions/ShortcutAction" }, + { + "properties": { + "action": { "type": "string", "pattern": "setColorScheme" }, + "colorScheme": { + "type": "string", + "default": "", + "description": "the name of the scheme to apply to the active pane" + } + } + } + ], + "required": [ "name" ] + }, "WtAction": { "description": "Arguments corresponding to a wt Action", "allOf": [ @@ -350,6 +368,7 @@ { "$ref": "#/definitions/SplitPaneAction" }, { "$ref": "#/definitions/OpenSettingsAction" }, { "$ref": "#/definitions/SetTabColorAction" }, + { "$ref": "#/definitions/SetColorSchemeAction" }, { "$ref": "#/definitions/WtAction" }, { "$ref": "#/definitions/CloseOtherTabsAction" }, { "$ref": "#/definitions/CloseTabsAfterAction" }, diff --git a/src/cascadia/TerminalApp/ActionAndArgs.cpp b/src/cascadia/TerminalApp/ActionAndArgs.cpp index f784345ba5a..f4511a00d26 100644 --- a/src/cascadia/TerminalApp/ActionAndArgs.cpp +++ b/src/cascadia/TerminalApp/ActionAndArgs.cpp @@ -36,6 +36,7 @@ static constexpr std::string_view ToggleRetroEffectKey{ "toggleRetroEffect" }; static constexpr std::string_view ToggleFocusModeKey{ "toggleFocusMode" }; static constexpr std::string_view ToggleFullscreenKey{ "toggleFullscreen" }; static constexpr std::string_view ToggleAlwaysOnTopKey{ "toggleAlwaysOnTop" }; +static constexpr std::string_view SetColorSchemeKey{ "setColorScheme" }; static constexpr std::string_view SetTabColorKey{ "setTabColor" }; static constexpr std::string_view OpenTabColorPickerKey{ "openTabColorPicker" }; static constexpr std::string_view RenameTabKey{ "renameTab" }; @@ -83,6 +84,7 @@ namespace winrt::TerminalApp::implementation { ResizePaneKey, ShortcutAction::ResizePane }, { MoveFocusKey, ShortcutAction::MoveFocus }, { OpenSettingsKey, ShortcutAction::OpenSettings }, + { SetColorSchemeKey, ShortcutAction::SetColorScheme }, { ToggleRetroEffectKey, ShortcutAction::ToggleRetroEffect }, { ToggleFocusModeKey, ShortcutAction::ToggleFocusMode }, { ToggleFullscreenKey, ShortcutAction::ToggleFullscreen }, @@ -125,6 +127,8 @@ namespace winrt::TerminalApp::implementation { ShortcutAction::OpenSettings, winrt::TerminalApp::implementation::OpenSettingsArgs::FromJson }, + { ShortcutAction::SetColorScheme, winrt::TerminalApp::implementation::SetColorSchemeArgs::FromJson }, + { ShortcutAction::SetTabColor, winrt::TerminalApp::implementation::SetTabColorArgs::FromJson }, { ShortcutAction::RenameTab, winrt::TerminalApp::implementation::RenameTabArgs::FromJson }, @@ -280,6 +284,7 @@ namespace winrt::TerminalApp::implementation { ShortcutAction::TogglePaneZoom, RS_(L"TogglePaneZoomCommandKey") }, { ShortcutAction::Invalid, L"" }, { ShortcutAction::Find, RS_(L"FindCommandKey") }, + { ShortcutAction::SetColorScheme, L"" }, { ShortcutAction::SetTabColor, RS_(L"ResetTabColorCommandKey") }, { ShortcutAction::OpenTabColorPicker, RS_(L"OpenTabColorPickerCommandKey") }, { ShortcutAction::RenameTab, RS_(L"ResetTabNameCommandKey") }, diff --git a/src/cascadia/TerminalApp/ActionArgs.cpp b/src/cascadia/TerminalApp/ActionArgs.cpp index 27425c58fc7..eedf3338d9a 100644 --- a/src/cascadia/TerminalApp/ActionArgs.cpp +++ b/src/cascadia/TerminalApp/ActionArgs.cpp @@ -15,6 +15,7 @@ #include "AdjustFontSizeArgs.g.cpp" #include "SplitPaneArgs.g.cpp" #include "OpenSettingsArgs.g.cpp" +#include "SetColorSchemeArgs.g.cpp" #include "SetTabColorArgs.g.cpp" #include "RenameTabArgs.g.cpp" #include "ExecuteCommandlineArgs.g.cpp" @@ -229,6 +230,19 @@ namespace winrt::TerminalApp::implementation } } + winrt::hstring SetColorSchemeArgs::GenerateName() const + { + // "Set color scheme to "{_SchemeName}"" + if (!_SchemeName.empty()) + { + return winrt::hstring{ + fmt::format(std::wstring_view(RS_(L"SetColorSchemeCommandKey")), + _SchemeName.c_str()) + }; + } + return L""; + } + winrt::hstring SetTabColorArgs::GenerateName() const { // "Set tab color to #RRGGBB" diff --git a/src/cascadia/TerminalApp/ActionArgs.h b/src/cascadia/TerminalApp/ActionArgs.h index 941b4716a8f..ac84dde5a5c 100644 --- a/src/cascadia/TerminalApp/ActionArgs.h +++ b/src/cascadia/TerminalApp/ActionArgs.h @@ -15,6 +15,7 @@ #include "AdjustFontSizeArgs.g.h" #include "SplitPaneArgs.g.h" #include "OpenSettingsArgs.g.h" +#include "SetColorSchemeArgs.g.h" #include "SetTabColorArgs.g.h" #include "RenameTabArgs.g.h" #include "ExecuteCommandlineArgs.g.h" @@ -332,6 +333,38 @@ namespace winrt::TerminalApp::implementation } }; + struct SetColorSchemeArgs : public SetColorSchemeArgsT + { + SetColorSchemeArgs() = default; + GETSET_PROPERTY(winrt::hstring, SchemeName, L""); + + static constexpr std::string_view NameKey{ "colorScheme" }; + + public: + hstring GenerateName() const; + + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_SchemeName == _SchemeName; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + JsonUtils::GetValueForKey(json, NameKey, args->_SchemeName); + if (args->_SchemeName.empty()) + { + return { nullptr, { ::TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } }; + } + return { *args, {} }; + } + }; + struct SetTabColorArgs : public SetTabColorArgsT { SetTabColorArgs() = default; diff --git a/src/cascadia/TerminalApp/ActionArgs.idl b/src/cascadia/TerminalApp/ActionArgs.idl index bfeee27d3f6..e57c5243903 100644 --- a/src/cascadia/TerminalApp/ActionArgs.idl +++ b/src/cascadia/TerminalApp/ActionArgs.idl @@ -106,6 +106,11 @@ namespace TerminalApp SettingsTarget Target { get; }; }; + [default_interface] runtimeclass SetColorSchemeArgs : IActionArgs + { + String SchemeName { get; }; + }; + [default_interface] runtimeclass SetTabColorArgs : IActionArgs { Windows.Foundation.IReference TabColor { get; }; diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index c58a95b248c..1f062241e04 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -291,6 +291,27 @@ namespace winrt::TerminalApp::implementation args.Handled(true); } + void TerminalPage::_HandleSetColorScheme(const IInspectable& /*sender*/, + const TerminalApp::ActionEventArgs& args) + { + args.Handled(false); + if (const auto& realArgs = args.ActionArgs().try_as()) + { + if (auto activeTab = _GetFocusedTab()) + { + if (auto activeControl = activeTab->GetActiveTerminalControl()) + { + auto controlSettings = activeControl.Settings(); + if (_settings->ApplyColorScheme(controlSettings, realArgs.SchemeName())) + { + activeControl.UpdateSettings(controlSettings); + args.Handled(true); + } + } + } + } + } + void TerminalPage::_HandleSetTabColor(const IInspectable& /*sender*/, const TerminalApp::ActionEventArgs& args) { diff --git a/src/cascadia/TerminalApp/CascadiaSettings.cpp b/src/cascadia/TerminalApp/CascadiaSettings.cpp index 1206437256f..bca917d8480 100644 --- a/src/cascadia/TerminalApp/CascadiaSettings.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettings.cpp @@ -744,3 +744,26 @@ const ColorScheme* CascadiaSettings::GetColorSchemeForProfile(const GUID profile return nullptr; } } + +// Method Description: +// - Apply the color scheme (provided by name) to the given IControlSettings. +// The settings are modified in-place. +// - If the name doesn't correspond to any of our schemes, this does nothing. +// Arguments: +// - settings: the IControlSettings object to modify +// - name: the name of the scheme to apply +// Return Value: +// - true iff we found a matching scheme for the name schemeName +bool CascadiaSettings::ApplyColorScheme(winrt::Microsoft::Terminal::TerminalControl::IControlSettings& settings, + std::wstring_view schemeName) +{ + std::wstring name{ schemeName }; + auto schemeAndName = _globals.GetColorSchemes().find(name); + if (schemeAndName != _globals.GetColorSchemes().end()) + { + const auto& scheme = schemeAndName->second; + scheme.ApplyScheme(settings); + return true; + } + return false; +} diff --git a/src/cascadia/TerminalApp/CascadiaSettings.h b/src/cascadia/TerminalApp/CascadiaSettings.h index 08a65fba5d7..981264e10f2 100644 --- a/src/cascadia/TerminalApp/CascadiaSettings.h +++ b/src/cascadia/TerminalApp/CascadiaSettings.h @@ -74,6 +74,8 @@ class TerminalApp::CascadiaSettings final std::vector& GetWarnings(); + bool ApplyColorScheme(winrt::Microsoft::Terminal::TerminalControl::IControlSettings& settings, std::wstring_view schemeName); + private: GlobalAppSettings _globals; std::vector _profiles; diff --git a/src/cascadia/TerminalApp/ColorScheme.cpp b/src/cascadia/TerminalApp/ColorScheme.cpp index b04090b6e03..af70c3595e4 100644 --- a/src/cascadia/TerminalApp/ColorScheme.cpp +++ b/src/cascadia/TerminalApp/ColorScheme.cpp @@ -67,7 +67,7 @@ ColorScheme::~ColorScheme() // - terminalSettings: the object to apply our settings to. // Return Value: // - -void ColorScheme::ApplyScheme(TerminalSettings terminalSettings) const +void ColorScheme::ApplyScheme(const winrt::Microsoft::Terminal::TerminalControl::IControlSettings& terminalSettings) const { terminalSettings.DefaultForeground(static_cast(_defaultForeground)); terminalSettings.DefaultBackground(static_cast(_defaultBackground)); diff --git a/src/cascadia/TerminalApp/ColorScheme.h b/src/cascadia/TerminalApp/ColorScheme.h index 4eafdc75b7c..2267eb8f006 100644 --- a/src/cascadia/TerminalApp/ColorScheme.h +++ b/src/cascadia/TerminalApp/ColorScheme.h @@ -37,7 +37,7 @@ class TerminalApp::ColorScheme ColorScheme(std::wstring name, til::color defaultFg, til::color defaultBg, til::color cursorColor); ~ColorScheme(); - void ApplyScheme(winrt::TerminalApp::TerminalSettings terminalSettings) const; + void ApplyScheme(const winrt::Microsoft::Terminal::TerminalControl::IControlSettings& terminalSettings) const; static ColorScheme FromJson(const Json::Value& json); bool ShouldBeLayered(const Json::Value& json) const; diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 25fc712d10f..aaded2a06b4 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -529,6 +529,10 @@ Toggle command palette + + Set color scheme to {0} + {0} will be replaced with the name of a color scheme as defined by the user. + Set tab color to {0} {0} will be replaced with a color, displayed in hexadecimal (#RRGGBB) notation. diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index 2f6a1a280c6..862eb1a9de6 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -185,6 +185,11 @@ namespace winrt::TerminalApp::implementation _ToggleCommandPaletteHandlers(*this, *eventArgs); break; } + case ShortcutAction::SetColorScheme: + { + _SetColorSchemeHandlers(*this, *eventArgs); + break; + } case ShortcutAction::SetTabColor: { _SetTabColorHandlers(*this, *eventArgs); diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.h b/src/cascadia/TerminalApp/ShortcutActionDispatch.h index 963bfbea447..1005129b531 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.h +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.h @@ -52,6 +52,7 @@ namespace winrt::TerminalApp::implementation TYPED_EVENT(ToggleFullscreen, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(ToggleAlwaysOnTop, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(ToggleCommandPalette, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(SetColorScheme, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(SetTabColor, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(OpenTabColorPicker, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(RenameTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl index 4136e44a97e..83681760755 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl @@ -37,6 +37,7 @@ namespace TerminalApp ToggleFullscreen, ToggleAlwaysOnTop, OpenSettings, + SetColorScheme, SetTabColor, OpenTabColorPicker, RenameTab, @@ -86,6 +87,7 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler ToggleFullscreen; event Windows.Foundation.TypedEventHandler ToggleAlwaysOnTop; event Windows.Foundation.TypedEventHandler ToggleCommandPalette; + event Windows.Foundation.TypedEventHandler SetColorScheme; event Windows.Foundation.TypedEventHandler SetTabColor; event Windows.Foundation.TypedEventHandler OpenTabColorPicker; event Windows.Foundation.TypedEventHandler RenameTab; diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 309fb12fe09..3b245440c03 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -890,6 +890,7 @@ namespace winrt::TerminalApp::implementation _actionDispatch->ToggleFullscreen({ this, &TerminalPage::_HandleToggleFullscreen }); _actionDispatch->ToggleAlwaysOnTop({ this, &TerminalPage::_HandleToggleAlwaysOnTop }); _actionDispatch->ToggleCommandPalette({ this, &TerminalPage::_HandleToggleCommandPalette }); + _actionDispatch->SetColorScheme({ this, &TerminalPage::_HandleSetColorScheme }); _actionDispatch->SetTabColor({ this, &TerminalPage::_HandleSetTabColor }); _actionDispatch->OpenTabColorPicker({ this, &TerminalPage::_HandleOpenTabColorPicker }); _actionDispatch->RenameTab({ this, &TerminalPage::_HandleRenameTab }); diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 1228226f6c1..30ca3bced58 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -222,6 +222,7 @@ namespace winrt::TerminalApp::implementation void _HandleToggleFocusMode(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleToggleFullscreen(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleToggleAlwaysOnTop(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); + void _HandleSetColorScheme(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleSetTabColor(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleOpenTabColorPicker(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleRenameTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index d14fb9c9061..245413fe75c 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -2838,6 +2838,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation _renderer->ResetErrorStateAndResume(); } + IControlSettings TermControl::Settings() const + { + return _settings; + } + Windows::Foundation::IReference TermControl::TabColor() noexcept { auto coreColor = _terminal->GetTabColor(); diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index f3d91c5c0b3..a3f26712962 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -102,6 +102,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation const Windows::UI::Xaml::Thickness GetPadding(); TerminalConnection::ConnectionState ConnectionState() const; + IControlSettings Settings() const; static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi); static Windows::Foundation::Size GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars, diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index 89e4634e968..85b6e602cfd 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -39,6 +39,8 @@ namespace Microsoft.Terminal.TerminalControl void UpdateSettings(Microsoft.Terminal.TerminalControl.IControlSettings newSettings); + Microsoft.Terminal.TerminalControl.IControlSettings Settings { get; }; + event TitleChangedEventArgs TitleChanged; event FontSizeChangedEventArgs FontSizeChanged; event Windows.Foundation.TypedEventHandler CopyToClipboard; From e7a1a675af7d3aaa0444fd8d15e3652ffccd70c3 Mon Sep 17 00:00:00 2001 From: James Holderness Date: Mon, 10 Aug 2020 18:06:16 +0100 Subject: [PATCH 11/22] Add support for the "doubly underlined" graphic rendition attribute (#7223) This PR adds support for the ANSI _doubly underlined_ graphic rendition attribute, which is enabled by the `SGR 21` escape sequence. There was already an `ExtendedAttributes::DoublyUnderlined` flag in the `TextAttribute` class, but I needed to add `SetDoublyUnderlined` and `IsDoublyUnderlined` methods to access that flag, and update the `SetGraphicsRendition` methods of the two dispatchers to set the attribute on receipt of the `SGR 21` sequence. I also had to update the existing `SGR 24` handler to reset _DoublyUnderlined_ in addition to _Underlined_, since they share the same reset sequence. For the rendering, I've added a new grid line type, which essentially just draws an additional line with the same thickness as the regular underline, but slightly below it - I found a gap of around 0.05 "em" between the lines looked best. If there isn't enough space in the cell for that gap, the second line will be clamped to overlap the first, so you then just get a thicker line. If there isn't even enough space below for a thicker line, we move the offset _above_ the first line, but just enough to make it thicker. The only other complication was the update of the `Xterm256Engine` in the VT renderer. As mentioned above, the two underline attributes share the same reset sequence, so to forward that state over conpty we require a slightly more complicated process than with most other attributes (similar to _Bold_ and _Faint_). We first check whether either underline attribute needs to be turned off to send the reset sequence, and then check individually if each of them needs to be turned back on again. ## Validation Steps Performed For testing, I've extended the existing attribute tests in `AdapterTest`, `VTRendererTest`, and `ScreenBufferTests`, to make sure we're covering both the _Underlined_ and _DoublyUnderlined_ attributes. I've also manually tested the `SGR 21` sequence in conhost and Windows Terminal, with a variety of fonts and font sizes, to make sure the rendering was reasonably distinguishable from a single underline. Closes #2916 --- src/buffer/out/TextAttribute.cpp | 10 ++++ src/buffer/out/TextAttribute.hpp | 2 + .../TerminalCore/TerminalDispatchGraphics.cpp | 4 ++ src/host/ut_host/ScreenBufferTests.cpp | 47 ++++++++++++++++++- src/host/ut_host/VtRendererTests.cpp | 29 +++++++++++- src/inc/conattrs.hpp | 3 +- src/renderer/base/renderer.cpp | 5 ++ src/renderer/dx/DxRenderer.cpp | 29 +++++++++++- src/renderer/dx/DxRenderer.hpp | 1 + src/renderer/gdi/gdirenderer.hpp | 1 + src/renderer/gdi/paint.cpp | 8 +++- src/renderer/gdi/state.cpp | 18 +++++++ src/renderer/inc/IRenderEngine.hpp | 3 +- src/renderer/vt/VtSequences.cpp | 11 +++++ src/renderer/vt/Xterm256Engine.cpp | 24 ++++++++-- src/renderer/vt/vtrenderer.hpp | 1 + src/terminal/adapter/DispatchTypes.hpp | 1 - .../adapter/adaptDispatchGraphics.cpp | 4 ++ .../adapter/ut_adapter/adapterTest.cpp | 9 +++- 19 files changed, 195 insertions(+), 15 deletions(-) diff --git a/src/buffer/out/TextAttribute.cpp b/src/buffer/out/TextAttribute.cpp index ad7ee0546e7..06c94184432 100644 --- a/src/buffer/out/TextAttribute.cpp +++ b/src/buffer/out/TextAttribute.cpp @@ -249,6 +249,11 @@ bool TextAttribute::IsUnderlined() const noexcept return WI_IsFlagSet(_extendedAttrs, ExtendedAttributes::Underlined); } +bool TextAttribute::IsDoublyUnderlined() const noexcept +{ + return WI_IsFlagSet(_extendedAttrs, ExtendedAttributes::DoublyUnderlined); +} + bool TextAttribute::IsOverlined() const noexcept { return WI_IsFlagSet(_wAttrLegacy, COMMON_LVB_GRID_HORIZONTAL); @@ -294,6 +299,11 @@ void TextAttribute::SetUnderlined(bool isUnderlined) noexcept WI_UpdateFlag(_extendedAttrs, ExtendedAttributes::Underlined, isUnderlined); } +void TextAttribute::SetDoublyUnderlined(bool isDoublyUnderlined) noexcept +{ + WI_UpdateFlag(_extendedAttrs, ExtendedAttributes::DoublyUnderlined, isDoublyUnderlined); +} + void TextAttribute::SetOverlined(bool isOverlined) noexcept { WI_UpdateFlag(_wAttrLegacy, COMMON_LVB_GRID_HORIZONTAL, isOverlined); diff --git a/src/buffer/out/TextAttribute.hpp b/src/buffer/out/TextAttribute.hpp index 7cec03f75e6..22c61a6aa91 100644 --- a/src/buffer/out/TextAttribute.hpp +++ b/src/buffer/out/TextAttribute.hpp @@ -95,6 +95,7 @@ class TextAttribute final bool IsInvisible() const noexcept; bool IsCrossedOut() const noexcept; bool IsUnderlined() const noexcept; + bool IsDoublyUnderlined() const noexcept; bool IsOverlined() const noexcept; bool IsReverseVideo() const noexcept; @@ -105,6 +106,7 @@ class TextAttribute final void SetInvisible(bool isInvisible) noexcept; void SetCrossedOut(bool isCrossedOut) noexcept; void SetUnderlined(bool isUnderlined) noexcept; + void SetDoublyUnderlined(bool isDoublyUnderlined) noexcept; void SetOverlined(bool isOverlined) noexcept; void SetReverseVideo(bool isReversed) noexcept; diff --git a/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp b/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp index f8ff0d129da..635d9bded26 100644 --- a/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp +++ b/src/cascadia/TerminalCore/TerminalDispatchGraphics.cpp @@ -158,8 +158,12 @@ bool TerminalDispatch::SetGraphicsRendition(const gsl::span_expectedAttribute = TextAttribute{ 0 }; _testGetSet->_expectedAttribute.SetUnderlined(true); break; + case DispatchTypes::GraphicsOptions::DoublyUnderlined: + Log::Comment(L"Testing graphics 'Doubly Underlined'"); + _testGetSet->_attribute = TextAttribute{ 0 }; + _testGetSet->_expectedAttribute = TextAttribute{ 0 }; + _testGetSet->_expectedAttribute.SetDoublyUnderlined(true); + break; case DispatchTypes::GraphicsOptions::Overline: Log::Comment(L"Testing graphics 'Overline'"); _testGetSet->_attribute = TextAttribute{ 0 }; @@ -1334,6 +1340,7 @@ class AdapterTest Log::Comment(L"Testing graphics 'No Underline'"); _testGetSet->_attribute = TextAttribute{ 0 }; _testGetSet->_attribute.SetUnderlined(true); + _testGetSet->_attribute.SetDoublyUnderlined(true); _testGetSet->_expectedAttribute = TextAttribute{ 0 }; break; case DispatchTypes::GraphicsOptions::NoOverline: From e6c71cb62a8389d7e7868a9bbacff4f5975bb514 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Mon, 10 Aug 2020 12:48:33 -0700 Subject: [PATCH 12/22] Allow profile.padding to be an int (or any other type :|) (#7235) ## Summary of the Pull Request We're expecting that people have treated `padding` as an integer, and the type-based converter is too strict for that. This PR widens its scope and explicitly allows for it in the schema. ## PR Checklist * [x] Closes #7234 --- doc/cascadia/profiles.schema.json | 11 +++++++++-- src/cascadia/TerminalApp/JsonUtils.h | 19 +++++++++++++++++++ src/cascadia/TerminalApp/Profile.cpp | 6 +++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 38bdd5352ab..fbdba1eb742 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -735,8 +735,15 @@ "padding": { "default": "8, 8, 8, 8", "description": "Sets the padding around the text within the window. Can have three different formats:\n -\"#\" sets the same padding for all sides \n -\"#, #\" sets the same padding for left-right and top-bottom\n -\"#, #, #, #\" sets the padding individually for left, top, right, and bottom.", - "pattern": "^-?[0-9]+(\\.[0-9]+)?( *, *-?[0-9]+(\\.[0-9]+)?|( *, *-?[0-9]+(\\.[0-9]+)?){3})?$", - "type": "string" + "oneOf": [ + { + "pattern": "^-?[0-9]+(\\.[0-9]+)?( *, *-?[0-9]+(\\.[0-9]+)?|( *, *-?[0-9]+(\\.[0-9]+)?){3})?$", + "type": "string" + }, + { + "type": "integer" + } + ] }, "scrollbarState": { "default": "visible", diff --git a/src/cascadia/TerminalApp/JsonUtils.h b/src/cascadia/TerminalApp/JsonUtils.h index b98ade1da9d..9a9c9c676e5 100644 --- a/src/cascadia/TerminalApp/JsonUtils.h +++ b/src/cascadia/TerminalApp/JsonUtils.h @@ -360,6 +360,25 @@ namespace TerminalApp::JsonUtils } }; + template + struct PermissiveStringConverter + { + }; + + template<> + struct PermissiveStringConverter + { + std::wstring FromJson(const Json::Value& json) + { + return til::u8u16(json.asString()); + } + + bool CanConvert(const Json::Value& /*unused*/) + { + return true; + } + }; + // Method Description: // - Helper that will populate a reference with a value converted from a json object. // Arguments: diff --git a/src/cascadia/TerminalApp/Profile.cpp b/src/cascadia/TerminalApp/Profile.cpp index 22e627ad896..b1ad96ae3f2 100644 --- a/src/cascadia/TerminalApp/Profile.cpp +++ b/src/cascadia/TerminalApp/Profile.cpp @@ -402,7 +402,11 @@ void Profile::LayerJson(const Json::Value& json) JsonUtils::GetValueForKey(json, UseAcrylicKey, _useAcrylic); JsonUtils::GetValueForKey(json, SuppressApplicationTitleKey, _suppressApplicationTitle); JsonUtils::GetValueForKey(json, CloseOnExitKey, _closeOnExitMode); - JsonUtils::GetValueForKey(json, PaddingKey, _padding); + + // Padding was never specified as an integer, but it was a common working mistake. + // Allow it to be permissive. + JsonUtils::GetValueForKey(json, PaddingKey, _padding, JsonUtils::PermissiveStringConverter{}); + JsonUtils::GetValueForKey(json, ScrollbarStateKey, _scrollbarState); JsonUtils::GetValueForKey(json, StartingDirectoryKey, _startingDirectory); JsonUtils::GetValueForKey(json, IconKey, _icon); From c03677b0c9f5b9a0a56c9767c7e65e0a0e723dd7 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Mon, 10 Aug 2020 14:48:27 -0700 Subject: [PATCH 13/22] Resolve the default profile during defaults load, don't crash on launch (#7237) The "default profile as name" feature in 1.1 broke the loading of default settings, as we would never get to the validation phase where the default profile string was transformed into a guid. I moved knowledge of the "unparsed default profile" optional to the consumer so that we could make sure we only attempted to deserialize it once (and only if it was present.) Fixes #7236. ## PR Checklist * [x] Closes #7236 --- src/cascadia/TerminalApp/CascadiaSettings.cpp | 9 ++++++--- .../TerminalApp/CascadiaSettingsSerialization.cpp | 6 +++--- src/cascadia/TerminalApp/GlobalAppSettings.cpp | 4 ++-- src/cascadia/TerminalApp/GlobalAppSettings.h | 2 +- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/cascadia/TerminalApp/CascadiaSettings.cpp b/src/cascadia/TerminalApp/CascadiaSettings.cpp index bca917d8480..182ae429b2d 100644 --- a/src/cascadia/TerminalApp/CascadiaSettings.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettings.cpp @@ -225,9 +225,12 @@ void CascadiaSettings::_ValidateProfilesHaveGuid() void CascadiaSettings::_ResolveDefaultProfile() { const auto unparsedDefaultProfile{ GlobalSettings().UnparsedDefaultProfile() }; - auto maybeParsedDefaultProfile{ _GetProfileGuidByName(unparsedDefaultProfile) }; - auto defaultProfileGuid{ til::coalesce_value(maybeParsedDefaultProfile, GUID{}) }; - GlobalSettings().DefaultProfile(defaultProfileGuid); + if (unparsedDefaultProfile) + { + auto maybeParsedDefaultProfile{ _GetProfileGuidByName(*unparsedDefaultProfile) }; + auto defaultProfileGuid{ til::coalesce_value(maybeParsedDefaultProfile, GUID{}) }; + GlobalSettings().DefaultProfile(defaultProfileGuid); + } } // Method Description: diff --git a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp index 1a8f2b6e71f..85b51bf549a 100644 --- a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp @@ -61,7 +61,7 @@ std::unique_ptr CascadiaSettings::LoadAll() // GH 3588, we need this below to know if the user chose something that wasn't our default. // Collect it up here in case it gets modified by any of the other layers between now and when // the user's preferences are loaded and layered. - const auto hardcodedDefaultGuid = resultPtr->GlobalSettings().UnparsedDefaultProfile(); + const auto hardcodedDefaultGuid = resultPtr->GlobalSettings().DefaultProfile(); std::optional fileData = _ReadUserSettings(); const bool foundFile = fileData.has_value(); @@ -141,12 +141,11 @@ std::unique_ptr CascadiaSettings::LoadAll() // is a lot of computation we can skip if no one cares. if (TraceLoggingProviderEnabled(g_hTerminalAppProvider, 0, MICROSOFT_KEYWORD_MEASURES)) { - const auto hardcodedDefaultGuidAsGuid = Utils::GuidFromString(hardcodedDefaultGuid); const auto guid = resultPtr->GlobalSettings().DefaultProfile(); // Compare to the defaults.json one that we set on install. // If it's different, log what the user chose. - if (hardcodedDefaultGuidAsGuid != guid) + if (hardcodedDefaultGuid != guid) { TraceLoggingWrite( g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider @@ -229,6 +228,7 @@ std::unique_ptr CascadiaSettings::LoadDefaults() // them from a file (and the potential that could fail) resultPtr->_ParseJsonString(DefaultJson, true); resultPtr->LayerJson(resultPtr->_defaultSettings); + resultPtr->_ResolveDefaultProfile(); return resultPtr; } diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.cpp b/src/cascadia/TerminalApp/GlobalAppSettings.cpp index 00ce2cc3310..afeca688c6d 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalApp/GlobalAppSettings.cpp @@ -89,9 +89,9 @@ GUID GlobalAppSettings::DefaultProfile() const return _defaultProfile; } -std::wstring GlobalAppSettings::UnparsedDefaultProfile() const +std::optional GlobalAppSettings::UnparsedDefaultProfile() const { - return _unparsedDefaultProfile.value(); + return _unparsedDefaultProfile; } AppKeyBindings GlobalAppSettings::GetKeybindings() const noexcept diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.h b/src/cascadia/TerminalApp/GlobalAppSettings.h index 78222106716..ba51109fa0b 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.h +++ b/src/cascadia/TerminalApp/GlobalAppSettings.h @@ -56,7 +56,7 @@ class TerminalApp::GlobalAppSettings final // by higher layers in the app. void DefaultProfile(const GUID defaultProfile) noexcept; GUID DefaultProfile() const; - std::wstring UnparsedDefaultProfile() const; + std::optional UnparsedDefaultProfile() const; GETSET_PROPERTY(int32_t, InitialRows); // default value set in constructor GETSET_PROPERTY(int32_t, InitialCols); // default value set in constructor From b07c1e49da801dca853b97a0faeb0963a5fb494c Mon Sep 17 00:00:00 2001 From: Leon Liang Date: Tue, 11 Aug 2020 07:03:12 -0700 Subject: [PATCH 14/22] Advanced Tab Switcher (#6732) ![TabSwitchingv2](https://user-images.githubusercontent.com/57155886/88237962-5505d500-cc35-11ea-8384-d91699155067.gif) ## Summary of the Pull Request This PR adds the Advanced Tab Switcher (ATS) to Terminal. It'll work similarly to VSCode's tab switcher. Because this implementation rides off a lot of the Command Palette's XAML code, it'll look just like the Command Palette, and also have support for tab title search. ## References #3753 - ATS Spec Closes #1502 --- doc/cascadia/profiles.schema.json | 26 ++ src/cascadia/TerminalApp/ActionAndArgs.cpp | 4 + src/cascadia/TerminalApp/ActionArgs.cpp | 19 + src/cascadia/TerminalApp/ActionArgs.h | 28 ++ src/cascadia/TerminalApp/ActionArgs.idl | 5 + .../TerminalApp/AppActionHandlers.cpp | 26 ++ src/cascadia/TerminalApp/Command.h | 3 + src/cascadia/TerminalApp/Command.idl | 2 + src/cascadia/TerminalApp/CommandPalette.cpp | 366 +++++++++++++++++- src/cascadia/TerminalApp/CommandPalette.h | 40 +- src/cascadia/TerminalApp/CommandPalette.idl | 12 +- src/cascadia/TerminalApp/CommandPalette.xaml | 131 ++++--- .../Resources/en-US/Resources.resw | 15 + .../TerminalApp/ShortcutActionDispatch.cpp | 5 + .../TerminalApp/ShortcutActionDispatch.h | 1 + .../TerminalApp/ShortcutActionDispatch.idl | 4 +- src/cascadia/TerminalApp/Tab.cpp | 4 +- src/cascadia/TerminalApp/Tab.h | 2 +- src/cascadia/TerminalApp/Tab.idl | 2 +- src/cascadia/TerminalApp/TerminalPage.cpp | 21 +- src/cascadia/TerminalApp/TerminalPage.h | 1 + .../TerminalSettingsSerializationHelpers.h | 9 + src/cascadia/inc/cppwinrt_utils.h | 4 +- 23 files changed, 644 insertions(+), 86 deletions(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index fbdba1eb742..f1e1843bf96 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -67,6 +67,7 @@ "wt", "closeOtherTabs", "closeTabsAfter", + "tabSwitcher", "unbound" ], "type": "string" @@ -88,6 +89,14 @@ ], "type": "string" }, + "AnchorKey": { + "enum": [ + "ctrl", + "alt", + "shift" + ], + "type": "string" + }, "NewTerminalArgs": { "properties": { "commandline": { @@ -352,6 +361,22 @@ ], "required": [ "index" ] }, + "TabSwitcherAction": { + "description": "Arguments corresponding to a Tab Switcher Action", + "allOf": [ + { "$ref": "#/definitions/ShortcutAction" }, + { + "properties": { + "action": { "type": "string", "pattern": "tabSwitcher" }, + "anchorKey": { + "$ref": "#/definitions/AnchorKey", + "default": null, + "description": "If provided, the tab switcher will stay open as long as the anchor key is held down. The anchor key should be part of the keybinding that opens the switcher." + } + } + } + ] + }, "Keybinding": { "additionalProperties": false, "properties": { @@ -372,6 +397,7 @@ { "$ref": "#/definitions/WtAction" }, { "$ref": "#/definitions/CloseOtherTabsAction" }, { "$ref": "#/definitions/CloseTabsAfterAction" }, + { "$ref": "#/definitions/TabSwitcherAction" }, { "type": "null" } ] }, diff --git a/src/cascadia/TerminalApp/ActionAndArgs.cpp b/src/cascadia/TerminalApp/ActionAndArgs.cpp index f4511a00d26..fadadac3b24 100644 --- a/src/cascadia/TerminalApp/ActionAndArgs.cpp +++ b/src/cascadia/TerminalApp/ActionAndArgs.cpp @@ -44,6 +44,7 @@ static constexpr std::string_view ExecuteCommandlineKey{ "wt" }; static constexpr std::string_view ToggleCommandPaletteKey{ "commandPalette" }; static constexpr std::string_view CloseOtherTabsKey{ "closeOtherTabs" }; static constexpr std::string_view CloseTabsAfterKey{ "closeTabsAfter" }; +static constexpr std::string_view ToggleTabSwitcherKey{ "tabSwitcher" }; static constexpr std::string_view ActionKey{ "action" }; @@ -100,6 +101,7 @@ namespace winrt::TerminalApp::implementation { ToggleCommandPaletteKey, ShortcutAction::ToggleCommandPalette }, { CloseOtherTabsKey, ShortcutAction::CloseOtherTabs }, { CloseTabsAfterKey, ShortcutAction::CloseTabsAfter }, + { ToggleTabSwitcherKey, ShortcutAction::ToggleTabSwitcher }, }; using ParseResult = std::tuple>; @@ -139,6 +141,8 @@ namespace winrt::TerminalApp::implementation { ShortcutAction::CloseTabsAfter, winrt::TerminalApp::implementation::CloseTabsAfterArgs::FromJson }, + { ShortcutAction::ToggleTabSwitcher, winrt::TerminalApp::implementation::ToggleTabSwitcherArgs::FromJson }, + { ShortcutAction::Invalid, nullptr }, }; diff --git a/src/cascadia/TerminalApp/ActionArgs.cpp b/src/cascadia/TerminalApp/ActionArgs.cpp index eedf3338d9a..d6e7219fd13 100644 --- a/src/cascadia/TerminalApp/ActionArgs.cpp +++ b/src/cascadia/TerminalApp/ActionArgs.cpp @@ -19,6 +19,7 @@ #include "SetTabColorArgs.g.cpp" #include "RenameTabArgs.g.cpp" #include "ExecuteCommandlineArgs.g.cpp" +#include "ToggleTabSwitcherArgs.g.h" #include @@ -303,4 +304,22 @@ namespace winrt::TerminalApp::implementation _Index) }; } + + winrt::hstring ToggleTabSwitcherArgs::GenerateName() const + { + // If there's an anchor key set, don't generate a name so that + // it won't show up in the command palette. Only an unanchored + // tab switcher should be able to be toggled from the palette. + // TODO: GH#7179 - once this goes in, make sure to hide the + // anchor mode command that was given a name in settings. + if (_AnchorKey != Windows::System::VirtualKey::None) + { + return L""; + } + else + { + return RS_(L"ToggleTabSwitcherCommandKey"); + } + } + } diff --git a/src/cascadia/TerminalApp/ActionArgs.h b/src/cascadia/TerminalApp/ActionArgs.h index ac84dde5a5c..7c768d58054 100644 --- a/src/cascadia/TerminalApp/ActionArgs.h +++ b/src/cascadia/TerminalApp/ActionArgs.h @@ -21,6 +21,7 @@ #include "ExecuteCommandlineArgs.g.h" #include "CloseOtherTabsArgs.g.h" #include "CloseTabsAfterArgs.g.h" +#include "ToggleTabSwitcherArgs.g.h" #include "../../cascadia/inc/cppwinrt_utils.h" #include "Utils.h" @@ -512,6 +513,33 @@ namespace winrt::TerminalApp::implementation } }; + struct ToggleTabSwitcherArgs : public ToggleTabSwitcherArgsT + { + ToggleTabSwitcherArgs() = default; + GETSET_PROPERTY(Windows::System::VirtualKey, AnchorKey, Windows::System::VirtualKey::None); + + static constexpr std::string_view AnchorJsonKey{ "anchorKey" }; + + public: + hstring GenerateName() const; + + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_AnchorKey == _AnchorKey; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + JsonUtils::GetValueForKey(json, AnchorJsonKey, args->_AnchorKey); + return { *args, {} }; + } + }; } namespace winrt::TerminalApp::factory_implementation diff --git a/src/cascadia/TerminalApp/ActionArgs.idl b/src/cascadia/TerminalApp/ActionArgs.idl index e57c5243903..a460d712a92 100644 --- a/src/cascadia/TerminalApp/ActionArgs.idl +++ b/src/cascadia/TerminalApp/ActionArgs.idl @@ -135,4 +135,9 @@ namespace TerminalApp { UInt32 Index { get; }; }; + + [default_interface] runtimeclass ToggleTabSwitcherArgs : IActionArgs + { + Windows.System.VirtualKey AnchorKey { get; }; + }; } diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 1f062241e04..19a8c44f2ad 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -285,6 +285,7 @@ namespace winrt::TerminalApp::implementation { // TODO GH#6677: When we add support for commandline mode, first set the // mode that the command palette should be in, before making it visible. + CommandPalette().EnableCommandPaletteMode(); CommandPalette().Visibility(CommandPalette().Visibility() == Visibility::Visible ? Visibility::Collapsed : Visibility::Visible); @@ -414,6 +415,7 @@ namespace winrt::TerminalApp::implementation actionArgs.Handled(true); } } + void TerminalPage::_HandleCloseTabsAfter(const IInspectable& /*sender*/, const TerminalApp::ActionEventArgs& actionArgs) { @@ -436,4 +438,28 @@ namespace winrt::TerminalApp::implementation actionArgs.Handled(true); } } + + void TerminalPage::_HandleToggleTabSwitcher(const IInspectable& /*sender*/, + const TerminalApp::ActionEventArgs& args) + { + if (const auto& realArgs = args.ActionArgs().try_as()) + { + auto anchorKey = realArgs.AnchorKey(); + + auto opt = _GetFocusedTabIndex(); + uint32_t startIdx = opt ? *opt : 0; + + if (anchorKey != VirtualKey::None) + { + // TODO: GH#7178 - delta should also have the option of being -1, in the case when + // a user decides to open the tab switcher going to the prev tab. + int delta = 1; + startIdx = (startIdx + _tabs.Size() + delta) % _tabs.Size(); + } + + CommandPalette().EnableTabSwitcherMode(anchorKey, startIdx); + CommandPalette().Visibility(Visibility::Visible); + } + args.Handled(true); + } } diff --git a/src/cascadia/TerminalApp/Command.h b/src/cascadia/TerminalApp/Command.h index 2882fc8244a..b037df3beb7 100644 --- a/src/cascadia/TerminalApp/Command.h +++ b/src/cascadia/TerminalApp/Command.h @@ -32,10 +32,13 @@ namespace winrt::TerminalApp::implementation static std::vector<::TerminalApp::SettingsLoadWarnings> LayerJson(std::unordered_map& commands, const Json::Value& json); + winrt::Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker propertyChangedRevoker; + WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); OBSERVABLE_GETSET_PROPERTY(winrt::hstring, Name, _PropertyChangedHandlers); OBSERVABLE_GETSET_PROPERTY(winrt::TerminalApp::ActionAndArgs, Action, _PropertyChangedHandlers); OBSERVABLE_GETSET_PROPERTY(winrt::hstring, KeyChordText, _PropertyChangedHandlers); + OBSERVABLE_GETSET_PROPERTY(winrt::Windows::UI::Xaml::Controls::IconSource, IconSource, _PropertyChangedHandlers, nullptr); }; } diff --git a/src/cascadia/TerminalApp/Command.idl b/src/cascadia/TerminalApp/Command.idl index 80e1a2b476b..f54de393f9e 100644 --- a/src/cascadia/TerminalApp/Command.idl +++ b/src/cascadia/TerminalApp/Command.idl @@ -12,5 +12,7 @@ namespace TerminalApp String Name; ActionAndArgs Action; String KeyChordText; + + Windows.UI.Xaml.Controls.IconSource IconSource; } } diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index f6fdfa9567b..b743d8c1e29 100644 --- a/src/cascadia/TerminalApp/CommandPalette.cpp +++ b/src/cascadia/TerminalApp/CommandPalette.cpp @@ -3,6 +3,11 @@ #include "pch.h" #include "CommandPalette.h" +#include "ActionAndArgs.h" +#include "ActionArgs.h" +#include "Command.h" + +#include #include "CommandPalette.g.cpp" @@ -12,15 +17,18 @@ using namespace winrt::Windows::UI::Core; using namespace winrt::Windows::UI::Xaml; using namespace winrt::Windows::System; using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Foundation::Collections; namespace winrt::TerminalApp::implementation { - CommandPalette::CommandPalette() + CommandPalette::CommandPalette() : + _switcherStartIdx{ 0 } { InitializeComponent(); _filteredActions = winrt::single_threaded_observable_vector(); - _allActions = winrt::single_threaded_vector(); + _allCommands = winrt::single_threaded_vector(); + _allTabActions = winrt::single_threaded_vector(); if (CommandPaletteShadow()) { @@ -38,8 +46,26 @@ namespace winrt::TerminalApp::implementation RegisterPropertyChangedCallback(UIElement::VisibilityProperty(), [this](auto&&, auto&&) { if (Visibility() == Visibility::Visible) { - _searchBox().Focus(FocusState::Programmatic); - _filteredActionsView().SelectedIndex(0); + if (_currentMode == CommandPaletteMode::TabSwitcherMode) + { + if (_anchorKey != VirtualKey::None) + { + _searchBox().Visibility(Visibility::Collapsed); + _filteredActionsView().Focus(FocusState::Keyboard); + } + else + { + _searchBox().Focus(FocusState::Programmatic); + } + + _filteredActionsView().SelectedIndex(_switcherStartIdx); + _filteredActionsView().ScrollIntoView(_filteredActionsView().SelectedItem()); + } + else + { + _searchBox().Focus(FocusState::Programmatic); + _filteredActionsView().SelectedIndex(0); + } TraceLoggingWrite( g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider @@ -55,6 +81,19 @@ namespace winrt::TerminalApp::implementation _dismissPalette(); } }); + + // Focusing the ListView when the Command Palette control is set to Visible + // for the first time fails because the ListView hasn't finished loading by + // the time Focus is called. Luckily, We can listen to SizeChanged to know + // when the ListView has been measured out and is ready, and we'll immediately + // revoke the handler because we only needed to handle it once on initialization. + _sizeChangedRevoker = _filteredActionsView().SizeChanged(winrt::auto_revoke, [this](auto /*s*/, auto /*e*/) { + if (_currentMode == CommandPaletteMode::TabSwitcherMode && _anchorKey != VirtualKey::None) + { + _filteredActionsView().Focus(FocusState::Keyboard); + } + _sizeChangedRevoker.revoke(); + }); } // Method Description: @@ -77,6 +116,36 @@ namespace winrt::TerminalApp::implementation _filteredActionsView().ScrollIntoView(_filteredActionsView().SelectedItem()); } + void CommandPalette::_previewKeyDownHandler(IInspectable const& /*sender*/, + Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e) + { + auto key = e.OriginalKey(); + + // Some keypresses such as Tab, Return, Esc, and Arrow Keys are ignored by controls because + // they're not considered input key presses. While they don't raise KeyDown events, + // they do raise PreviewKeyDown events. + // + // Only give anchored tab switcher the ability to cycle through tabs with the tab button. + // For unanchored mode, accessibility becomes an issue when we try to hijack tab since it's + // a really widely used keyboard navigation key. + if (_currentMode == CommandPaletteMode::TabSwitcherMode && + key == VirtualKey::Tab && + _anchorKey != VirtualKey::None) + { + auto const state = CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Shift); + if (WI_IsFlagSet(state, CoreVirtualKeyStates::Down)) + { + _selectNextItem(false); + e.Handled(true); + } + else + { + _selectNextItem(true); + e.Handled(true); + } + } + } + // Method Description: // - Process keystrokes in the input box. This is used for moving focus up // and down the list of commands in Action mode, and for executing @@ -108,7 +177,7 @@ namespace winrt::TerminalApp::implementation if (const auto selectedItem = _filteredActionsView().SelectedItem()) { - _dispatchCommand(selectedItem.try_as()); + _dispatchCommand(selectedItem.try_as()); } e.Handled(true); @@ -129,6 +198,34 @@ namespace winrt::TerminalApp::implementation } } + void CommandPalette::_keyUpHandler(IInspectable const& /*sender*/, + Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e) + { + auto key = e.OriginalKey(); + + if (_currentMode == CommandPaletteMode::TabSwitcherMode) + { + if (_anchorKey && key == _anchorKey.value()) + { + // Once the user lifts the anchor key, we'll switch to the currently selected tab + // then close the tab switcher. + + if (const auto selectedItem = _filteredActionsView().SelectedItem()) + { + if (const auto data = selectedItem.try_as()) + { + const auto actionAndArgs = data.Action(); + _dispatch.DoAction(actionAndArgs); + _updateFilteredActions(); + _dismissPalette(); + } + } + + e.Handled(true); + } + } + } + // Method Description: // - This event is triggered when someone clicks anywhere in the bounds of // the window that's _not_ the command palette UI. When that happens, @@ -171,6 +268,28 @@ namespace winrt::TerminalApp::implementation _dispatchCommand(e.ClickedItem().try_as()); } + // Method Description: + // - Retrieve the list of commands that we should currently be filtering. + // * If the user has command with subcommands, this will return that command's subcommands. + // * If we're in Tab Switcher mode, return the tab actions. + // * Otherwise, just return the list of all the top-level commands. + // Arguments: + // - + // Return Value: + // - A list of Commands to filter. + Collections::IVector CommandPalette::_commandsToFilter() + { + switch (_currentMode) + { + case CommandPaletteMode::ActionMode: + return _allCommands; + case CommandPaletteMode::TabSwitcherMode: + return _allTabActions; + default: + return _allCommands; + } + } + // Method Description: // - Helper method for retrieving the action from a command the user // selected, and dispatching that command. Also fires a tracelogging event @@ -184,6 +303,10 @@ namespace winrt::TerminalApp::implementation { if (command) { + // Close before we dispatch so that actions that open the command + // palette like the Tab Switcher will be able to have the last laugh. + _close(); + const auto actionAndArgs = command.Action(); _dispatch.DoAction(actionAndArgs); @@ -194,8 +317,6 @@ namespace winrt::TerminalApp::implementation TraceLoggingUInt32(_searchBox().Text().size(), "SearchTextLength", "Number of characters in the search string"), TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance)); - - _close(); } } @@ -235,17 +356,59 @@ namespace winrt::TerminalApp::implementation _noMatchesText().Visibility(_filteredActions.Size() > 0 ? Visibility::Collapsed : Visibility::Visible); } - Collections::IObservableVector CommandPalette::FilteredActions() + Collections::IObservableVector CommandPalette::FilteredActions() { return _filteredActions; } - void CommandPalette::SetActions(Collections::IVector const& actions) + void CommandPalette::SetCommands(Collections::IVector const& actions) { - _allActions = actions; + _allCommands = actions; _updateFilteredActions(); } + void CommandPalette::EnableCommandPaletteMode() + { + _switchToMode(CommandPaletteMode::ActionMode); + _updateFilteredActions(); + } + + void CommandPalette::_switchToMode(CommandPaletteMode mode) + { + // The smooth remove/add animations that happen during + // UpdateFilteredActions don't work very well when switching between + // modes because of the sheer amount of remove/adds. So, let's just + // clear + append when switching between modes. + if (mode != _currentMode) + { + _currentMode = mode; + _filteredActions.Clear(); + auto commandsToFilter = _commandsToFilter(); + + for (auto action : commandsToFilter) + { + _filteredActions.Append(action); + } + + switch (_currentMode) + { + case CommandPaletteMode::TabSwitcherMode: + { + SearchBoxText(RS_(L"TabSwitcher_SearchBoxText")); + NoMatchesText(RS_(L"TabSwitcher_NoMatchesText")); + ControlName(RS_(L"TabSwitcherControlName")); + break; + } + case CommandPaletteMode::ActionMode: + default: + SearchBoxText(RS_(L"CommandPalette_SearchBox/PlaceholderText")); + NoMatchesText(RS_(L"CommandPalette_NoMatchesText/Text")); + ControlName(RS_(L"CommandPaletteControlName")); + break; + } + } + } + // This is a helper to aid in sorting commands by their `Name`s, alphabetically. static bool _compareCommandNames(const TerminalApp::Command& lhs, const TerminalApp::Command& rhs) { @@ -259,13 +422,23 @@ namespace winrt::TerminalApp::implementation { TerminalApp::Command command; int weight; + int inOrderCounter; bool operator<(const WeightedCommand& other) const { - // If two commands have the same weight, then we'll sort them alphabetically. if (weight == other.weight) { - return !_compareCommandNames(command, other.command); + // If two commands have the same weight, then we'll sort them alphabetically. + // If they both have the same name, fall back to the order in which they were + // pushed into the heap. + if (command.Name() == other.command.Name()) + { + return inOrderCounter > other.inOrderCounter; + } + else + { + return !_compareCommandNames(command, other.command); + } } return weight < other.weight; } @@ -286,16 +459,30 @@ namespace winrt::TerminalApp::implementation auto searchText = _searchBox().Text(); const bool addAll = searchText.empty(); + auto commandsToFilter = _commandsToFilter(); + // If there's no filter text, then just add all the commands in order to the list. // - TODO GH#6647:Possibly add the MRU commands first in order, followed // by the rest of the commands. if (addAll) { + // If TabSwitcherMode, just add all as is. We don't want + // them to be sorted alphabetically. + if (_currentMode == CommandPaletteMode::TabSwitcherMode) + { + for (auto action : commandsToFilter) + { + actions.push_back(action); + } + + return actions; + } + // Add all the commands, but make sure they're sorted alphabetically. std::vector sortedCommands; - sortedCommands.reserve(_allActions.Size()); + sortedCommands.reserve(commandsToFilter.Size()); - for (auto action : _allActions) + for (auto action : commandsToFilter) { sortedCommands.push_back(action); } @@ -325,7 +512,12 @@ namespace winrt::TerminalApp::implementation // appear first in the list. The ordering will be determined by the // match weight produced by _getWeight. std::priority_queue heap; - for (auto action : _allActions) + + // TODO GH#7205: Find a better way to ensure that WCs of the same + // weight and name stay in the order in which they were pushed onto + // the PQ. + uint32_t counter = 0; + for (auto action : commandsToFilter) { const auto weight = CommandPalette::_getWeight(searchText, action.Name()); if (weight > 0) @@ -333,6 +525,8 @@ namespace winrt::TerminalApp::implementation WeightedCommand wc; wc.command = action; wc.weight = weight; + wc.inOrderCounter = counter++; + heap.push(wc); } } @@ -502,8 +696,150 @@ namespace winrt::TerminalApp::implementation { Visibility(Visibility::Collapsed); + // Reset visibility in case anchor mode tab switcher just finished. + _searchBox().Visibility(Visibility::Visible); + // Clear the text box each time we close the dialog. This is consistent with VsCode. _searchBox().Text(L""); } + // Method Description: + // - Listens for changes to TerminalPage's _tabs vector. Updates our vector of + // tab switching commands accordingly. + // Arguments: + // - s: The vector being listened to. + // - e: The vector changed args that tells us whether a change, insert, or removal was performed + // on the listened-to vector. + // Return Value: + // - + void CommandPalette::OnTabsChanged(const IInspectable& s, const IVectorChangedEventArgs& e) + { + if (auto tabList = s.try_as>()) + { + auto idx = e.Index(); + auto changedEvent = e.CollectionChange(); + + switch (changedEvent) + { + case CollectionChange::ItemChanged: + { + winrt::com_ptr item; + item.copy_from(winrt::get_self(_allTabActions.GetAt(idx))); + item->propertyChangedRevoker.revoke(); + + auto tab = tabList.GetAt(idx); + GenerateCommandForTab(idx, false, tab); + UpdateTabIndices(idx); + break; + } + case CollectionChange::ItemInserted: + { + auto tab = tabList.GetAt(idx); + GenerateCommandForTab(idx, true, tab); + UpdateTabIndices(idx); + break; + } + case CollectionChange::ItemRemoved: + { + winrt::com_ptr item; + item.copy_from(winrt::get_self(_allTabActions.GetAt(idx))); + item->propertyChangedRevoker.revoke(); + + _allTabActions.RemoveAt(idx); + UpdateTabIndices(idx); + break; + } + } + + _updateFilteredActions(); + } + } + + // Method Description: + // - In the case where a tab is removed or reordered, the given indices of + // the tab switch commands following the removed/reordered tab will get out of sync by 1 + // (e.g. if tab 1 is removed, tabs 2,3,4,... need to become tabs 1,2,3,...) + // This function just loops through the tabs following startIdx and adjusts their given indices. + // Arguments: + // - startIdx: The index to start the update loop at. + // Return Value: + // - + void CommandPalette::UpdateTabIndices(const uint32_t startIdx) + { + if (startIdx != _allTabActions.Size() - 1) + { + for (auto i = startIdx; i < _allTabActions.Size(); ++i) + { + auto command = _allTabActions.GetAt(i); + + command.Action().Args().as()->TabIndex(i); + } + } + } + + // Method Description: + // - Create a tab switching command based on the given tab object and insert/update the command + // at the given index. The command will call a SwitchToTab action on the given idx. + // Arguments: + // - idx: The index to insert or update the tab switch command. + // - tab: The tab object to refer to when creating the tab switch command. + // Return Value: + // - + void CommandPalette::GenerateCommandForTab(const uint32_t idx, bool inserted, TerminalApp::Tab& tab) + { + auto focusTabAction = winrt::make_self(); + auto args = winrt::make_self(); + args->TabIndex(idx); + + focusTabAction->Action(ShortcutAction::SwitchToTab); + focusTabAction->Args(*args); + + auto command = winrt::make_self(); + command->Action(*focusTabAction); + command->Name(tab.Title()); + command->IconSource(tab.IconSource()); + + // Listen for changes to the Tab so we can update this Command's attributes accordingly. + auto weakThis{ get_weak() }; + auto weakCommand{ command->get_weak() }; + command->propertyChangedRevoker = tab.PropertyChanged(winrt::auto_revoke, [weakThis, weakCommand, tab](auto&&, const Windows::UI::Xaml::Data::PropertyChangedEventArgs& args) { + auto palette{ weakThis.get() }; + auto command{ weakCommand.get() }; + + if (palette && command) + { + if (args.PropertyName() == L"Title") + { + if (command->Name() != tab.Title()) + { + command->Name(tab.Title()); + } + } + if (args.PropertyName() == L"IconSource") + { + if (command->IconSource() != tab.IconSource()) + { + command->IconSource(tab.IconSource()); + } + } + } + }); + + if (inserted) + { + _allTabActions.InsertAt(idx, *command); + } + else + { + _allTabActions.SetAt(idx, *command); + } + } + + void CommandPalette::EnableTabSwitcherMode(const VirtualKey& anchorKey, const uint32_t startIdx) + { + _switcherStartIdx = startIdx; + _anchorKey = anchorKey; + _switchToMode(CommandPaletteMode::TabSwitcherMode); + _updateFilteredActions(); + } } diff --git a/src/cascadia/TerminalApp/CommandPalette.h b/src/cascadia/TerminalApp/CommandPalette.h index a14466f4f36..b062b42003c 100644 --- a/src/cascadia/TerminalApp/CommandPalette.h +++ b/src/cascadia/TerminalApp/CommandPalette.h @@ -8,26 +8,50 @@ namespace winrt::TerminalApp::implementation { + enum class CommandPaletteMode + { + ActionMode = 0, + TabSwitcherMode + }; + struct CommandPalette : CommandPaletteT { CommandPalette(); Windows::Foundation::Collections::IObservableVector FilteredActions(); - void SetActions(Windows::Foundation::Collections::IVector const& actions); + + void SetCommands(Windows::Foundation::Collections::IVector const& actions); + void EnableCommandPaletteMode(); void SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch); + // Tab Switcher + void EnableTabSwitcherMode(const Windows::System::VirtualKey& anchorKey, const uint32_t startIdx); + void OnTabsChanged(const Windows::Foundation::IInspectable& s, const Windows::Foundation::Collections::IVectorChangedEventArgs& e); + + WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); + OBSERVABLE_GETSET_PROPERTY(winrt::hstring, NoMatchesText, _PropertyChangedHandlers); + OBSERVABLE_GETSET_PROPERTY(winrt::hstring, SearchBoxText, _PropertyChangedHandlers); + OBSERVABLE_GETSET_PROPERTY(winrt::hstring, ControlName, _PropertyChangedHandlers); + private: friend struct CommandPaletteT; // for Xaml to bind events Windows::Foundation::Collections::IObservableVector _filteredActions{ nullptr }; - Windows::Foundation::Collections::IVector _allActions{ nullptr }; + + Windows::Foundation::Collections::IVector _allCommands{ nullptr }; winrt::TerminalApp::ShortcutActionDispatch _dispatch; + Windows::Foundation::Collections::IVector _commandsToFilter(); + void _filterTextChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); + void _previewKeyDownHandler(Windows::Foundation::IInspectable const& sender, + Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e); void _keyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e); + void _keyUpHandler(Windows::Foundation::IInspectable const& sender, + Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e); void _rootPointerPressed(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); void _backdropPointerPressed(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); @@ -41,6 +65,18 @@ namespace winrt::TerminalApp::implementation static int _getWeight(const winrt::hstring& searchText, const winrt::hstring& name); void _close(); + CommandPaletteMode _currentMode; + void _switchToMode(CommandPaletteMode mode); + + // Tab Switcher + std::optional _anchorKey; + void GenerateCommandForTab(const uint32_t idx, bool inserted, winrt::TerminalApp::Tab& tab); + void UpdateTabIndices(const uint32_t startIdx); + Windows::Foundation::Collections::IVector _allTabActions{ nullptr }; + uint32_t _switcherStartIdx; + + winrt::Windows::UI::Xaml::Controls::ListView::SizeChanged_revoker _sizeChangedRevoker; + void _dispatchCommand(const TerminalApp::Command& command); void _dismissPalette(); diff --git a/src/cascadia/TerminalApp/CommandPalette.idl b/src/cascadia/TerminalApp/CommandPalette.idl index f0e7c9bb539..8286077a4e4 100644 --- a/src/cascadia/TerminalApp/CommandPalette.idl +++ b/src/cascadia/TerminalApp/CommandPalette.idl @@ -5,14 +5,22 @@ import "../Command.idl"; namespace TerminalApp { - [default_interface] runtimeclass CommandPalette : Windows.UI.Xaml.Controls.Grid + [default_interface] runtimeclass CommandPalette : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged { CommandPalette(); + String NoMatchesText { get; }; + String SearchBoxText { get; }; + String ControlName { get; }; + Windows.Foundation.Collections.IObservableVector FilteredActions { get; }; - void SetActions(Windows.Foundation.Collections.IVector actions); + void SetCommands(Windows.Foundation.Collections.IVector actions); + void EnableCommandPaletteMode(); void SetDispatch(ShortcutActionDispatch dispatch); + + void EnableTabSwitcherMode(Windows.System.VirtualKey anchorKey, UInt32 startIdx); + void OnTabsChanged(IInspectable s, Windows.Foundation.Collections.IVectorChangedEventArgs e); } } diff --git a/src/cascadia/TerminalApp/CommandPalette.xaml b/src/cascadia/TerminalApp/CommandPalette.xaml index 39b0e1a25be..50b35e8bbb6 100644 --- a/src/cascadia/TerminalApp/CommandPalette.xaml +++ b/src/cascadia/TerminalApp/CommandPalette.xaml @@ -1,6 +1,6 @@ - xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:Windows10version1903="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 8)" + TabNavigation="Cycle" + IsTabStop="True" + AllowFocusOnInteraction="True" PointerPressed="_rootPointerPressed" - mc:Ignorable="d"> + PreviewKeyDown="_previewKeyDownHandler" + KeyDown="_keyDownHandler" + PreviewKeyUp="_keyUpHandler" + mc:Ignorable="d" + AutomationProperties.Name="{x:Bind ControlName, Mode=OneWay}"> - + + - + - - - - - + + + + + - - - - + + + + - + - VerticalAlignment="Stretch"> - HorizontalAlignment="Stretch" VerticalAlignment="Top"> - - - - - + + + + + - - + - - + Grid.Row="1" + Text="{x:Bind NoMatchesText, Mode=OneWay}"> + - AllowDrop="False" IsItemClickEnabled="True" ItemClick="_listItemClicked" + PreviewKeyDown="_keyDownHandler" ItemsSource="{x:Bind FilteredActions}"> - - + + - - - + - - - - - - + + + + + + - + - - - - - + - - - - - + + + + + - + - + + diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index aaded2a06b4..c891d53df6a 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -529,6 +529,9 @@ Toggle command palette + + Command Palette + Set color scheme to {0} {0} will be replaced with the name of a color scheme as defined by the user. @@ -562,6 +565,18 @@ Close tabs after index {0} {0} will be replaced with a number + + Tab Switcher + + + Toggle tab switcher + + + Type a tab name... + + + No matching tab name + Crimson diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index 862eb1a9de6..e8b9eb778c4 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -220,6 +220,11 @@ namespace winrt::TerminalApp::implementation _CloseTabsAfterHandlers(*this, *eventArgs); break; } + case ShortcutAction::ToggleTabSwitcher: + { + _ToggleTabSwitcherHandlers(*this, *eventArgs); + break; + } default: return false; } diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.h b/src/cascadia/TerminalApp/ShortcutActionDispatch.h index 1005129b531..fa139848e63 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.h +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.h @@ -59,6 +59,7 @@ namespace winrt::TerminalApp::implementation TYPED_EVENT(ExecuteCommandline, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(CloseOtherTabs, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(CloseTabsAfter, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(ToggleTabSwitcher, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); // clang-format on private: diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl index 83681760755..b0341d4bf81 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl @@ -44,7 +44,8 @@ namespace TerminalApp ExecuteCommandline, ToggleCommandPalette, CloseOtherTabs, - CloseTabsAfter + CloseTabsAfter, + ToggleTabSwitcher }; [default_interface] runtimeclass ActionAndArgs { @@ -94,5 +95,6 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler ExecuteCommandline; event Windows.Foundation.TypedEventHandler CloseOtherTabs; event Windows.Foundation.TypedEventHandler CloseTabsAfter; + event Windows.Foundation.TypedEventHandler ToggleTabSwitcher; } } diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index eb396275303..ead28ce1f02 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -18,6 +18,7 @@ using namespace winrt::Windows::System; namespace winrt { namespace MUX = Microsoft::UI::Xaml; + namespace WUX = Windows::UI::Xaml; } namespace winrt::TerminalApp::implementation @@ -225,7 +226,8 @@ namespace winrt::TerminalApp::implementation if (auto tab{ weakThis.get() }) { - IconPath(_lastIconPath); + // The TabViewItem Icon needs MUX while the IconSourceElement in the CommandPalette needs WUX... + IconSource(GetColoredIcon(_lastIconPath)); _tabViewItem.IconSource(GetColoredIcon(_lastIconPath)); } } diff --git a/src/cascadia/TerminalApp/Tab.h b/src/cascadia/TerminalApp/Tab.h index 6e3e5cc5b95..02055b05767 100644 --- a/src/cascadia/TerminalApp/Tab.h +++ b/src/cascadia/TerminalApp/Tab.h @@ -73,7 +73,7 @@ namespace winrt::TerminalApp::implementation DECLARE_EVENT(ColorCleared, _colorCleared, winrt::delegate<>); OBSERVABLE_GETSET_PROPERTY(winrt::hstring, Title, _PropertyChangedHandlers); - OBSERVABLE_GETSET_PROPERTY(winrt::hstring, IconPath, _PropertyChangedHandlers); + OBSERVABLE_GETSET_PROPERTY(winrt::Windows::UI::Xaml::Controls::IconSource, IconSource, _PropertyChangedHandlers, nullptr); private: std::shared_ptr _rootPane{ nullptr }; diff --git a/src/cascadia/TerminalApp/Tab.idl b/src/cascadia/TerminalApp/Tab.idl index 955c243845a..5aba64605fc 100644 --- a/src/cascadia/TerminalApp/Tab.idl +++ b/src/cascadia/TerminalApp/Tab.idl @@ -6,6 +6,6 @@ namespace TerminalApp [default_interface] runtimeclass Tab : Windows.UI.Xaml.Data.INotifyPropertyChanged { String Title { get; }; - String IconPath { get; }; + Windows.UI.Xaml.Controls.IconSource IconSource { get; }; } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 3b245440c03..3838e4ccf50 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -80,9 +80,20 @@ namespace winrt::TerminalApp::implementation { command.KeyChordText(KeyChordSerialization::ToString(keyChord)); } + + // Set the default IconSource to a BitmapIconSource with a null source + // (instead of just nullptr) because there's a really weird crash when swapping + // data bound IconSourceElements in a ListViewTemplate (i.e. CommandPalette). + // Swapping between nullptr IconSources and non-null IconSources causes a crash + // to occur, but swapping between IconSources with a null source and non-null IconSources + // work perfectly fine :shrug:. + winrt::Windows::UI::Xaml::Controls::BitmapIconSource icon; + icon.UriSource(nullptr); + command.IconSource(icon); + commandsCollection.Append(command); } - CommandPalette().SetActions(commandsCollection); + CommandPalette().SetCommands(commandsCollection); } } @@ -211,6 +222,13 @@ namespace winrt::TerminalApp::implementation } }); + _tabs.VectorChanged([weakThis{ get_weak() }](auto&& s, auto&& e) { + if (auto page{ weakThis.get() }) + { + page->CommandPalette().OnTabsChanged(s, e); + } + }); + // Once the page is actually laid out on the screen, trigger all our // startup actions. Things like Panes need to know at least how big the // window will be, so they can subdivide that space. @@ -897,6 +915,7 @@ namespace winrt::TerminalApp::implementation _actionDispatch->ExecuteCommandline({ this, &TerminalPage::_HandleExecuteCommandline }); _actionDispatch->CloseOtherTabs({ this, &TerminalPage::_HandleCloseOtherTabs }); _actionDispatch->CloseTabsAfter({ this, &TerminalPage::_HandleCloseTabsAfter }); + _actionDispatch->ToggleTabSwitcher({ this, &TerminalPage::_HandleToggleTabSwitcher }); } // Method Description: diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 30ca3bced58..984f1064245 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -230,6 +230,7 @@ namespace winrt::TerminalApp::implementation void _HandleToggleCommandPalette(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleCloseOtherTabs(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleCloseTabsAfter(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); + void _HandleToggleTabSwitcher(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); // Make sure to hook new actions up in _RegisterActionCallbacks! #pragma endregion diff --git a/src/cascadia/TerminalApp/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalApp/TerminalSettingsSerializationHelpers.h index f7058a49a74..80459845a09 100644 --- a/src/cascadia/TerminalApp/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalApp/TerminalSettingsSerializationHelpers.h @@ -270,3 +270,12 @@ JSON_ENUM_MAPPER(::winrt::TerminalApp::SettingsTarget) pair_type{ "allFiles", ValueType::AllFiles }, }; }; + +JSON_ENUM_MAPPER(::winrt::Windows::System::VirtualKey) +{ + JSON_MAPPINGS(3) = { + pair_type{ "ctrl", ValueType::Control }, + pair_type{ "alt", ValueType::Menu }, + pair_type{ "shift", ValueType::Shift }, + }; +}; diff --git a/src/cascadia/inc/cppwinrt_utils.h b/src/cascadia/inc/cppwinrt_utils.h index 3d9599bbeef..dcc53ef23ce 100644 --- a/src/cascadia/inc/cppwinrt_utils.h +++ b/src/cascadia/inc/cppwinrt_utils.h @@ -114,7 +114,7 @@ private: \ // private _setName() method, that the class can internally use to change the // value when it _knows_ it doesn't need to raise the PropertyChanged event // (like when the class is being initialized). -#define OBSERVABLE_GETSET_PROPERTY(type, name, event) \ +#define OBSERVABLE_GETSET_PROPERTY(type, name, event, ...) \ public: \ type name() { return _##name; }; \ void name(const type& value) \ @@ -127,7 +127,7 @@ public: }; \ \ private: \ - const type _##name; \ + const type _##name{ __VA_ARGS__ }; \ void _set##name(const type& value) \ { \ const_cast(_##name) = value; \ From 7ccd1f6f1a3315484ad8728208e9487f9b7a0928 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Tue, 11 Aug 2020 12:50:13 -0700 Subject: [PATCH 15/22] Display meaningful errors when JSON types don't match (#7241) This pull request completes (and somewhat rewrites) the JsonUtils error handling arc. Deserialization errors, no longer represented by trees of exceptions that must be rethrown and caught, are now transformed at catch time into a message explaining what we expected and where we expected it. Instead of exception trees, a deserialization failure will result in a single type of exception with the originating JSON object from which we can determine the contents and location of the failure. Because most of the error message actually comes from the JSON schema or the actual supported types, and the other jsoncpp errors are not localized I've made the decision to **not** localize these messages. --- src/cascadia/TerminalApp/AppLogic.cpp | 6 + src/cascadia/TerminalApp/CascadiaSettings.h | 8 ++ .../CascadiaSettingsSerialization.cpp | 75 ++++++++-- src/cascadia/TerminalApp/JsonUtils.h | 129 +++++++++++------- .../TerminalSettingsSerializationHelpers.h | 9 ++ src/cascadia/ut_app/JsonUtilsTests.cpp | 52 ++++--- 6 files changed, 194 insertions(+), 85 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index b0257b431a6..9b6c3eddc77 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -632,6 +632,12 @@ namespace winrt::TerminalApp::implementation hr = E_INVALIDARG; _settingsLoadExceptionText = _GetErrorText(ex.Error()); } + catch (const ::TerminalApp::SettingsTypedDeserializationException& e) + { + hr = E_INVALIDARG; + std::string_view what{ e.what() }; + _settingsLoadExceptionText = til::u8u16(what); + } catch (...) { hr = wil::ResultFromCaughtException(); diff --git a/src/cascadia/TerminalApp/CascadiaSettings.h b/src/cascadia/TerminalApp/CascadiaSettings.h index 981264e10f2..a4b61893112 100644 --- a/src/cascadia/TerminalApp/CascadiaSettings.h +++ b/src/cascadia/TerminalApp/CascadiaSettings.h @@ -39,9 +39,17 @@ namespace TerminalAppUnitTests namespace TerminalApp { + class SettingsTypedDeserializationException; class CascadiaSettings; }; +class TerminalApp::SettingsTypedDeserializationException final : public std::runtime_error +{ +public: + SettingsTypedDeserializationException(const std::string_view description) : + runtime_error(description.data()) {} +}; + class TerminalApp::CascadiaSettings final { public: diff --git a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp index 85b51bf549a..bba84551f4d 100644 --- a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp @@ -42,6 +42,54 @@ static constexpr std::string_view Utf8Bom{ u8"\uFEFF" }; static constexpr std::string_view SettingsSchemaFragment{ "\n" R"( "$schema": "https://aka.ms/terminal-profiles-schema")" }; +static std::tuple _LineAndColumnFromPosition(const std::string_view string, ptrdiff_t position) +{ + size_t line = 1, column = position + 1; + auto lastNL = string.find_last_of('\n', position); + if (lastNL != std::string::npos) + { + column = (position - lastNL); + line = std::count(string.cbegin(), string.cbegin() + lastNL + 1, '\n') + 1; + } + + return { line, column }; +} + +static void _CatchRethrowSerializationExceptionWithLocationInfo(std::string_view settingsString) +{ + std::string msg; + + try + { + throw; + } + catch (const JsonUtils::DeserializationError& e) + { + static constexpr std::string_view basicHeader{ "* Line {line}, Column {column}\n{message}" }; + static constexpr std::string_view keyedHeader{ "* Line {line}, Column {column} ({key})\n{message}" }; + + std::string jsonValueAsString{ "array or object" }; + try + { + jsonValueAsString = e.jsonValue.asString(); + } + catch (...) + { + // discard: we're in the middle of error handling + } + + msg = fmt::format(" Have: \"{}\"\n Expected: {}", jsonValueAsString, e.expectedType); + + auto [l, c] = _LineAndColumnFromPosition(settingsString, e.jsonValue.getOffsetStart()); + msg = fmt::format((e.key ? keyedHeader : basicHeader), + fmt::arg("line", l), + fmt::arg("column", c), + fmt::arg("key", e.key.value_or("")), + fmt::arg("message", msg)); + throw SettingsTypedDeserializationException{ msg }; + } +} + // Method Description: // - Creates a CascadiaSettings from whatever's saved on disk, or instantiates // a new one with the default values. If we're running as a packaged app, @@ -90,16 +138,23 @@ std::unique_ptr CascadiaSettings::LoadAll() needToWriteFile = true; } - // See microsoft/terminal#2325: find the defaultSettings from the user's - // settings. Layer those settings upon all the existing profiles we have - // (defaults and dynamic profiles). We'll also set - // _userDefaultProfileSettings here. When we LayerJson below to apply the - // user settings, we'll make sure to use these defaultSettings _before_ any - // profiles the user might have. - resultPtr->_ApplyDefaultsFromUserSettings(); - - // Apply the user's settings - resultPtr->LayerJson(resultPtr->_userSettings); + try + { + // See microsoft/terminal#2325: find the defaultSettings from the user's + // settings. Layer those settings upon all the existing profiles we have + // (defaults and dynamic profiles). We'll also set + // _userDefaultProfileSettings here. When we LayerJson below to apply the + // user settings, we'll make sure to use these defaultSettings _before_ any + // profiles the user might have. + resultPtr->_ApplyDefaultsFromUserSettings(); + + // Apply the user's settings + resultPtr->LayerJson(resultPtr->_userSettings); + } + catch (...) + { + _CatchRethrowSerializationExceptionWithLocationInfo(resultPtr->_userSettingsString); + } // After layering the user settings, check if there are any new profiles // that need to be inserted into their user settings file. diff --git a/src/cascadia/TerminalApp/JsonUtils.h b/src/cascadia/TerminalApp/JsonUtils.h index 9a9c9c676e5..b15eb1478a2 100644 --- a/src/cascadia/TerminalApp/JsonUtils.h +++ b/src/cascadia/TerminalApp/JsonUtils.h @@ -69,52 +69,24 @@ namespace TerminalApp::JsonUtils }; } - // These exceptions cannot use localized messages, as we do not have - // guaranteed access to the resource loader. - class TypeMismatchException : public std::runtime_error + class DeserializationError : public std::runtime_error { public: - TypeMismatchException() : - runtime_error("unexpected data type") {} - }; - - class KeyedException : public std::runtime_error - { - public: - KeyedException(const std::string_view key, std::exception_ptr exception) : - runtime_error(fmt::format("error parsing \"{0}\"", key).c_str()), - _key{ key }, - _innerException{ std::move(exception) } {} - - std::string GetKey() const - { - return _key; - } + DeserializationError(const Json::Value& value) : + runtime_error("failed to deserialize"), + jsonValue{ value } {} - [[noreturn]] void RethrowInner() const + void SetKey(std::string_view newKey) { - std::rethrow_exception(_innerException); - } - - private: - std::string _key; - std::exception_ptr _innerException; - }; - - class UnexpectedValueException : public std::runtime_error - { - public: - UnexpectedValueException(const std::string_view value) : - runtime_error(fmt::format("unexpected value \"{0}\"", value).c_str()), - _value{ value } {} - - std::string GetValue() const - { - return _value; + if (!key) + { + key = newKey; + } } - private: - std::string _value; + std::optional key; + Json::Value jsonValue; + std::string expectedType; }; template @@ -123,6 +95,8 @@ namespace TerminalApp::JsonUtils // Forward-declare these so the linker can pick up specializations from elsewhere! T FromJson(const Json::Value&); bool CanConvert(const Json::Value& json); + + std::string TypeDescription() const { return ""; } }; template<> @@ -137,6 +111,11 @@ namespace TerminalApp::JsonUtils { return json.isString(); } + + std::string TypeDescription() const + { + return "string"; + } }; template<> @@ -151,6 +130,11 @@ namespace TerminalApp::JsonUtils { return json.isString(); } + + std::string TypeDescription() const + { + return "string"; + } }; #ifdef WINRT_BASE_H @@ -177,6 +161,11 @@ namespace TerminalApp::JsonUtils { return json.isBool(); } + + std::string TypeDescription() const + { + return "true | false"; + } }; template<> @@ -191,6 +180,11 @@ namespace TerminalApp::JsonUtils { return json.isInt(); } + + std::string TypeDescription() const + { + return "number"; + } }; template<> @@ -205,6 +199,11 @@ namespace TerminalApp::JsonUtils { return json.isUInt(); } + + std::string TypeDescription() const + { + return "number (>= 0)"; + } }; template<> @@ -219,6 +218,11 @@ namespace TerminalApp::JsonUtils { return json.isNumeric(); } + + std::string TypeDescription() const + { + return "number"; + } }; template<> @@ -233,6 +237,11 @@ namespace TerminalApp::JsonUtils { return json.isNumeric(); } + + std::string TypeDescription() const + { + return "number"; + } }; template<> @@ -253,6 +262,11 @@ namespace TerminalApp::JsonUtils const auto string{ Detail::GetStringView(json) }; return string.length() == 38 && string.front() == '{' && string.back() == '}'; } + + std::string TypeDescription() const + { + return "guid"; + } }; // (GUID and winrt::guid are mutually convertible!) @@ -279,6 +293,11 @@ namespace TerminalApp::JsonUtils const auto string{ Detail::GetStringView(json) }; return (string.length() == 7 || string.length() == 4) && string.front() == '#'; } + + std::string TypeDescription() const + { + return "color (#rrggbb, #rgb)"; + } }; template @@ -298,13 +317,22 @@ namespace TerminalApp::JsonUtils } } - throw UnexpectedValueException{ name }; + DeserializationError e{ json }; + e.expectedType = TypeDescription(); + throw e; } bool CanConvert(const Json::Value& json) { return json.isString(); } + + std::string TypeDescription() const + { + std::vector names; + std::transform(TBase::mappings.cbegin(), TBase::mappings.cend(), std::back_inserter(names), [](auto&& p) { return p.first; }); + return fmt::format("{}", fmt::join(names, " | ")); + } }; // FlagMapper is EnumMapper, but it works for bitfields. @@ -343,7 +371,9 @@ namespace TerminalApp::JsonUtils (value == AllClear && newFlag != AllClear))) { // attempt to combine AllClear (explicitly) with anything else - throw UnexpectedValueException{ element.asString() }; + DeserializationError e{ element }; + e.expectedType = TypeDescription(); + throw e; } value |= newFlag; } @@ -377,6 +407,11 @@ namespace TerminalApp::JsonUtils { return true; } + + std::string TypeDescription() const + { + return "any"; + } }; // Method Description: @@ -407,7 +442,9 @@ namespace TerminalApp::JsonUtils { if (!conv.CanConvert(json)) { - throw TypeMismatchException{}; + DeserializationError e{ json }; + e.expectedType = conv.TypeDescription(); + throw e; } target = conv.FromJson(json); @@ -435,10 +472,10 @@ namespace TerminalApp::JsonUtils { return GetValue(*found, target, std::forward(conv)); } - catch (...) + catch (DeserializationError& e) { - // Wrap any caught exceptions in one that preserves context. - throw KeyedException(key, std::current_exception()); + e.SetKey(key); + throw; // rethrow now that it has a key } } return false; diff --git a/src/cascadia/TerminalApp/TerminalSettingsSerializationHelpers.h b/src/cascadia/TerminalApp/TerminalSettingsSerializationHelpers.h index 80459845a09..c1e60b6a705 100644 --- a/src/cascadia/TerminalApp/TerminalSettingsSerializationHelpers.h +++ b/src/cascadia/TerminalApp/TerminalSettingsSerializationHelpers.h @@ -101,6 +101,8 @@ JSON_ENUM_MAPPER(::TerminalApp::CloseOnExitMode) { return EnumMapper::CanConvert(json) || json.isBool(); } + + using EnumMapper::TypeDescription; }; // This specialization isn't using JSON_ENUM_MAPPER because we need to have a different @@ -151,6 +153,8 @@ struct ::TerminalApp::JsonUtils::ConversionTrait<::winrt::Windows::UI::Text::Fon { return BaseEnumMapper::CanConvert(json) || json.isUInt(); } + + using EnumMapper::TypeDescription; }; JSON_ENUM_MAPPER(::winrt::Windows::UI::Xaml::ElementTheme) @@ -231,6 +235,11 @@ struct ::TerminalApp::JsonUtils::ConversionTrait<::TerminalApp::LaunchPosition> { return json.isString(); } + + std::string TypeDescription() const + { + return "x, y"; + } }; // Possible Direction values diff --git a/src/cascadia/ut_app/JsonUtilsTests.cpp b/src/cascadia/ut_app/JsonUtilsTests.cpp index f3f3c7c5b2c..44d2c02fe44 100644 --- a/src/cascadia/ut_app/JsonUtilsTests.cpp +++ b/src/cascadia/ut_app/JsonUtilsTests.cpp @@ -33,6 +33,8 @@ struct ConversionTrait { return value.isInt(); } + + std::string TypeDescription() const { return ""; } }; // Converts a JSON string value to an int and multiplies it by a specified factor @@ -49,6 +51,8 @@ struct CustomConverter { return true; } + + std::string TypeDescription() const { return ""; } }; enum class JsonTestEnum : int @@ -130,7 +134,7 @@ namespace TerminalAppUnitTests //// 1. Bare Value //// //// 1.a. Type Invalid - Exception //// - VERIFY_THROWS_SPECIFIC(GetValue(object), TypeMismatchException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValue(object), DeserializationError, _ReturnTrueForException); //// 1.b. JSON NULL - Zero Value //// std::string zeroValueString{}; @@ -141,7 +145,7 @@ namespace TerminalAppUnitTests //// 2. Optional //// //// 2.a. Type Invalid - Exception //// - VERIFY_THROWS_SPECIFIC(GetValue>(object), TypeMismatchException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValue>(object), DeserializationError, _ReturnTrueForException); //// 2.b. JSON NULL - nullopt //// VERIFY_ARE_EQUAL(std::nullopt, GetValue>(Json::Value::nullSingleton())); @@ -160,7 +164,7 @@ namespace TerminalAppUnitTests std::string output{ "sentinel" }; // explicitly not the zero value //// 1.a. Type Invalid - Exception //// - VERIFY_THROWS_SPECIFIC(GetValue(object, outputRedHerring), TypeMismatchException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValue(object, outputRedHerring), DeserializationError, _ReturnTrueForException); VERIFY_ARE_EQUAL(5, outputRedHerring); // unchanged //// 1.b. JSON NULL - Unchanged //// @@ -176,7 +180,7 @@ namespace TerminalAppUnitTests std::optional optionalOutput{ "sentinel2" }; // explicitly not nullopt //// 2.a. Type Invalid - Exception //// - VERIFY_THROWS_SPECIFIC(GetValue(object, optionalOutputRedHerring), TypeMismatchException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValue(object, optionalOutputRedHerring), DeserializationError, _ReturnTrueForException); VERIFY_ARE_EQUAL(6, optionalOutputRedHerring); // unchanged //// 2.b. JSON NULL - nullopt //// @@ -202,7 +206,7 @@ namespace TerminalAppUnitTests //// 1. Bare Value //// //// 1.a. Type Invalid - Exception //// - VERIFY_THROWS_SPECIFIC(GetValueForKey(object, key), KeyedException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValueForKey(object, key), DeserializationError, _ReturnTrueForException); //// 1.b. JSON NULL - Zero Value //// std::string zeroValueString{}; @@ -216,7 +220,7 @@ namespace TerminalAppUnitTests //// 2. Optional //// //// 2.a. Type Invalid - Exception //// - VERIFY_THROWS_SPECIFIC(GetValueForKey>(object, key), KeyedException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValueForKey>(object, key), DeserializationError, _ReturnTrueForException); //// 2.b. JSON NULL - nullopt //// VERIFY_ARE_EQUAL(std::nullopt, GetValueForKey>(object, nullKey)); @@ -245,7 +249,7 @@ namespace TerminalAppUnitTests std::string output{ "sentinel" }; // explicitly not the zero value //// 1.a. Type Invalid - Exception //// - VERIFY_THROWS_SPECIFIC(GetValueForKey(object, key, outputRedHerring), KeyedException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValueForKey(object, key, outputRedHerring), DeserializationError, _ReturnTrueForException); VERIFY_ARE_EQUAL(5, outputRedHerring); // unchanged //// 1.b. JSON NULL - Unchanged //// @@ -267,7 +271,7 @@ namespace TerminalAppUnitTests std::optional optionalOutput{ "sentinel2" }; // explicitly not nullopt //// 2.a. Type Invalid - Exception //// - VERIFY_THROWS_SPECIFIC(GetValueForKey(object, key, optionalOutputRedHerring), KeyedException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValueForKey(object, key, optionalOutputRedHerring), DeserializationError, _ReturnTrueForException); VERIFY_ARE_EQUAL(6, optionalOutputRedHerring); // unchanged //// 2.b. JSON NULL - nullopt //// @@ -321,12 +325,12 @@ namespace TerminalAppUnitTests TryBasicType(testGuid, testGuidString); - VERIFY_THROWS_SPECIFIC(GetValue({ "NOT_A_GUID" }), TypeMismatchException, _ReturnTrueForException); - VERIFY_THROWS_SPECIFIC(GetValue({ "{too short for a guid but just a bit}" }), TypeMismatchException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValue({ "NOT_A_GUID" }), DeserializationError, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValue({ "{too short for a guid but just a bit}" }), DeserializationError, _ReturnTrueForException); VERIFY_THROWS_SPECIFIC(GetValue({ "{proper length string not a guid tho?}" }), std::exception, _ReturnTrueForException); - VERIFY_THROWS_SPECIFIC(GetValue({ "#" }), TypeMismatchException, _ReturnTrueForException); - VERIFY_THROWS_SPECIFIC(GetValue({ "#1234567890" }), TypeMismatchException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValue({ "#" }), DeserializationError, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValue({ "#1234567890" }), DeserializationError, _ReturnTrueForException); } void JsonUtilsTests::BasicTypeWithCustomConverter() @@ -366,7 +370,7 @@ namespace TerminalAppUnitTests // Unknown value should produce something? Json::Value stringUnknown{ "unknown" }; - VERIFY_THROWS_SPECIFIC(GetValue(stringUnknown), UnexpectedValueException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValue(stringUnknown), DeserializationError, _ReturnTrueForException); } void JsonUtilsTests::FlagMapper() @@ -401,17 +405,17 @@ namespace TerminalAppUnitTests Json::Value arrayNoneFirst{ Json::arrayValue }; arrayNoneFirst.append({ "none" }); arrayNoneFirst.append({ "first" }); - VERIFY_THROWS_SPECIFIC(GetValue(arrayNoneFirst), UnexpectedValueException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValue(arrayNoneFirst), DeserializationError, _ReturnTrueForException); // Stacking Any + None (Exception; same as above, different order) Json::Value arrayFirstNone{ Json::arrayValue }; arrayFirstNone.append({ "first" }); arrayFirstNone.append({ "none" }); - VERIFY_THROWS_SPECIFIC(GetValue(arrayFirstNone), UnexpectedValueException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValue(arrayFirstNone), DeserializationError, _ReturnTrueForException); // Unknown flag value? Json::Value stringUnknown{ "unknown" }; - VERIFY_THROWS_SPECIFIC(GetValue(stringUnknown), UnexpectedValueException, _ReturnTrueForException); + VERIFY_THROWS_SPECIFIC(GetValue(stringUnknown), DeserializationError, _ReturnTrueForException); } void JsonUtilsTests::NestedExceptionDuringKeyParse() @@ -420,20 +424,10 @@ namespace TerminalAppUnitTests Json::Value object{ Json::objectValue }; object[key] = Json::Value{ "string" }; - auto CheckKeyedException = [](const KeyedException& k) { - try - { - k.RethrowInner(); - } - catch (TypeMismatchException&) - { - // This Keyed exception contained the correct inner. - return true; - } - // This Keyed exception did not contain the correct inner. - return false; + auto CheckKeyInException = [](const DeserializationError& k) { + return k.key.has_value(); }; - VERIFY_THROWS_SPECIFIC(GetValueForKey(object, key), KeyedException, CheckKeyedException); + VERIFY_THROWS_SPECIFIC(GetValueForKey(object, key), DeserializationError, CheckKeyInException); } } From bc642bbf2a51e792b1eddb219d8ae3117bed9d3c Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 11 Aug 2020 14:57:45 -0500 Subject: [PATCH 16/22] Fix viewport moving when we've scrolled up and circled the buffer (#7247) If you scroll up to view the scrollback, then we want the viewport to "stay in place", as new output comes in (see #6062). This works fine up until the buffer circles. In this case, the mutable viewport isn't actually moving, so we never set `updatedViewport` to true. This regressed in #6062 Closes #7222 --- src/cascadia/TerminalCore/Terminal.cpp | 18 +++- .../TerminalBufferTests.cpp | 84 +++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalCore/Terminal.cpp b/src/cascadia/TerminalCore/Terminal.cpp index 4709eeaf0e8..f6b3950a262 100644 --- a/src/cascadia/TerminalCore/Terminal.cpp +++ b/src/cascadia/TerminalCore/Terminal.cpp @@ -843,8 +843,12 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition) } } - if (updatedViewport) + // If the viewport moved, or we circled the buffer, we might need to update + // our _scrollOffset + if (updatedViewport || newRows != 0) { + const auto oldScrollOffset = _scrollOffset; + // scroll if... // - no selection is active // - viewport is already at the bottom @@ -852,6 +856,18 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition) _scrollOffset = scrollToOutput ? 0 : _scrollOffset + scrollAmount + newRows; + // Clamp the range to make sure that we don't scroll way off the top of the buffer + _scrollOffset = std::clamp(_scrollOffset, + 0, + _buffer->GetSize().Height() - _mutableViewport.Height()); + + // If the new scroll offset is different, then we'll still want to raise a scroll event + updatedViewport = updatedViewport || (oldScrollOffset != _scrollOffset); + } + + // If the viewport moved, then send a scrolling notification. + if (updatedViewport) + { _NotifyScrollEvent(); } diff --git a/src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp b/src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp index 5fbc2d7403d..e4636081803 100644 --- a/src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp +++ b/src/cascadia/UnitTests_TerminalCore/TerminalBufferTests.cpp @@ -39,6 +39,8 @@ class TerminalCoreUnitTests::TerminalBufferTests final TEST_METHOD(TestWrappingCharByChar); TEST_METHOD(TestWrappingALongString); + TEST_METHOD(DontSnapToOutputTest); + TEST_METHOD_SETUP(MethodSetup) { // STEP 1: Set up the Terminal @@ -149,3 +151,85 @@ void TerminalBufferTests::TestWrappingALongString() TestUtils::VerifyExpectedString(termTb, TestUtils::Test100CharsString, { 0, 0 }); } + +void TerminalBufferTests::DontSnapToOutputTest() +{ + auto& termTb = *term->_buffer; + auto& termSm = *term->_stateMachine; + const auto initialView = term->GetViewport(); + + VERIFY_ARE_EQUAL(0, initialView.Top()); + VERIFY_ARE_EQUAL(TerminalViewHeight, initialView.BottomExclusive()); + VERIFY_ARE_EQUAL(0, term->_scrollOffset); + + // -1 so that we don't print the last \n + for (int i = 0; i < TerminalViewHeight + 8 - 1; i++) + { + termSm.ProcessString(L"x\n"); + } + + const auto secondView = term->GetViewport(); + + VERIFY_ARE_EQUAL(8, secondView.Top()); + VERIFY_ARE_EQUAL(TerminalViewHeight + 8, secondView.BottomExclusive()); + VERIFY_ARE_EQUAL(0, term->_scrollOffset); + + Log::Comment(L"Scroll up one line"); + term->_scrollOffset = 1; + + const auto thirdView = term->GetViewport(); + VERIFY_ARE_EQUAL(7, thirdView.Top()); + VERIFY_ARE_EQUAL(TerminalViewHeight + 7, thirdView.BottomExclusive()); + VERIFY_ARE_EQUAL(1, term->_scrollOffset); + + Log::Comment(L"Print a few lines, to see that the viewport stays where it was"); + for (int i = 0; i < 8; i++) + { + termSm.ProcessString(L"x\n"); + } + + const auto fourthView = term->GetViewport(); + VERIFY_ARE_EQUAL(7, fourthView.Top()); + VERIFY_ARE_EQUAL(TerminalViewHeight + 7, fourthView.BottomExclusive()); + VERIFY_ARE_EQUAL(1 + 8, term->_scrollOffset); + + Log::Comment(L"Print enough lines to get the buffer just about ready to " + L"circle (on the next newline)"); + auto viewBottom = term->_mutableViewport.BottomInclusive(); + do + { + termSm.ProcessString(L"x\n"); + viewBottom = term->_mutableViewport.BottomInclusive(); + } while (viewBottom < termTb.GetSize().BottomInclusive()); + + const auto fifthView = term->GetViewport(); + VERIFY_ARE_EQUAL(7, fifthView.Top()); + VERIFY_ARE_EQUAL(TerminalViewHeight + 7, fifthView.BottomExclusive()); + VERIFY_ARE_EQUAL(TerminalHistoryLength - 7, term->_scrollOffset); + + Log::Comment(L"Print 3 more lines, and see that we stick to where the old " + L"rows now are in the buffer (after circling)"); + for (int i = 0; i < 3; i++) + { + termSm.ProcessString(L"x\n"); + Log::Comment(NoThrowString().Format( + L"_scrollOffset: %d", term->_scrollOffset)); + } + const auto sixthView = term->GetViewport(); + VERIFY_ARE_EQUAL(4, sixthView.Top()); + VERIFY_ARE_EQUAL(TerminalViewHeight + 4, sixthView.BottomExclusive()); + VERIFY_ARE_EQUAL(TerminalHistoryLength - 4, term->_scrollOffset); + + Log::Comment(L"Print 8 more lines, and see that we're now just stuck at the" + L"top of the buffer"); + for (int i = 0; i < 8; i++) + { + termSm.ProcessString(L"x\n"); + Log::Comment(NoThrowString().Format( + L"_scrollOffset: %d", term->_scrollOffset)); + } + const auto seventhView = term->GetViewport(); + VERIFY_ARE_EQUAL(0, seventhView.Top()); + VERIFY_ARE_EQUAL(TerminalViewHeight, seventhView.BottomExclusive()); + VERIFY_ARE_EQUAL(TerminalHistoryLength, term->_scrollOffset); +} From c5d5500758c011f7378552a78589ae38fd807ee5 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Tue, 11 Aug 2020 13:08:03 -0700 Subject: [PATCH 17/22] tools: add Get-OSSConhostLog (#7250) This script takes a range of commits and generates a commit log with the git2git-excluded file changes filtered out. It also replaces GitHub issue numbers with GH-XXX so as to not confuse Git2Git or Azure DevOps. Community contributions are tagged with CC- so they can be detected later. The output looks like this: ``` Carlos Zamora (2) * Pass mouse button state into HandleMouse instead of asking win32 (GH-6765) Dustin L. Howett (6) * Disable MinimalCoreWin when OpenConsoleUniversalApp is false (GH-7203) James Holderness (1) * Add support for the "doubly underlined" graphic rendition attribute (CC-7223) ``` Yes, the numbers are wrong. No, it doesn't really matter. --- .github/actions/spell-check/expect/expect.txt | 11 +++- tools/Get-OSSConhostLog.ps1 | 65 +++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 tools/Get-OSSConhostLog.ps1 diff --git a/.github/actions/spell-check/expect/expect.txt b/.github/actions/spell-check/expect/expect.txt index 5a74915444a..9379acedf80 100644 --- a/.github/actions/spell-check/expect/expect.txt +++ b/.github/actions/spell-check/expect/expect.txt @@ -352,6 +352,7 @@ conserv consoleapi CONSOLECONTROL CONSOLEENDTASK +consolegit CONSOLEIME consoleinternal Consoleroot @@ -422,6 +423,7 @@ cstdlib cstr cstring cstyle +CSV CSwitch CText ctime @@ -886,6 +888,7 @@ getwriter Gfun gfx gh +gitfilters github gitlab gle @@ -1056,6 +1059,8 @@ IInteract IInteractivity IIo IList +imagemagick +Imatch ime Imm IMouse @@ -1072,7 +1077,6 @@ INITCOMMONCONTROLSEX INITDIALOG initguid INITMENU -imagemagick inkscape inl INLINEPREFIX @@ -1520,8 +1524,8 @@ nothrow NOTICKS NOTIMPL notin -NOTOPMOST NOTNULL +NOTOPMOST NOTRACK NOTSUPPORTED notypeopt @@ -1610,8 +1614,8 @@ OSCBG OSCCT OSCFG OSCRCC -OSCSCC OSCSCB +OSCSCC OSCWT OSDEPENDSROOT osfhandle @@ -2337,6 +2341,7 @@ Toolset tooltip TOPDOWNDIB TOPLEFT +toplevel TOPRIGHT TOpt tosign diff --git a/tools/Get-OSSConhostLog.ps1 b/tools/Get-OSSConhostLog.ps1 new file mode 100644 index 00000000000..4c206effa8e --- /dev/null +++ b/tools/Get-OSSConhostLog.ps1 @@ -0,0 +1,65 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +################################ +# This script takes a range of commits and generates +# a commit log with the git2git-excluded file changes +# filtered out. +# +# It also replaces GitHub issue numbers with GH-XXX so +# as to not confuse Git2Git or Azure DevOps. +# Community contributions are tagged with CC- so they +# can be detected later. + +[CmdletBinding()] +Param( + [string]$RevisionRange +) + +Function Test-MicrosoftPerson($email) { + Return $email -like "*@microsoft.com" +} + +# Replaces github PR numbers with GH-XXX or CC-XXX (community contribution) +# and issue numbers with GH-XXX +Function Mangle-CommitMessage($object) { + $Prefix = "GH-" + If (-Not (Test-MicrosoftPerson $object.Email)) { + $Prefix = "CC-" + } + + $s = $object.Subject -Replace "\(#(\d+)\)", "(${Prefix}`$1)" + $s = $s -Replace "#(\d+)","GH-`$1" + $s +} + +Function Get-Git2GitIgnoresAsExcludes() { + $filters = (Get-Content (Join-Path (& git rev-parse --show-toplevel) consolegit2gitfilters.json) | ConvertFrom-Json) + $excludes = $filters.ContainsFilters | ? { $_ -Ne "/." } | % { $_ -Replace "^/","" } + $excludes += $filters.SuffixFilters | % { "**/*$_"; "*$_" } + $excludes += $filters.PrefixFilters | % { "**/$_*"; "$_*" } + $excludes | % { ":(top,exclude)$_" } +} + +$Excludes = Get-Git2GitIgnoresAsExcludes +Write-Verbose "IGNORING: $Excludes" +$Entries = & git log $RevisionRange "--pretty=format:%an%x1C%ae%x1C%s" -- $Excludes | + ConvertFrom-CSV -Delimiter "`u{001C}" -Header Author,Email,Subject + +Write-Verbose ("{0} unfiltered log entries" -f $Entries.Count) + +$Grouped = $Entries | Group Email +$Grouped | % { + $e = $_.Group[0].Email + $p = $_.Group[0].Author + "$p ($($_.Group.Count))" + $_.Group | % { + If ($_.Subject -Imatch "^Merge") { + # Skip merge commits + Return + } + $cm = Mangle-CommitMessage $_ + "* $cm" + } + "" +} From fe82e97ff6e532e2bf367344657c7b510bb56dc6 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 11 Aug 2020 18:56:58 -0500 Subject: [PATCH 18/22] Enable partial rebuilds of the TerminalControl project again (#7248) This regressed around the #7163 timeframe. We're discussing this on chat currently. It might break the intellisense on the `#include ` line in VS 16.7, but we're not _really_ sure? Intellisense has been notoriously flaky for us. I'm running 16.6.5, and it works for me. @lhecker is running 16.7 and confirmed it worked there. If the CI build passes, then this definitely will work for 16.7. --- src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj b/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj index 42006cbda86..29c99c3eeae 100644 --- a/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj +++ b/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj @@ -8,6 +8,10 @@ StaticLibrary 10.0.17763.0 Microsoft.Terminal.TerminalControl + + + true + +[Command Palette Spec]: https://github.com/microsoft/terminal/blob/master/doc/specs/%232046%20-%20Command%20Palette.md +[New Tab Menu Customization Spec]: https://github.com/microsoft/terminal/blob/master/doc/specs/%231571%20-%20New%20Tab%20Menu%20Customization.md + +[#1571]: https://github.com/microsoft/terminal/issues/1571 +[#1912]: https://github.com/microsoft/terminal/issues/1912 +[#3337]: https://github.com/microsoft/terminal/issues/3337 +[#5025]: https://github.com/microsoft/terminal/issues/5025 +[#5524]: https://github.com/microsoft/terminal/issues/5524 +[#5633]: https://github.com/microsoft/terminal/issues/5633 +[#6532]: https://github.com/microsoft/terminal/issues/6532 +[#6899]: https://github.com/microsoft/terminal/issues/6899 diff --git a/doc/specs/#6899 - Action IDs/data-mockup-002.png b/doc/specs/#6899 - Action IDs/data-mockup-002.png new file mode 100644 index 0000000000000000000000000000000000000000..1a165d59fd5b5d0a7ffdaeaafe77f15be540329c GIT binary patch literal 106114 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 z zbbc?He=?)~*8MV#5E69gv!9c&It6zp{;Di3QY|ZX&7a`+7mRhvLj9L2gAy!C!UGyZUJ(-dm~jB4$jK=7rM(=%E&$TbZQiZ zEww`g6J3ebg|NxB7-NfsUYUwa>L(6AF(}s5Rh(=4nYtVkd|&~Q0Y#C7758o*OV3}&38@oz8~Lb zd)NBb`Ug7ZV2o>==YH&m%K#VvIE>YL041HLlzk|;E2eqkz?_~ivuM*Meao{LGNO_Y zDv<=uO*mKzohiLw_4K=kjW6UbqMIN-VvCD}e5?Ptuj87u=Q~mp;#|9Di$ylacd-J? z*QT|`^tha(0-yyHUQV;Ql8oR3Kqobv_@&Bz05k;p0V{4$V=P$%#XFPx2_flKBh_Xu zF#|p9kL#Z>6XE!zo=+Tfrs+_e;#|Xs#J=6~D*Ao@!)#gWD682I$)4+IbRHA4JSI)b zA&a=Au2Z2^8$wLTjjEYxMTg`s$X@xAp}%0|j=>6J9}Fl&!l`PlrdK?f1oN81hqGb+ ziz1*heDZNl1}B?R^OWrQ)#EK_75;t}S&g6SK~vay*ar zo>)Y4GFUzZR-B2P`qVIL(JXQ@k8CbeOp8{7WJZ1nx91bp?#02^;08}QdiB&2n@8S7Pt=g8Fhh<|bDe{|IwPf` zRyo-}+{Ip0{LUs$7*Jw%WxuM;@YORkBz%jVIW-7~83gIp(U%5Nm2i`Hc6*l+AWLH-0 z!rch3=6Zq!ba{S>g5J7oApyGVC0(p{AuWEk6EDlLn*s;#pC{<|w~qtl(Whr-oe4D} z5tAD*P%KH46|Ha*4M@U$&t?z2Ss$Jd@hL;OfS z!TOu3&>VDhBqwh~Nd%6v3k7Na(i_!vwgYK#zUTufrlr5_p$T@|4iQv`FtpCFYf2;< zL5Yy&c`Lrw$CbXXU;4Fm*b3SSW@SBfP6c0QeYoaBwPgOHSkH z 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 E2T5tfAOHXW literal 0 HcmV?d00001 diff --git a/doc/specs/#6899 - Action IDs/data-mockup-actions-and-ids-and-keys.png b/doc/specs/#6899 - Action IDs/data-mockup-actions-and-ids-and-keys.png new file mode 100644 index 0000000000000000000000000000000000000000..f1148daaf3ce440d7e71fa64f944fedae35f8f25 GIT binary patch literal 133455 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%0Dx3Jy=SSKPKp>P^( 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 literal 0 HcmV?d00001 From a34cfa4e78c46e1a964ede019c97448b44068928 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 12 Aug 2020 08:40:38 -0500 Subject: [PATCH 21/22] Mini-spec for New Tab Menu Customization (#5888) * This is a mini-spec for how I see this working * good bot * These were some typos * Addd a future consideration about the command palette and commands * Update spec to reflect discussion with Carlos * update spec to reflect investigations in Command Palette Addenda 1 * add references to #6899, and minor bits of review feedback * add `remainingProfiles` as a way of adding all the user's other profiles quickly to the menu as well * clarify why we're not doing it in the profiles list * no two commits do not contain a misspelling of separate --- .../#1571 - New Tab Menu Customization.md | 300 ++++++++++++++++++ .../Menu-Customization-000.png | Bin 0 -> 46941 bytes 2 files changed, 300 insertions(+) create mode 100644 doc/specs/#1571 - New Tab Menu Customization/#1571 - New Tab Menu Customization.md create mode 100644 doc/specs/#1571 - New Tab Menu Customization/Menu-Customization-000.png diff --git a/doc/specs/#1571 - New Tab Menu Customization/#1571 - New Tab Menu Customization.md b/doc/specs/#1571 - New Tab Menu Customization/#1571 - New Tab Menu Customization.md new file mode 100644 index 00000000000..210db5499c0 --- /dev/null +++ b/doc/specs/#1571 - New Tab Menu Customization/#1571 - New Tab Menu Customization.md @@ -0,0 +1,300 @@ +--- +author: Mike Griese @zadjii-msft +created on: 2020-5-13 +last updated: 2020-08-04 +issue id: 1571 +--- + +# New Tab Menu Customization + +## Abstract + +Many users have lots and _lots_ of profiles that they use. Some of these +profiles the user might not use that frequently. When that happens, the new tab +dropdown can become quite cluttered. + +A common ask is for the ability to reorder and reorganize this dropdown. This +spec provides a design for how the user might be able to specify the +customization in their settings. + +## Inspiration + +Largely, this spec was inspired by discussion in +[#1571](https://github.com/microsoft/terminal/issues/1571#issuecomment-519504048) +and the _many_ linked threads. + +## Solution Design + +This design proposes adding a new setting `"newTabMenu"`. When unset, (the +default), the new tab menu is populated with all the profiles, in the order they +appear in the users settings file. When set, this enables the user to control +the appearance of the new tab dropdown. Let's take a look at an example: + +```json +{ + "profiles":{ ... }, + "newTabMenu": [ + { "type":"profile", "profile": "cmd" }, + { "type":"profile", "profile": "Windows PowerShell" }, + { "type":"separator" }, + { + "type":"folder", + "name": "ssh", + "icon": "C:\\path\\to\\icon.png", + "entries":[ + { "type":"profile", "profile": "Host 1" }, + { "type":"profile", "profile": "8.8.8.8" }, + { "type":"profile", "profile": "Host 2" } + ] + }, + { "type":"separator" }, + { "type":"profile", "profile": "Ubuntu-18.04" }, + { "type":"profile", "profile": "Fedora" } + ] +} +``` + +If a user were to use this as their new tab menu, that they would get is a menu +that looks like this: + +![fig 1](Menu-Customization-000.png) + +_fig 1_: A _very rough_ mockup of what this feature might look like + +There are five `type`s of objects in this menu: +* `"type":"profile"`: This is a profile. Clicking on this entry will open a new + tab, with that profile. The profile is identified with the `"profile"` + parameter, which accepts either a profile `name` or GUID. The icon for this + entry will be the profile's icon, and the text on the entry will be the + profile's name. +* `"type":"separator"`: This represents a XAML `MenuFlyoutSeparator`, enabling + the user to visually space out entries. +* `"type":"folder"`: This represents a nested menu of entries. + - The `"name"` property provides a string of text to display for the group. + - The `"icon"` property provides a path to a image to use as the icon. This + property is optional. + - The `"entries"` property specifies a list of menu entries that will appear + nested under this entry. This can contain other `"type":"folder"` groups as + well! +* `"type":"action"`: This represents a menu entry that should execute a specific + `ShortcutAction`. + - the `id` property will specify the global action ID (see [#6899], [#7175]) + to identify the action to perform when the user selects the entry. Actions + with invalid IDs will be ignored and omitted from the list. + - The text for this entry will be the action's label (which is + either provided as the `"name"` in the global list of actions, or the + generated name if no `name` was provided) + - The icon for this entry will similarly re-use the action's `icon`. +* `"type":"remainingProfiles"`: This is a special type of entry that will be + expanded to contain one `"type":"profile"` entry for every profile that was + not already listed in the menu. This will allow users to add one entry for + just "all the profiles they haven't manually added to the menu". + - This type of entry can only be specified once - trying to add it to the menu + twice will raise a warning, and ignore all but the first `remainingProfiles` + entry. + - This type of entry can also be set inside a `folder` entry, allowing users + to highlight only a couple profiles in the top-level of the menu, but + enabling all other profiles to also be accessible. + - The "name" of these entries will simply be the name of the profile + - The "icon" of these entries will simply be the profile's icon + +The "default" new tab menu could be imagined as the following blob of json: + +```json +{ + "newTabMenu": [ + { "type":"remainingProfiles" } + ] +} +``` + +### Other considerations + +Also considered during the investigation for this feature was re-using the list +of profiles to expose the structure of the new tab menu. For example, doing +something like: + +```json +"profiles": { + "defaults": {}, + "list": + [ + { "name": "cmd" }, + { "name": "powershell" }, + { "type": "separator" }, + { + "type": "folder" , + "profiles": [ + { "name": "ubuntu" } + ] + } + ] +} +``` + +This option was not pursued because we felt that it needlessly complicated the +contents of the list of profiles objects. We'd rather have the `profiles` list +exclusively contain `Profile` objects, and have other elements of the json +_refer_ to those profiles. What if someone would like to have an action that +opened a new tab with profile index 4, and then they set that action as entry 4 +in the profile's list? That would certainly be some sort of unexpected behavior. + +Additionally, what if someone wants to have an entry that opens a tab with one +pane with one profile in it, and another pane with different profile in it? Or +what if they want the same profile to appear twice in the menu? + +By overloading the structure of the `profiles` list, we're forcing all other +consumers of the list of profiles to care about the structure of the elements of +the list. These other consumers should only really care about the list of +profiles, and not necessarily how they're structured in the new tab dropdown. +Furthermore, it complicates the list of profiles, by adding actions intermixed +with the profiles. + +The design chosen in this spec more cleanly separates the responsibilities of +the list of profiles and the contents of the new tab menu. This way, each object +can be defined independent of the structure of the other. + +## UI/UX Design + +See the above _figure 1_. + +The profile's `icon` will also appear as the icon on `profile` entries. If +there's a keybinding bound to open a new tab with that profile, then that will +also be added to the `MenuFlyoutItem` as the accelerator text, similar to the +text we have nowadays. + +Beneath the list of profiles will _always_ be the same "Settings", "Feedback" +and "About" entries, separated by a `MenuFlyoutSeparator`. This is consistent +with the UI as it exists with no customization. These entries cannot be removed +with this feature, only the list of profiles customized. + +## Capabilities + +### Accessibility + +This menu will be added to the XAML tree in the same fashion as the current new +tab flyout, so there should be no dramatic change here. + +### Security + +_(no change expected)_ + +### Reliability + +_(no change expected)_ + +### Compatibility + +_(no change expected)_ + +### Performance, Power, and Efficiency + +_(no change expected)_ + +## Potential Issues + +Currently, the `openTab` and `splitPane` keybindings will accept a `index` +parameter to say either: +* "Create a new tab/pane with the N'th profile" +* "Create a new tab/pane with the profile at index N in the new +tab dropdown". + +These two were previously synonymous, as the N'th profile was always the N'th in +the dropdown. However, with this change, we'll be changing the meaning of that +argument to mean explicitly the first option - "Open a tab/pane with the N'th +profile". + +A previous version of this spec considered changing the meaning of that +parameter to mean "open the entry at index N", the second option. However, in +[Command Palette, Addendum 1], we found that naming that command would become +unnecessarily complex. + +To cover that above scenario, we could consider adding an `index` parameter to +the `openNewTabDropdown` action. If specified, that would open either the N'th +action in the dropdown (ignoring separators), or open the dropdown with the n'th +item selected. + +The N'th entry in the menu won't always be a profile: it might be a folder with +more options, or it might be an action (that might not be opening a new tab/pane +at all). + +Given all the above scenarios, `openNewTabDropdown` with an `"index":N` +parameter will behave in the following ways. If the Nth top-level entry in the +new tab menu is a: +* `"type":"profile"`: perform the `newTab` or `splitPane` action with that profile. +* `"type":"folder"`: Focus the first element in the sub menu, so the user could + navigate it with the keyboard. +* `"type":"separator"`: Ignore these when counting top-level entries. +* `"type":"action"`: Perform the action. + +So for example: + +``` +New Tab Button ▽ +├─ Folder 1 +│ └─ Profile A +│ └─ Action B +├─ Separator +├─ Folder 2 +│ └─ Profile C +│ └─ Profile D +├─ Action E +└─ Profile F +``` + +And assuming the user has bound: +```json +{ + "bindings": + [ + { "command": { "action": "openNewTabDropdown", "index": 0 }, "keys": "ctrl+shift+1" }, + { "command": { "action": "openNewTabDropdown", "index": 1 }, "keys": "ctrl+shift+2" }, + { "command": { "action": "openNewTabDropdown", "index": 2 }, "keys": "ctrl+shift+3" }, + { "command": { "action": "openNewTabDropdown", "index": 3 }, "keys": "ctrl+shift+4" }, + ] +} +``` + +* ctrl+shift+1 focuses "Profile A", but the user needs to press + enter/space to creates a new tab/split +* ctrl+shift+2 focuses "Profile C", but the user needs to press + enter/space to creates a new tab/split +* ctrl+shift+3 performs Action E +* ctrl+shift+4 Creates a new tab/split with Profile F + +## Future considerations + +* The user could set a `"name"`/`"text"`, or `"icon"` property to these menu + items manually, to override the value from the profile or action. These + settings would be totally optional, but it's not unreasonable that someone + might want this. +* We may want to consider adding a default icon for all folders or actions in + the menu. For example, a folder (like 📁) for `folder` entries, or something + like ⚡ for actions. We'll leave these unset by default, and evaluate setting + these icons by default in the future. +* Something considered during review was a way to specify "All my WSL profiles". + Maybe the user wants to have all their profiles generated by the WSL Distro + Generator appear in a "WSL" folder. This would likely require a more elaborate + filtering syntax, to be able to select only profiles where a certain property + has a specific value. Consider the user who has multiple "SSH + me@\.com" profiles, and they want all their "SSH\*" profiles to + appear in an "SSH" folder. This feels out-of-scope for this spec. +* A similar structure could potentially also be used for customizing the context + menu within a control, or the context menu for the tab. (see [#3337]) + - In both of those cases, it might be important to somehow refer to the + context of the current tab or control in the json. Think for example about + "Close tab" or "Close other tabs" - currently, those work by _knowing_ which + tab the "action" is specified for, not by actually using a `closeTab` action. + In the future, they might need to be implemented as something like + - Close Tab: `{ "action": "closeTab", "index": "${selectedTab.index}" }` + - Close Other Tabs: `{ "action": "closeTabs", "otherThan": "${selectedTab.index}" }` + - Close Tabs to the Right: `{ "action": "closeTabs", "after": "${selectedTab.index}" }` + + + +[#2046]: https://github.com/microsoft/terminal/issues/2046 +[Command Palette, Addendum 1]: https://github.com/microsoft/terminal/blob/master/doc/specs/%232046%20-%20Unified%20keybindings%20and%20commands%2C%20and%20synthesized%20action%20names.md + +[#3337]: https://github.com/microsoft/terminal/issues/3337 +[#6899]: https://github.com/microsoft/terminal/issues/6899 +[#7175]: https://github.com/microsoft/terminal/issues/7175 diff --git a/doc/specs/#1571 - New Tab Menu Customization/Menu-Customization-000.png b/doc/specs/#1571 - New Tab Menu Customization/Menu-Customization-000.png new file mode 100644 index 0000000000000000000000000000000000000000..54ade166f34e15377326e2c0f18feeb7bb0ea8fb GIT binary patch literal 46941 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�%D&*n=DESo9x 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
j zWlD7+l=y5?XPpZCzQX`o6!DDrLPQ{2zt0iOh_J6j0FDSC)=;B6h&=wy{x)g^2Nr3c za)P&C_;|$m^s@F1Yve2wIcsrmN(Q|h}O8`$k$ zY=O%W(6i6@(OvfCxfPyK>9Oy*oli#(f<}v$6nuFKB#%?|2kKGNuKP6`8qTjHdtBb-^r8v|3pF@7mJ>=fPGC=t0U+Qg? z%8J2`OpFpq#|*yE*RG1+5xpF{@tqkx2a0%&1_9U?sl-l=yj{-wg6YJvk&4a52SXwB z%q_^vsosNfSeo-u$KHL)gjTx%v+>+8P9=U{e0e1cIwnGyBw2V&s|auUDCrdqJ>zm$v!4FGWWUPTxQ>g$?!l$^sFeLTm^Rw-XnA;qrhJr z>`@$ACnp702vVD2mXxny>fe~p4nFr&+N=d)Og9xINJfns<2TNe3zwSt^uSS3P$E|y zzXPZ+$5lKg=X9DN!_67t3pJo@?DniWgMTu$EAs>lNa|BOg19&zUM!9p#YbLkQk}uY zB@owW@8~fo@y_klKU)6L)iFGG&E6Av57)yG;Y_P5Z62wtv4j!d0l-WDpgwQ=_jF=1 zrAURzZN^-$TbA%E=-(OQ`L}Yn9y~Y_uCuJRfb<=2+fGIesL6ivWZ7==gZaO9hWC^&vklXMF~E$m#Aw=C*2gy*aiXC zAg7s!`bfXrKxl-m_;_k@E1K{~gt@lskI__0$}m9QrKzU7qXwktk+! zt5MJTu%+w7lOiEo>ti!;GlI!_43LDmj7*P~>G2oZ8psHPilOJn^WxCb*GD<)=ZH!S`94FzYm$AFfFSOe zY^$kEfv8+#7%r|Tk~}sX^k1a_)4qX|6JSx|ZnY45!M9lj730gL?v$fy{3mtR?kBvZ zjVdr0YBB%}*8bG@3(993t^wB5>&~TU#;i0;sB1F@gpyZAq{9MXL2B91Ddp|@@GBmC zid*;xNWhZ0qA|!>d589p(21K?4L|JLB_o78I^%adh(6w$GG|Nvso=TS_SK{8jDBTC zbZtqOecMml6+o~U*h4L!WT#yuGiG%9S=TDjF_a8KuG`0GP0E7EW!q!_f%kvAX%X1A z9zqL9R^CAGTXVE#c}SnI2^Mza?-qkYn6rO5^U7!(pcUY;HmNBB zBGvaQ^D1K<W0ofce3Sw)?dGI0f~47KDyXk!Jqu;W1#z3nT7!da66!3YHe!Z=(WR%g zDbegI@(Hl26zD2lJukuL)-eyqEj+6vW69Ey1fL;0Vi!ulK2GL;zk+hKbRfVgg-_Y< zPnkQ%R8g3R!x1siHt7FG%Aa`>1%N;;taUdczS{N<3x_AdmvVUIgnc}u!FjZ(6z7m4 zA-5XynD&e1Gsyx?iCiA8A_Bh{Dil%V5_szX&sfb?f>P-s4z$Sa?oM;uC1j!=!rNyS zv<6xgO%W(|na`e01`{7m3|$l2%aw}B6hLkBru+Pc-WRMXJmL02)jNzd7=xgTcr&{! zAqrr1P&7OmF_CzcCxTQfqEoV-{ITggN2;sSn^&SJLFUbjXsgJ8#)}-IWZbn0wBwM^ zU(<4`B96m9WCJ5X&L4>57ruBA7qYOUHXdUn<3JBs5D_KrQF?0mZ(>75gI+Wyj0ej; z|B!y>@)Q-A8; z(exd5YUWn@`0%gz|R}N$p-DYf+=e~o}$WQdh*seFVu%W(4LkD5S&>jo#6X?rYy^IpHm<@UJ zhnLFWqDe)CgA3E0<||!XMljv`IogNJV>@7+MPR+;Ph&$6$ItF!VfDOUR8fbw@Iw6l ztWz+jk3~+r79?XY1YA;wRaY-WW!D^1d=|7n-%CF2a7&C5R7-M?vRQ212meZhQlz=0 zB+OWMUnb9Hr)pCWrtH+<2!&;}?y_a};qIdf73^|Z$ir_{Cq+nM0$XcA8@hW|LFr-F z1MmwX0`6?^?d?41OcvNcW9pYFLS&-g8!`eTef>SmWY5T<$(P|P?`h2lQw>=EwtnRW zI>z57vT6ctf|O4$>hzW&ZZRsG)@X5)H{E(cNlYO`cG%J?KYJcDUE8IgjaqC4BZ0qeX;wj)gS2T}u>m zHVY!s`|)rgSe@G`(qS>GB) z$^3%-cyx8Ue`R%u5>km!>#s=(tUGe+%nv$oy4Z;o+o(BIsbdfhW}4g{y6OCjYPua( zC*iq-d8^E1Ki~xtQ881x0yTDh7LduoS;!;gOqjC7%pwao6%W2Q!Y-6%f*M$F=-m3x zEg8!*4)3wKdz{!6cGv!XMgd(Wezgr;e?>?bBP@}LTp-8FhxuRzG}ulP>6#WhQmSus zyu6G5)kK@aywJue|3;z zX0JaQe0FRCut)L%Jb>9K6>GWT&!G3fyv$*JLdgej|fyz1VzKkwy z0!nvBT>M>m+`VTDz^mv!Mkl5V+AhvjSWK2}!I zyICH*I(0y@)2qPnvAqGfElzb3_e3j$N*o_(6f#M;hHP_^J=T&rcUpmxjattv7Yy%a z%sdt+#n_H;O@S5%v#=Mkq0QP5RQT;dNuzu0bI`=jR2meARArzj#C!8R6A_uRfwa`% zs?EjP^#^UPoP+1jZVw)MQxW$2e`yTyaI4_lI#qh^>M^g8ZXt7xt_A!GxX2vD+%?-C!q8S`*Hl?3O_$7cVD}izEnUBP%Ap`RKDV~%bgp`vU8A=U zM^R-jCM6VJ-Aw3=9_|WC25*-&>3Yo%Tpj+j}{fu95(fvkatsG*2K81f8%7`DdBpld}8d= z`vp#;-P~IFD+qzFx$kA=>sEUQ?uqoiu-xrCZACHKurkufIF<;<*~*w`Lba#EuZOvl zPHw`WlIPwelAonud#%vo z+uKQ@n~CU5^IfO6bg+w^cU4RoHQTV=LgEV4c6;<;wlO`^>*4w|_rp?D)g~hsP{#7TuQp neH$Q)t~CAsf0E*{#slOl_zN9Fe$xdI@OMMk@UKE`o8bQf8WLro literal 0 HcmV?d00001 From a2721c104343575945320b0df0d4809fc4f0cdce Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Wed, 12 Aug 2020 15:46:53 +0200 Subject: [PATCH 22/22] Fixed #3799: Introduce sendInput command (#7249) ## Summary of the Pull Request This PR enables users to send arbitrary text input to the shell via a keybinding. ## PR Checklist * [x] Closes #3799 * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] 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 * [x] Schema updated. * [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3799 ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed Added the following keybindings: ```json { "keys": "p", "command": { "action": "sendInput", "input": "foobar" } }, { "keys": "q", "command": { "action": "sendInput", "input": "\u001b[A" } }, ``` Ensured that when pressing P "foobar" is echoed to the shell and when pressing Q the shell history is being navigated backwards. --- doc/cascadia/SettingsSchema.md | 1 + doc/cascadia/profiles.schema.json | 24 ++++++++++++++ src/cascadia/TerminalApp/ActionAndArgs.cpp | 5 +++ src/cascadia/TerminalApp/ActionArgs.cpp | 13 ++++++++ src/cascadia/TerminalApp/ActionArgs.h | 32 +++++++++++++++++++ src/cascadia/TerminalApp/ActionArgs.idl | 5 +++ .../TerminalApp/AppActionHandlers.cpp | 15 +++++++++ .../TerminalApp/DebugTapConnection.cpp | 26 ++------------- .../Resources/en-US/Resources.resw | 4 +++ .../TerminalApp/ShortcutActionDispatch.cpp | 6 ++++ .../TerminalApp/ShortcutActionDispatch.h | 1 + .../TerminalApp/ShortcutActionDispatch.idl | 2 ++ src/cascadia/TerminalApp/TerminalPage.cpp | 1 + src/cascadia/TerminalApp/TerminalPage.h | 1 + src/cascadia/TerminalApp/Utils.cpp | 25 +++++++++++++++ src/cascadia/TerminalApp/Utils.h | 7 ++++ .../TerminalApp/lib/TerminalAppLib.vcxproj | 1 + .../lib/TerminalAppLib.vcxproj.filters | 3 +- src/cascadia/TerminalControl/TermControl.cpp | 27 +++++++++++++--- src/cascadia/TerminalControl/TermControl.h | 4 ++- src/cascadia/TerminalControl/TermControl.idl | 1 + 21 files changed, 175 insertions(+), 29 deletions(-) create mode 100644 src/cascadia/TerminalApp/Utils.cpp diff --git a/doc/cascadia/SettingsSchema.md b/doc/cascadia/SettingsSchema.md index 9c58edc89f4..66e5cb67113 100644 --- a/doc/cascadia/SettingsSchema.md +++ b/doc/cascadia/SettingsSchema.md @@ -142,6 +142,7 @@ For commands with arguments: | `scrollUp` | Move the screen up. | | | | | `scrollUpPage` | Move the screen up a whole page. | | | | | `scrollDownPage` | Move the screen down a whole page. | | | | +| `sendInput` | Sends some text input to the shell. | `input` | string | The text input to feed into the shell.
ANSI escape sequences may be used. Escape codes like `\x1b` must be written as `\u001b`.
For instance the input `"text\n"` will write "text" followed by a newline. `"\u001b[D"` will behave as if the left arrow button had been pressed. | | `splitPane` | Halve the size of the active pane and open another. Without any arguments, this will open the default profile in the new pane. | 1. `split`*
2. `commandLine`
3. `startingDirectory`
4. `tabTitle`
5. `index`
6. `profile`
7. `splitMode` | 1. `vertical`, `horizontal`, `auto`
2. string
3. string
4. string
5. integer
6. string
7. string | 1. How the pane will split. `auto` will split in the direction that provides the most surface area.
2. Executable run within the pane.
3. Directory in which the pane will open.
4. Title of the tab when the new pane is focused.
5. Profile that will open based on its position in the dropdown (starting at 0).
6. Profile that will open based on its GUID or name.
7. Controls how the pane splits. Only accepts `duplicate` which will duplicate the focused pane's profile into a new pane. | | `switchToTab` | Open a specific tab depending on index. | `index`* | integer | Tab that will open based on its position in the tab bar (starting at 0). | | `toggleFullscreen` | Switch between fullscreen and default window sizes. | | | | diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index f1e1843bf96..e2253724a54 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -52,6 +52,7 @@ "scrollDownPage", "scrollUp", "scrollUpPage", + "sendInput", "splitPane", "switchToTab", "toggleFocusMode", @@ -230,6 +231,28 @@ ], "required": [ "direction" ] }, + "SendInputAction": { + "description": "Arguments corresponding to a Send Input Action", + "allOf": [ + { + "$ref": "#/definitions/ShortcutAction" + }, + { + "properties": { + "action": { + "type": "string", + "pattern": "sendInput" + }, + "input": { + "type": "string", + "default": "", + "description": "The text input to feed into the shell. ANSI escape sequences may be used. Escape codes like \\x1b must be written as \\u001b." + } + } + } + ], + "required": [ "input" ] + }, "SplitPaneAction": { "description": "Arguments corresponding to a Split Pane Action", "allOf": [ @@ -390,6 +413,7 @@ { "$ref": "#/definitions/SwitchToTabAction" }, { "$ref": "#/definitions/MoveFocusAction" }, { "$ref": "#/definitions/ResizePaneAction" }, + { "$ref": "#/definitions/SendInputAction" }, { "$ref": "#/definitions/SplitPaneAction" }, { "$ref": "#/definitions/OpenSettingsAction" }, { "$ref": "#/definitions/SetTabColorAction" }, diff --git a/src/cascadia/TerminalApp/ActionAndArgs.cpp b/src/cascadia/TerminalApp/ActionAndArgs.cpp index fadadac3b24..150a31c92ea 100644 --- a/src/cascadia/TerminalApp/ActionAndArgs.cpp +++ b/src/cascadia/TerminalApp/ActionAndArgs.cpp @@ -27,6 +27,7 @@ static constexpr std::string_view ScrolluppageKey{ "scrollUpPage" }; static constexpr std::string_view ScrolldownpageKey{ "scrollDownPage" }; static constexpr std::string_view SwitchToTabKey{ "switchToTab" }; static constexpr std::string_view OpenSettingsKey{ "openSettings" }; // TODO GH#2557: Add args for OpenSettings +static constexpr std::string_view SendInputKey{ "sendInput" }; static constexpr std::string_view SplitPaneKey{ "splitPane" }; static constexpr std::string_view TogglePaneZoomKey{ "togglePaneZoom" }; static constexpr std::string_view ResizePaneKey{ "resizePane" }; @@ -90,6 +91,7 @@ namespace winrt::TerminalApp::implementation { ToggleFocusModeKey, ShortcutAction::ToggleFocusMode }, { ToggleFullscreenKey, ShortcutAction::ToggleFullscreen }, { ToggleAlwaysOnTopKey, ShortcutAction::ToggleAlwaysOnTop }, + { SendInputKey, ShortcutAction::SendInput }, { SplitPaneKey, ShortcutAction::SplitPane }, { TogglePaneZoomKey, ShortcutAction::TogglePaneZoom }, { SetTabColorKey, ShortcutAction::SetTabColor }, @@ -125,6 +127,8 @@ namespace winrt::TerminalApp::implementation { ShortcutAction::AdjustFontSize, winrt::TerminalApp::implementation::AdjustFontSizeArgs::FromJson }, + { ShortcutAction::SendInput, winrt::TerminalApp::implementation::SendInputArgs::FromJson }, + { ShortcutAction::SplitPane, winrt::TerminalApp::implementation::SplitPaneArgs::FromJson }, { ShortcutAction::OpenSettings, winrt::TerminalApp::implementation::OpenSettingsArgs::FromJson }, @@ -284,6 +288,7 @@ namespace winrt::TerminalApp::implementation { ShortcutAction::ToggleFocusMode, RS_(L"ToggleFocusModeCommandKey") }, { ShortcutAction::ToggleFullscreen, RS_(L"ToggleFullscreenCommandKey") }, { ShortcutAction::ToggleAlwaysOnTop, RS_(L"ToggleAlwaysOnTopCommandKey") }, + { ShortcutAction::SendInput, L"" }, { ShortcutAction::SplitPane, RS_(L"SplitPaneCommandKey") }, { ShortcutAction::TogglePaneZoom, RS_(L"TogglePaneZoomCommandKey") }, { ShortcutAction::Invalid, L"" }, diff --git a/src/cascadia/TerminalApp/ActionArgs.cpp b/src/cascadia/TerminalApp/ActionArgs.cpp index d6e7219fd13..1bc3983481d 100644 --- a/src/cascadia/TerminalApp/ActionArgs.cpp +++ b/src/cascadia/TerminalApp/ActionArgs.cpp @@ -13,6 +13,7 @@ #include "ResizePaneArgs.g.cpp" #include "MoveFocusArgs.g.cpp" #include "AdjustFontSizeArgs.g.cpp" +#include "SendInputArgs.g.cpp" #include "SplitPaneArgs.g.cpp" #include "OpenSettingsArgs.g.cpp" #include "SetColorSchemeArgs.g.cpp" @@ -21,6 +22,8 @@ #include "ExecuteCommandlineArgs.g.cpp" #include "ToggleTabSwitcherArgs.g.h" +#include "Utils.h" + #include namespace winrt::TerminalApp::implementation @@ -167,6 +170,16 @@ namespace winrt::TerminalApp::implementation } } + winrt::hstring SendInputArgs::GenerateName() const + { + // The string will be similar to the following: + // * "Send Input: ...input..." + + auto escapedInput = VisualizeControlCodes(_Input); + auto name = fmt::format(std::wstring_view(RS_(L"SendInputCommandKey")), escapedInput); + return winrt::hstring{ name }; + } + winrt::hstring SplitPaneArgs::GenerateName() const { // The string will be similar to the following: diff --git a/src/cascadia/TerminalApp/ActionArgs.h b/src/cascadia/TerminalApp/ActionArgs.h index 7c768d58054..d52cc3f4494 100644 --- a/src/cascadia/TerminalApp/ActionArgs.h +++ b/src/cascadia/TerminalApp/ActionArgs.h @@ -13,6 +13,7 @@ #include "ResizePaneArgs.g.h" #include "MoveFocusArgs.g.h" #include "AdjustFontSizeArgs.g.h" +#include "SendInputArgs.g.h" #include "SplitPaneArgs.g.h" #include "OpenSettingsArgs.g.h" #include "SetColorSchemeArgs.g.h" @@ -270,6 +271,37 @@ namespace winrt::TerminalApp::implementation } }; + struct SendInputArgs : public SendInputArgsT + { + SendInputArgs() = default; + GETSET_PROPERTY(winrt::hstring, Input, L""); + + static constexpr std::string_view InputKey{ "input" }; + + public: + hstring GenerateName() const; + + bool Equals(const IActionArgs& other) + { + if (auto otherAsUs = other.try_as(); otherAsUs) + { + return otherAsUs->_Input == _Input; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + JsonUtils::GetValueForKey(json, InputKey, args->_Input); + if (args->_Input.empty()) + { + return { nullptr, { ::TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } }; + } + return { *args, {} }; + } + }; + struct SplitPaneArgs : public SplitPaneArgsT { SplitPaneArgs() = default; diff --git a/src/cascadia/TerminalApp/ActionArgs.idl b/src/cascadia/TerminalApp/ActionArgs.idl index a460d712a92..ee50771eb94 100644 --- a/src/cascadia/TerminalApp/ActionArgs.idl +++ b/src/cascadia/TerminalApp/ActionArgs.idl @@ -94,6 +94,11 @@ namespace TerminalApp Int32 Delta { get; }; }; + [default_interface] runtimeclass SendInputArgs : IActionArgs + { + String Input { get; }; + }; + [default_interface] runtimeclass SplitPaneArgs : IActionArgs { SplitState SplitStyle { get; }; diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 19a8c44f2ad..80a06e733de 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -89,6 +89,21 @@ namespace winrt::TerminalApp::implementation args.Handled(true); } + void TerminalPage::_HandleSendInput(const IInspectable& /*sender*/, + const TerminalApp::ActionEventArgs& args) + { + if (args == nullptr) + { + args.Handled(false); + } + else if (const auto& realArgs = args.ActionArgs().try_as()) + { + const auto termControl = _GetActiveControl(); + termControl.SendInput(realArgs.Input()); + args.Handled(true); + } + } + void TerminalPage::_HandleSplitPane(const IInspectable& /*sender*/, const TerminalApp::ActionEventArgs& args) { diff --git a/src/cascadia/TerminalApp/DebugTapConnection.cpp b/src/cascadia/TerminalApp/DebugTapConnection.cpp index 21994920ecd..d149ad46213 100644 --- a/src/cascadia/TerminalApp/DebugTapConnection.cpp +++ b/src/cascadia/TerminalApp/DebugTapConnection.cpp @@ -3,6 +3,7 @@ #include "pch.h" #include "DebugTapConnection.h" +#include "Utils.h" using namespace ::winrt::Microsoft::Terminal::TerminalConnection; using namespace ::winrt::Windows::Foundation; @@ -91,36 +92,15 @@ namespace winrt::Microsoft::TerminalApp::implementation return ConnectionState::Failed; } - static std::wstring _sanitizeString(const std::wstring_view str) - { - std::wstring newString{ str.begin(), str.end() }; - for (auto& ch : newString) - { - if (ch < 0x20) - { - ch += 0x2400; - } - else if (ch == 0x20) - { - ch = 0x2423; // replace space with ␣ - } - else if (ch == 0x7f) - { - ch = 0x2421; // replace del with ␡ - } - } - return newString; - } - void DebugTapConnection::_OutputHandler(const hstring str) { - _TerminalOutputHandlers(_sanitizeString(str)); + _TerminalOutputHandlers(VisualizeControlCodes(str)); } // Called by the DebugInputTapConnection to print user input void DebugTapConnection::_PrintInput(const hstring& str) { - auto clean{ _sanitizeString(str) }; + auto clean{ VisualizeControlCodes(str) }; auto formatted{ wil::str_printf(L"\x1b[91m%ls\x1b[m", clean.data()) }; _TerminalOutputHandlers(formatted); } diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index c891d53df6a..c8951fac9f2 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -449,6 +449,10 @@ New tab + + Send Input: "{0}" + {0} will be replaced with a string of input as defined by the user + Split pane diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index e8b9eb778c4..20a43791c2d 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -113,6 +113,12 @@ namespace winrt::TerminalApp::implementation break; } + case ShortcutAction::SendInput: + { + _SendInputHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::SplitVertical: case ShortcutAction::SplitHorizontal: case ShortcutAction::SplitPane: diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.h b/src/cascadia/TerminalApp/ShortcutActionDispatch.h index fa139848e63..9da3aadcdf2 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.h +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.h @@ -35,6 +35,7 @@ namespace winrt::TerminalApp::implementation TYPED_EVENT(SwitchToTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(NextTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(PrevTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(SendInput, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(SplitPane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(TogglePaneZoom, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(AdjustFontSize, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl index b0341d4bf81..e13c0433565 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl @@ -20,6 +20,7 @@ namespace TerminalApp PrevTab, SplitVertical, SplitHorizontal, + SendInput, SplitPane, TogglePaneZoom, SwitchToTab, @@ -71,6 +72,7 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler SwitchToTab; event Windows.Foundation.TypedEventHandler NextTab; event Windows.Foundation.TypedEventHandler PrevTab; + event Windows.Foundation.TypedEventHandler SendInput; event Windows.Foundation.TypedEventHandler SplitPane; event Windows.Foundation.TypedEventHandler TogglePaneZoom; event Windows.Foundation.TypedEventHandler AdjustFontSize; diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 3838e4ccf50..22547b2e005 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -889,6 +889,7 @@ namespace winrt::TerminalApp::implementation _actionDispatch->ScrollDown({ this, &TerminalPage::_HandleScrollDown }); _actionDispatch->NextTab({ this, &TerminalPage::_HandleNextTab }); _actionDispatch->PrevTab({ this, &TerminalPage::_HandlePrevTab }); + _actionDispatch->SendInput({ this, &TerminalPage::_HandleSendInput }); _actionDispatch->SplitPane({ this, &TerminalPage::_HandleSplitPane }); _actionDispatch->TogglePaneZoom({ this, &TerminalPage::_HandleTogglePaneZoom }); _actionDispatch->ScrollUpPage({ this, &TerminalPage::_HandleScrollUpPage }); diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 984f1064245..d89f96ca931 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -203,6 +203,7 @@ namespace winrt::TerminalApp::implementation void _HandleScrollDown(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleNextTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandlePrevTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); + void _HandleSendInput(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleSplitPane(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleTogglePaneZoom(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleScrollUpPage(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); diff --git a/src/cascadia/TerminalApp/Utils.cpp b/src/cascadia/TerminalApp/Utils.cpp new file mode 100644 index 00000000000..46f07b9bd93 --- /dev/null +++ b/src/cascadia/TerminalApp/Utils.cpp @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation +// Licensed under the MIT license. + +#include "pch.h" +#include "Utils.h" + +std::wstring VisualizeControlCodes(std::wstring str) noexcept +{ + for (auto& ch : str) + { + if (ch < 0x20) + { + ch += 0x2400; + } + else if (ch == 0x20) + { + ch = 0x2423; // replace space with ␣ + } + else if (ch == 0x7f) + { + ch = 0x2421; // replace del with ␡ + } + } + return str; +} diff --git a/src/cascadia/TerminalApp/Utils.h b/src/cascadia/TerminalApp/Utils.h index cb23bac450d..91915804139 100644 --- a/src/cascadia/TerminalApp/Utils.h +++ b/src/cascadia/TerminalApp/Utils.h @@ -115,3 +115,10 @@ TIconSource GetColoredIcon(const winrt::hstring& path) return nullptr; } + +std::wstring VisualizeControlCodes(std::wstring str) noexcept; + +inline std::wstring VisualizeControlCodes(std::wstring_view str) noexcept +{ + return VisualizeControlCodes(std::wstring{ str }); +} diff --git a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj b/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj index f3c98e58e4e..aecf0ef0847 100644 --- a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj +++ b/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj @@ -189,6 +189,7 @@ + ../TerminalSettings.idl diff --git a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters b/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters index fea379bc66c..9a80a146c43 100644 --- a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters +++ b/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters @@ -59,6 +59,7 @@ + settings @@ -202,4 +203,4 @@ app - \ No newline at end of file + diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 245413fe75c..058e478bc72 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -104,8 +104,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation }; _connectionOutputEventToken = _connection.TerminalOutput(onReceiveOutputFn); - auto inputFn = std::bind(&TermControl::_SendInputToConnection, this, std::placeholders::_1); - _terminal->SetWriteInputCallback(inputFn); + _terminal->SetWriteInputCallback([this](std::wstring& wstr) { + _SendInputToConnection(wstr); + }); _terminal->UpdateSettings(settings); @@ -296,6 +297,18 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } } } + + // Method Description: + // - Writes the given sequence as input to the active terminal connection, + // Arguments: + // - wstr: the string of characters to write to the terminal connection. + // Return Value: + // - + void TermControl::SendInput(const winrt::hstring& wstr) + { + _SendInputToConnection(wstr); + } + void TermControl::ToggleRetroEffect() { auto lock = _terminal->LockForWriting(); @@ -1764,12 +1777,18 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation } // Method Description: - // - Writes the given sequence as input to the active terminal connection, + // - Writes the given sequence as input to the active terminal connection. + // - This method has been overloaded to allow zero-copy winrt::param::hstring optimizations. // Arguments: // - wstr: the string of characters to write to the terminal connection. // Return Value: // - - void TermControl::_SendInputToConnection(const std::wstring& wstr) + void TermControl::_SendInputToConnection(const winrt::hstring& wstr) + { + _connection.WriteInput(wstr); + } + + void TermControl::_SendInputToConnection(std::wstring_view wstr) { _connection.WriteInput(wstr); } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index a3f26712962..b34ea7b813c 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -81,6 +81,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void AdjustFontSize(int fontSizeDelta); void ResetFontSize(); + void SendInput(const winrt::hstring& input); void ToggleRetroEffect(); winrt::fire_and_forget RenderEngineSwapChainChanged(); @@ -221,7 +222,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation void _CursorTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e); void _SetEndSelectionPointAtCursor(Windows::Foundation::Point const& cursorPosition); - void _SendInputToConnection(const std::wstring& wstr); + void _SendInputToConnection(const winrt::hstring& wstr); + void _SendInputToConnection(std::wstring_view wstr); void _SendPastedTextToConnection(const std::wstring& wstr); void _SwapChainSizeChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e); void _SwapChainScaleChanged(Windows::UI::Xaml::Controls::SwapChainPanel const& sender, Windows::Foundation::IInspectable const& args); diff --git a/src/cascadia/TerminalControl/TermControl.idl b/src/cascadia/TerminalControl/TermControl.idl index 85b6e602cfd..4e3eefa0c44 100644 --- a/src/cascadia/TerminalControl/TermControl.idl +++ b/src/cascadia/TerminalControl/TermControl.idl @@ -71,6 +71,7 @@ namespace Microsoft.Terminal.TerminalControl void AdjustFontSize(Int32 fontSizeDelta); void ResetFontSize(); + void SendInput(String input); void ToggleRetroEffect(); Windows.Foundation.IReference TabColor { get; };