Allow overriding tab switcher mode on command level (#9507)

## Summary of the Pull Request

Currently, when the MRU is enabled we lose the keybinding allowing us to 
go forward/backward (aka right/left in LTR) in the tab view.

To fix that, this PR introduces "tabSwitcherMode" optional parameter to 
the prevTab / nextTab commands.
If it is not provided the global setting will be used.


So if you want to go to adjacent tabs, even if MRU is enabled on the
system level you can use:
```
{ "command": { "action": "prevTab", "tabSwitcherMode": "inOrder" }, "keys": "ctrl+f1"}
{ "command": { "action": "nextTab", "tabSwitcherMode": "inOrder" }, "keys": "ctrl+f2"}
```
or even
```
{"command": { "action": "prevTab", "tabSwitcherMode": "disabled" }, "keys": "ctrl+f1"}
{ "command": { "action": "nextTab", "tabSwitcherMode": "disabled" }, "keys": "ctrl+f2"}
```
if you don't want tab switcher to show up

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes https://github.com/microsoft/terminal/issues/9330
* [x] CLA signed. 
* [x] Tests added/passed
* [ ] Documentation updated - not yet. Waiting for approval.
* [x] Schema updated.
* [ ] I've discussed this with core contributors already.
This commit is contained in:
Don-Vito 2021-03-24 00:00:07 +02:00 committed by GitHub
parent da3f02a6e2
commit da24f7d939
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 177 additions and 23 deletions

View file

@ -231,6 +231,19 @@
},
"type": "object"
},
"SwitchToAdjacentTabArgs" : {
"oneOf": [
{ "type": "null" },
{
"enum": [
"mru",
"inOrder",
"disabled"
],
"type": "string"
}
]
},
"ShortcutAction": {
"properties": {
"action": {
@ -602,6 +615,38 @@
}
]
},
"PrevTabAction": {
"description": "Arguments corresponding to a Previous Tab Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type":"string", "pattern": "prevTab" },
"tabSwitcherMode": {
"$ref": "#/definitions/SwitchToAdjacentTabArgs",
"default": null,
"description": "Move to the previous tab using \"tabSwitcherMode\". If no mode is provided, use the one globally defined one."
}
}
}
]
},
"NextTabAction": {
"description": "Arguments corresponding to a Next Tab Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type":"string", "pattern": "nextTab" },
"tabSwitcherMode": {
"$ref": "#/definitions/SwitchToAdjacentTabArgs",
"default": null,
"description": "Move to the next tab using \"tabSwitcherMode\". If no mode is provided, use the one globally defined one."
}
}
}
]
},
"Keybinding": {
"additionalProperties": false,
"properties": {
@ -628,6 +673,8 @@
{ "$ref": "#/definitions/MoveTabAction" },
{ "$ref": "#/definitions/FindMatchAction" },
{ "$ref": "#/definitions/NewWindowAction" },
{ "$ref": "#/definitions/NextTabAction" },
{ "$ref": "#/definitions/PrevTabAction" },
{ "type": "null" }
]
},

View file

