Repository: microsoft/terminal (language: cpp)

Issue:
[Settings] : System menu pop-up doesn't open inside 'Settings' window, when user press 'Alt + Space' key.
### Windows Terminal version

1.12.3472.0

### Windows build number

22509.1011

### Other Software

**Test Environment: **
OS: Windows 11 Version Dev (OS Build 22509.1011)
App: Windows Terminal Preview

### Steps to reproduce

**Repro Steps: **

1.Open Windows Terminal.
2.Open Settings page using 'Ctr+,'
3.Now try to open the 'System menu' pop-up by pressing 'Alt + Space' key.
4.Observe the issue.

**User Experience: **
Users will not be able to 'System menu' pop-up functionalities in 'Settings' window, if System menu pop-up doesn't open inside 'Settings' window on pressing 'Alt + Space' key.

Attachment : 
[System menu pop-up doesn't open inside 'Settings' window, when user press 'Alt + Space' key..zip](https://github.com/microsoft/terminal/files/7728290/System.menu.pop-up.doesn.t.open.inside.Settings.window.when.user.press.Alt.%2B.Space.key.zip)


### Expected Behavior

System menu pop-up should open inside 'Settings' window, when user press 'Alt + Space' key.

### Actual Behavior

System menu pop-up doesn't open inside 'Settings' window, when user press 'Alt + Space' key.
Add system menu support from SUI & read-only panes
## Summary of the Pull Request
Adds support for the system menu to appear from the Settings UI and read-only panes.

## PR Checklist
Closes #11970

## Detailed Description of the Pull Request / Additional comments
This is another case of needing the DirectKeyListener. Alt+Space just doesn't go through the normal key event handler, so we needed to add support for it in both of these places.

## Validation Steps Performed
- [X] Tested ALT+SPACE from settings UI
- [X] Tested ALT+SPACE from read-only pane


Discussion / hints:
Huh. Sure doesn't. Probably should. I'm guessing there's some magic reason that Alt+Space isn't delivered to the SUI, which is causing us to never raise a `OpenSystemMenu` action, so it never gets to `TerminalPage::_HandleOpenSystemMenu`. That's where I'd start.
Note to selves: it just generally doesn't work from the command palette either. Why does it need to go through a `TermControl`? that's weird.

Or read-only panes. weird. 
So the reason this doesn't work in the settings UI is because `Alt` + `Space` is special cased in the app's main method to delegate through to `AppHost::OnDirectKeyEvent()`, which in turn delegates through to `AppLogic::OnDirectKeyEvent()`.

This method iterates through the UI tree and passes the key event through to `IDirectKeyListener` implementations - of which the settings UI's `MainPage` isn't one.

Hitting `Alt` + `Space` in the command palette doesn't work either - it does implement `IDirectKeyListener`, but only seems to care about the `Alt` key-up event and doesn't handle `Alt` + `Space`.

I've been looking at this for a while now, and can't come up with a nice way of refactoring the code so that hitting `Alt` + `Space` works in all three places. The `TermControl` logic below doesn't refactor out (I was thinking up to `AppLogic`) well - as it uses methods on `ControlSettings`, which `AppLogic` (or `MainPage` for that matter) doesn't know anything about.

https://github.com/microsoft/terminal/blob/210a98e44940f880175436b050151fb8c1e4b45d/src/cascadia/TerminalControl/TermControl.cpp#L963-L988

Oddly, the "Open system menu" action does work if you click it from within the command palette - it just doesn't work if you press the enter key with it highlighted. In both cases the action does fire, and `IslandWindow::OpenSystemMenu()` does get called - but when enter is pressed, the call to `TrackPopupMenu()` doesn't seem to do anything.
Originally filed in MSFT-41390832


Fix patch:
diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp
index a6fdc4ba6b2..5a27e45251f 100644
--- a/src/cascadia/TerminalApp/TerminalPage.cpp
+++ b/src/cascadia/TerminalApp/TerminalPage.cpp
@@ -1332,6 +1332,29 @@ namespace winrt::TerminalApp::implementation
         e.Handled(true);
     }
 
+    bool TerminalPage::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down)
+    {
+        const auto modifiers = _GetPressedModifierKeys();
+        if (vkey == VK_SPACE && modifiers.IsAltPressed() && down)
+        {
+            if (const auto actionMap = _settings.ActionMap())
+            {
+                if (const auto cmd = actionMap.GetActionByKeyChord({
+                        modifiers.IsCtrlPressed(),
+                        modifiers.IsAltPressed(),
+                        modifiers.IsShiftPressed(),
+                        modifiers.IsWinPressed(),
+                        gsl::narrow_cast<int32_t>(vkey),
+                        scanCode,
+                    }))
+                {
+                    return _actionDispatch->DoAction(cmd.ActionAndArgs());
+                }
+            }
+        }
+        return false;
+    }
+
     // Method Description:
     // - Get the modifier keys that are currently pressed. This can be used to
     //   find out which modifiers (ctrl, alt, shift) are pressed in events that
diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h
index e2291270b1e..519d8786eaf 100644
--- a/src/cascadia/TerminalApp/TerminalPage.h
+++ b/src/cascadia/TerminalApp/TerminalPage.h
@@ -136,6 +136,8 @@ namespace winrt::TerminalApp::implementation
         void OpenSettingsUI();
         void WindowActivated(const bool activated);
 
+        bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
+
         WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
 
         // -------------------------------- WinRT Events ---------------------------------
diff --git a/src/cascadia/TerminalApp/TerminalPage.idl b/src/cascadia/TerminalApp/TerminalPage.idl
index 89ea3ec3277..5535c527a21 100644
--- a/src/cascadia/TerminalApp/TerminalPage.idl
+++ b/src/cascadia/TerminalApp/TerminalPage.idl
@@ -1,6 +1,7 @@
 // Copyright (c) Microsoft Corporation.
 // Licensed under the MIT license.
 import "TaskbarState.idl";
+import "IDirectKeyListener.idl";
 
 namespace TerminalApp
 {
@@ -16,7 +17,7 @@ namespace TerminalApp
         Windows.Foundation.IAsyncOperation<Windows.UI.Xaml.Controls.ContentDialogResult> ShowDialog(Windows.UI.Xaml.Controls.ContentDialog dialog);
     };
 
-    [default_interface] runtimeclass TerminalPage : Windows.UI.Xaml.Controls.Page, Windows.UI.Xaml.Data.INotifyPropertyChanged
+    [default_interface] runtimeclass TerminalPage : Windows.UI.Xaml.Controls.Page, Windows.UI.Xaml.Data.INotifyPropertyChanged, IDirectKeyListener
     {
         TerminalPage();
 


Test patch: