Mice.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. using System;
  2. using System.Linq;
  3. using System.Threading;
  4. using Avalonia.Input;
  5. using Avalonia.Input.Raw;
  6. using Avalonia.Platform;
  7. namespace Avalonia.LinuxFramebuffer
  8. {
  9. public unsafe class Mice
  10. {
  11. private readonly double _width;
  12. private readonly double _height;
  13. private double _x;
  14. private double _y;
  15. public event Action<RawInputEventArgs> Event;
  16. public Mice(double width, double height)
  17. {
  18. _width = width;
  19. _height = height;
  20. }
  21. public void Start() => ThreadPool.UnsafeQueueUserWorkItem(_ => Worker(), null);
  22. private void Worker()
  23. {
  24. var mouseDevices = EvDevDevice.MouseDevices.Where(d => d.IsMouse).ToList();
  25. if (mouseDevices.Count == 0)
  26. return;
  27. var are = new AutoResetEvent(false);
  28. while (true)
  29. {
  30. try
  31. {
  32. var rfds = new fd_set {count = mouseDevices.Count};
  33. for (int c = 0; c < mouseDevices.Count; c++)
  34. rfds.fds[c] = mouseDevices[c].Fd;
  35. IntPtr* timeval = stackalloc IntPtr[2];
  36. timeval[0] = new IntPtr(0);
  37. timeval[1] = new IntPtr(100);
  38. are.WaitOne(30);
  39. foreach (var dev in mouseDevices)
  40. {
  41. while(true)
  42. {
  43. var ev = dev.NextEvent();
  44. if (!ev.HasValue)
  45. break;
  46. LinuxFramebufferPlatform.Threading.Send(() => ProcessEvent(dev, ev.Value));
  47. }
  48. }
  49. }
  50. catch (Exception e)
  51. {
  52. Console.Error.WriteLine(e.ToString());
  53. }
  54. }
  55. }
  56. static double TranslateAxis(input_absinfo axis, int value, double max)
  57. {
  58. return (value - axis.minimum) / (double) (axis.maximum - axis.minimum) * max;
  59. }
  60. private void ProcessEvent(EvDevDevice device, input_event ev)
  61. {
  62. if (ev.type == (short)EvType.EV_REL)
  63. {
  64. if (ev.code == (short) AxisEventCode.REL_X)
  65. _x = Math.Min(_width, Math.Max(0, _x + ev.value));
  66. else if (ev.code == (short) AxisEventCode.REL_Y)
  67. _y = Math.Min(_height, Math.Max(0, _y + ev.value));
  68. else
  69. return;
  70. Event?.Invoke(new RawPointerEventArgs(LinuxFramebufferPlatform.MouseDevice,
  71. LinuxFramebufferPlatform.Timestamp,
  72. LinuxFramebufferPlatform.TopLevel.InputRoot, RawPointerEventType.Move, new Point(_x, _y),
  73. InputModifiers.None));
  74. }
  75. if (ev.type ==(int) EvType.EV_ABS)
  76. {
  77. if (ev.code == (short) AbsAxis.ABS_X && device.AbsX.HasValue)
  78. _x = TranslateAxis(device.AbsX.Value, ev.value, _width);
  79. else if (ev.code == (short) AbsAxis.ABS_Y && device.AbsY.HasValue)
  80. _y = TranslateAxis(device.AbsY.Value, ev.value, _height);
  81. else
  82. return;
  83. Event?.Invoke(new RawPointerEventArgs(LinuxFramebufferPlatform.MouseDevice,
  84. LinuxFramebufferPlatform.Timestamp,
  85. LinuxFramebufferPlatform.TopLevel.InputRoot, RawPointerEventType.Move, new Point(_x, _y),
  86. InputModifiers.None));
  87. }
  88. if (ev.type == (short) EvType.EV_KEY)
  89. {
  90. RawPointerEventType? type = null;
  91. if (ev.code == (ushort) EvKey.BTN_LEFT)
  92. type = ev.value == 1 ? RawPointerEventType.LeftButtonDown : RawPointerEventType.LeftButtonUp;
  93. if (ev.code == (ushort)EvKey.BTN_RIGHT)
  94. type = ev.value == 1 ? RawPointerEventType.RightButtonDown : RawPointerEventType.RightButtonUp;
  95. if (ev.code == (ushort) EvKey.BTN_MIDDLE)
  96. type = ev.value == 1 ? RawPointerEventType.MiddleButtonDown : RawPointerEventType.MiddleButtonUp;
  97. if (!type.HasValue)
  98. return;
  99. Event?.Invoke(new RawPointerEventArgs(LinuxFramebufferPlatform.MouseDevice,
  100. LinuxFramebufferPlatform.Timestamp,
  101. LinuxFramebufferPlatform.TopLevel.InputRoot, type.Value, new Point(_x, _y), default(InputModifiers)));
  102. }
  103. }
  104. }
  105. }