Skip to content

Commit

Permalink
Use TouchDevice on Android.
Browse files Browse the repository at this point in the history
  • Loading branch information
jp2masa committed Mar 20, 2021
1 parent bfee402 commit 7fb6e14
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 95 deletions.
8 changes: 2 additions & 6 deletions src/Android/Avalonia.Android/AvaloniaActivity.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

using Android.App;
using Android.OS;
using Android.Views;
Expand All @@ -7,7 +6,6 @@ namespace Avalonia.Android
{
public abstract class AvaloniaActivity : Activity
{

internal AvaloniaView View;
object _content;

Expand Down Expand Up @@ -35,9 +33,7 @@ public object Content
}
}

public override bool DispatchKeyEvent(KeyEvent e)
{
return View.DispatchKeyEvent(e);
}
public override bool DispatchKeyEvent(KeyEvent e) =>
View.DispatchKeyEvent(e) ? true : base.DispatchKeyEvent(e);
}
}
14 changes: 0 additions & 14 deletions src/Android/Avalonia.Android/Platform/Input/AndroidMouseDevice.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using Android.Views;

using Avalonia.Android.OpenGL;
using Avalonia.Android.Platform.Input;
using Avalonia.Android.Platform.Specific;
using Avalonia.Android.Platform.Specific.Helpers;
using Avalonia.Controls;
Expand Down Expand Up @@ -35,7 +34,7 @@ public TopLevelImpl(Context context, bool placeOnTop = false)
_view = new ViewImpl(context, this, placeOnTop);
_keyboardHelper = new AndroidKeyboardEventsHelper<TopLevelImpl>(this);
_touchHelper = new AndroidTouchEventsHelper<TopLevelImpl>(this, () => InputRoot,
p => GetAvaloniaPointFromEvent(p));
GetAvaloniaPointFromEvent);

_gl = GlPlatformSurface.TryCreate(this);
_framebuffer = new FramebufferManager(this);
Expand All @@ -44,8 +43,6 @@ public TopLevelImpl(Context context, bool placeOnTop = false)
_view.Resources.DisplayMetrics.HeightPixels);
}



private bool _handleEvents;

public bool HandleEvents
Expand All @@ -58,7 +55,8 @@ public bool HandleEvents
}
}

public virtual Point GetAvaloniaPointFromEvent(MotionEvent e) => new Point(e.GetX(), e.GetY());
public virtual Point GetAvaloniaPointFromEvent(MotionEvent e, int pointerIndex) =>
new Point(e.GetX(pointerIndex), e.GetY(pointerIndex)) / RenderScaling;

public IInputRoot InputRoot { get; private set; }

Expand All @@ -76,7 +74,7 @@ public virtual Size ClientSize
}
}

public IMouseDevice MouseDevice => AndroidMouseDevice.Instance;
public IMouseDevice MouseDevice { get; } = new MouseDevice();

