mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Linux - Fixed input provider warnings
This commit is contained in:
parent
090d5b76e8
commit
6fe93ab2f7
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Linux.Providers.Input
|
||||||
|
{
|
||||||
|
public class ArtemisLinuxInputProviderException : Exception
|
||||||
|
{
|
||||||
|
public ArtemisLinuxInputProviderException() : base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArtemisLinuxInputProviderException(string? message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArtemisLinuxInputProviderException(string? message, Exception? innerException) : base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Linux.Providers.Input
|
||||||
|
{
|
||||||
|
public enum LinuxDeviceType
|
||||||
|
{
|
||||||
|
Keyboard,
|
||||||
|
Mouse,
|
||||||
|
Gamepad
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,6 @@
|
|||||||
using System;
|
using Artemis.Core;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection.Metadata;
|
|
||||||
using Humanizer;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Linux.Providers.Input
|
namespace Artemis.UI.Linux.Providers.Input
|
||||||
{
|
{
|
||||||
@ -12,75 +9,52 @@ namespace Artemis.UI.Linux.Providers.Input
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class LinuxInputDevice
|
public class LinuxInputDevice
|
||||||
{
|
{
|
||||||
public string InputId { get; }
|
public LinuxInputId InputId { get; }
|
||||||
public string? Bus { get; }
|
public string Name { get; }
|
||||||
public string? Vendor { get; }
|
public string[] Handlers { get; }
|
||||||
public string? Product { get; }
|
public string EventPath { get; }
|
||||||
public string? Version { get; }
|
public LinuxDeviceType DeviceType { get; }
|
||||||
public string? Name { get; }
|
|
||||||
public string? Phys { get; }
|
|
||||||
public string? Sysfs { get; }
|
|
||||||
public string? Uniq { get; }
|
|
||||||
public string[]? Handlers { get; }
|
|
||||||
public bool IsMouse => Handlers.Any(h => h.Contains("mouse"));
|
|
||||||
public bool IsKeyboard => Handlers.Any(h => h.Contains("kbd"));
|
|
||||||
public bool IsGamePad => Handlers.Any(h => h.Contains("js"));
|
|
||||||
public string EventPath => $"/dev/input/{Handlers.First(h => h.Contains("event"))}";
|
|
||||||
|
|
||||||
public LinuxInputDevice(IEnumerable<string> lines)
|
public LinuxInputDevice(IEnumerable<string> lines)
|
||||||
{
|
{
|
||||||
foreach (string line in lines)
|
foreach (string line in lines)
|
||||||
{
|
{
|
||||||
char dataType = line.First();
|
|
||||||
string data = line.Substring(3);
|
|
||||||
//get the first character in each line and set the according property with relevant data
|
//get the first character in each line and set the according property with relevant data
|
||||||
|
|
||||||
|
char dataType = line[0];
|
||||||
|
string data = line[3..];
|
||||||
switch (dataType)
|
switch (dataType)
|
||||||
{
|
{
|
||||||
case 'I':
|
case 'I':
|
||||||
InputId = data;
|
InputId = new LinuxInputId(data);
|
||||||
foreach (string component in data.Split(" "))
|
|
||||||
{
|
|
||||||
string?[] parts = component.Split('=');
|
|
||||||
switch (parts[0])
|
|
||||||
{
|
|
||||||
case "Bus":
|
|
||||||
Bus = parts[1];
|
|
||||||
break;
|
|
||||||
case "Vendor":
|
|
||||||
Vendor = parts[1];
|
|
||||||
break;
|
|
||||||
case "Product":
|
|
||||||
Product = parts[1];
|
|
||||||
break;
|
|
||||||
case "Version":
|
|
||||||
Version = parts[1];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
Name = data.Replace("\"", "")
|
Name = data.Replace("\"", "").Replace("Name=", "");
|
||||||
.Replace("Name=", "");
|
|
||||||
break;
|
|
||||||
case 'P':
|
|
||||||
Phys = data.Replace("Phys=", "");
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
Sysfs = data.Replace("Sysfs=", "");
|
|
||||||
break;
|
break;
|
||||||
case 'H':
|
case 'H':
|
||||||
Handlers = data.Replace("Handlers=", "").Split(" ");
|
Handlers = data.Replace("Handlers=", "").Split(" ");
|
||||||
break;
|
|
||||||
case 'U':
|
if (Handlers?.Any(h => h.Contains("mouse")) == true)
|
||||||
Uniq = data.Replace("Uniq=", "");
|
DeviceType = LinuxDeviceType.Mouse;
|
||||||
|
else if (Handlers?.Any(h => h.Contains("kbd")) == true)
|
||||||
|
DeviceType = LinuxDeviceType.Keyboard;
|
||||||
|
else if (Handlers?.Any(h => h.Contains("js")) == true)
|
||||||
|
DeviceType = LinuxDeviceType.Gamepad;
|
||||||
|
|
||||||
|
var evt = Handlers!.First(h => h.Contains("event"));
|
||||||
|
|
||||||
|
EventPath = $"/dev/input/{evt}";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//do we need any more of this data?
|
//do we need any more of this data?
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (InputId is null || Name is null || Handlers is null || EventPath is null)
|
||||||
|
{
|
||||||
|
throw new ArtemisLinuxInputProviderException("Linux device definition did not contain necessary data");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Overrides of Object
|
#region Overrides of Object
|
||||||
@ -89,5 +63,27 @@ namespace Artemis.UI.Linux.Providers.Input
|
|||||||
public override string ToString() => $"{Name} - {EventPath}";
|
public override string ToString() => $"{Name} - {EventPath}";
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public class LinuxInputId
|
||||||
|
{
|
||||||
|
public string Bus { get; }
|
||||||
|
public string Vendor { get; }
|
||||||
|
public string Product { get; }
|
||||||
|
public string Version { get; }
|
||||||
|
|
||||||
|
public LinuxInputId(string line)
|
||||||
|
{
|
||||||
|
var components = line.Split(" ")
|
||||||
|
.Select(c => c.Split('='))
|
||||||
|
.ToDictionary(c => c[0], c => c[1]);
|
||||||
|
|
||||||
|
Bus = components["Bus"];
|
||||||
|
Vendor = components["Vendor"];
|
||||||
|
Product = components["Product"];
|
||||||
|
Version = components["Version"];
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => $"Bus={Bus} Vendor={Vendor} Product={Product} Version={Version}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,7 +12,7 @@ namespace Artemis.UI.Linux.Providers.Input
|
|||||||
public static IEnumerable<LinuxInputDevice> Find()
|
public static IEnumerable<LinuxInputDevice> Find()
|
||||||
{
|
{
|
||||||
return File.ReadAllLines(DEVICES_FILE)
|
return File.ReadAllLines(DEVICES_FILE)
|
||||||
.PartitionBy(s => s == "") //split on empty lines
|
.PartitionBy(s => s?.Length == 0) //split on empty lines
|
||||||
.Select(lineGroup => new LinuxInputDevice(lineGroup));
|
.Select(lineGroup => new LinuxInputDevice(lineGroup));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ namespace Artemis.UI.Linux.Providers.Input
|
|||||||
return groupNumber;
|
return groupNumber;
|
||||||
};
|
};
|
||||||
return a
|
return a
|
||||||
.Select(x => new { Value = x, GroupNumber = getGroupNumber(predicate(x))} )
|
.Select(x => new { Value = x, GroupNumber = getGroupNumber(predicate(x)) })
|
||||||
.Where(x => x.GroupNumber != null)
|
.Where(x => x.GroupNumber != null)
|
||||||
.GroupBy(x => x.GroupNumber)
|
.GroupBy(x => x.GroupNumber)
|
||||||
.Select(g => g.Select(x => x.Value));
|
.Select(g => g.Select(x => x.Value));
|
||||||
|
|||||||
@ -3,7 +3,6 @@ using System.IO;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.UI.Linux.Utilities;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Linux.Providers.Input
|
namespace Artemis.UI.Linux.Providers.Input
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Linux.Utilities;
|
using Artemis.UI.Linux.Utilities;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
@ -20,7 +21,7 @@ namespace Artemis.UI.Linux.Providers.Input
|
|||||||
|
|
||||||
foreach (LinuxInputDevice deviceDefinition in LinuxInputDeviceFinder.Find())
|
foreach (LinuxInputDevice deviceDefinition in LinuxInputDeviceFinder.Find())
|
||||||
{
|
{
|
||||||
LinuxInputDeviceReader? reader = new LinuxInputDeviceReader(deviceDefinition);
|
LinuxInputDeviceReader? reader = new(deviceDefinition);
|
||||||
reader.InputEvent += OnInputEvent;
|
reader.InputEvent += OnInputEvent;
|
||||||
_readers.Add(reader);
|
_readers.Add(reader);
|
||||||
}
|
}
|
||||||
@ -30,68 +31,103 @@ namespace Artemis.UI.Linux.Providers.Input
|
|||||||
{
|
{
|
||||||
if (sender is not LinuxInputDeviceReader reader)
|
if (sender is not LinuxInputDeviceReader reader)
|
||||||
return;
|
return;
|
||||||
|
switch (reader.InputDevice.DeviceType)
|
||||||
if (reader.InputDevice.IsKeyboard)
|
|
||||||
{
|
{
|
||||||
HandleKeyboardData(reader.InputDevice, e);
|
case LinuxDeviceType.Keyboard:
|
||||||
}
|
HandleKeyboardData(reader.InputDevice, e);
|
||||||
else if (reader.InputDevice.IsMouse)
|
break;
|
||||||
{
|
case LinuxDeviceType.Mouse:
|
||||||
HandleMouseData(reader.InputDevice, e);
|
HandleMouseData(reader.InputDevice, e);
|
||||||
}
|
break;
|
||||||
else if (reader.InputDevice.IsGamePad)
|
case LinuxDeviceType.Gamepad:
|
||||||
{
|
break;
|
||||||
//TODO: handle game pad input?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleKeyboardData(LinuxInputDevice keyboard, LinuxInputEventArgs e)
|
private void HandleKeyboardData(LinuxInputDevice keyboard, LinuxInputEventArgs args)
|
||||||
{
|
{
|
||||||
switch (e.Type)
|
switch (args.Type)
|
||||||
{
|
{
|
||||||
case LinuxInputEventType.KEY:
|
case LinuxInputEventType.KEY:
|
||||||
KeyboardKey key = InputUtilities.KeyFromKeyCode((LinuxKeyboardKeyCodes) e.Code);
|
KeyboardKey key = InputUtilities.KeyFromKeyCode((LinuxKeyboardKeyCodes)args.Code);
|
||||||
bool isDown = e.Value != 0;
|
bool isDown = args.Value != 0;
|
||||||
|
|
||||||
_logger.Verbose($"Keyboard Key: {(LinuxKeyboardKeyCodes) e.Code} | Down: {isDown}");
|
_logger.Verbose($"Keyboard Key: {(LinuxKeyboardKeyCodes)args.Code} | Down: {isDown}");
|
||||||
|
|
||||||
//TODO: identify
|
var identifier = keyboard.InputId;
|
||||||
|
|
||||||
OnKeyboardDataReceived(null, key, isDown);
|
OnIdentifierReceived(identifier, InputDeviceType.Keyboard);
|
||||||
|
|
||||||
|
ArtemisDevice? device = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
device = _inputService.GetDeviceByIdentifier(this, identifier, InputDeviceType.Keyboard);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Warning(e, "Failed to retrieve input device by its identifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
OnKeyboardDataReceived(device, key, isDown);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
_logger.Verbose($"Unknown keyboard event type: {e.Type}");
|
_logger.Verbose($"Unknown keyboard event type: {args.Type}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleMouseData(LinuxInputDevice mouse, LinuxInputEventArgs e)
|
private void HandleMouseData(LinuxInputDevice mouse, LinuxInputEventArgs args)
|
||||||
{
|
{
|
||||||
switch (e.Type)
|
var identifier = mouse.InputId;
|
||||||
|
|
||||||
|
OnIdentifierReceived(identifier, InputDeviceType.Mouse);
|
||||||
|
|
||||||
|
ArtemisDevice? device = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
device = _inputService.GetDeviceByIdentifier(this, identifier, InputDeviceType.Mouse);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.Warning(e, "Failed to retrieve input device by its identifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (args.Type)
|
||||||
{
|
{
|
||||||
case LinuxInputEventType.KEY:
|
case LinuxInputEventType.KEY:
|
||||||
bool isDown = e.Value != 0;
|
bool isDown = args.Value != 0;
|
||||||
MouseButton button = InputUtilities.MouseButtonFromButtonCode((LinuxKeyboardKeyCodes)e.Code);
|
MouseButton button = InputUtilities.MouseButtonFromButtonCode((LinuxKeyboardKeyCodes)args.Code);
|
||||||
|
|
||||||
_logger.Verbose($"Mouse Button: {(LinuxKeyboardKeyCodes) e.Code} | Down: {isDown}");
|
_logger.Verbose($"Mouse Button: {(LinuxKeyboardKeyCodes)args.Code} | Down: {isDown}");
|
||||||
|
|
||||||
//TODO: identify
|
OnMouseButtonDataReceived(device, button, isDown);
|
||||||
|
|
||||||
OnMouseButtonDataReceived(null, button, isDown);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LinuxInputEventType.ABS:
|
|
||||||
LinuxAbsoluteAxis absoluteAxis = (LinuxAbsoluteAxis) e.Code;
|
|
||||||
_logger.Verbose($"Absolute mouse: axis={absoluteAxis} | value={e.Value}");
|
|
||||||
break;
|
|
||||||
case LinuxInputEventType.REL:
|
case LinuxInputEventType.REL:
|
||||||
LinuxRelativeAxis relativeAxis = (LinuxRelativeAxis) e.Code;
|
LinuxRelativeAxis relativeAxis = (LinuxRelativeAxis)args.Code;
|
||||||
_logger.Verbose($"Relative mouse: axis={relativeAxis} | value={e.Value}");
|
|
||||||
|
|
||||||
//TODO: handle mouse movement
|
_logger.Verbose($"Relative mouse: axis={relativeAxis} | value={args.Value}");
|
||||||
|
|
||||||
|
switch (relativeAxis)
|
||||||
|
{
|
||||||
|
case LinuxRelativeAxis.REL_WHEEL:
|
||||||
|
OnMouseScrollDataReceived(device, MouseScrollDirection.Vertical, args.Value);
|
||||||
|
break;
|
||||||
|
case LinuxRelativeAxis.REL_HWHEEL:
|
||||||
|
OnMouseScrollDataReceived(device, MouseScrollDirection.Horizontal, args.Value);
|
||||||
|
break;
|
||||||
|
case LinuxRelativeAxis.REL_X:
|
||||||
|
OnMouseMoveDataReceived(device, 0, 0, args.Value, 0);
|
||||||
|
break;
|
||||||
|
case LinuxRelativeAxis.REL_Y:
|
||||||
|
OnMouseMoveDataReceived(device, 0, 0, 0, args.Value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
_logger.Verbose($"Unknown mouse event type: {e.Type}");
|
_logger.Verbose($"Unknown mouse event type: {args.Type}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user