Skip to content

Proposal: Improved Cursor APIs #506

@adrientetar

Description

@adrientetar

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:

  1. 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).
  2. 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).
  3. 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.]
    image
    1455817022-FontLab2
    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
    2439707925-Glyphs1
    Glyphs on macOS
  4. 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

  1. In win32 a cursor can be created from a bitmap at runtime using CreateIconIndirect()
  2. 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?)

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature proposalNew feature proposalneeds-winui-3Indicates that feature can only be done in WinUI 3.0 or beyond. (needs winui 3)team-ControlsIssue for the Controls team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions