diff --git a/src/cascadia/TerminalSettingsEditor/Actions.cpp b/src/cascadia/TerminalSettingsEditor/Actions.cpp index 82c9288945..08c7835af3 100644 --- a/src/cascadia/TerminalSettingsEditor/Actions.cpp +++ b/src/cascadia/TerminalSettingsEditor/Actions.cpp @@ -7,7 +7,9 @@ #include "LibraryResources.h" #include "../TerminalSettingsModel/AllShortcutActions.h" +using namespace winrt::Windows::Foundation; using namespace winrt::Windows::UI::Xaml; +using namespace winrt::Windows::UI::Xaml::Controls; using namespace winrt::Windows::UI::Xaml::Navigation; namespace winrt::Microsoft::Terminal::Settings::Editor::implementation @@ -42,4 +44,65 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage)); } + + // Builds the "view all" flyout lazily on the first click of a + // row's "..." button, then caches it on the button so subsequent clicks + // just re-show it. + void Actions::ViewAllKeyChordsButton_Click(const IInspectable& sender, const RoutedEventArgs& /*e*/) + { + const auto button = sender.try_as + + + + @@ -208,7 +141,8 @@ + + + + + + + + - + + + - + + + - - - - - - - + - + - - - - - - - + - + - - - - - - - + - + - - - - - - - + - + - - - - - - - + - + - - - - - - - + - + - - - - - - - + - + - - - - - - - + - + - - - - - - - - - - - - - - - + + + + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/KeyChordVisual.cpp b/src/cascadia/TerminalSettingsEditor/KeyChordVisual.cpp new file mode 100644 index 0000000000..54bd0686bb --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/KeyChordVisual.cpp @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "KeyChordVisual.h" +#include "KeyChordVisual.g.cpp" + +using namespace winrt::Windows::UI::Xaml; +using namespace winrt::Windows::UI::Xaml::Controls; +using namespace winrt::Windows::Foundation; + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + DependencyProperty KeyChordVisual::_KeyChordProperty{ nullptr }; + + KeyChordVisual::KeyChordVisual() + { + InitializeComponent(); + _InitializeProperties(); + } + + void KeyChordVisual::_InitializeProperties() + { + if (!_KeyChordProperty) + { + _KeyChordProperty = + DependencyProperty::Register( + L"KeyChord", + xaml_typename(), + xaml_typename(), + PropertyMetadata{ nullptr, PropertyChangedCallback{ &KeyChordVisual::_OnKeyChordChanged } }); + } + } + + void KeyChordVisual::_OnKeyChordChanged(const DependencyObject& d, const DependencyPropertyChangedEventArgs& /*e*/) + { + if (const auto control{ d.try_as() }) + { + const auto controlImpl{ get_self(control) }; + controlImpl->_UpdateKeyVisuals(); + } + } + + // Capitalizes the first character of the provided string. + // Examples: "enter" -> "Enter", "f1" -> "F1", "v" -> "V" + static winrt::hstring _formatMainKeyName(std::wstring_view part) + { + if (part.empty()) + { + return {}; + } + + std::wstring buffer{ part }; + buffer[0] = til::toupper_ascii(buffer[0]); + return winrt::hstring{ buffer }; + } + + void KeyChordVisual::_UpdateKeyVisuals() + { + auto panel{ KeysPanel() }; + if (!panel) + { + return; + } + panel.Children().Clear(); + + const auto kc{ KeyChord() }; + if (!kc) + { + return; + } + + // Reuse the canonical serialization so the key naming stays in sync with the + // rest of the app. Then split on '+' (no key name in the table contains a literal + // '+'; VK_OEM_PLUS serializes as "plus") and render each part as its own visual. + const auto serialized{ Model::KeyChordSerialization::ToString(kc) }; + if (serialized.empty()) + { + return; + } + + const std::wstring_view full{ serialized }; + for (const auto part : til::split_iterator{ full, L'+' }) + { + if (til::equals_insensitive_ascii(part, L"win")) + { + _AddGlyphKey(); + } + else if (til::equals_insensitive_ascii(part, L"ctrl")) + { + _AddTextKey(L"Ctrl"); + } + else if (til::equals_insensitive_ascii(part, L"alt")) + { + _AddTextKey(L"Alt"); + } + else if (til::equals_insensitive_ascii(part, L"shift")) + { + _AddTextKey(L"Shift"); + } + else + { + _AddTextKey(_formatMainKeyName(part)); + } + } + } + + void KeyChordVisual::_AddTextKey(const winrt::hstring& text) + { + const auto tmpl{ Resources().Lookup(box_value(L"KeyChordVisualTextKeyTemplate")).as() }; + const auto border{ tmpl.LoadContent().as() }; + if (const auto tb{ border.Child().try_as() }) + { + tb.Text(text); + } + KeysPanel().Children().Append(border); + } + + void KeyChordVisual::_AddGlyphKey() + { + const auto tmpl{ Resources().Lookup(box_value(L"KeyChordVisualWindowsKeyTemplate")).as() }; + const auto border{ tmpl.LoadContent().as() }; + + // Provide an accessible name for the glyph since it has no text fallback. + if (const auto path{ border.Child() }) + { + Automation::AutomationProperties::SetName(path, L"Win"); + } + KeysPanel().Children().Append(border); + } +} diff --git a/src/cascadia/TerminalSettingsEditor/KeyChordVisual.h b/src/cascadia/TerminalSettingsEditor/KeyChordVisual.h new file mode 100644 index 0000000000..b8e06e851b --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/KeyChordVisual.h @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "KeyChordVisual.g.h" +#include "Utils.h" + +namespace winrt::Microsoft::Terminal::Settings::Editor::implementation +{ + struct KeyChordVisual : KeyChordVisualT + { + public: + KeyChordVisual(); + + DEPENDENCY_PROPERTY(Control::KeyChord, KeyChord); + + private: + static void _InitializeProperties(); + static void _OnKeyChordChanged(const Windows::UI::Xaml::DependencyObject& d, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e); + + void _UpdateKeyVisuals(); + void _AddTextKey(const winrt::hstring& text); + void _AddGlyphKey(); + }; +} + +namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation +{ + BASIC_FACTORY(KeyChordVisual); +} diff --git a/src/cascadia/TerminalSettingsEditor/KeyChordVisual.idl b/src/cascadia/TerminalSettingsEditor/KeyChordVisual.idl new file mode 100644 index 0000000000..7dd32097cc --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/KeyChordVisual.idl @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Microsoft.Terminal.Settings.Editor +{ + [default_interface] runtimeclass KeyChordVisual : Windows.UI.Xaml.Controls.UserControl + { + KeyChordVisual(); + + Microsoft.Terminal.Control.KeyChord KeyChord; + static Windows.UI.Xaml.DependencyProperty KeyChordProperty { get; }; + } +} diff --git a/src/cascadia/TerminalSettingsEditor/KeyChordVisual.xaml b/src/cascadia/TerminalSettingsEditor/KeyChordVisual.xaml new file mode 100644 index 0000000000..140b72a137 --- /dev/null +++ b/src/cascadia/TerminalSettingsEditor/KeyChordVisual.xaml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj index ba65864e3f..a3d16e6ea1 100644 --- a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj +++ b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj @@ -86,6 +86,9 @@ KeyChordListener.xaml + + KeyChordVisual.xaml + Launch.xaml @@ -213,6 +216,9 @@ Designer + + Designer + Designer @@ -294,6 +300,9 @@ KeyChordListener.xaml + + KeyChordVisual.xaml + Launch.xaml @@ -421,6 +430,10 @@ KeyChordListener.xaml Code + + KeyChordVisual.xaml + Code + Launch.xaml Code diff --git a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj.filters b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj.filters index 7efa01293a..dd276d82ec 100644 --- a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj.filters +++ b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj.filters @@ -52,6 +52,7 @@ + diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index 2320638f14..15dd044c37 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -289,8 +289,8 @@ Header for a control to toggle whether the terminal should automatically detect URLs and make them clickable, or not. - Default URL to use for the "Search web" action - Header for a control to set the query URL when using the "search web" action. + Default URL to use for the "Search web" shortcut + Header for a control to set the query URL when using the "search web" shortcut. The placeholder "%s" will be replaced with the search query. @@ -590,7 +590,7 @@ Additional description for what the "force vt input" setting does. Presented near "Globals_ForceVTInput.Header". - This allows actions such as Global Summon and Quake Mode actions to work even when no windows are open. + This allows shortcuts such as Global Summon and Quake Mode shortcuts to work even when no windows are open. Additional description for what the "allow headless" setting does. Presented near "Globals_AllowHeadless.Header". @@ -678,12 +678,12 @@ Header for the "defaults" menu item. This navigates to a page that lets you see and modify settings that affect profiles. This is the lowest layer of profile settings that all other profile settings are based on. If a profile doesn't define a setting, this page is responsible for figuring out what that setting is supposed to be. - Actions - Header for the "actions" menu item. This navigates to a page that lets you see the available commands in the app. + Shortcuts + Header for the "shortcuts" menu item. This navigates to a page that lets you see the available keyboard shortcuts in the app. (Resource key kept as "Nav_Actions" for stability.) - Edit Action... - Header for the "edit action" page. This is the page that lets you modify a specific command and its key bindings. + Edit Shortcut... + Header for the "edit shortcut" page. This is the page that lets you modify a specific command and its key bindings. (Resource key kept as "Nav_EditAction" for stability.) Extensions @@ -1786,28 +1786,28 @@ A description for what the delete unfocused appearance button does. - Learn more about actions - Disclaimer presented at the top of the actions page to redirect the user to documentation regarding actions. + Learn more about shortcuts + Disclaimer presented at the top of the shortcuts page to redirect the user to documentation regarding keyboard shortcuts. - Delete action - Button label that deletes the selected action. + Delete shortcut + Button label that deletes the selected shortcut. - Action name - Label for the text box that edits the action name. + Shortcut name + Label for the text box that edits the shortcut name. - Action name - Placeholder text for the text box where the user can edit the action name. + Shortcut name + Placeholder text for the text box where the user can edit the shortcut name. - Action type - Label for the combo box that edits the action type. + Shortcut type + Label for the combo box that edits the shortcut type (which action runs when this shortcut is invoked). - Keybindings - Name for a control which contains the list of keybindings for the current command. + Shortcuts + Name for a control which contains the list of keyboard shortcuts for the current command. Command details @@ -1818,44 +1818,44 @@ Label for the list of editable arguments for the currently selected action. - Keybindings - Label for the list of editable keybindings for the current command. + Shortcuts + Label for the list of editable keyboard shortcuts for the current command. - Add keybinding - Button label that adds a keybinding to the current action. + Add shortcut + Button label that adds a keyboard shortcut to the current action. and {} more Text that will be read out by a screen reader indicating that additional keybindings exist for this command. {} will be replaced by the number of additional keybindings. - Yes, delete key binding - Button label that confirms deletion of a key binding entry. + Yes, delete shortcut + Button label that confirms deletion of a keyboard shortcut entry. - Are you sure you want to delete this key binding? - Confirmation message displayed when the user attempts to delete a key binding entry. + Are you sure you want to delete this shortcut? + Confirmation message displayed when the user attempts to delete a keyboard shortcut entry. - Yes, delete action - Button label that confirms deletion of an action. + Yes, delete shortcut + Button label that confirms deletion of a shortcut entry. - Are you sure you want to delete this action? - Confirmation message displayed when the user attempts to delete an action. + Are you sure you want to delete this shortcut? + Confirmation message displayed when the user attempts to delete a shortcut entry. - Invalid key chord. Please enter a valid key chord. - Error message displayed when an invalid key chord is input by the user. + Invalid shortcut. Please enter a valid keyboard shortcut. + Error message displayed when an invalid keyboard shortcut is input by the user. Yes Button label that confirms the deletion of a conflicting key binding to allow the current key binding to be registered. - The provided key chord is already being used by the following action: - Error message displayed when a key chord that is already in use is input by the user. The name of the conflicting key chord is displayed after this message. + The provided shortcut is already being used by the following action: + Error message displayed when a keyboard shortcut that is already in use is input by the user. The name of the conflicting shortcut is displayed after this message. Would you like to overwrite it? @@ -1882,12 +1882,60 @@ Text label for a button that can be used to begin making changes to a key binding entry. - Add new - Button label that creates a new action on the actions page. + Add new shortcut + Button label that creates a new keyboard shortcut on the shortcuts page. - - Action - Label for a control that sets the action of a key binding. + + View all shortcuts + Tooltip for a button on each row of the Shortcuts page that opens a flyout listing every keyboard shortcut registered for that action. + + + No shortcuts + Empty-state message shown inside the "view all shortcuts" flyout (opened from each row's "..." button on the Shortcuts page) when the action has no keyboard shortcuts registered. + + + Shortcut type + Header for the shortcut-type setting on the Edit Shortcut page (lets the user pick which action runs when this shortcut is invoked). + + + Shortcut name + Header for the shortcut-name setting on the Edit Shortcut page (lets the user provide a friendly name for this shortcut). + + + Shortcuts + Header for the shortcuts expander on the Edit Shortcut page. + + + Customize keyboard shortcuts to speed up common actions and workflows. + Help text shown under the "Shortcuts" header on the Edit Shortcut page. + + + New shortcut + Header for the "add a new shortcut" row on the Edit Shortcut page. + + + Add shortcut + Label for the accent button that appends a new keyboard shortcut to the current action. + + + Additional customizations + Header for the additional customizations expander on the Edit Action page (contains action name and per-action argument settings). + + + Fine tune how shortcuts behave. + Help text shown under the "Additional customizations" header on the Edit Shortcut page. + + + Shortcut #{} + {Locked="#{}"} Header label for an individual keyboard shortcut inside the "Shortcuts" expander on the Edit Shortcut page. {} is replaced with the 1-based index of the shortcut (e.g. "Shortcut #1"). + + + Delete this shortcut + Header for the setting container that holds the "Delete shortcut" button at the bottom of the Edit Shortcut page. + + + This shortcut will be removed and any shortcuts associated with it will no longer work. + Help text shown under the "Delete this shortcut" setting container on the Edit Shortcut page. Use global setting diff --git a/src/cascadia/TerminalSettingsEditor/SettingContainerStyle.xaml b/src/cascadia/TerminalSettingsEditor/SettingContainerStyle.xaml index 4efa5be861..426990065e 100644 --- a/src/cascadia/TerminalSettingsEditor/SettingContainerStyle.xaml +++ b/src/cascadia/TerminalSettingsEditor/SettingContainerStyle.xaml @@ -121,6 +121,11 @@ 0,4,8,4 16 + + 16,8,8,8 + 64 + 0,4,0,0 + + + +