Skip to content

Commit

Permalink
Advanced Tab Switcher (#6732)
Browse files Browse the repository at this point in the history
![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
  • Loading branch information
leonMSFT authored Aug 11, 2020
1 parent c03677b commit b07c1e4
Show file tree
Hide file tree
Showing 23 changed files with 644 additions and 86 deletions.
26 changes: 26 additions & 0 deletions doc/cascadia/profiles.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"wt",
"closeOtherTabs",
"closeTabsAfter",
"tabSwitcher",
"unbound"
],
"type": "string"
Expand All @@ -88,6 +89,14 @@
],
"type": "string"
},
"AnchorKey": {
"enum": [
"ctrl",
"alt",
"shift"
],
"type": "string"
},
"NewTerminalArgs": {
"properties": {
"commandline": {
Expand Down Expand Up @@ -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": {
Expand All @@ -372,6 +397,7 @@
{ "$ref": "#/definitions/WtAction" },
{ "$ref": "#/definitions/CloseOtherTabsAction" },
{ "$ref": "#/definitions/CloseTabsAfterAction" },
{ "$ref": "#/definitions/TabSwitcherAction" },
{ "type": "null" }
]
},
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalApp/ActionAndArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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" };

Expand Down Expand Up @@ -100,6 +101,7 @@ namespace winrt::TerminalApp::implementation
{ ToggleCommandPaletteKey, ShortcutAction::ToggleCommandPalette },
{ CloseOtherTabsKey, ShortcutAction::CloseOtherTabs },
{ CloseTabsAfterKey, ShortcutAction::CloseTabsAfter },
{ ToggleTabSwitcherKey, ShortcutAction::ToggleTabSwitcher },
};

using ParseResult = std::tuple<IActionArgs, std::vector<::TerminalApp::SettingsLoadWarnings>>;
Expand Down Expand Up @@ -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 },
};

Expand Down
19 changes: 19 additions & 0 deletions src/cascadia/TerminalApp/ActionArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "SetTabColorArgs.g.cpp"
#include "RenameTabArgs.g.cpp"
#include "ExecuteCommandlineArgs.g.cpp"
#include "ToggleTabSwitcherArgs.g.h"

#include <LibraryResources.h>

Expand Down Expand Up @@ -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");
}
}

}
28 changes: 28 additions & 0 deletions src/cascadia/TerminalApp/ActionArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -512,6 +513,33 @@ namespace winrt::TerminalApp::implementation
}
};

struct ToggleTabSwitcherArgs : public ToggleTabSwitcherArgsT<ToggleTabSwitcherArgs>
{
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<ToggleTabSwitcherArgs>();
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<ToggleTabSwitcherArgs>();
JsonUtils::GetValueForKey(json, AnchorJsonKey, args->_AnchorKey);
return { *args, {} };
}
};
}

namespace winrt::TerminalApp::factory_implementation
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/TerminalApp/ActionArgs.idl
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,9 @@ namespace TerminalApp
{
UInt32 Index { get; };
};

[default_interface] runtimeclass ToggleTabSwitcherArgs : IActionArgs
{
Windows.System.VirtualKey AnchorKey { get; };
};
}
26 changes: 26 additions & 0 deletions src/cascadia/TerminalApp/AppActionHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -414,6 +415,7 @@ namespace winrt::TerminalApp::implementation
actionArgs.Handled(true);
}
}

void TerminalPage::_HandleCloseTabsAfter(const IInspectable& /*sender*/,
const TerminalApp::ActionEventArgs& actionArgs)
{
Expand All @@ -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<TerminalApp::ToggleTabSwitcherArgs>())
{
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);
}
}
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/Command.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ namespace winrt::TerminalApp::implementation
static std::vector<::TerminalApp::SettingsLoadWarnings> LayerJson(std::unordered_map<winrt::hstring, winrt::TerminalApp::Command>& 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);
};
}

Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/Command.idl
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ namespace TerminalApp
String Name;
ActionAndArgs Action;
String KeyChordText;

Windows.UI.Xaml.Controls.IconSource IconSource;
}
}
Loading

0 comments on commit b07c1e4

Please sign in to comment.