-
Notifications
You must be signed in to change notification settings - Fork 769
Description
Proposal: Improved Cursor APIs
Summary
UWP's story around custom cursors currently is suboptimal – one has to create a .cur file and build it into a .rc file packaged at compile time in order to use custom cursors in the code. We ought to allow runtime-creation of cursors (thereby bringing feature parity with win32) and more broadly consider more ergonomic APIs in order to facilitate building and iterating on cursors for developers so they can bring a more efficient and tailored experience to their users.
Rationale
Custom cursors in UWP are fabricated from a .cur file, a collection of BMP images of differing sizes, and packaged into the AppX bundle which means:
- Custom cursors are necessarily static, i.e. they can't be created dynamically at runtime. That's a significant limitation for complex apps, or apps that wish to let their users extend the core functionality through plugins (Adobe XD, for instance could be interested in this proposed API).
This is a limitation of UWP specifically, as win32, Cocoa, or other toolkits such as GTK all have APIs to create a cursor from a bitmap object (as opposed to packaged assets). - Developers currently have to go through a tedious process of generating bitmaps, packaging them and fetching the resulting resource ID from resource.h in order to even see their cursor on screen. This makes custom cursors hard to use.
For instance, Paint3D uses built-in OS cursors for almost all of its tools, where mspaint did use fully custom cursors all-around. Custom cursors signal the currently active tool to the user, or with special markers the action that will result from clicking at a particular spot (hit-testing, see pictures below), and as such are critical for high-quality experience in design applications (e.g. Adobe apps, Office etc.).
When talking about ergonomics, I do think we should consider how to facilitate handling of different DPI sizes, i.e. have an API to specify cursor as vector image of some sort, as was done for splashscreen icons (though that might not be desirable if antialiasing is a concern). - A common scenario of making custom cursors is what I refer to as "markers". A marker is a small icon that adds to the base system icon at a certain point (e.g. the spinner pointer) – this is often used in canvas-based apps to signal that clicking on this particular spot will result in a specific action taken.
It would be great to have some way to reuse system cursor and add an extra symbol to them (kinda like the spinner pointer, see below), I'm thinking an API that would "decal" the system cursor into a bitmap, alternatively specify to use a system cursor and then the custom color is overlaid with it. [Maybe even allow specifying a scaling factor (e.g. 3/4), if the source of system assets are vectorized that shouldn't technically be a problem.]
This is Fontlab 5 on Windows (font editor), showing special highlight when hovering over a point. This lets the user know that they're hit-testing the point, since the threshold of hit testing for such small items isn't necessarily intuitive esp. while one is moving quickly over the canvas
Glyphs on macOS - A common use-case of custom cursors is to set a cursor on a given widget; we could add a Cursor property to controls. For reference the current API goes like this:
void OnPointerEntered(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Xaml.Window.Current.CoreWindow.PointerCursor = new Windows.UI.Core.CoreCursor(
Windows.UI.Core.CoreCursorType.Hand, 1);
}
void OnPointerExited(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Xaml.Window.Current.CoreWindow.PointerCursor = new Windows.UI.Core.CoreCursor(
Windows.UI.Core.CoreCursorType.Arrow, 1);
}
TL;DR: great apps, primarily document-centered or design apps do need custom cursors, and we ought to make it easy for developers to prototype and iterate on them. Would be great if a XAML PM could spearhead this effort.
Functional Requirements
# | Feature | Priority |
---|---|---|
1 | A developer can create and set a custom cursor at runtime (or set of diff. size bitmaps) | Must |
1b | Cursor customization easily supports different DPIs (for example, could accept SVG or other vector sources) | Should |
2 | Custom cursors are specified in a version control-friendly way (no bin files) | Should |
3 | Developer can specify a control's custom cursor by setting the Cursor property | Could |
4 | A developer can create a cursor from a system cursor + their own extra drawing | Could |
5 | API to create an animated cursor? | Could |
Important Notes
- In win32 a cursor can be created from a bitmap at runtime using CreateIconIndirect()
- In regards to item #4, the community toolkit does have an extension for setting a system cursor over a specific UIElement in XAML.
Open Questions
We might want to think about animated cursors also (though that's not a priority for me). If there's an API for making a cursor from bitmap should there be one for animated cursors (e.g., a series of bitmaps?)