doc/articles/features/pointers-keyboard-and-other-user-inputs.md
User inputs are usually propagated using RoutedEvents. See Uno's routed events documentation to better understand their implementation on Uno.
| Routed Event | Android | iOS | Wasm | Skia Desktop | |
|---|---|---|---|---|---|
| focus events | |||||
GotFocus | Yes | Yes (1) | Yes (1) | Yes | Documentation |
LostFocus | Yes | Yes (1) | Yes (1) | Yes | Documentation |
| keyboard events | |||||
KeyDown | Hardware Only (2) | Yes (2) | Yes | Yes | Documentation |
KeyUp | Hardware Only (2) | Yes (2) | Yes | Yes | Documentation |
| pointer events | |||||
PointerCanceled | Yes | Yes | Yes | Yes | Documentation |
PointerCaptureLost | Yes | Yes | Yes | Yes | Documentation |
PointerEntered | Yes | Yes | Yes | Yes | Documentation |
PointerExited | Yes | Yes | Yes | Yes | Documentation |
PointerMoved | Yes | Yes | Yes | Yes | Documentation |
PointerPressed | Yes | Yes | Yes | Yes | Documentation |
PointerReleased | Yes | Yes | Yes | Yes | Documentation |
PointerWheelChanged | No | No | Yes | Yes | Documentation |
| manipulation events | |||||
ManipulationStarting | Yes | Yes | Yes | Yes | Documentation |
ManipulationStarted | Yes | Yes | Yes | Yes | Documentation |
ManipulationDelta | Yes | Yes | Yes | Yes | Documentation |
ManipulationInertiaStarting | Yes | Yes | Yes | Yes | Documentation |
ManipulationCompleted | Yes | Yes | Yes | Yes | Documentation |
| gesture events | |||||
Tapped | Yes | Yes | Yes | Yes | Documentation |
DoubleTapped | Yes | Yes | Yes | Yes | Documentation |
RightTapped | Yes | Yes | Yes | Yes | Documentation |
Holding | Yes | Yes | Yes | Yes | Documentation |
| drag and drop | |||||
DragStarting | Yes | Yes | Yes | Yes | Documentation |
DragEnter | Yes | Yes | Yes | Yes | Documentation |
DragOver | Yes | Yes | Yes | Yes | Documentation |
DragLeave | Yes | Yes | Yes | Yes | Documentation |
Drop | Yes | Yes | Yes | Yes | Documentation |
DropCompleted | Yes | Yes | Yes | Yes | Documentation |
Notes:
KeyDown and KeyUp events are generated only from hardware keyboards (Except for the Editor Action on soft keyboards,
those are translated as KeyUp with KeyCode.Enter). Some soft keyboard MAY generate those events, but your code shouldn't rely
on that. This is a limitation in the Android platform (see note on this link content).
Because of those limitations, Key Events are not being implemented as routed events on Android, so
AddHandler&RemoveHandlerwon't work for keyboard events. They won't bubble in managed code.
KeyDown & KeyUp routed events are generated from only a TextBox. Only character-related keyboard events are generated.
They are implemented as Routed Events and they are always bubbling in managed code.CoreWindow.KeyUp and CoreWindow.KeyDown events, as well as UIElement.KeyUp and UIElement.KeyDown events for Skia Desktop.These events are the base for all other pointing device related events (i.e. Manipulation, Gesture and drag and dop events). They are directly linked to the native events of each platform:
Touches[Began|Moved|Ended|Cancelled] on iOSdispatchTouchEvent and dispatchGenericMotionEvent on Androidpointer[enter|leave|down|up|move|cancel] on WebAssemblyOn Skia however, they are fully managed events.
Like on WinUI, as soon as the system detects that the user wants to scroll, a control gets a PointerCancelled and that control won't receive
any other pointer event until the user releases the pointer. That behavior can be prevented by setting the ManipulationMode
to something other than System on a control nested in the ScrollViewer. For more information, see Manipulation events.
Be aware that on iOS, this will set DelaysContentTouches to false. So, it means that it will slightly reduce the performance
of the scrolling. For more information, see delaysContentTouches.
As those events are tightly coupled to the native events, Uno has to make some compromises:
PointerCaptureLost),
multiple managed events are raised from a single native event. These have multiple effects:
On WinUI if you have a control A and a nested control B, you will get:
B.PointerEnter
A.PointerEnter
B.PointerPressed
A.PointerPressed
but with UNO you will get:
B.PointerEnter
B.PointerPressed
A.PointerEnter
A.PointerPressed
If you handle the PointerEnter on B, the parent control A won't get the PointerEnter (as expected) nor the PointerPressed.
PointerEnter and PointerExit are going to be raised without taking clipping in consideration.
This means that you will get the enter earlier and the exit later than on other platforms.RenderTransform which overlaps one of its sibling elements,
the element at the top will get the pointer events.RoutedPointerEventArgs.FrameId will be reset to 0 after 49 days of running time of the application.Popup won't receive the unhandled pointer events.PointerReleased without getting a PointerPressed before.
(For instance if a child control handled the pressed event but not the released event).
On WASM as
TextElementinherits fromUIElement, it means that, unlike WinUI,TextBlockwon't raise thePointerReleasedevent when clicking on aHyperlink.
Hyperlink the Click will be raised before the PointerReleased.PointerPointProperties.PointerUpdateKind is not set on Android 5.x and lower (API level < 23)PointerDeviceType == Pen only for hovering
(i.e. Pointer<Enter|Move|Exit> - note that, as of 2019-11-28, once pressed PointerMove will be flagged as "touch")
and you won't be able to track the barrel button nor the eraser. For more information, see Bug report on Bugzilla.IsRightButtonPressed set (in addition to the IsBarrelButtonPressed). On WinUI and Android, you get this flag only if the barrel
button was pressed at the moment where you touched the screen, otherwise, you will have the IsLeftButtonPressed and the IsBarrelButtonPressed.Holding event is not raised after a given delay like on WinUI,
but instead, we rely on the fact that we usually get a lot of moves for those kinds of pointers,
so we raise the event only when we get a move that exceeds the defined thresholds for holding.Handled pointer events only for vertical scrolling,
then the events for the horizontal scroll component won't bubble through the parents.The capture of pointer is handled in managed code only. On WebAssembly, Uno however still requests the browser to capture the pointer,
but Uno does not rely on native [got|lost]pointercapture events.
To differentiate between mouse and touch device type for pointer events, include the following in your app's Info.plist:
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
Without this key, the current version of iPadOS reports mouse interaction as normal touch.
They are generated from the PointerXXX events (using the Microsoft.UI.Input.GestureRecognizer) and are bubbling in managed only.
They are generated from the PointerXXX events (using the Microsoft.UI.Input.GestureRecognizer) and are bubbling in managed only.
Note that Tapped and DoubleTapped are not linked in any way to a native equivalent, but are fully interpreted in managed code.
In order to match the WinUI behavior, on WASM, the default "Context menu" of the browser is disabled (except for the TextBox),
no matter if you use/handle the RightTapped event or not.
Be aware that on some browsers (Firefox for example), the user can still request to get the "Context menu" on right click.
<input>-based elementsWhile the browser context menu enabled on TextBox and PasswordBox by default, it will be disabled when ContextFlyout is set on the control.
To manually disable the context menu on a UIElement which represents a HTML <input>, you can manually set the context-menu-disabled CSS class:
#if __WASM__
MyInputElement.SetCssClasses("context-menu-disabled");
#endif
Those events are also 100% managed events, built from the PointerXXX events (using the Microsoft.UI.Input.GestureRecognizer)
A drag and drop operation can be used to move content within an app, but it can also be used to copy / move / link between apps. While intra-app drag and drop is supported on all platforms without limitations, inter-app drag and drop requires platform-specific support. The table and sections below describe supported functionality and limitations for each platform.
| From uno app to external | From external app to uno | |
|---|---|---|
| Android | No | No |
| iOS | No | No |
| Wasm | No | Yes (Text, Link, Image, File, Html, Rtf) |
| macOS | Yes (Text, Link, Image, Html, Rtf) | Yes (Text, Link, Image, File, Html, Rtf) |
| Skia Desktop (Windows) | Yes (Text, Link, Image, File, Html, Rtf) | Yes (Text, Link, Image, File, Html, Rtf) |
| Skia Linux | No | No |
DataPackage before the Drop event.
This a limitations of web browsers.
Any attempt to read it before the Drop will result into a timeout exception after a hard coded delay of 10 seconds.Uri.IsWellFormedUriString(text, UriKind.Absolute) returns true.WinUI has the following standard data formats that correspond with a URI/URL:
Several platforms such as macOS, iOS, and Android do not differentiate between them and only use a single URI/URL class or string.
When applying data to the native clipboard or dragging/dropping data from a DataPackage, only one URI/URL may be used. Therefore, all URI data formats are merged together into a single URI using the above-defined priority. WebLink is considered more specific than ApplicationLink.
When pulling data from the native clipboard or drag/drop data, this single native URI/URL is separated into the equivalent WinUI data format (since WinUI's direct equivalent standard data format 'Uri' is deprecated). The mapping is as follows:
For full compatibility, the Uri format within a DataPackage should still be populated regardless of #1 or #2.
AllowDrop = true),
when the pointer leaves the deepest / top most element but not the parent,
the parent element will also raise DragLeave and immediately after raise DragEnter.