From 111b88c8a342517c6d7859d0f161badff0d761d8 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 27 Nov 2019 15:51:38 -0600 Subject: [PATCH] Encapsulate dispatching `ShortcutActions` in it's own class (#3658) ## Summary of the Pull Request Moves all the code responsible for dispatching an `ActionAndArgs` to it's own class, `ShortcutActionDispatch`. Now, the `AppKeyBindings` just uses the single instance of a `ShortcutActionDispatch` that the `TerminalPage` owns to dispatch events, without the need to re-attach the event handlers every time we reload the settings. ## References This is something I originally did as a part of #2046. I need this now for #607. It's also a part of work for #3475 ## PR Checklist * [x] This is a bullet point within #3475 * [x] I work here * [ ] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments With this change, we'll be able to have other things dispatch `ShortcutAction`s easily, by constructing an `ActionAndArgs` and just passing it straight to the `ShortcutActionDispatch`. ## Validation Steps Performed Ran the Terminal, tried out some keybindings, namely Ctrl+c for copy when there is a selection, or send `^C` when there isn't. That still works. Reloading settings also still works. ----------------------------------------------- * Move action handling to it's own class separate from AKB. This is the first checkbox in #3475 (cherry picked from commit 696726b571d3d1fdf1d59844c76e182fc72cb2ea) * clean up doc comments --- src/cascadia/TerminalApp/AppKeyBindings.cpp | 182 +--------------- src/cascadia/TerminalApp/AppKeyBindings.h | 35 +-- src/cascadia/TerminalApp/AppKeyBindings.idl | 92 +------- .../TerminalApp/ShortcutActionDispatch.cpp | 202 ++++++++++++++++++ .../TerminalApp/ShortcutActionDispatch.h | 61 ++++++ .../TerminalApp/ShortcutActionDispatch.idl | 103 +++++++++ src/cascadia/TerminalApp/TerminalPage.cpp | 69 +++--- src/cascadia/TerminalApp/TerminalPage.h | 3 + .../TerminalApp/lib/TerminalAppLib.vcxproj | 7 + 9 files changed, 427 insertions(+), 327 deletions(-) create mode 100644 src/cascadia/TerminalApp/ShortcutActionDispatch.cpp create mode 100644 src/cascadia/TerminalApp/ShortcutActionDispatch.h create mode 100644 src/cascadia/TerminalApp/ShortcutActionDispatch.idl diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index 63b088c24..9fade7d93 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -70,190 +70,14 @@ namespace winrt::TerminalApp::implementation if (keyIter != _keyShortcuts.end()) { const auto actionAndArgs = keyIter->second; - return _DoAction(actionAndArgs); + return _dispatch.DoAction(actionAndArgs); } return false; } - bool AppKeyBindings::_DoAction(ActionAndArgs actionAndArgs) + void AppKeyBindings::SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch) { - const auto& action = actionAndArgs.Action(); - const auto& args = actionAndArgs.Args(); - auto eventArgs = args ? winrt::make_self(args) : - winrt::make_self(); - - switch (action) - { - case ShortcutAction::CopyText: - { - _CopyTextHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::CopyTextWithoutNewlines: - { - _CopyTextHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::PasteText: - { - _PasteTextHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::OpenNewTabDropdown: - { - _OpenNewTabDropdownHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::DuplicateTab: - { - _DuplicateTabHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::OpenSettings: - { - _OpenSettingsHandlers(*this, *eventArgs); - break; - } - - case ShortcutAction::NewTab: - case ShortcutAction::NewTabProfile0: - case ShortcutAction::NewTabProfile1: - case ShortcutAction::NewTabProfile2: - case ShortcutAction::NewTabProfile3: - case ShortcutAction::NewTabProfile4: - case ShortcutAction::NewTabProfile5: - case ShortcutAction::NewTabProfile6: - case ShortcutAction::NewTabProfile7: - case ShortcutAction::NewTabProfile8: - { - _NewTabHandlers(*this, *eventArgs); - break; - } - - case ShortcutAction::NewWindow: - { - _NewWindowHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::CloseWindow: - { - _CloseWindowHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::CloseTab: - { - _CloseTabHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::ClosePane: - { - _ClosePaneHandlers(*this, *eventArgs); - break; - } - - case ShortcutAction::ScrollUp: - { - _ScrollUpHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::ScrollDown: - { - _ScrollDownHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::ScrollUpPage: - { - _ScrollUpPageHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::ScrollDownPage: - { - _ScrollDownPageHandlers(*this, *eventArgs); - break; - } - - case ShortcutAction::NextTab: - { - _NextTabHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::PrevTab: - { - _PrevTabHandlers(*this, *eventArgs); - break; - } - - case ShortcutAction::SplitVertical: - { - _SplitVerticalHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::SplitHorizontal: - { - _SplitHorizontalHandlers(*this, *eventArgs); - break; - } - - case ShortcutAction::SwitchToTab: - case ShortcutAction::SwitchToTab0: - case ShortcutAction::SwitchToTab1: - case ShortcutAction::SwitchToTab2: - case ShortcutAction::SwitchToTab3: - case ShortcutAction::SwitchToTab4: - case ShortcutAction::SwitchToTab5: - case ShortcutAction::SwitchToTab6: - case ShortcutAction::SwitchToTab7: - case ShortcutAction::SwitchToTab8: - { - _SwitchToTabHandlers(*this, *eventArgs); - break; - } - - case ShortcutAction::ResizePane: - case ShortcutAction::ResizePaneLeft: - case ShortcutAction::ResizePaneRight: - case ShortcutAction::ResizePaneUp: - case ShortcutAction::ResizePaneDown: - { - _ResizePaneHandlers(*this, *eventArgs); - break; - } - - case ShortcutAction::MoveFocus: - case ShortcutAction::MoveFocusLeft: - case ShortcutAction::MoveFocusRight: - case ShortcutAction::MoveFocusUp: - case ShortcutAction::MoveFocusDown: - { - _MoveFocusHandlers(*this, *eventArgs); - break; - } - - case ShortcutAction::IncreaseFontSize: - { - _AdjustFontSizeHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::DecreaseFontSize: - { - _AdjustFontSizeHandlers(*this, *eventArgs); - break; - } - case ShortcutAction::ResetFontSize: - { - auto eventArgs = winrt::make_self(); - _ResetFontSizeHandlers(*this, *eventArgs); - return eventArgs->Handled(); - } - case ShortcutAction::ToggleFullscreen: - { - _ToggleFullscreenHandlers(*this, *eventArgs); - break; - } - default: - return false; - } - return eventArgs->Handled(); + _dispatch = dispatch; } // Method Description: diff --git a/src/cascadia/TerminalApp/AppKeyBindings.h b/src/cascadia/TerminalApp/AppKeyBindings.h index f4e06342d..58b1164cc 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.h +++ b/src/cascadia/TerminalApp/AppKeyBindings.h @@ -5,6 +5,7 @@ #include "AppKeyBindings.g.h" #include "ActionArgs.h" +#include "ShortcutActionDispatch.h" #include "..\inc\cppwinrt_utils.h" // fwdecl unittest classes @@ -54,36 +55,12 @@ namespace winrt::TerminalApp::implementation void LayerJson(const Json::Value& json); Json::Value ToJson(); - // clang-format off - TYPED_EVENT(CopyText, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(PasteText, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(OpenNewTabDropdown,TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(DuplicateTab, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(NewTab, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(NewWindow, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(CloseWindow, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(CloseTab, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(ClosePane, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(SwitchToTab, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(NextTab, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(PrevTab, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(SplitVertical, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(SplitHorizontal, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(AdjustFontSize, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(ResetFontSize, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(ScrollUp, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(ScrollDown, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(ScrollUpPage, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(ScrollDownPage, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(OpenSettings, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(ResizePane, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(MoveFocus, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - TYPED_EVENT(ToggleFullscreen, TerminalApp::AppKeyBindings, TerminalApp::ActionEventArgs); - // clang-format on + void SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch); private: std::unordered_map _keyShortcuts; - bool _DoAction(ActionAndArgs actionAndArgs); + + winrt::TerminalApp::ShortcutActionDispatch _dispatch{ nullptr }; friend class TerminalAppLocalTests::SettingsTests; friend class TerminalAppLocalTests::KeyBindingsTests; @@ -92,7 +69,5 @@ namespace winrt::TerminalApp::implementation namespace winrt::TerminalApp::factory_implementation { - struct AppKeyBindings : AppKeyBindingsT - { - }; + BASIC_FACTORY(AppKeyBindings); } diff --git a/src/cascadia/TerminalApp/AppKeyBindings.idl b/src/cascadia/TerminalApp/AppKeyBindings.idl index 15c5c1810..db287b792 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.idl +++ b/src/cascadia/TerminalApp/AppKeyBindings.idl @@ -1,75 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. import "../ActionArgs.idl"; +import "../ShortcutActionDispatch.idl"; namespace TerminalApp { - // TODO: GH#1069 - Many of these shortcut actions are "legacy" now that we - // have support for arbitrary args (#1142). We should remove them, and our - // legacy deserializers. - enum ShortcutAction - { - Invalid = 0, - CopyText, - CopyTextWithoutNewlines, - PasteText, - OpenNewTabDropdown, - DuplicateTab, - NewTab, - NewTabProfile0, // Legacy - NewTabProfile1, // Legacy - NewTabProfile2, // Legacy - NewTabProfile3, // Legacy - NewTabProfile4, // Legacy - NewTabProfile5, // Legacy - NewTabProfile6, // Legacy - NewTabProfile7, // Legacy - NewTabProfile8, // Legacy - NewWindow, - CloseWindow, - CloseTab, - ClosePane, - NextTab, - PrevTab, - SplitVertical, - SplitHorizontal, - SwitchToTab, - SwitchToTab0, // Legacy - SwitchToTab1, // Legacy - SwitchToTab2, // Legacy - SwitchToTab3, // Legacy - SwitchToTab4, // Legacy - SwitchToTab5, // Legacy - SwitchToTab6, // Legacy - SwitchToTab7, // Legacy - SwitchToTab8, // Legacy - IncreaseFontSize, - DecreaseFontSize, - ResetFontSize, - ScrollUp, - ScrollDown, - ScrollUpPage, - ScrollDownPage, - ResizePane, - ResizePaneLeft, // Legacy - ResizePaneRight, // Legacy - ResizePaneUp, // Legacy - ResizePaneDown, // Legacy - MoveFocus, - MoveFocusLeft, // Legacy - MoveFocusRight, // Legacy - MoveFocusUp, // Legacy - MoveFocusDown, // Legacy - ToggleFullscreen, - OpenSettings - }; - - [default_interface] runtimeclass ActionAndArgs { - ActionAndArgs(); - IActionArgs Args; - ShortcutAction Action; - }; - [default_interface] runtimeclass AppKeyBindings : Microsoft.Terminal.Settings.IKeyBindings { AppKeyBindings(); @@ -80,29 +15,6 @@ namespace TerminalApp Microsoft.Terminal.Settings.KeyChord GetKeyBindingForAction(ShortcutAction action); Microsoft.Terminal.Settings.KeyChord GetKeyBindingForActionWithArgs(ActionAndArgs actionAndArgs); - event Windows.Foundation.TypedEventHandler CopyText; - event Windows.Foundation.TypedEventHandler PasteText; - event Windows.Foundation.TypedEventHandler NewTab; - event Windows.Foundation.TypedEventHandler OpenNewTabDropdown; - event Windows.Foundation.TypedEventHandler DuplicateTab; - event Windows.Foundation.TypedEventHandler NewWindow; - event Windows.Foundation.TypedEventHandler CloseWindow; - event Windows.Foundation.TypedEventHandler CloseTab; - event Windows.Foundation.TypedEventHandler ClosePane; - event Windows.Foundation.TypedEventHandler SwitchToTab; - event Windows.Foundation.TypedEventHandler NextTab; - event Windows.Foundation.TypedEventHandler PrevTab; - event Windows.Foundation.TypedEventHandler SplitVertical; - event Windows.Foundation.TypedEventHandler SplitHorizontal; - event Windows.Foundation.TypedEventHandler AdjustFontSize; - event Windows.Foundation.TypedEventHandler ResetFontSize; - event Windows.Foundation.TypedEventHandler ScrollUp; - event Windows.Foundation.TypedEventHandler ScrollDown; - event Windows.Foundation.TypedEventHandler ScrollUpPage; - event Windows.Foundation.TypedEventHandler ScrollDownPage; - event Windows.Foundation.TypedEventHandler OpenSettings; - event Windows.Foundation.TypedEventHandler ResizePane; - event Windows.Foundation.TypedEventHandler MoveFocus; - event Windows.Foundation.TypedEventHandler ToggleFullscreen; + void SetDispatch(ShortcutActionDispatch dispatch); } } diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp new file mode 100644 index 000000000..6101bbe17 --- /dev/null +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -0,0 +1,202 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "ShortcutActionDispatch.h" + +#include "ShortcutActionDispatch.g.cpp" + +using namespace winrt::Microsoft::Terminal; +using namespace winrt::TerminalApp; + +namespace winrt::TerminalApp::implementation +{ + // Method Description: + // - Dispatch the appropriate event for the given ActionAndArgs. Constructs + // an ActionEventArgs to hold the IActionArgs payload for the event, and + // calls the matching handlers for that event. + // Arguments: + // - actionAndArgs: the ShortcutAction and associated args to raise an event for. + // Return Value: + // - true if we handled the event was handled, else false. + bool ShortcutActionDispatch::DoAction(const ActionAndArgs& actionAndArgs) + { + const auto& action = actionAndArgs.Action(); + const auto& args = actionAndArgs.Args(); + auto eventArgs = args ? winrt::make_self(args) : + winrt::make_self(); + + switch (action) + { + case ShortcutAction::CopyText: + { + _CopyTextHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::CopyTextWithoutNewlines: + { + _CopyTextHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::PasteText: + { + _PasteTextHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::OpenNewTabDropdown: + { + _OpenNewTabDropdownHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::DuplicateTab: + { + _DuplicateTabHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::OpenSettings: + { + _OpenSettingsHandlers(*this, *eventArgs); + break; + } + + case ShortcutAction::NewTab: + case ShortcutAction::NewTabProfile0: + case ShortcutAction::NewTabProfile1: + case ShortcutAction::NewTabProfile2: + case ShortcutAction::NewTabProfile3: + case ShortcutAction::NewTabProfile4: + case ShortcutAction::NewTabProfile5: + case ShortcutAction::NewTabProfile6: + case ShortcutAction::NewTabProfile7: + case ShortcutAction::NewTabProfile8: + { + _NewTabHandlers(*this, *eventArgs); + break; + } + + case ShortcutAction::NewWindow: + { + _NewWindowHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::CloseWindow: + { + _CloseWindowHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::CloseTab: + { + _CloseTabHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::ClosePane: + { + _ClosePaneHandlers(*this, *eventArgs); + break; + } + + case ShortcutAction::ScrollUp: + { + _ScrollUpHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::ScrollDown: + { + _ScrollDownHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::ScrollUpPage: + { + _ScrollUpPageHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::ScrollDownPage: + { + _ScrollDownPageHandlers(*this, *eventArgs); + break; + } + + case ShortcutAction::NextTab: + { + _NextTabHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::PrevTab: + { + _PrevTabHandlers(*this, *eventArgs); + break; + } + + case ShortcutAction::SplitVertical: + { + _SplitVerticalHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::SplitHorizontal: + { + _SplitHorizontalHandlers(*this, *eventArgs); + break; + } + + case ShortcutAction::SwitchToTab: + case ShortcutAction::SwitchToTab0: + case ShortcutAction::SwitchToTab1: + case ShortcutAction::SwitchToTab2: + case ShortcutAction::SwitchToTab3: + case ShortcutAction::SwitchToTab4: + case ShortcutAction::SwitchToTab5: + case ShortcutAction::SwitchToTab6: + case ShortcutAction::SwitchToTab7: + case ShortcutAction::SwitchToTab8: + { + _SwitchToTabHandlers(*this, *eventArgs); + break; + } + + case ShortcutAction::ResizePane: + case ShortcutAction::ResizePaneLeft: + case ShortcutAction::ResizePaneRight: + case ShortcutAction::ResizePaneUp: + case ShortcutAction::ResizePaneDown: + { + _ResizePaneHandlers(*this, *eventArgs); + break; + } + + case ShortcutAction::MoveFocus: + case ShortcutAction::MoveFocusLeft: + case ShortcutAction::MoveFocusRight: + case ShortcutAction::MoveFocusUp: + case ShortcutAction::MoveFocusDown: + { + _MoveFocusHandlers(*this, *eventArgs); + break; + } + + case ShortcutAction::IncreaseFontSize: + { + _AdjustFontSizeHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::DecreaseFontSize: + { + _AdjustFontSizeHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::ResetFontSize: + { + _ResetFontSizeHandlers(*this, *eventArgs); + break; + } + case ShortcutAction::ToggleFullscreen: + { + _ToggleFullscreenHandlers(*this, *eventArgs); + break; + } + default: + return false; + } + return eventArgs->Handled(); + } + +} diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.h b/src/cascadia/TerminalApp/ShortcutActionDispatch.h new file mode 100644 index 000000000..5c0262146 --- /dev/null +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.h @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +#include "ShortcutActionDispatch.g.h" +#include "ActionArgs.h" +#include "..\inc\cppwinrt_utils.h" + +// fwdecl unittest classes +namespace TerminalAppLocalTests +{ + class SettingsTests; + class KeyBindingsTests; +} + +namespace winrt::TerminalApp::implementation +{ + struct ShortcutActionDispatch : ShortcutActionDispatchT + { + ShortcutActionDispatch() = default; + + bool DoAction(const ActionAndArgs& actionAndArgs); + + // clang-format off + TYPED_EVENT(CopyText, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(PasteText, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(OpenNewTabDropdown,TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(DuplicateTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(NewTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(NewWindow, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(CloseWindow, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(CloseTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(ClosePane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(SwitchToTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(NextTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(PrevTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(SplitVertical, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(SplitHorizontal, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(AdjustFontSize, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(ResetFontSize, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(ScrollUp, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(ScrollDown, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(ScrollUpPage, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(ScrollDownPage, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(OpenSettings, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(ResizePane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(MoveFocus, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(ToggleFullscreen, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + // clang-format on + + private: + friend class TerminalAppLocalTests::SettingsTests; + friend class TerminalAppLocalTests::KeyBindingsTests; + }; +} + +namespace winrt::TerminalApp::factory_implementation +{ + BASIC_FACTORY(ShortcutActionDispatch); +} diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl new file mode 100644 index 000000000..5a1496b62 --- /dev/null +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl @@ -0,0 +1,103 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +import "../ActionArgs.idl"; + +namespace TerminalApp +{ + // TODO: GH#1069 - Many of these shortcut actions are "legacy" now that we + // have support for arbitrary args (#1142). We should remove them, and our + // legacy deserializers. + enum ShortcutAction + { + Invalid = 0, + CopyText, + CopyTextWithoutNewlines, + PasteText, + OpenNewTabDropdown, + DuplicateTab, + NewTab, + NewTabProfile0, // Legacy + NewTabProfile1, // Legacy + NewTabProfile2, // Legacy + NewTabProfile3, // Legacy + NewTabProfile4, // Legacy + NewTabProfile5, // Legacy + NewTabProfile6, // Legacy + NewTabProfile7, // Legacy + NewTabProfile8, // Legacy + NewWindow, + CloseWindow, + CloseTab, + ClosePane, + NextTab, + PrevTab, + SplitVertical, + SplitHorizontal, + SwitchToTab, + SwitchToTab0, // Legacy + SwitchToTab1, // Legacy + SwitchToTab2, // Legacy + SwitchToTab3, // Legacy + SwitchToTab4, // Legacy + SwitchToTab5, // Legacy + SwitchToTab6, // Legacy + SwitchToTab7, // Legacy + SwitchToTab8, // Legacy + IncreaseFontSize, + DecreaseFontSize, + ResetFontSize, + ScrollUp, + ScrollDown, + ScrollUpPage, + ScrollDownPage, + ResizePane, + ResizePaneLeft, // Legacy + ResizePaneRight, // Legacy + ResizePaneUp, // Legacy + ResizePaneDown, // Legacy + MoveFocus, + MoveFocusLeft, // Legacy + MoveFocusRight, // Legacy + MoveFocusUp, // Legacy + MoveFocusDown, // Legacy + ToggleFullscreen, + OpenSettings + }; + + [default_interface] runtimeclass ActionAndArgs { + ActionAndArgs(); + IActionArgs Args; + ShortcutAction Action; + }; + + [default_interface] runtimeclass ShortcutActionDispatch { + ShortcutActionDispatch(); + + Boolean DoAction(ActionAndArgs actionAndArgs); + + event Windows.Foundation.TypedEventHandler CopyText; + event Windows.Foundation.TypedEventHandler PasteText; + event Windows.Foundation.TypedEventHandler NewTab; + event Windows.Foundation.TypedEventHandler OpenNewTabDropdown; + event Windows.Foundation.TypedEventHandler DuplicateTab; + event Windows.Foundation.TypedEventHandler NewWindow; + event Windows.Foundation.TypedEventHandler CloseWindow; + event Windows.Foundation.TypedEventHandler CloseTab; + event Windows.Foundation.TypedEventHandler ClosePane; + event Windows.Foundation.TypedEventHandler SwitchToTab; + event Windows.Foundation.TypedEventHandler NextTab; + event Windows.Foundation.TypedEventHandler PrevTab; + event Windows.Foundation.TypedEventHandler SplitVertical; + event Windows.Foundation.TypedEventHandler SplitHorizontal; + event Windows.Foundation.TypedEventHandler AdjustFontSize; + event Windows.Foundation.TypedEventHandler ResetFontSize; + event Windows.Foundation.TypedEventHandler ScrollUp; + event Windows.Foundation.TypedEventHandler ScrollDown; + event Windows.Foundation.TypedEventHandler ScrollUpPage; + event Windows.Foundation.TypedEventHandler ScrollDownPage; + event Windows.Foundation.TypedEventHandler OpenSettings; + event Windows.Foundation.TypedEventHandler ResizePane; + event Windows.Foundation.TypedEventHandler MoveFocus; + event Windows.Foundation.TypedEventHandler ToggleFullscreen; + } +} diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index f48f3a6eb..598d361c8 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -96,6 +96,9 @@ namespace winrt::TerminalApp::implementation _setTitleBarContentHandlers(*this, _tabRow); } + // Hookup our event handlers to the ShortcutActionDispatch + _RegisterActionCallbacks(); + //Event Bindings (Early) _newTabButton.Click([this](auto&&, auto&&) { this->_OpenNewTab(std::nullopt); @@ -576,41 +579,51 @@ namespace winrt::TerminalApp::implementation } // Method Description: - // - Register our event handlers with the given keybindings object. This - // should be done regardless of what the events are actually bound to - - // this simply ensures the AppKeyBindings object will call us correctly - // for each event. + // - Configure the AppKeyBindings to use our ShortcutActionDispatch as the + // object to handle dispatching ShortcutAction events. // Arguments: // - bindings: A AppKeyBindings object to wire up with our event handlers void TerminalPage::_HookupKeyBindings(TerminalApp::AppKeyBindings bindings) noexcept { - // Hook up the KeyBinding object's events to our handlers. + bindings.SetDispatch(_actionDispatch); + } + + // Method Description: + // - Register our event handlers with our ShortcutActionDispatch. The + // ShortcutActionDispatch is responsible for raising the appropriate + // events for an ActionAndArgs. WE'll handle each possible event in our + // own way. + // Arguments: + // - + void TerminalPage::_RegisterActionCallbacks() + { + // Hook up the ShortcutActionDispatch object's events to our handlers. // They should all be hooked up here, regardless of whether or not // there's an actual keychord for them. - bindings.OpenNewTabDropdown({ this, &TerminalPage::_HandleOpenNewTabDropdown }); - bindings.DuplicateTab({ this, &TerminalPage::_HandleDuplicateTab }); - bindings.CloseTab({ this, &TerminalPage::_HandleCloseTab }); - bindings.ClosePane({ this, &TerminalPage::_HandleClosePane }); - bindings.CloseWindow({ this, &TerminalPage::_HandleCloseWindow }); - bindings.ScrollUp({ this, &TerminalPage::_HandleScrollUp }); - bindings.ScrollDown({ this, &TerminalPage::_HandleScrollDown }); - bindings.NextTab({ this, &TerminalPage::_HandleNextTab }); - bindings.PrevTab({ this, &TerminalPage::_HandlePrevTab }); - bindings.SplitVertical({ this, &TerminalPage::_HandleSplitVertical }); - bindings.SplitHorizontal({ this, &TerminalPage::_HandleSplitHorizontal }); - bindings.ScrollUpPage({ this, &TerminalPage::_HandleScrollUpPage }); - bindings.ScrollDownPage({ this, &TerminalPage::_HandleScrollDownPage }); - bindings.OpenSettings({ this, &TerminalPage::_HandleOpenSettings }); - bindings.PasteText({ this, &TerminalPage::_HandlePasteText }); - bindings.NewTab({ this, &TerminalPage::_HandleNewTab }); - bindings.SwitchToTab({ this, &TerminalPage::_HandleSwitchToTab }); - bindings.ResizePane({ this, &TerminalPage::_HandleResizePane }); - bindings.MoveFocus({ this, &TerminalPage::_HandleMoveFocus }); - bindings.CopyText({ this, &TerminalPage::_HandleCopyText }); - bindings.AdjustFontSize({ this, &TerminalPage::_HandleAdjustFontSize }); - bindings.ResetFontSize({ this, &TerminalPage::_HandleResetFontSize }); - bindings.ToggleFullscreen({ this, &TerminalPage::_HandleToggleFullscreen }); + _actionDispatch.OpenNewTabDropdown({ this, &TerminalPage::_HandleOpenNewTabDropdown }); + _actionDispatch.DuplicateTab({ this, &TerminalPage::_HandleDuplicateTab }); + _actionDispatch.CloseTab({ this, &TerminalPage::_HandleCloseTab }); + _actionDispatch.ClosePane({ this, &TerminalPage::_HandleClosePane }); + _actionDispatch.CloseWindow({ this, &TerminalPage::_HandleCloseWindow }); + _actionDispatch.ScrollUp({ this, &TerminalPage::_HandleScrollUp }); + _actionDispatch.ScrollDown({ this, &TerminalPage::_HandleScrollDown }); + _actionDispatch.NextTab({ this, &TerminalPage::_HandleNextTab }); + _actionDispatch.PrevTab({ this, &TerminalPage::_HandlePrevTab }); + _actionDispatch.SplitVertical({ this, &TerminalPage::_HandleSplitVertical }); + _actionDispatch.SplitHorizontal({ this, &TerminalPage::_HandleSplitHorizontal }); + _actionDispatch.ScrollUpPage({ this, &TerminalPage::_HandleScrollUpPage }); + _actionDispatch.ScrollDownPage({ this, &TerminalPage::_HandleScrollDownPage }); + _actionDispatch.OpenSettings({ this, &TerminalPage::_HandleOpenSettings }); + _actionDispatch.PasteText({ this, &TerminalPage::_HandlePasteText }); + _actionDispatch.NewTab({ this, &TerminalPage::_HandleNewTab }); + _actionDispatch.SwitchToTab({ this, &TerminalPage::_HandleSwitchToTab }); + _actionDispatch.ResizePane({ this, &TerminalPage::_HandleResizePane }); + _actionDispatch.MoveFocus({ this, &TerminalPage::_HandleMoveFocus }); + _actionDispatch.CopyText({ this, &TerminalPage::_HandleCopyText }); + _actionDispatch.AdjustFontSize({ this, &TerminalPage::_HandleAdjustFontSize }); + _actionDispatch.ResetFontSize({ this, &TerminalPage::_HandleResetFontSize }); + _actionDispatch.ToggleFullscreen({ this, &TerminalPage::_HandleToggleFullscreen }); } // Method Description: diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 754b014af..4a8aee576 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -65,6 +65,8 @@ namespace winrt::TerminalApp::implementation std::optional _rearrangeFrom; std::optional _rearrangeTo; + ShortcutActionDispatch _actionDispatch{}; + void _ShowAboutDialog(); void _ShowCloseWarningDialog(); @@ -80,6 +82,7 @@ namespace winrt::TerminalApp::implementation void _CloseWarningPrimaryButtonOnClick(Windows::UI::Xaml::Controls::ContentDialog sender, Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs eventArgs); void _HookupKeyBindings(TerminalApp::AppKeyBindings bindings) noexcept; + void _RegisterActionCallbacks(); void _UpdateTitle(std::shared_ptr tab); void _UpdateTabIcon(std::shared_ptr tab); diff --git a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj b/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj index 519fce75f..a8845addb 100644 --- a/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj +++ b/src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj @@ -87,6 +87,9 @@ + + ../ShortcutActionDispatch.idl + ../ActionArgs.idl @@ -141,6 +144,9 @@ ../AppKeyBindings.idl + + ../ShortcutActionDispatch.idl + ../ActionArgs.idl @@ -172,6 +178,7 @@ ../App.xaml +