Skip to content

Commit

Permalink
Merge pull request #12347 from flexxxxer/master
Browse files Browse the repository at this point in the history
Fix not working hotkey on a custom control. closes #12323
  • Loading branch information
maxkatz6 authored Aug 2, 2023
2 parents b702e24 + a5c7b1d commit 4d6cd42
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/Avalonia.Controls/HotkeyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,10 @@ static HotKeyManager()
return;
var control = args.Sender as Control;
if (control is not IClickableControl)
if (control is not IClickableControl and not ICommandSource)
{
Logging.Logger.TryGet(Logging.LogEventLevel.Warning, Logging.LogArea.Control)?.Log(control,
$"The element {args.Sender.GetType().Name} does not implement IClickableControl and does not support binding a HotKey ({args.NewValue}).");
$"The element {args.Sender.GetType().Name} does not implement IClickableControl nor ICommandSource and does not support binding a HotKey ({args.NewValue}).");
return;
}
Expand Down
122 changes: 122 additions & 0 deletions tests/Avalonia.Controls.UnitTests/HotKeyedControlsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
using System;
using System.Windows.Input;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.LogicalTree;
using Avalonia.Platform;
using Avalonia.UnitTests;
using Moq;
using Xunit;

namespace Avalonia.Controls.UnitTests
{
internal class HotKeyedTextBox : TextBox, ICommandSource
{
private class DelegateCommand : ICommand
{
private readonly Action _action;
public DelegateCommand(Action action) => _action = action;
public event EventHandler CanExecuteChanged { add { } remove { } }
public bool CanExecute(object parameter) => true;
public void Execute(object parameter) => _action();
}

public static readonly StyledProperty<KeyGesture> HotKeyProperty =
HotKeyManager.HotKeyProperty.AddOwner<HotKeyedTextBox>();

private KeyGesture _hotkey;

public KeyGesture HotKey
{
get => GetValue(HotKeyProperty);
set => SetValue(HotKeyProperty, value);
}

protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
if (_hotkey != null)
{
this.SetValue(HotKeyProperty, _hotkey);
}

base.OnAttachedToLogicalTree(e);
}

protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
if (this.HotKey != null)
{
_hotkey = this.HotKey;
this.SetValue(HotKeyProperty, null);
}

base.OnDetachedFromLogicalTree(e);
}

public void CanExecuteChanged(object sender, EventArgs e)
{
}

protected override Type StyleKeyOverride => typeof(TextBox);

public ICommand Command => _command;

public object CommandParameter => null;

private readonly DelegateCommand _command;

public HotKeyedTextBox()
{
_command = new DelegateCommand(() => Focus());
}
}

public class HotKeyedControlsTests
{
private static Window PreparedWindow(object content = null)
{
var platform = AvaloniaLocator.Current.GetRequiredService<IWindowingPlatform>();
var windowImpl = Mock.Get(platform.CreateWindow());
windowImpl.Setup(x => x.Compositor).Returns(RendererMocks.CreateDummyCompositor());
var w = new Window(windowImpl.Object) { Content = content };
w.ApplyTemplate();
return w;
}

private static IDisposable CreateServicesWithFocus()
{
return UnitTestApplication.Start(
TestServices.StyledWindow.With(
windowingPlatform: new MockWindowingPlatform(
null,
window => MockWindowingPlatform.CreatePopupMock(window).Object),
focusManager: new FocusManager(),
keyboardDevice: () => new KeyboardDevice()));
}

[Fact]
public void HotKeyedTextBox_Focus_Performed_On_Hotkey()
{
using var _ = CreateServicesWithFocus();

var keyboardDevice = new KeyboardDevice();
var hotKeyedTextBox = new HotKeyedTextBox { HotKey = new KeyGesture(Key.F, KeyModifiers.Control) };
var root = PreparedWindow();
root.Content = hotKeyedTextBox;
root.Show();

Assert.False(hotKeyedTextBox.IsFocused);

keyboardDevice.ProcessRawEvent(
new RawKeyEventArgs(
keyboardDevice,
0,
root,
RawKeyEventType.KeyDown,
Key.F,
RawInputModifiers.Control));

Assert.True(hotKeyedTextBox.IsFocused);
}
}
}

0 comments on commit 4d6cd42

Please sign in to comment.