@ -782,8 +782,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Switch to the next MRU tab, which is the fourth tab");
TestOnUIThread([&page]() {
ActionEventArgs eventArgs{};
page->_HandleNextTab(nullptr, eventArgs);
page->_SelectNextTab(true, nullptr);
});
Log::Comment(L"Sleep to let events propagate");
@ -804,8 +803,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Switch to the next MRU tab, which is the second tab");
TestOnUIThread([&page]() {
ActionEventArgs eventArgs{};
page->_HandleNextTab(nullptr, eventArgs);
page->_SelectNextTab(true, nullptr);
});
Log::Comment(L"Sleep to let events propagate");
@ -829,8 +827,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Switch to the next in-order tab, which is the third tab");
TestOnUIThread([&page]() {
ActionEventArgs eventArgs{};
page->_HandleNextTab(nullptr, eventArgs);
page->_SelectNextTab(true, nullptr);
});
TestOnUIThread([&page]() {
uint32_t focusedIndex = page->_GetFocusedTabIndex().value_or(-1);
@ -842,8 +839,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Switch to the next in-order tab, which is the fourth tab");
TestOnUIThread([&page]() {
ActionEventArgs eventArgs{};
page->_HandleNextTab(nullptr, eventArgs);
page->_SelectNextTab(true, nullptr);
});
TestOnUIThread([&page]() {
uint32_t focusedIndex = page->_GetFocusedTabIndex().value_or(-1);
@ -916,7 +912,7 @@ namespace TerminalAppLocalTests
Log::Comment(L"Switch to the next MRU tab, which is the third tab");
RunOnUIThread([&page]() {
page->_SelectNextTab(true);
page->_SelectNextTab(true, nullptr);
// In the course of a single tick, the Command Palette will:
// * open
// * select the proper tab from the mru's list

View file

@ -89,15 +89,23 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_HandleNextTab(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
_SelectNextTab(true);
args.Handled(true);
const auto& realArgs = args.ActionArgs().try_as<NextTabArgs>();
if (realArgs)
{
_SelectNextTab(true, realArgs.SwitcherMode());
args.Handled(true);
}
}
void TerminalPage::_HandlePrevTab(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
_SelectNextTab(false);
args.Handled(true);
const auto& realArgs = args.ActionArgs().try_as<PrevTabArgs>();
if (realArgs)
{
_SelectNextTab(false, realArgs.SwitcherMode());
args.Handled(true);
}
}
void TerminalPage::_HandleSendInput(const IInspectable& /*sender*/,

View file

@ -1527,10 +1527,10 @@ namespace winrt::TerminalApp::implementation
// Method Description:
// - Sets focus to the tab to the right or left the currently selected tab.
void TerminalPage::_SelectNextTab(const bool bMoveRight)
void TerminalPage::_SelectNextTab(const bool bMoveRight, const Windows::Foundation::IReference<Microsoft::Terminal::Settings::Model::TabSwitcherMode>& customTabSwitcherMode)
{
const auto index{ _GetFocusedTabIndex().value_or(0) };
const auto tabSwitchMode = _settings.GlobalSettings().TabSwitcherMode();
const auto tabSwitchMode = customTabSwitcherMode ? customTabSwitcherMode.Value() : _settings.GlobalSettings().TabSwitcherMode();
if (tabSwitchMode == TabSwitcherMode::Disabled)
{
uint32_t tabCount = _tabs.Size();

View file

@ -182,7 +182,7 @@ namespace winrt::TerminalApp::implementation
void _RegisterTerminalEvents(Microsoft::Terminal::Control::TermControl term, TerminalTab& hostingTab);
void _SelectNextTab(const bool bMoveRight);
void _SelectNextTab(const bool bMoveRight, const Windows::Foundation::IReference<Microsoft::Terminal::Settings::Model::TabSwitcherMode>& customTabSwitcherMode);
bool _SelectTab(const uint32_t tabIndex);
void _MoveFocus(const Microsoft::Terminal::Settings::Model::FocusDirection& direction);

View file

@ -151,6 +151,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{ ShortcutAction::ToggleCommandPalette, ToggleCommandPaletteArgs::FromJson },
{ ShortcutAction::FindMatch, FindMatchArgs::FromJson },
{ ShortcutAction::NewWindow, NewWindowArgs::FromJson },
{ ShortcutAction::PrevTab, PrevTabArgs::FromJson },
{ ShortcutAction::NextTab, NextTabArgs::FromJson },
{ ShortcutAction::Invalid, nullptr },
};

View file

@ -26,6 +26,8 @@
#include "FindMatchArgs.g.cpp"
#include "ToggleCommandPaletteArgs.g.cpp"
#include "NewWindowArgs.g.cpp"
#include "PrevTabArgs.g.cpp"
#include "NextTabArgs.g.cpp"
#include <LibraryResources.h>
@ -534,4 +536,26 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
fmt::format(L"{}, {}", RS_(L"NewWindowCommandKey"), newTerminalArgsStr)
};
}
winrt::hstring PrevTabArgs::GenerateName() const
{
if (!_SwitcherMode)
{
return RS_(L"PrevTabCommandKey");
}
const auto mode = _SwitcherMode.Value() == TabSwitcherMode::MostRecentlyUsed ? L"most recently used" : L"in order";
return winrt::hstring(fmt::format(L"{}, {}", RS_(L"PrevTabCommandKey"), mode));
}
winrt::hstring NextTabArgs::GenerateName() const
{
if (!_SwitcherMode)
{
return RS_(L"NextTabCommandKey");
}
const auto mode = _SwitcherMode.Value() == TabSwitcherMode::MostRecentlyUsed ? L"most recently used" : L"in order";
return winrt::hstring(fmt::format(L"{}, {}", RS_(L"NextTabCommandKey"), mode));
}
}

View file

@ -28,6 +28,8 @@
#include "ToggleCommandPaletteArgs.g.h"
#include "FindMatchArgs.g.h"
#include "NewWindowArgs.g.h"
#include "PrevTabArgs.g.h"
#include "NextTabArgs.g.h"
#include "../../cascadia/inc/cppwinrt_utils.h"
#include "JsonUtils.h"
@ -924,6 +926,71 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
}
};
struct PrevTabArgs : public PrevTabArgsT<PrevTabArgs>
{
PrevTabArgs() = default;
WINRT_PROPERTY(Windows::Foundation::IReference<TabSwitcherMode>, SwitcherMode, nullptr);
static constexpr std::string_view SwitcherModeKey{ "tabSwitcherMode" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<PrevTabArgs>();
if (otherAsUs)
{
return otherAsUs->_SwitcherMode == _SwitcherMode;
}
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<PrevTabArgs>();
JsonUtils::GetValueForKey(json, SwitcherModeKey, args->_SwitcherMode);
return { *args, {} };
}
IActionArgs Copy() const
{
auto copy{ winrt::make_self<PrevTabArgs>() };
copy->_SwitcherMode = _SwitcherMode;
return *copy;
}
};
struct NextTabArgs : public NextTabArgsT<NextTabArgs>
{
NextTabArgs() = default;
WINRT_PROPERTY(Windows::Foundation::IReference<TabSwitcherMode>, SwitcherMode, nullptr);
static constexpr std::string_view SwitcherModeKey{ "tabSwitcherMode" };
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& other)
{
auto otherAsUs = other.try_as<NextTabArgs>();
if (otherAsUs)
{
return otherAsUs->_SwitcherMode == _SwitcherMode;
}
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<NextTabArgs>();
JsonUtils::GetValueForKey(json, SwitcherModeKey, args->_SwitcherMode);
return { *args, {} };
}
IActionArgs Copy() const
{
auto copy{ winrt::make_self<NextTabArgs>() };
copy->_SwitcherMode = _SwitcherMode;
return *copy;
}
};
}
namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation

View file

@ -77,6 +77,13 @@ namespace Microsoft.Terminal.Settings.Model
CommandLine
};
enum TabSwitcherMode
{
MostRecentlyUsed,
InOrder,
Disabled,
};
[default_interface] runtimeclass NewTerminalArgs {
NewTerminalArgs();
NewTerminalArgs(Int32 profileIndex);
@ -226,4 +233,14 @@ namespace Microsoft.Terminal.Settings.Model
NewWindowArgs(NewTerminalArgs terminalArgs);
NewTerminalArgs TerminalArgs { get; };
};
[default_interface] runtimeclass PrevTabArgs : IActionArgs
{
Windows.Foundation.IReference<TabSwitcherMode> SwitcherMode;
};
[default_interface] runtimeclass NextTabArgs : IActionArgs
{
Windows.Foundation.IReference<TabSwitcherMode> SwitcherMode;
};
}

View file

@ -28,13 +28,6 @@ namespace Microsoft.Terminal.Settings.Model
MaximizedFocusMode,
};
enum TabSwitcherMode
{
MostRecentlyUsed,
InOrder,
Disabled,
};
enum WindowingMode
{
UseNew,