Browse Source

Added PhysicalKey handling for Android (#13006)

pull/12445/head
Julien Lebosquain 2 years ago
committed by GitHub
parent
commit
dd26b6d232
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 200
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyInterop.cs
  2. 38
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs
  3. 2
      src/Avalonia.Base/Input/KeySymbolHelper.cs

200
src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyInterop.cs

@ -0,0 +1,200 @@
#nullable enable
using System.Collections.Generic;
using Avalonia.Input;
namespace Avalonia.Android.Platform.Specific.Helpers;
internal static class AndroidKeyInterop
{
// evdev scan code to physical key map.
// https://github.com/chromium/chromium/blob/main/ui/events/keycodes/dom/dom_code_data.inc
// This list has the same order as the PhysicalKey enum.{
private static readonly Dictionary<byte, PhysicalKey> s_physicalKeyFromScanCode = new(0xA2)
{
// Writing System Keys
{ 0x29, PhysicalKey.Backquote },
{ 0x2B, PhysicalKey.Backslash },
{ 0x1A, PhysicalKey.BracketLeft },
{ 0x1B, PhysicalKey.BracketRight },
{ 0x33, PhysicalKey.Comma },
{ 0x0B, PhysicalKey.Digit0 },
{ 0x02, PhysicalKey.Digit1 },
{ 0x03, PhysicalKey.Digit2 },
{ 0x04, PhysicalKey.Digit3 },
{ 0x05, PhysicalKey.Digit4 },
{ 0x06, PhysicalKey.Digit5 },
{ 0x07, PhysicalKey.Digit6 },
{ 0x08, PhysicalKey.Digit7 },
{ 0x09, PhysicalKey.Digit8 },
{ 0x0A, PhysicalKey.Digit9 },
{ 0x0D, PhysicalKey.Equal },
{ 0x56, PhysicalKey.IntlBackslash },
{ 0x59, PhysicalKey.IntlRo },
{ 0x7C, PhysicalKey.IntlYen },
{ 0x1E, PhysicalKey.A },
{ 0x30, PhysicalKey.B },
{ 0x2E, PhysicalKey.C },
{ 0x20, PhysicalKey.D },
{ 0x12, PhysicalKey.E },
{ 0x21, PhysicalKey.F },
{ 0x22, PhysicalKey.G },
{ 0x23, PhysicalKey.H },
{ 0x17, PhysicalKey.I },
{ 0x24, PhysicalKey.J },
{ 0x25, PhysicalKey.K },
{ 0x26, PhysicalKey.L },
{ 0x32, PhysicalKey.M },
{ 0x31, PhysicalKey.N },
{ 0x18, PhysicalKey.O },
{ 0x19, PhysicalKey.P },
{ 0x10, PhysicalKey.Q },
{ 0x13, PhysicalKey.R },
{ 0x1F, PhysicalKey.S },
{ 0x14, PhysicalKey.T },
{ 0x16, PhysicalKey.U },
{ 0x2F, PhysicalKey.V },
{ 0x11, PhysicalKey.W },
{ 0x2D, PhysicalKey.X },
{ 0x15, PhysicalKey.Y },
{ 0x2C, PhysicalKey.Z },
{ 0x0C, PhysicalKey.Minus },
{ 0x34, PhysicalKey.Period },
{ 0x28, PhysicalKey.Quote },
{ 0x27, PhysicalKey.Semicolon },
{ 0x35, PhysicalKey.Slash },
// Functional Keys
{ 0x38, PhysicalKey.AltLeft },
{ 0x64, PhysicalKey.AltRight },
{ 0x0E, PhysicalKey.Backspace },
{ 0x3A, PhysicalKey.CapsLock },
{ 0x7F, PhysicalKey.ContextMenu },
{ 0x1D, PhysicalKey.ControlLeft },
{ 0x61, PhysicalKey.ControlRight },
{ 0x1C, PhysicalKey.Enter },
{ 0x7D, PhysicalKey.MetaLeft },
{ 0x7E, PhysicalKey.MetaRight },
{ 0x2A, PhysicalKey.ShiftLeft },
{ 0x36, PhysicalKey.ShiftRight },
{ 0x39, PhysicalKey.Space },
{ 0x0F, PhysicalKey.Tab },
{ 0x5C, PhysicalKey.Convert },
{ 0x5D, PhysicalKey.KanaMode },
{ 0x7A, PhysicalKey.Lang1 },
{ 0x7B, PhysicalKey.Lang2 },
{ 0x5A, PhysicalKey.Lang3 },
{ 0x5B, PhysicalKey.Lang4 },
{ 0x55, PhysicalKey.Lang5 },
{ 0x5E, PhysicalKey.NonConvert },
// Control Pad Section
{ 0x6F, PhysicalKey.Delete },
{ 0x6B, PhysicalKey.End },
{ 0x8A, PhysicalKey.Help },
{ 0x66, PhysicalKey.Home },
{ 0x6E, PhysicalKey.Insert },
{ 0x6D, PhysicalKey.PageDown },
{ 0x68, PhysicalKey.PageUp },
// Arrow Pad Section
{ 0x6C, PhysicalKey.ArrowDown },
{ 0x69, PhysicalKey.ArrowLeft },
{ 0x6A, PhysicalKey.ArrowRight },
{ 0x67, PhysicalKey.ArrowUp },
// Numpad Section
{ 0x45, PhysicalKey.NumLock },
{ 0x52, PhysicalKey.NumPad0 },
{ 0x4F, PhysicalKey.NumPad1 },
{ 0x50, PhysicalKey.NumPad2 },
{ 0x51, PhysicalKey.NumPad3 },
{ 0x4B, PhysicalKey.NumPad4 },
{ 0x4C, PhysicalKey.NumPad5 },
{ 0x4D, PhysicalKey.NumPad6 },
{ 0x47, PhysicalKey.NumPad7 },
{ 0x48, PhysicalKey.NumPad8 },
{ 0x49, PhysicalKey.NumPad9 },
{ 0x4E, PhysicalKey.NumPadAdd },
//{ , PhysicalKey.NumPadClear },
{ 0x79, PhysicalKey.NumPadComma },
{ 0x53, PhysicalKey.NumPadDecimal },
{ 0x62, PhysicalKey.NumPadDivide },
{ 0x60, PhysicalKey.NumPadEnter },
{ 0x75, PhysicalKey.NumPadEqual },
{ 0x37, PhysicalKey.NumPadMultiply },
{ 0xB3, PhysicalKey.NumPadParenLeft },
{ 0xB4, PhysicalKey.NumPadParenRight },
{ 0x4A, PhysicalKey.NumPadSubtract },
// Function Section
{ 0x01, PhysicalKey.Escape },
{ 0x3B, PhysicalKey.F1 },
{ 0x3C, PhysicalKey.F2 },
{ 0x3D, PhysicalKey.F3 },
{ 0x3E, PhysicalKey.F4 },
{ 0x3F, PhysicalKey.F5 },
{ 0x40, PhysicalKey.F6 },
{ 0x41, PhysicalKey.F7 },
{ 0x42, PhysicalKey.F8 },
{ 0x43, PhysicalKey.F9 },
{ 0x44, PhysicalKey.F10 },
{ 0x57, PhysicalKey.F11 },
{ 0x58, PhysicalKey.F12 },
{ 0xB7, PhysicalKey.F13 },
{ 0xB8, PhysicalKey.F14 },
{ 0xB9, PhysicalKey.F15 },
{ 0xBA, PhysicalKey.F16 },
{ 0xBB, PhysicalKey.F17 },
{ 0xBC, PhysicalKey.F18 },
{ 0xBD, PhysicalKey.F19 },
{ 0xBE, PhysicalKey.F20 },
{ 0xBF, PhysicalKey.F21 },
{ 0xC0, PhysicalKey.F22 },
{ 0xC1, PhysicalKey.F23 },
{ 0xC2, PhysicalKey.F24 },
{ 0x63, PhysicalKey.PrintScreen },
{ 0x46, PhysicalKey.ScrollLock },
{ 0x77, PhysicalKey.Pause },
// Media Keys
{ 0x9E, PhysicalKey.BrowserBack },
{ 0x9C, PhysicalKey.BrowserFavorites },
{ 0x9F, PhysicalKey.BrowserForward },
{ 0xAC, PhysicalKey.BrowserHome },
{ 0xAD, PhysicalKey.BrowserRefresh },
{ 0xD9, PhysicalKey.BrowserSearch },
{ 0x80, PhysicalKey.BrowserStop },
{ 0xA1, PhysicalKey.Eject },
{ 0x90, PhysicalKey.LaunchApp1 },
{ 0x8C, PhysicalKey.LaunchApp2 },
{ 0x9B, PhysicalKey.LaunchMail },
{ 0xA4, PhysicalKey.MediaPlayPause },
{ 0xAB, PhysicalKey.MediaSelect },
{ 0xA6, PhysicalKey.MediaStop },
{ 0xA3, PhysicalKey.MediaTrackNext },
{ 0xA5, PhysicalKey.MediaTrackPrevious },
{ 0x74, PhysicalKey.Power },
{ 0x8E, PhysicalKey.Sleep },
{ 0x72, PhysicalKey.AudioVolumeDown },
{ 0x71, PhysicalKey.AudioVolumeMute },
{ 0x73, PhysicalKey.AudioVolumeUp },
{ 0x8F, PhysicalKey.WakeUp },
// Legacy Keys
{ 0x81, PhysicalKey.Again },
{ 0x85, PhysicalKey.Copy },
{ 0x89, PhysicalKey.Cut },
{ 0x88, PhysicalKey.Find },
{ 0x86, PhysicalKey.Open },
{ 0x87, PhysicalKey.Paste },
//{ , PhysicalKey.Props },
{ 0x84, PhysicalKey.Select },
{ 0x83, PhysicalKey.Undo }
};
public static PhysicalKey PhysicalKeyFromScanCode(int scanCode)
=> scanCode is > 0 and <= 255 && s_physicalKeyFromScanCode.TryGetValue((byte)scanCode, out var result) ?
result :
PhysicalKey.None;
}

38
src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs

@ -1,3 +1,5 @@
#nullable enable
using System;
using Android.Views;
using Avalonia.Android.Platform.Input;
@ -30,11 +32,11 @@ namespace Avalonia.Android.Platform.Specific.Helpers
return DispatchKeyEventInternal(e, out callBase);
}
static string UnicodeTextInput(KeyEvent keyEvent)
static string? UnicodeTextInput(KeyEvent keyEvent)
{
return keyEvent.Action == KeyEventActions.Multiple
&& keyEvent.RepeatCount == 0
&& !string.IsNullOrEmpty(keyEvent?.Characters)
&& !string.IsNullOrEmpty(keyEvent.Characters)
? keyEvent.Characters
: null;
}
@ -49,6 +51,9 @@ namespace Avalonia.Android.Platform.Specific.Helpers
return null;
}
var physicalKey = AndroidKeyInterop.PhysicalKeyFromScanCode(e.ScanCode);
var keySymbol = GetKeySymbol(e.UnicodeChar, physicalKey);
var rawKeyEvent = new RawKeyEventArgs(
AndroidKeyboardDevice.Instance,
Convert.ToUInt64(e.EventTime),
@ -56,8 +61,8 @@ namespace Avalonia.Android.Platform.Specific.Helpers
e.Action == KeyEventActions.Down ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
AndroidKeyboardDevice.ConvertKey(e.KeyCode),
GetModifierKeys(e),
PhysicalKey.None,
e.DisplayLabel == '\0' ? null : new string(e.DisplayLabel, 1));
physicalKey,
keySymbol);
_view.Input(rawKeyEvent);
@ -94,6 +99,31 @@ namespace Avalonia.Android.Platform.Specific.Helpers
return rv;
}
private static string? GetKeySymbol(int unicodeChar, PhysicalKey physicalKey)
{
// Handle a very limited set of control characters so that we're consistent with other platforms
// (matches KeySymbolHelper.IsAllowedAsciiKeySymbol)
switch (physicalKey)
{
case PhysicalKey.Backspace:
return "\b";
case PhysicalKey.Tab:
return "\t";
case PhysicalKey.Enter:
case PhysicalKey.NumPadEnter:
return "\r";
case PhysicalKey.Escape:
return "\u001B";
default:
if (unicodeChar <= 0x7F)
{
var asciiChar = (char)unicodeChar;
return KeySymbolHelper.IsAllowedAsciiKeySymbol(asciiChar) ? asciiChar.ToString() : null;
}
return char.ConvertFromUtf32(unicodeChar);
}
}
public void Dispose()
{
HandleEvents = false;

2
src/Avalonia.Base/Input/KeySymbolHelper.cs

@ -18,7 +18,7 @@ internal static class KeySymbolHelper
}
}
if (c == 0x07) // delete
if (c == 0x7F) // delete
return false;
return true;

Loading…
Cancel
Save