/// <summary> /// keyboard = event0, mouse = /dev/input/mice /// should not have to open all of them /// https://thehackerdiary.wordpress.com/2017/04/21/exploring-devinput-1/ /// </summary> public static async Task Watch(string inputEvent, Action <MouseInputEventData> callback, CancellationToken token) { TaskCompletionSource <bool> cancellationCompletionSource = new TaskCompletionSource <bool>(); using (FileStream stream = new FileStream(Path.Combine(KeyboardDevPath, inputEvent), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, true)) using (token.Register(() => cancellationCompletionSource.TrySetResult(true))) { while (!token.IsCancellationRequested) { int read = 0; byte[] keyBuffer = new byte[MouseInputEventData.Size]; while (read < MouseInputEventData.Size && !token.IsCancellationRequested) { Task <int> readTask = stream.ReadAsync(keyBuffer, 0, MouseInputEventData.Size - read, token); if (readTask != await Task.WhenAny(readTask, cancellationCompletionSource.Task)) { throw new OperationCanceledException(token); } if (readTask.Exception?.InnerException != null) { throw readTask.Exception.InnerException; } read += readTask.Result; } // 40, 24, 56 MouseInputEventData eventData = new MouseInputEventData { Button = (MouseButton)(keyBuffer[0] == 40 || keyBuffer[0] == 24 || keyBuffer[0] == 56 ? 8 : keyBuffer[0]), Position = new Vector2((sbyte)keyBuffer[1], (sbyte)-keyBuffer[2]) }; callback(eventData); } } }
private void OnWatchTaskEventCallback(MouseInputEventData eventData) => OnMouseInputData?.Invoke(this, eventData);
private static void InternalMouseInputEvent(object sender, MouseInputEventData eventData) { CursorPosition = Vector2.Clamp(CursorPosition + eventData.Position, Vector2.Zero, CursorBounds); OnMouseInputEvent?.Invoke(sender, eventData); }