Fix CommandPalette to prefer inner interactions over bindings (#9056)

* Currently TerminalPage registers on CmdPal key events:
  * To invoke bindings when the palette is open
  * Since some key combinations are not triggered by KeyDown 
    it registers for PreviewKeyDown
* As a result bindings might be preferred over navigation
  (e.g., ctrl+v will paste into Terminal rather than into search box)
* To fix this, I moved all interactions inside the CmdPal into
  PreviewKeyDown as well
* In addition, added specific handling for copy/paste
  which now allow to interact with search box even if not focused

Closes #9044
This commit is contained in:
Don-Vito 2021-02-10 22:35:46 +02:00 committed by GitHub
parent 3b247812ce
commit ed19301ad3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 62 deletions

View file

@ -240,6 +240,9 @@ namespace winrt::TerminalApp::implementation
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
auto key = e.OriginalKey();
auto const ctrlDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
auto const altDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
auto const shiftDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
// Some keypresses such as Tab, Return, Esc, and Arrow Keys are ignored by controls because
// they're not considered input key presses. While they don't raise KeyDown events,
@ -250,10 +253,6 @@ namespace winrt::TerminalApp::implementation
// a really widely used keyboard navigation key.
if (_currentMode == CommandPaletteMode::TabSwitchMode && _keymap)
{
auto const ctrlDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control), CoreVirtualKeyStates::Down);
auto const altDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Menu), CoreVirtualKeyStates::Down);
auto const shiftDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
winrt::Microsoft::Terminal::TerminalControl::KeyChord kc{ ctrlDown, altDown, shiftDown, static_cast<int32_t>(key) };
const auto action = _keymap.TryLookup(kc);
if (action)
@ -269,41 +268,21 @@ namespace winrt::TerminalApp::implementation
e.Handled(true);
}
}
}
else if (key == VirtualKey::Home)
{
auto const state = CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control);
if (WI_IsFlagSet(state, CoreVirtualKeyStates::Down))
{
ScrollToTop();
e.Handled(true);
}
}
else if (key == VirtualKey::End)
{
auto const state = CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Control);
if (WI_IsFlagSet(state, CoreVirtualKeyStates::Down))
{
ScrollToBottom();
e.Handled(true);
}
}
}
// Method Description:
// - Process keystrokes in the input box. This is used for moving focus up
// and down the list of commands in Action mode, and for executing
// commands in both Action mode and Commandline mode.
// Arguments:
// - e: the KeyRoutedEventArgs containing info about the keystroke.
// Return Value:
// - <none>
void CommandPalette::_keyDownHandler(IInspectable const& /*sender*/,
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
auto key = e.OriginalKey();
return;
}
if (key == VirtualKey::Up)
if (key == VirtualKey::Home && ctrlDown)
{
ScrollToTop();
e.Handled(true);
}
else if (key == VirtualKey::End && ctrlDown)
{
ScrollToBottom();
e.Handled(true);
}
else if (key == VirtualKey::Up)
{
// Action Mode: Move focus to the next item in the list.
SelectNextItem(false);
@ -349,16 +328,22 @@ namespace winrt::TerminalApp::implementation
e.Handled(true);
}
else if (key == VirtualKey::Back)
else if (key == VirtualKey::Back && _searchBox().Text().empty() && _lastFilterTextWasEmpty && _currentMode == CommandPaletteMode::ActionMode)
{
// If the last filter text was empty, and we're backspacing from
// that state, then the user "backspaced" the virtual '>' we're
// using as the action mode indicator. Switch into commandline mode.
if (_searchBox().Text().empty() && _lastFilterTextWasEmpty && _currentMode == CommandPaletteMode::ActionMode)
{
_switchToMode(CommandPaletteMode::CommandlineMode);
}
_switchToMode(CommandPaletteMode::CommandlineMode);
e.Handled(true);
}
else if (key == VirtualKey::C && ctrlDown)
{
_searchBox().CopySelectionToClipboard();
e.Handled(true);
}
else if (key == VirtualKey::V && ctrlDown)
{
_searchBox().PasteFromClipboard();
e.Handled(true);
}
}

View file

@ -75,8 +75,7 @@ namespace winrt::TerminalApp::implementation
Windows::UI::Xaml::RoutedEventArgs const& args);
void _previewKeyDownHandler(Windows::Foundation::IInspectable const& sender,
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
void _keyDownHandler(Windows::Foundation::IInspectable const& sender,
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
void _keyUpHandler(Windows::Foundation::IInspectable const& sender,
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);

View file

@ -16,7 +16,6 @@ the MIT License. See LICENSE in the project root for license information. -->
AllowFocusOnInteraction="True"
PointerPressed="_rootPointerPressed"
PreviewKeyDown="_previewKeyDownHandler"
KeyDown="_keyDownHandler"
PreviewKeyUp="_keyUpHandler"
LostFocus="_lostFocusHandler"
mc:Ignorable="d"
@ -47,13 +46,13 @@ the MIT License. See LICENSE in the project root for license information. -->
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="16"/>
<!-- icon -->
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<!-- command label -->
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<!-- key chord -->
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="16"/>
<!-- gutter for scrollbar -->
</Grid.ColumnDefinitions>
@ -119,15 +118,15 @@ the MIT License. See LICENSE in the project root for license information. -->
<Grid HorizontalAlignment="Stretch" ColumnSpacing="8" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="16"/>
<!-- icon / progress -->
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<!-- command label -->
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<!-- gutter for indicators -->
<ColumnDefinition Width="Auto"/>
<!-- Indicators -->
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="16"/>
<!-- gutter for scrollbar -->
</Grid.ColumnDefinitions>
@ -160,12 +159,12 @@ the MIT License. See LICENSE in the project root for license information. -->
VerticalAlignment="Center"
HorizontalAlignment="Right"
Orientation="Horizontal">
<FontIcon
FontFamily="Segoe MDL2 Assets"
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).BellIndicator, Mode=OneWay}"
Glyph="&#xEA8F;"
FontSize="12"
<FontIcon
FontFamily="Segoe MDL2 Assets"
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).BellIndicator, Mode=OneWay}"
Glyph="&#xEA8F;"
FontSize="12"
Margin="0,0,8,0"/>
<FontIcon
@ -187,7 +186,7 @@ the MIT License. See LICENSE in the project root for license information. -->
</ListViewItem>
</DataTemplate>
<local:PaletteItemTemplateSelector x:Key="PaletteItemTemplateSelector" TabItemTemplate="{StaticResource TabItemTemplate}" GeneralItemTemplate="{StaticResource GeneralItemTemplate}"/>
<local:PaletteItemTemplateSelector x:Key="PaletteItemTemplateSelector" TabItemTemplate="{StaticResource TabItemTemplate}" GeneralItemTemplate="{StaticResource GeneralItemTemplate}"/>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
@ -431,7 +430,6 @@ the MIT License. See LICENSE in the project root for license information. -->
AllowDrop="False"
IsItemClickEnabled="True"
ItemClick="_listItemClicked"
PreviewKeyDown="_keyDownHandler"
ItemsSource="{x:Bind FilteredActions}"
ItemTemplateSelector="{StaticResource PaletteItemTemplateSelector}">
</ListView>