public Action Closed { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,17 @@ public class AndroidTouchEventsHelper<TView> : IDisposable where TView : ITopLev
private TView _view;
public bool HandleEvents { get; set; }

public AndroidTouchEventsHelper(TView view, Func<IInputRoot> getInputRoot, Func<MotionEvent, Point> getPointfunc)
public AndroidTouchEventsHelper(TView view, Func<IInputRoot> getInputRoot, Func<MotionEvent, int, Point> getPointfunc)
{
this._view = view;
HandleEvents = true;
_getPointFunc = getPointfunc;
_getInputRoot = getInputRoot;
}

private DateTime _lastTouchMoveEventTime = DateTime.Now;
private Point? _lastTouchMovePoint;
private Func<MotionEvent, Point> _getPointFunc;
private TouchDevice _touchDevice = new TouchDevice();
private Func<MotionEvent, int, Point> _getPointFunc;
private Func<IInputRoot> _getInputRoot;
private Point _point;

public bool? DispatchTouchEvent(MotionEvent e, out bool callBase)
{
Expand All @@ -33,89 +31,44 @@ public AndroidTouchEventsHelper(TView view, Func<IInputRoot> getInputRoot, Func<
return null;
}

RawPointerEventType? mouseEventType = null;
var eventTime = DateTime.Now;

//Basic touch support
switch (e.Action)
var pointerEventType = e.Action switch
{
case MotionEventActions.Move:
//may be bot flood the evnt system with too many event especially on not so powerfull mobile devices
if ((eventTime - _lastTouchMoveEventTime).TotalMilliseconds > 10)
{
mouseEventType = RawPointerEventType.Move;
}
break;

case MotionEventActions.Down:
mouseEventType = RawPointerEventType.LeftButtonDown;
MotionEventActions.Down => RawPointerEventType.TouchBegin,
MotionEventActions.Up => RawPointerEventType.TouchEnd,
MotionEventActions.Cancel => RawPointerEventType.TouchCancel,
_ => RawPointerEventType.TouchUpdate
};

break;
if (e.Action.HasFlag(MotionEventActions.PointerDown))
{
pointerEventType = RawPointerEventType.TouchBegin;
}

case MotionEventActions.Up:
mouseEventType = RawPointerEventType.LeftButtonUp;
break;
if (e.Action.HasFlag(MotionEventActions.PointerUp))
{
pointerEventType = RawPointerEventType.TouchEnd;
}

if (mouseEventType != null)
for (int i = 0; i < e.PointerCount; i++)
{
//if point is in view otherwise it's possible avalonia not to find the proper window to dispatch the event
_point = _getPointFunc(e);
var point = _getPointFunc(e, i);

double x = _view.View.GetX();
double y = _view.View.GetY();
double r = x + _view.View.Width;
double b = y + _view.View.Height;

if (x <= _point.X && r >= _point.X && y <= _point.Y && b >= _point.Y)
if (x <= point.X && r >= point.X && y <= point.Y && b >= point.Y)
{
var inputRoot = _getInputRoot();
var mouseDevice = Avalonia.Android.Platform.Input.AndroidMouseDevice.Instance;

//in order the controls to work in a predictable way
//we need to generate mouse move before first mouse down event
//as this is the way buttons are working every time
//otherwise there is a problem sometimes
if (mouseEventType == RawPointerEventType.LeftButtonDown)
{
var me = new RawPointerEventArgs(mouseDevice, (uint)eventTime.Ticks, inputRoot,
RawPointerEventType.Move, _point, RawInputModifiers.None);
_view.Input(me);
}

var mouseEvent = new RawPointerEventArgs(mouseDevice, (uint)eventTime.Ticks, inputRoot,
mouseEventType.Value, _point, RawInputModifiers.LeftMouseButton);
var mouseEvent = new RawTouchEventArgs(_touchDevice, (uint)eventTime.Ticks, inputRoot,
i == e.ActionIndex ? pointerEventType : RawPointerEventType.TouchUpdate, point, RawInputModifiers.None, e.GetPointerId(i));
_view.Input(mouseEvent);

if (e.Action == MotionEventActions.Move && mouseDevice.Captured == null)
{
if (_lastTouchMovePoint != null)
{
//raise mouse scroll event so the scrollers
//are moving with the cursor
double vectorX = _point.X - _lastTouchMovePoint.Value.X;
double vectorY = _point.Y - _lastTouchMovePoint.Value.Y;
//based on test correction of 0.02 is working perfect
double correction = 0.02;
var ps = AndroidPlatform.Instance.LayoutScalingFactor;
var mouseWheelEvent = new RawMouseWheelEventArgs(
mouseDevice,
(uint)eventTime.Ticks,
inputRoot,
_point,
new Vector(vectorX * correction / ps, vectorY * correction / ps), RawInputModifiers.LeftMouseButton);
_view.Input(mouseWheelEvent);
}
_lastTouchMovePoint = _point;
_lastTouchMoveEventTime = eventTime;
}
else if (e.Action == MotionEventActions.Down)
{
_lastTouchMovePoint = _point;
}
else
{
_lastTouchMovePoint = null;
}
}
}

Expand Down

0 comments on commit 7fb6e14

Please sign in to comment.