Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass <Alt> to the application #6461

Merged
merged 7 commits into from
Jun 11, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/spell-check/dictionary/apis.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ IBind
IClass
IComparable
ICustom
IDirect
IExplorer
IMap
IObject
Expand Down
11 changes: 6 additions & 5 deletions src/cascadia/TerminalApp/AppLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -906,20 +906,21 @@ namespace winrt::TerminalApp::implementation

// Method Description:
// - Implements the F7 handler (per GH#638)
// - Implements the Alt handler (per GH#6421)
// Return value:
// - whether F7 was handled
bool AppLogic::OnF7Pressed()
// - whether the key was handled
bool AppLogic::OnGotAKey(const uint32_t vkey, const bool down)
{
if (_root)
{
// Manually bubble the OnF7Pressed event up through the focus tree.
// Manually bubble the OnAltReleased event up through the focus tree.
zadjii-msft marked this conversation as resolved.
Show resolved Hide resolved
zadjii-msft marked this conversation as resolved.
Show resolved Hide resolved
auto xamlRoot{ _root->XamlRoot() };
auto focusedObject{ Windows::UI::Xaml::Input::FocusManager::GetFocusedElement(xamlRoot) };
do
{
if (auto f7Listener{ focusedObject.try_as<IF7Listener>() })
if (auto keyListener{ focusedObject.try_as<IDirectKeyListener>() })
{
if (f7Listener.OnF7Pressed())
if (keyListener.OnGotAKey(vkey, down))
{
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/TerminalApp/AppLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ namespace winrt::TerminalApp::implementation

hstring Title();
void TitlebarClicked();
bool OnF7Pressed();
bool OnGotAKey(const uint32_t vkey, const bool down);

void WindowCloseButtonClicked();

Expand Down
4 changes: 2 additions & 2 deletions src/cascadia/TerminalApp/AppLogic.idl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import "../TerminalPage.idl";
import "../ShortcutActionDispatch.idl";
import "../IF7Listener.idl";
import "../IDirectKeyListener.idl";

namespace TerminalApp
{
Expand All @@ -14,7 +14,7 @@ namespace TerminalApp
FullscreenMode,
};

[default_interface] runtimeclass AppLogic : IF7Listener
[default_interface] runtimeclass AppLogic : IDirectKeyListener
{
AppLogic();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ namespace TerminalApp
// Instead, we just pin the uuid and include it in both TermControl and App
// If you update this one, please update the one in TerminalControl\TermControl.idl
// If you change this interface, please update the guid.
// If you press F7 and get a runtime error, go make sure both copies are the same.
// If you press F7 or Alt and get a runtime error, go make sure both copies are the same.
[uuid("339e1a87-5315-4da6-96f0-565549b6472b")]
interface IF7Listener
{
Boolean OnF7Pressed();
interface IDirectKeyListener {
Boolean OnGotAKey(UInt32 vkey, Boolean down);
}
}
2 changes: 1 addition & 1 deletion src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@
<ItemGroup>
<!-- If you add idl files here, make sure to include their implementation's
header in TerminalApp.vcxproj (as well as in this file) -->
<Midl Include="../IF7Listener.idl" />
<Midl Include="../IDirectKeyListener.idl" />
<Midl Include="../App.idl">
<DependentUpon>../App.xaml</DependentUpon>
</Midl>
Expand Down
56 changes: 33 additions & 23 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,36 +683,46 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
}

// Method Description:
// - Manually generate an F7 event into the key bindings or terminal.
// This is required as part of GH#638.
// - Manually handles key events for certain keys that can't be passed to us
// normally. Namely, the keys we're concerned with are F7 down and Alt up.
// Return value:
// - Whether F7 was handled.
bool TermControl::OnF7Pressed()
// - Whether the key was handled.
bool TermControl::OnGotAKey(const uint32_t vkey, const bool down)
{
bool handled{ false };
auto bindings{ _settings.KeyBindings() };

const auto modifiers{ _GetPressedModifierKeys() };

if (bindings)
{
handled = bindings.TryKeyChord({
modifiers.IsCtrlPressed(),
modifiers.IsAltPressed(),
modifiers.IsShiftPressed(),
VK_F7,
});
}

if (!handled)
auto handled = false;
if (vkey == VK_MENU && !down)
{
// _TrySendKeyEvent pretends it didn't handle F7 for some unknown reason.
(void)_TrySendKeyEvent(VK_F7, 0, modifiers, true);
// GH#6438: Note that we're _not_ sending the key up here - that'll
// get passed through XAML to our KeyUp handler normally.
// Manually generate an Alt KeyUp event into the key bindings or terminal.
// This is required as part of GH#6421.
(void)_TrySendKeyEvent(VK_MENU, 0, modifiers, false);
handled = true;
}
else if (vkey == VK_F7 && down)
{
// Manually generate an F7 event into the key bindings or terminal.
// This is required as part of GH#638.
auto bindings{ _settings.KeyBindings() };

if (bindings)
{
handled = bindings.TryKeyChord({
modifiers.IsCtrlPressed(),
modifiers.IsAltPressed(),
modifiers.IsShiftPressed(),
VK_F7,
});
}

if (!handled)
{
// _TrySendKeyEvent pretends it didn't handle F7 for some unknown reason.
(void)_TrySendKeyEvent(VK_F7, 0, modifiers, true);
// GH#6438: Note that we're _not_ sending the key up here - that'll
// get passed through XAML to our KeyUp handler normally.
handled = true;
}
}
return handled;
}

Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/TerminalControl/TermControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation

void CreateSearchBoxControl();

bool OnF7Pressed();
bool OnGotAKey(const uint32_t vkey, const bool down);

bool OnMouseWheel(const Windows::Foundation::Point location, const int32_t delta);

Expand Down
11 changes: 5 additions & 6 deletions src/cascadia/TerminalControl/TermControl.idl
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ namespace Microsoft.Terminal.TerminalControl

// C++/winrt makes it difficult to share this idl between two projects,
// Instead, we just pin the uuid and include it in both TermControl and App
// If you update this one, please update TerminalApp\IF7Listener.idl.
// If you update this one, please update TerminalApp\IDirectKeyListener.idl.
// If you change this interface, please update the guid.
// If you press F7 and get a runtime error, go make sure both copies are the same.
// If you press F7 or Alt and get a runtime error, go make sure both copies are the same.
[uuid("339e1a87-5315-4da6-96f0-565549b6472b")]
interface IF7Listener
{
Boolean OnF7Pressed();
interface IDirectKeyListener {
Boolean OnGotAKey(UInt32 vkey, Boolean down);
}

runtimeclass CopyToClipboardEventArgs
Expand All @@ -32,7 +31,7 @@ namespace Microsoft.Terminal.TerminalControl
void HandleClipboardData(String data);
}

[default_interface] runtimeclass TermControl : Windows.UI.Xaml.Controls.UserControl, IF7Listener, IMouseWheelListener
[default_interface] runtimeclass TermControl : Windows.UI.Xaml.Controls.UserControl, IDirectKeyListener, IMouseWheelListener
{
TermControl();
TermControl(Microsoft.Terminal.Settings.IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
Expand Down
4 changes: 2 additions & 2 deletions src/cascadia/WindowsTerminal/AppHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ AppHost::~AppHost()
_app = nullptr;
}

bool AppHost::OnF7Pressed()
bool AppHost::OnGotAKey(const uint32_t vkey, const bool down)
{
if (_logic)
{
return _logic.OnF7Pressed();
return _logic.OnGotAKey(vkey, down);
}
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/WindowsTerminal/AppHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class AppHost
void AppTitleChanged(const winrt::Windows::Foundation::IInspectable& sender, winrt::hstring newTitle);
void LastTabClosed(const winrt::Windows::Foundation::IInspectable& sender, const winrt::TerminalApp::LastTabClosedEventArgs& args);
void Initialize();
bool OnF7Pressed();
bool OnGotAKey(const uint32_t vkey, const bool down);

private:
bool _useNonClientArea;
Expand Down
19 changes: 18 additions & 1 deletion src/cascadia/WindowsTerminal/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ static bool _messageIsF7Keypress(const MSG& message)
{
return (message.message == WM_KEYDOWN || message.message == WM_SYSKEYDOWN) && message.wParam == VK_F7;
}
static bool _messageIsAltKeyup(const MSG& message)
{
return (message.message == WM_KEYUP || message.message == WM_SYSKEYUP) && message.wParam == VK_MENU;
}

int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
{
Expand Down Expand Up @@ -137,13 +141,26 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
// been handled we can discard the message before we even translate it.
if (_messageIsF7Keypress(message))
{
if (host.OnF7Pressed())
if (host.OnGotAKey(VK_F7, true))
{
// The application consumed the F7. Don't let Xaml get it.
continue;
}
}

// GH#6421 - System XAML will never send an Alt KeyUp event. So, similar
// to how we'll steal the F7 KeyDown above, we'll steal the Alt KeyUp
// here, and plumb it through.
if (_messageIsAltKeyup(message))
{
// Let's pass <Alt> to the application
if (host.OnGotAKey(VK_MENU, false))
{
// The application consumed the Alt. Don't let Xaml get it.
continue;
}
}

TranslateMessage(&message);
DispatchMessage(&message);
}
Expand Down