Skip to content

Commit

Permalink
Adding auto-UI shortcuts to menu based on keymappings (#924)
Browse files Browse the repository at this point in the history
* Adding vsconfig file for VS2019 help to prompt for missing components requried.

* Adding a keybinding for launching the settings.  Suggested fix for #683

* Modified to comma per PR feedback

* Implements 791 for profile and settings shortcuts (most frequent and have shortcuts)

* Quick change for consistency (missed in first checkin due to using ENUM) on using 'Ctrl' instead of 'Control'

* Adding UI shortcut generation to new keybinding mappings.  Resolving #791

* Making a few changes on reviewer feedback for shortcut UI.

* Additional reviewer feedback on variable name change (not a member var)
  • Loading branch information
timheuer authored and zadjii-msft committed May 22, 2019
1 parent 83b1395 commit e9a3d16
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 0 deletions.
55 changes: 55 additions & 0 deletions src/cascadia/TerminalApp/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,26 @@ namespace winrt::TerminalApp::implementation
void App::_CreateNewTabFlyout()
{
auto newTabFlyout = Controls::MenuFlyout{};
auto keyBindings = _settings->GetKeybindings();

for (int profileIndex = 0; profileIndex < _settings->GetProfiles().size(); profileIndex++)
{
const auto& profile = _settings->GetProfiles()[profileIndex];
auto profileMenuItem = Controls::MenuFlyoutItem{};

// add the keyboard shortcuts for the first 9 profiles
if (profileIndex < 9)
{
// enum value for ShortcutAction::NewTabProfileX; 0==NewTabProfile0
auto profileKeyChord = keyBindings.GetKeyBinding(static_cast<ShortcutAction>(profileIndex + static_cast<int>(ShortcutAction::NewTabProfile0)));

// make sure we find one to display
if (profileKeyChord)
{
_SetAcceleratorForMenuItem(profileMenuItem, profileKeyChord);
}
}

auto profileName = profile.GetName();
winrt::hstring hName{ profileName };
profileMenuItem.Text(hName);
Expand Down Expand Up @@ -254,6 +269,12 @@ namespace winrt::TerminalApp::implementation
settingsItem.Click({ this, &App::_SettingsButtonOnClick });
newTabFlyout.Items().Append(settingsItem);

auto settingsKeyChord = keyBindings.GetKeyBinding(ShortcutAction::OpenSettings);
if (settingsKeyChord)
{
_SetAcceleratorForMenuItem(settingsItem, settingsKeyChord);
}

// Create the feedback button.
auto feedbackFlyout = Controls::MenuFlyoutItem{};
feedbackFlyout.Text(L"Feedback");
Expand Down Expand Up @@ -899,6 +920,40 @@ namespace winrt::TerminalApp::implementation
}
}


// Method Description:
// - Takes a MenuFlyoutItem and a corresponding KeyChord value and creates the accelerator for UI display.
// Takes into account a special case for an error condition for a comma
// Arguments:
// - MenuFlyoutItem that will be displayed, and a KeyChord to map an accelerator
void App::_SetAcceleratorForMenuItem(Windows::UI::Xaml::Controls::MenuFlyoutItem& menuItem, const winrt::Microsoft::Terminal::Settings::KeyChord& keyChord)
{
// work around https://github.com/microsoft/microsoft-ui-xaml/issues/708 in case of VK_OEM_COMMA
if (keyChord.Vkey() != VK_OEM_COMMA)
{
// use the XAML shortcut to give us the automatic capabilities
auto menuShortcut = Windows::UI::Xaml::Input::KeyboardAccelerator{};

// TODO: Modify this when https://github.com/microsoft/terminal/issues/877 is resolved
menuShortcut.Key(static_cast<Windows::System::VirtualKey>(keyChord.Vkey()));

// inspect the modifiers from the KeyChord and set the flags int he XAML value
auto modifiers = AppKeyBindings::ConvertVKModifiers(keyChord.Modifiers());

// add the modifiers to the shortcut
menuShortcut.Modifiers(modifiers);

// add to the menu
menuItem.KeyboardAccelerators().Append(menuShortcut);
}
else // we've got a comma, so need to just use the alternate method
{
// extract the modifier and key to a nice format
auto overrideString = AppKeyBindings::FormatOverrideShortcutText(keyChord.Modifiers());
menuItem.KeyboardAcceleratorTextOverride(overrideString + L" ,");
}
}

// -------------------------------- 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
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/App.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ namespace winrt::TerminalApp::implementation
std::vector<std::shared_ptr<Tab>> _tabs;

std::unique_ptr<::TerminalApp::CascadiaSettings> _settings;
std::unique_ptr<TerminalApp::AppKeyBindings> _keyBindings;

bool _loadedInitialSettings;

Expand Down Expand Up @@ -111,6 +112,7 @@ namespace winrt::TerminalApp::implementation
void _ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme);

