Browse Source

restrict souce of input event sto parent view on android (#19289)

release/11.3.3
Emmanuel Hansen 6 months ago
committed by Julien Lebosquain
parent
commit
ccbb126ce1
No known key found for this signature in database GPG Key ID: 1833CAD10ACC46FD
  1. 5
      src/Android/Avalonia.Android/AvaloniaActivity.cs
  2. 67
      src/Android/Avalonia.Android/AvaloniaView.Input.cs
  3. 21
      src/Android/Avalonia.Android/AvaloniaView.cs
  4. 3
      src/Android/Avalonia.Android/Platform/Input/AndroidInputMethod.cs
  5. 30
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

5
src/Android/Avalonia.Android/AvaloniaActivity.cs

@ -8,10 +8,10 @@ using Android.OS;
using Android.Runtime;
using Android.Views;
using AndroidX.AppCompat.App;
using Avalonia.Platform;
using Avalonia.Android.Platform;
using Avalonia.Android.Platform.Storage;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform;
namespace Avalonia.Android;
@ -48,6 +48,9 @@ public class AvaloniaActivity : AppCompatActivity, IAvaloniaActivity
SetContentView(_view);
// By default, the view isn't focused if the activity is created anew, so we force focus.
_view.RequestFocus();
_listener = new GlobalLayoutListener(_view);
_view.ViewTreeObserver?.AddOnGlobalLayoutListener(_listener);

67
src/Android/Avalonia.Android/AvaloniaView.Input.cs

@ -0,0 +1,67 @@
using System;
using Android.Views;
using Android.Views.InputMethods;
using Avalonia.Android.Platform.SkiaPlatform;
namespace Avalonia.Android
{
public partial class AvaloniaView : IInitEditorInfo
{
private Func<TopLevelImpl, EditorInfo, IInputConnection>? _initEditorInfo;
public override IInputConnection OnCreateInputConnection(EditorInfo? outAttrs)
{
return _initEditorInfo?.Invoke(_view, outAttrs!)!;
}
void IInitEditorInfo.InitEditorInfo(Func<TopLevelImpl, EditorInfo, IInputConnection> init)
{
_initEditorInfo = init;
}
protected override void OnFocusChanged(bool gainFocus, FocusSearchDirection direction, global::Android.Graphics.Rect? previouslyFocusedRect)
{
base.OnFocusChanged(gainFocus, direction, previouslyFocusedRect);
_accessHelper.OnFocusChanged(gainFocus, (int)direction, previouslyFocusedRect);
}
protected override bool DispatchHoverEvent(MotionEvent? e)
{
return _accessHelper.DispatchHoverEvent(e!) || base.DispatchHoverEvent(e);
}
protected override bool DispatchGenericPointerEvent(MotionEvent? e)
{
var result = _view.PointerHelper.DispatchMotionEvent(e, out var callBase);
var baseResult = callBase && base.DispatchGenericPointerEvent(e);
return result ?? baseResult;
}
public override bool DispatchTouchEvent(MotionEvent? e)
{
var result = _view.PointerHelper.DispatchMotionEvent(e, out var callBase);
var baseResult = callBase && base.DispatchTouchEvent(e);
if(result == true)
{
// Request focus for this view
RequestFocus();
}
return result ?? baseResult;
}
public override bool DispatchKeyEvent(KeyEvent? e)
{
var res = _view.KeyboardHelper.DispatchKeyEvent(e, out var callBase);
if (res == false)
callBase = !_accessHelper.DispatchKeyEvent(e!) && callBase;
var baseResult = callBase && base.DispatchKeyEvent(e);
return res ?? baseResult;
}
}
}

21
src/Android/Avalonia.Android/AvaloniaView.cs

@ -17,7 +17,7 @@ using Avalonia.Rendering;
namespace Avalonia.Android
{
public class AvaloniaView : FrameLayout
public partial class AvaloniaView : FrameLayout
{
private EmbeddableControlRoot _root;
private readonly ViewImpl _view;
@ -71,24 +71,6 @@ namespace Avalonia.Android
_root = null!;
}
protected override void OnFocusChanged(bool gainFocus, FocusSearchDirection direction, global::Android.Graphics.Rect? previouslyFocusedRect)
{
base.OnFocusChanged(gainFocus, direction, previouslyFocusedRect);
_accessHelper.OnFocusChanged(gainFocus, (int)direction, previouslyFocusedRect);
}
protected override bool DispatchHoverEvent(MotionEvent? e)
{
return _accessHelper.DispatchHoverEvent(e!) || base.DispatchHoverEvent(e);
}
public override bool DispatchKeyEvent(KeyEvent? e)
{
if (!_view.View.DispatchKeyEvent(e))
return _accessHelper.DispatchKeyEvent(e!) || base.DispatchKeyEvent(e);
return true;
}
[SupportedOSPlatform("android24.0")]
public override void OnVisibilityAggregated(bool isVisible)
{
@ -149,7 +131,6 @@ namespace Avalonia.Android
{
public ViewImpl(AvaloniaView avaloniaView) : base(avaloniaView)
{
View.Focusable = true;
View.FocusChange += ViewImpl_FocusChange;
}

3
src/Android/Avalonia.Android/Platform/Input/AndroidInputMethod.cs

@ -44,9 +44,6 @@ namespace Avalonia.Android.Platform.Input
public AndroidInputMethod(TView host)
{
if (host.OnCheckIsTextEditor() == false)
throw new InvalidOperationException("Host should return true from OnCheckIsTextEditor()");
_host = host;
_imm = host.Context?.GetSystemService(Context.InputMethodService).JavaCast<InputMethodManager>()
?? throw new InvalidOperationException("Context.InputMethodService is expected to be not null.");

30
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -5,9 +5,7 @@ using Android.Content;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Runtime;
using Android.Text;
using Android.Views;
using Android.Views.InputMethods;
using AndroidX.AppCompat.App;
using Avalonia.Android.Platform.Input;
using Avalonia.Android.Platform.Specific;
@ -37,7 +35,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
private readonly AndroidKeyboardEventsHelper<TopLevelImpl> _keyboardHelper;
private readonly AndroidMotionEventsHelper _pointerHelper;
private readonly AndroidInputMethod<ViewImpl> _textInputMethod;
private readonly AndroidInputMethod<AvaloniaView> _textInputMethod;
private readonly INativeControlHostImpl _nativeControlHost;
private readonly IStorageProvider? _storageProvider;
private readonly AndroidSystemNavigationManagerImpl _systemNavigationManager;
@ -56,7 +54,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
}
_view = new ViewImpl(avaloniaView.Context, this, placeOnTop);
_textInputMethod = new AndroidInputMethod<ViewImpl>(_view);
_textInputMethod = new AndroidInputMethod<AvaloniaView>(avaloniaView);
_keyboardHelper = new AndroidKeyboardEventsHelper<TopLevelImpl>(this);
_pointerHelper = new AndroidMotionEventsHelper(this);
_gl = new EglGlPlatformSurface(this);
@ -169,7 +167,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
Resized?.Invoke(size, WindowResizeReason.Layout);
}
class ViewImpl : InvalidationAwareSurfaceView, ISurfaceHolderCallback, IInitEditorInfo
class ViewImpl : InvalidationAwareSurfaceView, ISurfaceHolderCallback
{
private readonly TopLevelImpl _tl;
private Size _oldSize;
@ -246,24 +244,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
base.SurfaceChanged(holder, format, width, height);
}
public sealed override bool OnCheckIsTextEditor()
{
return true;
}
private Func<TopLevelImpl, EditorInfo, IInputConnection>? _initEditorInfo;
public void InitEditorInfo(Func<TopLevelImpl, EditorInfo, IInputConnection> init)
{
_initEditorInfo = init;
}
public sealed override IInputConnection OnCreateInputConnection(EditorInfo? outAttrs)
{
return _initEditorInfo?.Invoke(_tl, outAttrs!)!;
}
}
public IPopupImpl? CreatePopup() => null;
@ -307,6 +287,10 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public double Scaling => RenderScaling;
internal AndroidKeyboardEventsHelper<TopLevelImpl> KeyboardHelper => _keyboardHelper;
internal AndroidMotionEventsHelper PointerHelper => _pointerHelper;
public void SetTransparencyLevelHint(IReadOnlyList<WindowTransparencyLevel> transparencyLevels)
{
if (_view.Context is not AvaloniaMainActivity activity)

Loading…
Cancel
Save