Browse Source

feat(LibInputBackend) Handle events only from specific input handler devices (#15001)

* refactor(LibInputBackend): Move HandleTouch in `LibInputBackend.Tocuch.cs`

* feat(LibInputBackend) Handle events only from specific input handler devices

- Added LibInputBackendOptions
- Added LibInputBackend ctor overload that accepts LibInputBackendOptions
- Moved input thread initialization from ctor to the Initialize method

* fix: nits

* fix: Address review

* fix: Address review
pull/15134/head
workgroupengineering 3 years ago
committed by GitHub
parent
commit
40c630b7b5
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 51
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Touch.cs
  2. 82
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs
  3. 15
      src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackendOptions.cs

51
src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Touch.cs

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using Avalonia.Input;
using Avalonia.Input.Raw;
using static Avalonia.LinuxFramebuffer.Input.LibInput.LibInputNativeUnsafeMethods;
namespace Avalonia.LinuxFramebuffer.Input.LibInput;
public partial class LibInputBackend
{
private readonly Dictionary<int, Point> _pointers = new();
private readonly TouchDevice _touch = new();
private void HandleTouch(IntPtr ev, LibInputEventType type)
{
var tev = libinput_event_get_touch_event(ev);
if (tev == IntPtr.Zero)
return;
if (type < LibInputEventType.LIBINPUT_EVENT_TOUCH_FRAME)
{
var info = _screen.ScaledSize;
var slot = libinput_event_touch_get_slot(tev);
Point pt;
if (type == LibInputEventType.LIBINPUT_EVENT_TOUCH_DOWN
|| type == LibInputEventType.LIBINPUT_EVENT_TOUCH_MOTION)
{
var x = libinput_event_touch_get_x_transformed(tev, (int)info.Width);
var y = libinput_event_touch_get_y_transformed(tev, (int)info.Height);
pt = new Point(x, y);
_pointers[slot] = pt;
}
else
{
_pointers.TryGetValue(slot, out pt);
_pointers.Remove(slot);
}
var ts = libinput_event_touch_get_time_usec(tev) / 1000;
if (_inputRoot == null)
return;
ScheduleInput(new RawTouchEventArgs(_touch, ts,
_inputRoot,
type == LibInputEventType.LIBINPUT_EVENT_TOUCH_DOWN ? RawPointerEventType.TouchBegin
: type == LibInputEventType.LIBINPUT_EVENT_TOUCH_UP ? RawPointerEventType.TouchEnd
: type == LibInputEventType.LIBINPUT_EVENT_TOUCH_MOTION ? RawPointerEventType.TouchUpdate
: RawPointerEventType.TouchCancel,
pt, RawInputModifiers.None, slot));
}
}
}

82
src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs

@ -1,5 +1,5 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Avalonia.Input;
@ -9,27 +9,27 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
{
public partial class LibInputBackend : IInputBackend
{
private IScreenInfoProvider _screen;
private IInputRoot _inputRoot;
private TouchDevice _touch = new TouchDevice();
private const string LibInput = nameof(Avalonia.LinuxFramebuffer) + "/" + nameof(Avalonia.LinuxFramebuffer.Input) + "/" + nameof(LibInput);
private Action<RawInputEventArgs> _onInput;
private Dictionary<int, Point> _pointers = new Dictionary<int, Point>();
private IScreenInfoProvider? _screen;
private IInputRoot? _inputRoot;
private const string LibInput = nameof(LinuxFramebuffer) + "/" + nameof(Input) + "/" + nameof(LibInput);
private Action<RawInputEventArgs>? _onInput;
private readonly LibInputBackendOptions? _options;
public LibInputBackend()
{
var ctx = libinput_path_create_context();
new Thread(() => InputThread(ctx))
{
IsBackground = true
}.Start();
_options = default;
}
public LibInputBackend(LibInputBackendOptions options)
{
_options = options;
}
private unsafe void InputThread(IntPtr ctx)
private unsafe void InputThread(IntPtr ctx, LibInputBackendOptions options)
{
var fd = libinput_get_fd(ctx);
foreach (var f in Directory.GetFiles("/dev/input", "event*"))
foreach (var f in options.Events!)
libinput_path_add_device(ctx, f);
while (true)
{
@ -37,8 +37,8 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
libinput_dispatch(ctx);
while ((ev = libinput_get_event(ctx)) != IntPtr.Zero)
{
var type = libinput_event_get_type(ev);
if (type >= LibInputEventType.LIBINPUT_EVENT_TOUCH_DOWN &&
type <= LibInputEventType.LIBINPUT_EVENT_TOUCH_CANCEL)
HandleTouch(ev, type);
@ -56,50 +56,24 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
}
}
private void ScheduleInput(RawInputEventArgs ev) => _onInput.Invoke(ev);
private void HandleTouch(IntPtr ev, LibInputEventType type)
{
var tev = libinput_event_get_touch_event(ev);
if (tev == IntPtr.Zero)
return;
if (type < LibInputEventType.LIBINPUT_EVENT_TOUCH_FRAME)
{
var info = _screen.ScaledSize;
var slot = libinput_event_touch_get_slot(tev);
Point pt;
if (type == LibInputEventType.LIBINPUT_EVENT_TOUCH_DOWN
|| type == LibInputEventType.LIBINPUT_EVENT_TOUCH_MOTION)
{
var x = libinput_event_touch_get_x_transformed(tev, (int)info.Width);
var y = libinput_event_touch_get_y_transformed(tev, (int)info.Height);
pt = new Point(x, y);
_pointers[slot] = pt;
}
else
{
_pointers.TryGetValue(slot, out pt);
_pointers.Remove(slot);
}
var ts = libinput_event_touch_get_time_usec(tev) / 1000;
if (_inputRoot == null)
return;
ScheduleInput(new RawTouchEventArgs(_touch, ts,
_inputRoot,
type == LibInputEventType.LIBINPUT_EVENT_TOUCH_DOWN ? RawPointerEventType.TouchBegin
: type == LibInputEventType.LIBINPUT_EVENT_TOUCH_UP ? RawPointerEventType.TouchEnd
: type == LibInputEventType.LIBINPUT_EVENT_TOUCH_MOTION ? RawPointerEventType.TouchUpdate
: RawPointerEventType.TouchCancel,
pt, RawInputModifiers.None, slot));
}
}
private void ScheduleInput(RawInputEventArgs ev) => _onInput?.Invoke(ev);
public void Initialize(IScreenInfoProvider screen, Action<RawInputEventArgs> onInput)
{
_screen = screen;
_onInput = onInput;
var ctx = libinput_path_create_context();
var options = new LibInputBackendOptions()
{
Events = _options?.Events is null
? Directory.GetFiles("/dev/input", "event*")
: _options.Events,
};
new Thread(() => InputThread(ctx, options))
{
Name = "Input Manager Worker",
IsBackground = true
}.Start();
}
public void SetInputRoot(IInputRoot root)

15
src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackendOptions.cs

@ -0,0 +1,15 @@
#nullable enable
using System.Collections.Generic;
namespace Avalonia.LinuxFramebuffer.Input.LibInput;
/// <summary>
/// LibInputBackend Options.
/// </summary>
public sealed record class LibInputBackendOptions
{
/// <summary>
/// List Events of events handler to monitoring eg: /dev/eventX.
/// </summary>
public IReadOnlyList<string>? Events { get; init; } = null;
}
Loading…
Cancel
Save