static Windows::UI::Xaml::Controls::IconElement _GetIconFromProfile(const ::TerminalApp::Profile& profile);
static void _SetAcceleratorForMenuItem(Windows::UI::Xaml::Controls::MenuFlyoutItem& menuItem, const winrt::Microsoft::Terminal::Settings::KeyChord& keyChord);
};
}

Expand Down
62 changes: 62 additions & 0 deletions src/cascadia/TerminalApp/AppKeyBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ static const std::map<std::wstring_view, ShortcutAction> commandNames {
{ SWITCHTOTAB6_KEY, ShortcutAction::SwitchToTab6 },
{ SWITCHTOTAB7_KEY, ShortcutAction::SwitchToTab7 },
{ SWITCHTOTAB8_KEY, ShortcutAction::SwitchToTab8 },
{ OPENSETTINGS_KEY, ShortcutAction::OpenSettings },
};

namespace winrt::TerminalApp::implementation
Expand All @@ -92,6 +93,15 @@ namespace winrt::TerminalApp::implementation
_keyShortcuts[chord] = action;
}

Microsoft::Terminal::Settings::KeyChord AppKeyBindings::GetKeyBinding(TerminalApp::ShortcutAction const& action)
{
for (auto& kv : _keyShortcuts)
{
if (kv.second == action) return kv.first;
}
return { nullptr };
}

bool AppKeyBindings::TryKeyChord(const Settings::KeyChord& kc)
{
const auto keyIter = _keyShortcuts.find(kc);
Expand Down Expand Up @@ -344,4 +354,56 @@ namespace winrt::TerminalApp::implementation

return bindingsArray;
}

// Method Description:
// - 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 keyModifiers = Windows::System::VirtualKeyModifiers::None;

if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Ctrl))
{
keyModifiers |= Windows::System::VirtualKeyModifiers::Control;
}
if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Shift))
{
keyModifiers |= Windows::System::VirtualKeyModifiers::Shift;
}
if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Alt))
{
// note: Menu is the Alt VK_MENU
keyModifiers |= Windows::System::VirtualKeyModifiers::Menu;
}

return keyModifiers;
}

// Method Description:
// - Handles the special case of providing a text override for the UI shortcut due to VK_OEM_COMMA issue.
// Looks at the flags from the KeyChord modifiers and provides a concatenated string value of all
// in the same order that XAML would put them as well.
// Return Value:
// - a WinRT hstring representation of the key modifiers for the shortcut
//NOTE: This needs to be localized with https://github.com/microsoft/terminal/issues/794 if XAML framework issue not resolved before then
winrt::hstring AppKeyBindings::FormatOverrideShortcutText(Settings::KeyModifiers modifiers)
{
std::wstring buffer{ L"" };

if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Ctrl))
{
buffer += L"Ctrl+";
}
if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Shift))
{
buffer += L"Shift+";
}
if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Alt))
{
buffer += L"Alt+";
}

return winrt::hstring{ buffer };
}
}
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/AppKeyBindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,12 @@ namespace winrt::TerminalApp::implementation

static TerminalApp::AppKeyBindings FromJson(Windows::Data::Json::JsonArray const& json);
Windows::Data::Json::JsonArray ToJson();
static Windows::System::VirtualKeyModifiers ConvertVKModifiers(winrt::Microsoft::Terminal::Settings::KeyModifiers modifiers);
static winrt::hstring FormatOverrideShortcutText(winrt::Microsoft::Terminal::Settings::KeyModifiers modifiers);

bool TryKeyChord(winrt::Microsoft::Terminal::Settings::KeyChord const& kc);
void SetKeyBinding(TerminalApp::ShortcutAction const& action, winrt::Microsoft::Terminal::Settings::KeyChord const& chord);
Microsoft::Terminal::Settings::KeyChord GetKeyBinding(TerminalApp::ShortcutAction const& action);

DECLARE_EVENT(CopyText, _CopyTextHandlers, TerminalApp::CopyTextEventArgs);
DECLARE_EVENT(PasteText, _PasteTextHandlers, TerminalApp::PasteTextEventArgs);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/AppKeyBindings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ namespace TerminalApp
static AppKeyBindings FromJson(Windows.Data.Json.JsonArray json);

void SetKeyBinding(ShortcutAction action, Microsoft.Terminal.Settings.KeyChord chord);
Microsoft.Terminal.Settings.KeyChord GetKeyBinding(ShortcutAction action);

event CopyTextEventArgs CopyText;
event PasteTextEventArgs PasteText;
Expand Down

0 comments on commit e9a3d16

Please sign in to comment.