AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
25.97k stars 2.25k forks source link

Rethink IInputDevice API #7939

Open maxkatz6 opened 2 years ago

maxkatz6 commented 2 years ago

Is your feature request related to a problem? Please describe.

After working with "IPointerDevice" related API I found number of problems:

  1. IPointerDevice API is meant to be used only by internal APIs. It translates raw events into developer-friendly PointerEventArgs events.
  2. InputManager is a static and partially useless class. Developers should handle Pointer* events with bubble or tunnel strategy instead of raw events. But there are use cases, when raw events are still useful, like NonClient input.
  3. MouseDevice handles pointerover functionality causing conflicts with future PenDevice implementation (fixed by https://github.com/AvaloniaUI/Avalonia/pull/7905).
  4. Because of multiple handling raw pointers in multiple places (different IPointerDevice, pointerover handling...) we can execute InputHitTest multiple times per single input (partially fixed with an internal hack in #7905)
  5. Users might expect a single pointer device to map into a single physical device. In our case, single IPointerDevice can work with multiple physical devices of the same type.
  6. User can't get a list of pointer devices per top-level, but only TopLevel.MouseDevice. Furthermore, on some backends TopLevel.MouseDevice always returns a fake instance.
  7. KeyboardDevice? For some reason, it partially handles focus management and does more job than just translating raw events. It also conflicts with GamepadDevice implementation.
  8. Conflict of terminology. PointerDevice in UWP works only as an informational class with details about specific physical device. Though UWP also has MouseCapabilities/TouchCapabilities, which only confuses me. Probably not the best part to port into Avalonia.

Describe the solution you'd like

  1. Move raw pointers handling logic to the TopLevel or any other single place instead of having multiple possible pointer devices with duplicated logic. Hit test is supposed to be executed once and pointer over to be handled in the same place.
  2. Deprecate InputManager.
  3. Refactor KeyboardDevice.
  4. UWP-like PointerDevice API with information about pointer device capabilities is not a goal, but nice to have in the future.
grokys commented 2 years ago

I agree with most of the points, though the input manager is kinda useful in a couple of niche situations:

For the first 2 points we could add additional higher-level APIs to handle these situations, but I think we should keep an API for handling raw events if only for debugging. I'd be fine with changing the API if there are problems with the current one.

maxkatz6 commented 1 year ago

Not a breaking change anymore, as IPointerDevice/IInputDevice was made internal.

flier268 commented 1 year ago

How could I use a barcode scanner? I used the InputManager to hook the keyboard before Avalonia 11, but the API is now internal.

I tried using InputElement.KeyDownEvent, but received 'Avalonia.Input.Key.ImeProcessed' instead of 'Avalonia.Input.Key.D2' as I expected. Additionally, this approach does not provide a Timestamp, so I had to add a Stopwatch to measure the timing. (Since barcode scanner input is very fast, I use the key interval to distinguish between scanner input and human input.)