csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.8 KiB
123 lines
3.8 KiB
using System;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using Avalonia.Input;
|
|
using Avalonia.Input.Raw;
|
|
|
|
namespace Avalonia.LinuxFramebuffer.Input.EvDev
|
|
{
|
|
internal class EvDevSingleTouchScreen : EvDevDeviceHandler
|
|
{
|
|
private readonly IScreenInfoProvider _screenInfo;
|
|
private readonly Matrix _calibration;
|
|
private input_absinfo _axisX;
|
|
private input_absinfo _axisY;
|
|
private TouchDevice _device = new TouchDevice();
|
|
|
|
private int _currentX, _currentY;
|
|
private bool _hasMovement;
|
|
private bool? _pressAction;
|
|
|
|
public EvDevSingleTouchScreen(EvDevDevice device, EvDevTouchScreenDeviceDescription description,
|
|
IScreenInfoProvider screenInfo) : base(device)
|
|
{
|
|
if (device.AbsX == null || device.AbsY == null)
|
|
throw new ArgumentException("Device is not a touchscreen");
|
|
_screenInfo = screenInfo;
|
|
|
|
_calibration = description.CalibrationMatrix;
|
|
_axisX = device.AbsX.Value;
|
|
_axisY = device.AbsY.Value;
|
|
}
|
|
|
|
protected override void HandleEvent(input_event ev)
|
|
{
|
|
if (ev.Type == EvType.EV_ABS)
|
|
{
|
|
if (ev.Axis == AbsAxis.ABS_X)
|
|
{
|
|
_currentX = ev.value;
|
|
_hasMovement = true;
|
|
}
|
|
|
|
if (ev.Axis == AbsAxis.ABS_Y)
|
|
{
|
|
_currentY = ev.value;
|
|
_hasMovement = true;
|
|
}
|
|
}
|
|
|
|
if (ev.Type == EvType.EV_KEY)
|
|
{
|
|
if (ev.Key == EvKey.BTN_TOUCH)
|
|
{
|
|
_pressAction = ev.value != 0;
|
|
}
|
|
}
|
|
|
|
if (ev.Type == EvType.EV_SYN)
|
|
{
|
|
if (_pressAction != null)
|
|
RaiseEvent(_pressAction == true ? RawPointerEventType.TouchBegin : RawPointerEventType.TouchEnd,
|
|
ev.Timestamp);
|
|
else if(_hasMovement)
|
|
RaiseEvent(RawPointerEventType.TouchUpdate, ev.Timestamp);
|
|
_hasMovement = false;
|
|
_pressAction = null;
|
|
}
|
|
}
|
|
|
|
void RaiseEvent(RawPointerEventType type, ulong timestamp)
|
|
{
|
|
var point = new Point(_currentX, _currentY);
|
|
|
|
var touchWidth = _axisX.maximum - _axisX.minimum;
|
|
var touchHeight = _axisY.maximum - _axisY.minimum;
|
|
|
|
var screenSize = _screenInfo.ScaledSize;
|
|
|
|
// Normalize to 0-(max-min)
|
|
point -= new Point(_axisX.minimum, _axisY.minimum);
|
|
|
|
// Apply calibration matrix
|
|
point *= _calibration;
|
|
|
|
// Transform to display pixel grid
|
|
point = new Point(point.X * screenSize.Width / touchWidth, point.Y * screenSize.Height / touchHeight);
|
|
|
|
RaiseEvent(new RawTouchEventArgs(_device, timestamp, InputRoot,
|
|
type, point, RawInputModifiers.None, 1));
|
|
}
|
|
}
|
|
|
|
internal abstract class EvDevDeviceHandler
|
|
{
|
|
private IInputRoot? _inputRoot;
|
|
|
|
public event Action<RawInputEventArgs>? OnEvent;
|
|
|
|
public EvDevDeviceHandler(EvDevDevice device)
|
|
{
|
|
Device = device;
|
|
}
|
|
|
|
public EvDevDevice Device { get; }
|
|
|
|
[AllowNull]
|
|
public IInputRoot InputRoot
|
|
{
|
|
get => _inputRoot ?? throw new InvalidOperationException($"{nameof(InputRoot)} hasn't been set");
|
|
set => _inputRoot = value;
|
|
}
|
|
|
|
public void HandleEvents()
|
|
{
|
|
input_event? ev;
|
|
while ((ev = Device.NextEvent()) != null)
|
|
HandleEvent(ev.Value);
|
|
}
|
|
|
|
protected void RaiseEvent(RawInputEventArgs ev) => OnEvent?.Invoke(ev);
|
|
|
|
protected abstract void HandleEvent(input_event ev);
|
|
}
|
|
}
|
|
|