| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- using System;
- using System.Runtime.Versioning;
- using Android.Views;
- using Avalonia.Android.Platform.Input;
- using Avalonia.Android.Platform.SkiaPlatform;
- using Avalonia.Input;
- using Avalonia.Input.Raw;
- namespace Avalonia.Android.Platform.Specific.Helpers
- {
- internal class AndroidKeyboardEventsHelper<TView> : IDisposable where TView : TopLevelImpl, IAndroidView
- {
- private readonly TView _view;
- public bool HandleEvents { get; set; }
- public AndroidKeyboardEventsHelper(TView view)
- {
- _view = view;
- HandleEvents = true;
- }
- public bool? DispatchKeyEvent(KeyEvent? e, out bool callBase)
- {
- if (!HandleEvents || e is null)
- {
- callBase = true;
- return null;
- }
- return DispatchKeyEventInternal(e, out callBase);
- }
- [ObsoletedOSPlatform("android29.0")]
- static string? UnicodeTextInput(KeyEvent keyEvent)
- {
- return keyEvent.Action == KeyEventActions.Multiple
- && keyEvent.RepeatCount == 0
- && !string.IsNullOrEmpty(keyEvent.Characters)
- ? keyEvent.Characters
- : null;
- }
- private bool? DispatchKeyEventInternal(KeyEvent e, out bool callBase)
- {
- var unicodeTextInput = OperatingSystem.IsAndroidVersionAtLeast(29) ? null : UnicodeTextInput(e);
- var inputRoot = _view.InputRoot;
- if ((e.Action == KeyEventActions.Multiple && unicodeTextInput == null)
- || inputRoot is null)
- {
- callBase = true;
- return null;
- }
- var physicalKey = AndroidKeyInterop.PhysicalKeyFromScanCode(e.ScanCode);
- var keySymbol = GetKeySymbol(e.UnicodeChar, physicalKey);
- var keyDeviceType = GetKeyDeviceType(e);
- var rawKeyEvent = new RawKeyEventArgs(
- AndroidKeyboardDevice.Instance!,
- Convert.ToUInt64(e.EventTime),
- inputRoot,
- e.Action == KeyEventActions.Down ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
- AndroidKeyboardDevice.ConvertKey(e.KeyCode),
- GetModifierKeys(e),
- physicalKey,
- keyDeviceType,
- keySymbol);
- _view.Input?.Invoke(rawKeyEvent);
- bool handled = rawKeyEvent.Handled;
- if ((e.Action == KeyEventActions.Down && e.UnicodeChar >= 32)
- || unicodeTextInput != null)
- {
- var rawTextEvent = new RawTextInputEventArgs(
- AndroidKeyboardDevice.Instance!,
- Convert.ToUInt64(e.EventTime),
- inputRoot,
- unicodeTextInput ?? Convert.ToChar(e.UnicodeChar).ToString()
- );
- _view.Input?.Invoke(rawTextEvent);
- handled = handled || rawTextEvent.Handled;
- }
- if (e.Action == KeyEventActions.Up)
- {
- //nothing to do here more call base no need of more events
- callBase = true;
- return null;
- }
- callBase = false;
- return handled;
- }
- private static RawInputModifiers GetModifierKeys(KeyEvent e)
- {
- var rv = RawInputModifiers.None;
- if (e.IsCtrlPressed) rv |= RawInputModifiers.Control;
- if (e.IsShiftPressed) rv |= RawInputModifiers.Shift;
- 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);
- }
- }
- private KeyDeviceType GetKeyDeviceType(KeyEvent e)
- {
- var source = e.Device?.Sources ?? InputSourceType.Unknown;
- // Remote controller reports itself as "DPad | Keyboard", which is confusing,
- // so we need to double-check KeyboardType as well.
- if (source.HasAnyFlag(InputSourceType.Dpad)
- && e.Device?.KeyboardType == InputKeyboardType.NonAlphabetic)
- return KeyDeviceType.Remote;
- // ReSharper disable BitwiseOperatorOnEnumWithoutFlags - it IS flags enum under the hood.
- if (source.HasAnyFlag(InputSourceType.Joystick | InputSourceType.Gamepad))
- return KeyDeviceType.Gamepad;
- // ReSharper restore BitwiseOperatorOnEnumWithoutFlags
- return KeyDeviceType.Keyboard; // fallback to the keyboard, if unknown.
- }
- public void Dispose()
- {
- HandleEvents = false;
- }
- }
- }
|