Skip to content

[Proposal] API to query whether SDL_Pen devices are internal or external #13065

@Susko3

Description

@Susko3

Definitions

  • internal pen device – a pen the user is using directly over the screen – the digitizer "is" the screen (example: S Pen, Apple Pencil, Microsoft Surface, Wacom tablets with built in screen)
  • external pen device – a pen where the digitizer and screen are separate (normal graphics tablets, virtual tablets (using S Pen via phone to control PC))

N.B.: it might make sense to call these direct and indirect.

API proposal

// SDL_pen.h

typedef enum SDL_PenLocation // tentative name
{
    SDL_PEN_LOCATION_UNKNOWN,
    SDL_PEN_LOCATION_INTERNAL,
    SDL_PEN_LOCATION_EXTERNAL
} SDL_PenLocation;

extern SDL_DECLSPEC SDL_PenLocation SDLCALL SDL_GetPenLocation(SDL_PenID instance_id);

Usage

SDL_Event event = ...;
switch (event.type)
{
case SDL_EVENT_PEN_PROXIMITY_IN:
    SDL_PenID id = event.pproximity.which; // also works for all other pen events
    SDL_PenLocation location = SDL_GetPenLocation(id);
    // do game logic with `location`        
    break;
}

This API is useful for any game that has a custom cursor and only wants it visible in certain scenarios. For external pens, it needs to show the cursor so that the user knows where it's pointing. For internal pens, it doesn't need to show the cursor as the physical pen is the cursor, the user can clearly see where it's pointing.

External Internal
User needs the cursor so they know where they're pointing to. Similar to a mouse. Image Cursor is redundant. Similar to touch. Image

Cross-platform support

Windows 🟡

Global state via GetSystemMetrics(SM_DIGITIZER). I've done a bit of testing with an external tablet, and the API reports both NID_INTEGRATED_PEN and NID_EXTERNAL_PEN for it. Might need to find a better API.

N.B.: It might be difficult to tell whether a tablet with a built-in screen is internal or external, as the HDMI screen and the USB digitizer are two separate devices and the user must manually map the two together.

https://learn.microsoft.com/en-us/windows/win32/wintouch/getting-started-with-multi-touch-messages#testing-the-capabilities-of-the-input-digitizer

Android 🟢

Per-pen state via InputDevice.isExternal(). Works quite well, tested on an S Pen and two USB tablets.

iOS ❔

No support for pens?

iPadOS ❔

People tell me the only supported pen is the Apple Pencil, and that is always internal.

Others ❔

Always report SDL_PEN_LOCATION_UNKNOWN.

Implementation

Re-use the existing SDL_PenInfo, just add an extra flag the backends can report, and publicly expose only this flag.

typedef struct SDL_PenInfo
{
SDL_PenCapabilityFlags capabilities; /**< bitflags of device capabilities */
float max_tilt; /**< Physical maximum tilt angle, for XTILT and YTILT, or -1.0f if unknown. Pens cannot typically tilt all the way to 90 degrees, so this value is usually less than 90.0. */
Uint32 wacom_id; /**< For Wacom devices: wacom tool type ID, otherwise 0 (useful e.g. with libwacom) */
int num_buttons; /**< Number of pen buttons (not counting the pen tip), or -1 if unknown. */
SDL_PenSubtype subtype; /**< type of pen device */
} SDL_PenInfo;
// Backend calls this when a new pen device is hotplugged, plus once for each pen already connected at startup.
// Note that name and info are copied but currently unused; this is placeholder for a potentially more robust API later.
// Both are allowed to be NULL.
extern SDL_PenID SDL_AddPenDevice(Uint64 timestamp, const char *name, const SDL_PenInfo *info, void *handle);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions