Skip to content

Commit

Permalink
merge from master
Browse files Browse the repository at this point in the history
  • Loading branch information
leonMSFT committed Oct 21, 2020
2 parents b0b5fc1 + 895ac06 commit f5e9d95
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 71 deletions.
2 changes: 2 additions & 0 deletions .github/actions/spell-check/dictionary/names.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ mbadolato
Mehrain
mgravell
michaelniksa
michkap
migrie
mikegr
mikemaccana
miloush
miniksa
niksa
oising
Expand Down
8 changes: 8 additions & 0 deletions src/cascadia/TerminalApp/AppActionHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,14 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_HandleOpenTabSearch(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
// Tab search is always in-order.
auto tabCommands = winrt::single_threaded_vector<Command>();
for (const auto& tab : _tabs)
{
tabCommands.Append(tab.SwitchToTabCommand());
}
CommandPalette().SetTabActions(tabCommands);

auto opt = _GetFocusedTabIndex();
uint32_t startIdx = opt.value_or(0);

Expand Down
45 changes: 6 additions & 39 deletions src/cascadia/TerminalApp/CommandPalette.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,12 @@ namespace winrt::TerminalApp::implementation
_updateFilteredActions();
}

void CommandPalette::SetTabActions(Collections::IVector<Command> const& tabs)
{
_allTabActions = tabs;
_updateFilteredActions();
}

void CommandPalette::EnableCommandPaletteMode()
{
_switchToMode(CommandPaletteMode::ActionMode);
Expand Down Expand Up @@ -976,45 +982,6 @@ namespace winrt::TerminalApp::implementation
_currentNestedCommands.Clear();
}

// 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:
// - <none>
void CommandPalette::OnTabsChanged(const IInspectable& s, const IVectorChangedEventArgs& e)
{
if (auto tabList = s.try_as<IObservableVector<TerminalApp::ITab>>())
{
auto idx = e.Index();
auto changedEvent = e.CollectionChange();

switch (changedEvent)
{
case CollectionChange::ItemChanged:
{
break;
}
case CollectionChange::ItemInserted:
{
auto tab = tabList.GetAt(idx);
_allTabActions.InsertAt(idx, tab.SwitchToTabCommand());
break;
}
case CollectionChange::ItemRemoved:
{
_allTabActions.RemoveAt(idx);
break;
}
}

_updateFilteredActions();
}
}

void CommandPalette::EnableTabSwitcherMode(const bool searchMode, const uint32_t startIdx)
{
_switcherStartIdx = startIdx;
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/TerminalApp/CommandPalette.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace winrt::TerminalApp::implementation
Windows::Foundation::Collections::IObservableVector<Microsoft::Terminal::Settings::Model::Command> FilteredActions();

void SetCommands(Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::Command> const& actions);
void SetTabActions(Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::Command> const& tabs);
void SetKeyBindings(Microsoft::Terminal::TerminalControl::IKeyBindings bindings);

void EnableCommandPaletteMode();
Expand All @@ -35,7 +36,6 @@ namespace winrt::TerminalApp::implementation

// Tab Switcher
void EnableTabSwitcherMode(const bool searchMode, 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);
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/TerminalApp/CommandPalette.idl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace TerminalApp
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Model.Command> FilteredActions { get; };

void SetCommands(Windows.Foundation.Collections.IVector<Microsoft.Terminal.Settings.Model.Command> actions);
void SetTabActions(Windows.Foundation.Collections.IVector<Microsoft.Terminal.Settings.Model.Command> tabs);
void SetKeyBindings(Microsoft.Terminal.TerminalControl.IKeyBindings bindings);
void EnableCommandPaletteMode();

Expand All @@ -27,6 +28,5 @@ namespace TerminalApp
void SetDispatch(ShortcutActionDispatch dispatch);

void EnableTabSwitcherMode(Boolean searchMode, UInt32 startIdx);
void OnTabsChanged(IInspectable s, Windows.Foundation.Collections.IVectorChangedEventArgs e);
}
}
79 changes: 53 additions & 26 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ namespace winrt::TerminalApp::implementation
{
TerminalPage::TerminalPage() :
_tabs{ winrt::single_threaded_observable_vector<TerminalApp::ITab>() },
_mruTabActions{ winrt::single_threaded_vector<Command>() },
_startupActions{ winrt::single_threaded_vector<ActionAndArgs>() }
{
InitializeComponent();
Expand Down Expand Up @@ -224,13 +225,6 @@ namespace winrt::TerminalApp::implementation
}
});

_tabs.VectorChanged([weakThis{ get_weak() }](auto&& s, auto&& e) {
if (auto page{ weakThis.get() })
{
page->CommandPalette().OnTabsChanged(s, e);
}
});

// Settings AllowDependentAnimations will affect whether animations are
// enabled application-wide, so we don't need to check it each time we
// want to create an animation.
Expand Down Expand Up @@ -674,6 +668,7 @@ namespace winrt::TerminalApp::implementation

// Add the new tab to the list of our tabs.
_tabs.Append(*newTabImpl);
_mruTabActions.Append(newTabImpl->SwitchToTabCommand());

newTabImpl->SetDispatch(*_actionDispatch);

Expand Down Expand Up @@ -1042,6 +1037,13 @@ namespace winrt::TerminalApp::implementation
auto tab{ _tabs.GetAt(tabIndex) };
tab.Shutdown();

uint32_t mruIndex;
if (_mruTabActions.IndexOf(_tabs.GetAt(tabIndex).SwitchToTabCommand(), mruIndex))
{
_mruTabActions.RemoveAt(mruIndex);
CommandPalette().SetTabActions(_mruTabActions);
}

_tabs.RemoveAt(tabIndex);
_tabView.TabItems().RemoveAt(tabIndex);
_UpdateTabIndices();
Expand Down Expand Up @@ -1170,29 +1172,34 @@ namespace winrt::TerminalApp::implementation
// - Sets focus to the tab to the right or left the currently selected tab.
void TerminalPage::_SelectNextTab(const bool bMoveRight)
{
if (auto index{ _GetFocusedTabIndex() })
if (_settings.GlobalSettings().UseTabSwitcher())
{
uint32_t tabCount = _tabs.Size();
// Wraparound math. By adding tabCount and then calculating modulo tabCount,
// we clamp the values to the range [0, tabCount) while still supporting moving
// leftward from 0 to tabCount - 1.
const auto newTabIndex = ((tabCount + *index + (bMoveRight ? 1 : -1)) % tabCount);
CommandPalette().SetTabActions(_mruTabActions);

if (_settings.GlobalSettings().UseTabSwitcher())
{
if (CommandPalette().Visibility() == Visibility::Visible)
{
CommandPalette().SelectNextItem(bMoveRight);
}
// Since ATS is always MRU, our focused tab index is always 0.
// So, going next should go to index 1, and going prev should wrap to the end.
uint32_t tabCount = _mruTabActions.Size();
auto newTabIndex = ((tabCount + (bMoveRight ? 1 : -1)) % tabCount);

CommandPalette().EnableTabSwitcherMode(false, newTabIndex);
CommandPalette().Visibility(Visibility::Visible);
if (CommandPalette().Visibility() == Visibility::Visible)
{
CommandPalette().SelectNextItem(bMoveRight);
}
else
{
_SelectTab(newTabIndex);
CommandPalette().EnableTabSwitcherMode(false, newTabIndex);
CommandPalette().Visibility(Visibility::Visible);
}
}
else if (auto index{ _GetFocusedTabIndex() })
{
uint32_t tabCount = _tabs.Size();
// Wraparound math. By adding tabCount and then calculating modulo tabCount,
// we clamp the values to the range [0, tabCount) while still supporting moving
// leftward from 0 to tabCount - 1.
auto newTabIndex = ((tabCount + *index + (bMoveRight ? 1 : -1)) % tabCount);
_SelectTab(newTabIndex);
}
}

// Method Description:
Expand Down Expand Up @@ -1927,10 +1934,6 @@ namespace winrt::TerminalApp::implementation
_rearrangeTo = eventArgs.Index();
}
}
else
{
_UpdateCommandsForPalette();
}

_UpdateTabView();
}
Expand Down Expand Up @@ -1983,6 +1986,7 @@ namespace winrt::TerminalApp::implementation
if (CommandPalette().Visibility() != Visibility::Visible)
{
tab.Focus(FocusState::Programmatic);
_UpdateMRUTab(index);
}

// Raise an event that our title changed
Expand Down Expand Up @@ -2501,6 +2505,7 @@ namespace winrt::TerminalApp::implementation
if (auto index{ _GetFocusedTabIndex() })
{
_tabs.GetAt(*index).Focus(FocusState::Programmatic);
_UpdateMRUTab(index.value());
}
}

Expand Down Expand Up @@ -2560,6 +2565,7 @@ namespace winrt::TerminalApp::implementation

// Add the new tab to the list of our tabs.
_tabs.Append(*newTabImpl);
_mruTabActions.Append(newTabImpl->SwitchToTabCommand());

// Don't capture a strong ref to the tab. If the tab is removed as this
// is called, we don't really care anymore about handling the event.
Expand Down Expand Up @@ -2656,6 +2662,27 @@ namespace winrt::TerminalApp::implementation
tab.SwitchToTabCommand(command);
}

// Method Description:
// - Bumps the tab in its in-order index up to the top of the mru list.
// Arguments:
// - index: the in-order index of the tab to bump.
// Return Value:
// - <none>
void TerminalPage::_UpdateMRUTab(const uint32_t index)
{
uint32_t mruIndex;
auto command = _tabs.GetAt(index).SwitchToTabCommand();
if (_mruTabActions.IndexOf(command, mruIndex))
{
if (mruIndex > 0)
{
_mruTabActions.RemoveAt(mruIndex);
_mruTabActions.InsertAt(0, command);
CommandPalette().SetTabActions(_mruTabActions);
}
}
}

// -------------------------------- 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.
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ namespace winrt::TerminalApp::implementation
Microsoft::Terminal::Settings::Model::CascadiaSettings _settings{ nullptr };

Windows::Foundation::Collections::IObservableVector<TerminalApp::ITab> _tabs;
Windows::Foundation::Collections::IVector<winrt::Microsoft::Terminal::Settings::Model::Command> _mruTabActions;
winrt::com_ptr<TerminalTab> _GetTerminalTabImpl(const ITab& tab) const;

void _UpdateTabIndices();

winrt::Microsoft::Terminal::Settings::Model::Command _switchToSettingsCommand{ nullptr };
Expand Down Expand Up @@ -211,6 +213,8 @@ namespace winrt::TerminalApp::implementation
void _ReapplyCompactTabSize();

void _MakeSwitchToTabCommand(const ITab& tab, const uint32_t index);
void _UpdateTabSwitcherCommands(const bool mru);
void _UpdateMRUTab(const uint32_t index);

#pragma region ActionHandlers
// These are all defined in AppActionHandlers.cpp
Expand Down
40 changes: 37 additions & 3 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// keybindings on the keyUp, then we'll still send the keydown to the
// connected terminal application, and something like ctrl+shift+T will
// emit a ^T to the pipe.
if (!modifiers.IsAltGrPressed() && keyDown && _TryHandleKeyBinding(vkey, modifiers))
if (!modifiers.IsAltGrPressed() && keyDown && _TryHandleKeyBinding(vkey, scanCode, modifiers))
{
e.Handled(true);
return;
Expand All @@ -917,21 +917,54 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// - Attempt to handle this key combination as a key binding
// Arguments:
// - vkey: The vkey of the key pressed.
// - scanCode: The scan code of the key pressed.
// - modifiers: The ControlKeyStates representing the modifier key states.
bool TermControl::_TryHandleKeyBinding(const WORD vkey, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const
bool TermControl::_TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const
{
auto bindings = _settings.KeyBindings();
if (!bindings)
{
return false;
}

return bindings.TryKeyChord({
auto success = bindings.TryKeyChord({
modifiers.IsCtrlPressed(),
modifiers.IsAltPressed(),
modifiers.IsShiftPressed(),
vkey,
});
if (!success)
{
return false;
}

// Let's assume the user has bound the dead key "^" to a sendInput command that sends "b".
// If the user presses the two keys "^a" it'll produce "bâ", despite us marking the key event as handled.
// The following is used to manually "consume" such dead keys and clear them from the keyboard state.
_ClearKeyboardState(vkey, scanCode);
return true;
}

// Method Description:
// - Discards currently pressed dead keys.
// Arguments:
// - vkey: The vkey of the key pressed.
// - scanCode: The scan code of the key pressed.
void TermControl::_ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept
{
std::array<BYTE, 256> keyState;
if (!GetKeyboardState(keyState.data()))
{
return;
}

// As described in "Sometimes you *want* to interfere with the keyboard's state buffer":
// http://archives.miloush.net/michkap/archive/2006/09/10/748775.html
// > "The key here is to keep trying to pass stuff to ToUnicode until -1 is not returned."
std::array<wchar_t, 16> buffer;
while (ToUnicodeEx(vkey, scanCode, keyState.data(), buffer.data(), gsl::narrow_cast<int>(buffer.size()), 0b1, nullptr) < 0)
{
}
}

// Method Description:
Expand All @@ -941,6 +974,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// - Makes the cursor briefly visible during typing.
// Arguments:
// - vkey: The vkey of the key pressed.
// - scanCode: The scan code of the key pressed.
// - states: The Microsoft::Terminal::Core::ControlKeyStates representing the modifier key states.
// - keyDown: If true, the key was pressed, otherwise the key was released.
bool TermControl::_TrySendKeyEvent(const WORD vkey,
Expand Down
3 changes: 2 additions & 1 deletion src/cascadia/TerminalControl/TermControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation

void _KeyHandler(Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e, const bool keyDown);
::Microsoft::Terminal::Core::ControlKeyStates _GetPressedModifierKeys() const;
bool _TryHandleKeyBinding(const WORD vkey, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const;
bool _TryHandleKeyBinding(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers) const;
void _ClearKeyboardState(const WORD vkey, const WORD scanCode) const noexcept;
bool _TrySendKeyEvent(const WORD vkey, const WORD scanCode, ::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown);
bool _TrySendMouseEvent(Windows::UI::Input::PointerPoint const& point);
bool _CanSendVTMouseInput();
Expand Down

0 comments on commit f5e9d95

Please sign in to comment.