pen: Rework public API.

This changes the API in various ways, and updates the backends for this.

Overall, this is a massive simplification of the API, as most future backends
can't support the previously-offered API.

This also removes the testautomation pen code (not only did these interfaces
change completely, it also did something no other test did: mock the internal
API), and replaces testpen.c with a different implementation (the existing
code was fine, it was just easier to start from scratch than update it).
This commit is contained in:
Ryan C. Gordon
2024-05-26 11:38:40 -04:00
parent 2b853121fe
commit a9d70dbacb
29 changed files with 1429 additions and 5146 deletions
@@ -212,12 +212,6 @@
<ClCompile Include="..\..\..\test\testautomation_main.c" />
<ClCompile Include="..\..\..\test\testautomation_math.c" />
<ClCompile Include="..\..\..\test\testautomation_mouse.c" />
<ClCompile Include="..\..\..\test\testautomation_pen.c">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile Include="..\..\..\test\testautomation_pixels.c" />
<ClCompile Include="..\..\..\test\testautomation_platform.c" />
<ClCompile Include="..\..\..\test\testautomation_properties.c" />
@@ -1274,7 +1274,6 @@
4537749212091504002F0F45 /* testshape.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testshape.app; sourceTree = BUILT_PRODUCTS_DIR; };
453774A4120915E3002F0F45 /* testshape.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testshape.c; sourceTree = "<group>"; };
66E88E8A203B778F0004D44E /* testyuv_cvt.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = testyuv_cvt.c; sourceTree = "<group>"; };
A1A859442BC72FC20045DD6C /* testautomation_pen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_pen.c; sourceTree = "<group>"; };
A1A859482BC72FC20045DD6C /* testautomation_properties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_properties.c; sourceTree = "<group>"; };
A1A859492BC72FC20045DD6C /* testautomation_subsystems.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_subsystems.c; sourceTree = "<group>"; };
A1A8594A2BC72FC20045DD6C /* testautomation_log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_log.c; sourceTree = "<group>"; };
@@ -1804,7 +1803,6 @@
F35E56B62983130A00A43A5F /* testautomation_main.c */,
F35E56BA2983130B00A43A5F /* testautomation_math.c */,
F35E56CD2983130F00A43A5F /* testautomation_mouse.c */,
A1A859442BC72FC20045DD6C /* testautomation_pen.c */,
F35E56C02983130C00A43A5F /* testautomation_pixels.c */,
F35E56C32983130D00A43A5F /* testautomation_platform.c */,
A1A859482BC72FC20045DD6C /* testautomation_properties.c */,
+104 -49
View File
@@ -151,8 +151,6 @@ typedef enum SDL_EventType
in an event watcher, the window handle is still valid and can still be used to retrieve any userdata
associated with the window. Otherwise, the handle has already been destroyed and all resources
associated with it are invalid */
SDL_EVENT_WINDOW_PEN_ENTER, /**< Window has gained focus of the pressure-sensitive pen with ID "data1" */
SDL_EVENT_WINDOW_PEN_LEAVE, /**< Window has lost focus of the pressure-sensitive pen with ID "data1" */
SDL_EVENT_WINDOW_HDR_STATE_CHANGED, /**< Window HDR properties have changed */
SDL_EVENT_WINDOW_FIRST = SDL_EVENT_WINDOW_SHOWN,
SDL_EVENT_WINDOW_LAST = SDL_EVENT_WINDOW_HDR_STATE_CHANGED,
@@ -227,11 +225,14 @@ typedef enum SDL_EventType
SDL_EVENT_SENSOR_UPDATE = 0x1200, /**< A sensor was updated */
/* Pressure-sensitive pen events */
SDL_EVENT_PEN_DOWN = 0x1300, /**< Pressure-sensitive pen touched drawing surface */
SDL_EVENT_PEN_PROXIMITY_IN = 0x1300, /**< Pressure-sensitive pen has become available */
SDL_EVENT_PEN_PROXIMITY_OUT, /**< Pressure-sensitive pen has become unavailable */
SDL_EVENT_PEN_DOWN, /**< Pressure-sensitive pen touched drawing surface */
SDL_EVENT_PEN_UP, /**< Pressure-sensitive pen stopped touching drawing surface */
SDL_EVENT_PEN_MOTION, /**< Pressure-sensitive pen moved, or angle/pressure changed */
SDL_EVENT_PEN_BUTTON_DOWN, /**< Pressure-sensitive pen button pressed */
SDL_EVENT_PEN_BUTTON_UP, /**< Pressure-sensitive pen button released */
SDL_EVENT_PEN_MOTION, /**< Pressure-sensitive pen is moving on the tablet */
SDL_EVENT_PEN_AXIS, /**< Pressure-sensitive pen angle/pressure/etc changed */
/* Camera hotplug events */
SDL_EVENT_CAMERA_DEVICE_ADDED = 0x1400, /**< A new camera device is available */
@@ -426,7 +427,7 @@ typedef struct SDL_MouseMotionEvent
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_WindowID windowID; /**< The window with mouse focus, if any */
SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */
SDL_MouseID which; /**< The mouse instance id or SDL_TOUCH_MOUSEID */
SDL_MouseButtonFlags state; /**< The current button state */
float x; /**< X coordinate, relative to window */
float y; /**< Y coordinate, relative to window */
@@ -445,7 +446,7 @@ typedef struct SDL_MouseButtonEvent
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_WindowID windowID; /**< The window with mouse focus, if any */
SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */
SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID */
Uint8 button; /**< The mouse button index */
Uint8 state; /**< SDL_PRESSED or SDL_RELEASED */
Uint8 clicks; /**< 1 for single-click, 2 for double-click, etc. */
@@ -465,7 +466,7 @@ typedef struct SDL_MouseWheelEvent
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_WindowID windowID; /**< The window with mouse focus, if any */
SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */
SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID */
float x; /**< The amount scrolled horizontally, positive to the right and negative to the left */
float y; /**< The amount scrolled vertically, positive away from the user and negative toward the user */
SDL_MouseWheelDirection direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
@@ -714,67 +715,119 @@ typedef struct SDL_TouchFingerEvent
SDL_WindowID windowID; /**< The window underneath the finger, if any */
} SDL_TouchFingerEvent;
/**
* Pressure-sensitive pen touched or stopped touching surface (event.ptip.*)
* Pressure-sensitive pen proximity event structure (event.pmotion.*)
*
* When a pen becomes visible to the system (it is close enough to a tablet,
* etc), SDL will send an SDL_EVENT_PEN_PROXIMITY_IN event with the new
* pen's ID. This ID is valid until the pen leaves proximity again (has
* been removed from the tablet's area, the tablet has been unplugged, etc).
* If the same pen reenters proximity again, it will be given a new ID.
*
* Note that "proximity" means "close enough for the tablet to know the tool
* is there." The pen touching and lifting off from the tablet while not
* leaving the area are handled by SDL_EVENT_PEN_DOWN and SDL_EVENT_PEN_UP.
*
* \since This struct is available since SDL 3.0.0.
*/
typedef struct SDL_PenTipEvent
typedef struct SDL_PenProximityEvent
{
SDL_EventType type; /**< SDL_EVENT_PEN_PROXIMITY_IN or SDL_EVENT_PEN_PROXIMITY_OUT */
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_WindowID windowID; /**< The window with mouse focus, if any */
SDL_PenID which; /**< The pen instance id */
} SDL_PenProximityEvent;
/**
* Pressure-sensitive pen motion event structure (event.pmotion.*)
*
* Depending on the hardware, you may get motion events when the
* pen is not touching a tablet, for tracking a pen even when it
* isn't drawing. You should listen for SDL_EVENT_PEN_DOWN and
* SDL_EVENT_PEN_UP events, or check `pen_state & SDL_PEN_INPUT_DOWN`
* to decide if a pen is "drawing" when dealing with pen motion.
*
* \since This struct is available since SDL 3.0.0.
*/
typedef struct SDL_PenMotionEvent
{
SDL_EventType type; /**< SDL_EVENT_PEN_MOTION */
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_WindowID windowID; /**< The window with mouse focus, if any */
SDL_PenID which; /**< The pen instance id */
SDL_PenInputFlags pen_state; /**< Complete pen input state at time of event */
float x; /**< X position of pen on tablet */
float y; /**< Y position of pen on tablet */
} SDL_PenMotionEvent;
/**
* Pressure-sensitive pen touched event structure (event.ptouch.*)
*
* These events come when a pen touches a surface (a tablet, etc),
* or lifts off from one.
*
* \since This struct is available since SDL 3.0.0.
*/
typedef struct SDL_PenTouchEvent
{
SDL_EventType type; /**< SDL_EVENT_PEN_DOWN or SDL_EVENT_PEN_UP */
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_WindowID windowID; /**< The window with pen focus, if any */
SDL_PenID which; /**< The pen instance id */
Uint8 tip; /**< SDL_PEN_TIP_INK when using a regular pen tip, or SDL_PEN_TIP_ERASER if the pen is being used as an eraser (e.g., flipped to use the eraser tip) */
Uint8 state; /**< SDL_PRESSED on SDL_EVENT_PEN_DOWN and SDL_RELEASED on SDL_EVENT_PEN_UP */
Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.), SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */
float x; /**< X coordinate, relative to window */
float y; /**< Y coordinate, relative to window */
float axes[SDL_PEN_NUM_AXES]; /**< Pen axes such as pressure and tilt (ordered as per SDL_PenAxis) */
} SDL_PenTipEvent;
/**
* Pressure-sensitive pen motion / pressure / angle event structure
* (event.pmotion.*)
*
* \since This struct is available since SDL 3.0.0.
*/
typedef struct SDL_PenMotionEvent
{
SDL_EventType type; /**< SDL_EVENT_PEN_MOTION */
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_WindowID windowID; /**< The window with pen focus, if any */
SDL_PenID which; /**< The pen instance id */
Uint8 padding1;
Uint8 padding2;
Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.), SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */
float x; /**< X coordinate, relative to window */
float y; /**< Y coordinate, relative to window */
float axes[SDL_PEN_NUM_AXES]; /**< Pen axes such as pressure and tilt (ordered as per SDL_PenAxis) */
} SDL_PenMotionEvent;
SDL_PenInputFlags pen_state; /**< Complete pen input state at time of event */
float x; /**< X position of pen on tablet */
float y; /**< Y position of pen on tablet */
Uint8 eraser; /**< Non-zero if eraser end is used (not all pens support this). */
Uint8 state; /**< SDL_PRESSED (pen is touching) or SDL_RELEASED (pen is lifted off) */
} SDL_PenTouchEvent;
/**
* Pressure-sensitive pen button event structure (event.pbutton.*)
*
* This is for buttons on the pen itself that the user might click.
* The pen itself pressing down to draw triggers a SDL_EVENT_PEN_DOWN
* event instead.
*
* \since This struct is available since SDL 3.0.0.
*/
typedef struct SDL_PenButtonEvent
{
SDL_EventType type; /**< SDL_EVENT_PEN_BUTTON_DOWN or SDL_EVENT_PEN_BUTTON_UP */
SDL_EventType type; /**< SDL_EVENT_PEN_BUTTON_DOWN or SDL_EVENT_PEN_BUTTON_UP */
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_WindowID windowID; /**< The window with mouse focus, if any */
SDL_PenID which; /**< The pen instance id */
SDL_PenInputFlags pen_state; /**< Complete pen input state at time of event */
float x; /**< X position of pen on tablet */
float y; /**< Y position of pen on tablet */
Uint8 button; /**< The pen button index (first button is 1). */
Uint8 state; /**< SDL_PRESSED or SDL_RELEASED */
} SDL_PenButtonEvent;
/**
* Pressure-sensitive pen pressure / angle event structure
* (event.paxis.*)
*
* You might get some of these events even if the pen isn't touching the tablet.
*
* \since This struct is available since SDL 3.0.0.
*/
typedef struct SDL_PenAxisEvent
{
SDL_EventType type; /**< SDL_EVENT_PEN_AXIS */
Uint32 reserved;
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
SDL_WindowID windowID; /**< The window with pen focus, if any */
SDL_PenID which; /**< The pen instance id */
Uint8 button; /**< The pen button index (1 represents the pen tip for compatibility with mouse events) */
Uint8 state; /**< SDL_PRESSED or SDL_RELEASED */
Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.), SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */
float x; /**< X coordinate, relative to window */
float y; /**< Y coordinate, relative to window */
float axes[SDL_PEN_NUM_AXES]; /**< Pen axes such as pressure and tilt (ordered as per SDL_PenAxis) */
} SDL_PenButtonEvent;
SDL_PenInputFlags pen_state; /**< Complete pen input state at time of event */
float x; /**< X position of pen on tablet */
float y; /**< Y position of pen on tablet */
SDL_PenAxis axis; /**< Axis that has changed */
float value; /**< New value of axis */
} SDL_PenAxisEvent;
/**
* An event used to drop text or request a file open by the system
@@ -894,9 +947,11 @@ typedef union SDL_Event
SDL_QuitEvent quit; /**< Quit request event data */
SDL_UserEvent user; /**< Custom event data */
SDL_TouchFingerEvent tfinger; /**< Touch finger event data */
SDL_PenTipEvent ptip; /**< Pen tip touching or leaving drawing surface */
SDL_PenMotionEvent pmotion; /**< Pen change in position, pressure, or angle */
SDL_PenButtonEvent pbutton; /**< Pen button press */
SDL_PenProximityEvent pproximity; /**< Pen proximity event data */
SDL_PenTouchEvent ptouch; /**< Pen tip touching event data */
SDL_PenMotionEvent pmotion; /**< Pen motion event data */
SDL_PenButtonEvent pbutton; /**< Pen button event data */
SDL_PenAxisEvent paxis; /**< Pen axis event data */
SDL_DropEvent drop; /**< Drag and drop event data */
SDL_ClipboardEvent clipboard; /**< Clipboard event data */
+47 -221
View File
@@ -22,56 +22,65 @@
/**
* # CategoryPen
*
* Include file for SDL pen event handling.
* SDL pen event handling.
*
* This file describes operations for pressure-sensitive pen (stylus and/or
* SDL provides an API for pressure-sensitive pen (stylus and/or
* eraser) handling, e.g., for input and drawing tablets or suitably equipped
* mobile / tablet devices.
*
* To get started with pens:
* To get started with pens, simply handle SDL_EVENT_PEN_* events. When a pen
* starts providing input, SDL will assign it a unique SDL_PenID, which will
* remain for the life of the process, as long as the pen stays connected.
*
* - Listen to SDL_PenMotionEvent and SDL_PenButtonEvent
* - To avoid treating pen events as mouse events, ignore SDL_MouseMotionEvent
* and SDL_MouseButtonEvent whenever `which` == SDL_PEN_MOUSEID.
*
* We primarily identify pens by SDL_PenID. The implementation makes a best
* effort to relate each SDL_PenID to the same physical device during a
* session. Formerly valid SDL_PenID values remain valid even if a device
* disappears.
*
* For identifying pens across sessions, the API provides the type SDL_GUID .
* Pens may provide more than simple touch input; they might have other axes,
* such as pressure, tilt, rotation, etc.
*/
#ifndef SDL_pen_h_
#define SDL_pen_h_
#include <SDL3/SDL_error.h>
#include <SDL3/SDL_guid.h>
#include <SDL3/SDL_mouse.h>
#include <SDL3/SDL_stdinc.h>
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
typedef Uint32 SDL_PenID; /**< SDL_PenIDs identify pens uniquely within a session */
/**
* SDL pen instance IDs.
*
* Zero is used to signify an invalid/null device.
*
* These show up in pen events when SDL sees input from them. They remain
* consistent as long as SDL can recognize a tool to be the same pen; but if
* a pen physically leaves the area and returns, it might get a new ID.
*
* \since This datatype is available since SDL 3.0.0.
*/
typedef Uint32 SDL_PenID;
#define SDL_PEN_INVALID ((SDL_PenID)0) /**< Reserved invalid SDL_PenID is valid */
#define SDL_PEN_MOUSEID ((SDL_MouseID)-2) /**< Device ID for mouse events triggered by pen events */
#define SDL_PEN_INFO_UNKNOWN (-1) /**< Marks unknown information when querying the pen */
/**
* Pen axis indices
* Pen input flags, as reported by various pen events' `pen_state` field.
*
* Below are the valid indices to the "axis" array from SDL_PenMotionEvent and
* SDL_PenButtonEvent. The axis indices form a contiguous range of ints from 0
* to SDL_PEN_AXIS_LAST, inclusive. All "axis[]" entries are either normalised
* to 0..1 or report a (positive or negative) angle in degrees, with 0.0
* representing the centre. Not all pens/backends support all axes:
* unsupported entries are always "0.0f".
* \since This datatype is available since SDL 3.0.0.
*/
typedef Uint32 SDL_PenInputFlags;
#define SDL_PEN_INPUT_DOWN (1u << 0) /**< & to see if pen is pressed down */
#define SDL_PEN_INPUT_BUTTON_1 (1u << 1) /**< & to see if button 1 is pressed */
#define SDL_PEN_INPUT_BUTTON_2 (1u << 2) /**< & to see if button 2 is pressed */
#define SDL_PEN_INPUT_BUTTON_3 (1u << 3) /**< & to see if button 3 is pressed */
#define SDL_PEN_INPUT_BUTTON_4 (1u << 4) /**< & to see if button 4 is pressed */
#define SDL_PEN_INPUT_BUTTON_5 (1u << 5) /**< & to see if button 5 is pressed */
#define SDL_PEN_INPUT_ERASER_TIP (1u << 30) /**< & to see if eraser tip is used */
/**
* Pen axis indices.
*
* These are the valid values for the `axis` field in SDL_PenAxisEvent.
* All axes are either normalised to 0..1 or report a (positive or negative) angle
* in degrees, with 0.0 representing the centre. Not all pens/backends support all
* axes: unsupported axes are always zero.
*
* To convert angles for tilt and rotation into vector representation, use
* SDL_sinf on the XTILT, YTILT, or ROTATION component, for example:
@@ -82,200 +91,17 @@ typedef Uint32 SDL_PenID; /**< SDL_PenIDs identify pens uniquely within a sessio
*/
typedef enum SDL_PenAxis
{
SDL_PEN_AXIS_PRESSURE = 0, /**< Pen pressure. Unidirectional: 0..1.0 */
SDL_PEN_AXIS_XTILT, /**< Pen horizontal tilt angle. Bidirectional: -90.0..90.0 (left-to-right).
The physical max/min tilt may be smaller than -90.0 / 90.0, cf. SDL_PenCapabilityInfo */
SDL_PEN_AXIS_YTILT, /**< Pen vertical tilt angle. Bidirectional: -90.0..90.0 (top-to-down).
The physical max/min tilt may be smaller than -90.0 / 90.0, cf. SDL_PenCapabilityInfo */
SDL_PEN_AXIS_DISTANCE, /**< Pen distance to drawing surface. Unidirectional: 0.0..1.0 */
SDL_PEN_AXIS_ROTATION, /**< Pen barrel rotation. Bidirectional: -180..179.9 (clockwise, 0 is facing up, -180.0 is facing down). */
SDL_PEN_AXIS_SLIDER, /**< Pen finger wheel or slider (e.g., Airbrush Pen). Unidirectional: 0..1.0 */
SDL_PEN_NUM_AXES, /**< Last valid axis index */
SDL_PEN_AXIS_LAST = SDL_PEN_NUM_AXES - 1 /**< Last axis index plus 1 */
SDL_PEN_AXIS_PRESSURE, /**< Pen pressure. Unidirectional: 0 to 1.0 */
SDL_PEN_AXIS_XTILT, /**< Pen horizontal tilt angle. Bidirectional: -90.0 to 90.0 (left-to-right).
The physical max/min tilt may be smaller than -90.0 / 90.0, check SDL_PenCapabilityInfo */
SDL_PEN_AXIS_YTILT, /**< Pen vertical tilt angle. Bidirectional: -90.0 to 90.0 (top-to-down).
The physical max/min tilt may be smaller than -90.0 / 90.0 check SDL_PenCapabilityInfo */
SDL_PEN_AXIS_DISTANCE, /**< Pen distance to drawing surface. Unidirectional: 0.0 to 1.0 */
SDL_PEN_AXIS_ROTATION, /**< Pen barrel rotation. Bidirectional: -180 to 179.9 (clockwise, 0 is facing up, -180.0 is facing down). */
SDL_PEN_AXIS_SLIDER, /**< Pen finger wheel or slider (e.g., Airbrush Pen). Unidirectional: 0 to 1.0 */
SDL_PEN_NUM_AXES /**< Total known pen axis types in this version of SDL. This number may grow in future releases! */
} SDL_PenAxis;
/* Pen flags. These share a bitmask space with SDL_BUTTON_LEFT and friends. */
#define SDL_PEN_FLAG_DOWN_BIT_INDEX 13 /* Bit for storing that pen is touching the surface */
#define SDL_PEN_FLAG_INK_BIT_INDEX 14 /* Bit for storing has-non-eraser-capability status */
#define SDL_PEN_FLAG_ERASER_BIT_INDEX 15 /* Bit for storing is-eraser or has-eraser-capability property */
#define SDL_PEN_FLAG_AXIS_BIT_OFFSET 16 /* Bit for storing has-axis-0 property */
#define SDL_PEN_CAPABILITY(capbit) (1ul << (capbit))
#define SDL_PEN_AXIS_CAPABILITY(axis) SDL_PEN_CAPABILITY((axis) + SDL_PEN_FLAG_AXIS_BIT_OFFSET)
/* Pen tips */
#define SDL_PEN_TIP_INK SDL_PEN_FLAG_INK_BIT_INDEX /**< Regular pen tip (for drawing) touched the surface */
#define SDL_PEN_TIP_ERASER SDL_PEN_FLAG_ERASER_BIT_INDEX /**< Eraser pen tip touched the surface */
/**
* Pen capabilities reported by SDL_GetPenCapabilities.
*
* \since This datatype is available since SDL 3.0.0.
*/
typedef Uint32 SDL_PenCapabilityFlags;
#define SDL_PEN_DOWN_MASK SDL_PEN_CAPABILITY(SDL_PEN_FLAG_DOWN_BIT_INDEX) /**< Pen tip is currently touching the drawing surface. */
#define SDL_PEN_INK_MASK SDL_PEN_CAPABILITY(SDL_PEN_FLAG_INK_BIT_INDEX) /**< Pen has a regular drawing tip (SDL_GetPenCapabilities). For events (SDL_PenButtonEvent, SDL_PenMotionEvent, SDL_GetPenStatus) this flag is mutually exclusive with SDL_PEN_ERASER_MASK . */
#define SDL_PEN_ERASER_MASK SDL_PEN_CAPABILITY(SDL_PEN_FLAG_ERASER_BIT_INDEX) /**< Pen has an eraser tip (SDL_GetPenCapabilities) or is being used as eraser (SDL_PenButtonEvent , SDL_PenMotionEvent , SDL_GetPenStatus) */
#define SDL_PEN_AXIS_PRESSURE_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_PRESSURE) /**< Pen provides pressure information in axis SDL_PEN_AXIS_PRESSURE */
#define SDL_PEN_AXIS_XTILT_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_XTILT) /**< Pen provides horizontal tilt information in axis SDL_PEN_AXIS_XTILT */
#define SDL_PEN_AXIS_YTILT_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_YTILT) /**< Pen provides vertical tilt information in axis SDL_PEN_AXIS_YTILT */
#define SDL_PEN_AXIS_DISTANCE_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_DISTANCE) /**< Pen provides distance to drawing tablet in SDL_PEN_AXIS_DISTANCE */
#define SDL_PEN_AXIS_ROTATION_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_ROTATION) /**< Pen provides barrel rotation information in axis SDL_PEN_AXIS_ROTATION */
#define SDL_PEN_AXIS_SLIDER_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_SLIDER) /**< Pen provides slider / finger wheel or similar in axis SDL_PEN_AXIS_SLIDER */
#define SDL_PEN_AXIS_BIDIRECTIONAL_MASKS (SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK)
/**
* Pen types
*
* Some pens identify as a particular type of drawing device (e.g., an
* airbrush or a pencil).
*
* \since This enum is available since SDL 3.0.0
*/
typedef enum SDL_PenSubtype
{
SDL_PEN_TYPE_UNKNOWN = 0,
SDL_PEN_TYPE_ERASER = 1, /**< Eraser */
SDL_PEN_TYPE_PEN, /**< Generic pen; this is the default. */
SDL_PEN_TYPE_PENCIL, /**< Pencil */
SDL_PEN_TYPE_BRUSH, /**< Brush-like device */
SDL_PEN_TYPE_AIRBRUSH, /**< Airbrush device that "sprays" ink */
SDL_PEN_TYPE_LAST = SDL_PEN_TYPE_AIRBRUSH /**< Last valid pen type */
} SDL_PenSubtype;
/* Function prototypes */
/**
* Retrieves all pens that are connected to the system.
*
* Yields an array of SDL_PenID values. These identify and track pens
* throughout a session. To track pens across sessions (program restart), use
* SDL_GUID .
*
* \param count the number of pens in the array (number of array elements
* minus 1, i.e., not counting the terminator 0).
* \returns a 0 terminated array of SDL_PenID values, or NULL on failure. The
* array must be freed with SDL_free(). On a NULL return,
* SDL_GetError() is set.
*
* \since This function is available since SDL 3.0.0.
*/
extern SDL_DECLSPEC SDL_PenID * SDLCALL SDL_GetPens(int *count);
/**
* Retrieves the pen's current status.
*
* If the pen is detached (cf. SDL_PenConnected), this operation may return
* default values.
*
* \param instance_id the pen to query.
* \param x out-mode parameter for pen x coordinate. May be NULL.
* \param y out-mode parameter for pen y coordinate. May be NULL.
* \param axes out-mode parameter for axis information. May be null. The axes
* are in the same order as SDL_PenAxis.
* \param num_axes maximum number of axes to write to "axes".
* \returns a bit mask with the current pen button states (SDL_BUTTON_LMASK
* etc.), possibly SDL_PEN_DOWN_MASK, and exactly one of
* SDL_PEN_INK_MASK or SDL_PEN_ERASER_MASK , or 0 on error (see
* SDL_GetError()).
*
* \since This function is available since SDL 3.0.0.
*/
extern SDL_DECLSPEC Uint32 SDLCALL SDL_GetPenStatus(SDL_PenID instance_id, float *x, float *y, float *axes, size_t num_axes);
/**
* Retrieves an SDL_PenID for the given SDL_GUID.
*
* \param guid a pen GUID.
* \returns a valid SDL_PenID, or SDL_PEN_INVALID if there is no matching
* SDL_PenID.
*
* \since This function is available since SDL 3.0.0.
*/
extern SDL_DECLSPEC SDL_PenID SDLCALL SDL_GetPenFromGUID(SDL_GUID guid);
/**
* Retrieves the SDL_GUID for a given SDL_PenID.
*
* \param instance_id the pen to query.
* \returns the corresponding pen GUID; persistent across multiple sessions.
* If "instance_id" is SDL_PEN_INVALID, returns an all-zeroes GUID.
*
* \since This function is available since SDL 3.0.0.
*/
extern SDL_DECLSPEC SDL_GUID SDLCALL SDL_GetPenGUID(SDL_PenID instance_id);
/**
* Checks whether a pen is still attached.
*
* If a pen is detached, it will not show up for SDL_GetPens(). Other
* operations will still be available but may return default values.
*
* \param instance_id a pen ID.
* \returns SDL_TRUE if "instance_id" is valid and the corresponding pen is
* attached, or SDL_FALSE otherwise.
*
* \since This function is available since SDL 3.0.0.
*/
extern SDL_DECLSPEC SDL_bool SDLCALL SDL_PenConnected(SDL_PenID instance_id);
/**
* Retrieves a human-readable description for a SDL_PenID.
*
* \param instance_id the pen to query.
* \returns a string that contains the name of the pen, intended for human
* consumption. The string might or might not be localised, depending
* on platform settings. It is not guaranteed to be unique; use
* SDL_GetPenGUID() for (best-effort) unique identifiers. The pointer
* is managed by the SDL pen subsystem and must not be deallocated.
* The pointer remains valid until SDL is shut down. Returns NULL on
* error (cf. SDL_GetError()).
*
* \since This function is available since SDL 3.0.0.
*/
extern SDL_DECLSPEC const char * SDLCALL SDL_GetPenName(SDL_PenID instance_id);
/**
* Pen capabilities, as reported by SDL_GetPenCapabilities()
*
* \since This struct is available since SDL 3.0.0.
*/
typedef struct SDL_PenCapabilityInfo
{
float max_tilt; /**< Physical maximum tilt angle, for XTILT and YTILT, or SDL_PEN_INFO_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) */
Sint8 num_buttons; /**< Number of pen buttons (not counting the pen tip), or SDL_PEN_INFO_UNKNOWN */
} SDL_PenCapabilityInfo;
/**
* Retrieves capability flags for a given SDL_PenID.
*
* \param instance_id the pen to query.
* \param capabilities detail information about pen capabilities, such as the
* number of buttons.
* \returns a set of capability flags, cf. SDL_PEN_CAPABILITIES.
*
* \since This function is available since SDL 3.0.0.
*/
extern SDL_DECLSPEC SDL_PenCapabilityFlags SDLCALL SDL_GetPenCapabilities(SDL_PenID instance_id, SDL_PenCapabilityInfo *capabilities);
/**
* Retrieves the pen type for a given SDL_PenID.
*
* \param instance_id the pen to query.
* \returns the corresponding pen type (cf. SDL_PenSubtype) or 0 on error.
* Note that the pen type does not dictate whether the pen tip is
* SDL_PEN_TIP_INK or SDL_PEN_TIP_ERASER; to determine whether a pen
* is being used for drawing or in eraser mode, check either the pen
* tip on SDL_EVENT_PEN_DOWN, or the flag SDL_PEN_ERASER_MASK in the
* pen state.
*
* \since This function is available since SDL 3.0.0.
*/
extern SDL_DECLSPEC SDL_PenSubtype SDLCALL SDL_GetPenType(SDL_PenID instance_id);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
-8
View File
@@ -355,13 +355,6 @@ SDL3_0.0.0 {
SDL_GetNumberProperty;
SDL_GetOriginalMemoryFunctions;
SDL_GetPathInfo;
SDL_GetPenCapabilities;
SDL_GetPenFromGUID;
SDL_GetPenGUID;
SDL_GetPenName;
SDL_GetPenStatus;
SDL_GetPenType;
SDL_GetPens;
SDL_GetPerformanceCounter;
SDL_GetPerformanceFrequency;
SDL_GetPixelFormatDetails;
@@ -611,7 +604,6 @@ SDL3_0.0.0 {
SDL_PauseAudioStreamDevice;
SDL_PauseHaptic;
SDL_PeepEvents;
SDL_PenConnected;
SDL_PlayHapticRumble;
SDL_PollEvent;
SDL_PremultiplyAlpha;
-8
View File
@@ -380,13 +380,6 @@
#define SDL_GetNumberProperty SDL_GetNumberProperty_REAL
#define SDL_GetOriginalMemoryFunctions SDL_GetOriginalMemoryFunctions_REAL
#define SDL_GetPathInfo SDL_GetPathInfo_REAL
#define SDL_GetPenCapabilities SDL_GetPenCapabilities_REAL
#define SDL_GetPenFromGUID SDL_GetPenFromGUID_REAL
#define SDL_GetPenGUID SDL_GetPenGUID_REAL
#define SDL_GetPenName SDL_GetPenName_REAL
#define SDL_GetPenStatus SDL_GetPenStatus_REAL
#define SDL_GetPenType SDL_GetPenType_REAL
#define SDL_GetPens SDL_GetPens_REAL
#define SDL_GetPerformanceCounter SDL_GetPerformanceCounter_REAL
#define SDL_GetPerformanceFrequency SDL_GetPerformanceFrequency_REAL
#define SDL_GetPixelFormatDetails SDL_GetPixelFormatDetails_REAL
@@ -636,7 +629,6 @@
#define SDL_PauseAudioStreamDevice SDL_PauseAudioStreamDevice_REAL
#define SDL_PauseHaptic SDL_PauseHaptic_REAL
#define SDL_PeepEvents SDL_PeepEvents_REAL
#define SDL_PenConnected SDL_PenConnected_REAL
#define SDL_PlayHapticRumble SDL_PlayHapticRumble_REAL
#define SDL_PollEvent SDL_PollEvent_REAL
#define SDL_PremultiplyAlpha SDL_PremultiplyAlpha_REAL
-8
View File
@@ -400,13 +400,6 @@ SDL_DYNAPI_PROC(int,SDL_GetNumVideoDrivers,(void),(),return)
SDL_DYNAPI_PROC(Sint64,SDL_GetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return)
SDL_DYNAPI_PROC(void,SDL_GetOriginalMemoryFunctions,(SDL_malloc_func *a, SDL_calloc_func *b, SDL_realloc_func *c, SDL_free_func *d),(a,b,c,d),)
SDL_DYNAPI_PROC(int,SDL_GetPathInfo,(const char *a, SDL_PathInfo *b),(a,b),return)
SDL_DYNAPI_PROC(SDL_PenCapabilityFlags,SDL_GetPenCapabilities,(SDL_PenID a, SDL_PenCapabilityInfo *b),(a,b),return)
SDL_DYNAPI_PROC(SDL_PenID,SDL_GetPenFromGUID,(SDL_GUID a),(a),return)
SDL_DYNAPI_PROC(SDL_GUID,SDL_GetPenGUID,(SDL_PenID a),(a),return)
SDL_DYNAPI_PROC(const char*,SDL_GetPenName,(SDL_PenID a),(a),return)
SDL_DYNAPI_PROC(Uint32,SDL_GetPenStatus,(SDL_PenID a, float *b, float *c, float *d, size_t e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(SDL_PenSubtype,SDL_GetPenType,(SDL_PenID a),(a),return)
SDL_DYNAPI_PROC(SDL_PenID*,SDL_GetPens,(int *a),(a),return)
SDL_DYNAPI_PROC(Uint64,SDL_GetPerformanceCounter,(void),(),return)
SDL_DYNAPI_PROC(Uint64,SDL_GetPerformanceFrequency,(void),(),return)
SDL_DYNAPI_PROC(const SDL_PixelFormatDetails*,SDL_GetPixelFormatDetails,(SDL_PixelFormat a),(a),return)
@@ -647,7 +640,6 @@ SDL_DYNAPI_PROC(int,SDL_PauseAudioDevice,(SDL_AudioDeviceID a),(a),return)
SDL_DYNAPI_PROC(int,SDL_PauseAudioStreamDevice,(SDL_AudioStream *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_PauseHaptic,(SDL_Haptic *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_PeepEvents,(SDL_Event *a, int b, SDL_EventAction c, Uint32 d, Uint32 e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_PenConnected,(SDL_PenID a),(a),return)
SDL_DYNAPI_PROC(int,SDL_PlayHapticRumble,(SDL_Haptic *a, float b, Uint32 c),(a,b,c),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_PollEvent,(SDL_Event *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_PremultiplyAlpha,(int a, int b, SDL_PixelFormat c, const void *d, int e, SDL_PixelFormat f, void *g, int h, SDL_bool i),(a,b,c,d,e,f,g,h,i),return)
+21 -8
View File
@@ -153,17 +153,24 @@ SDL_EventCategory SDL_GetEventCategory(Uint32 type)
case SDL_EVENT_SENSOR_UPDATE:
return SDL_EVENTCATEGORY_SENSOR;
case SDL_EVENT_PEN_PROXIMITY_IN:
case SDL_EVENT_PEN_PROXIMITY_OUT:
return SDL_EVENTCATEGORY_PPROXIMITY;
case SDL_EVENT_PEN_DOWN:
case SDL_EVENT_PEN_UP:
return SDL_EVENTCATEGORY_PTIP;
case SDL_EVENT_PEN_MOTION:
return SDL_EVENTCATEGORY_PMOTION;
return SDL_EVENTCATEGORY_PTOUCH;
case SDL_EVENT_PEN_BUTTON_DOWN:
case SDL_EVENT_PEN_BUTTON_UP:
return SDL_EVENTCATEGORY_PBUTTON;
case SDL_EVENT_PEN_MOTION:
return SDL_EVENTCATEGORY_PMOTION;
case SDL_EVENT_PEN_AXIS:
return SDL_EVENTCATEGORY_PAXIS;
case SDL_EVENT_CAMERA_DEVICE_ADDED:
case SDL_EVENT_CAMERA_DEVICE_REMOVED:
case SDL_EVENT_CAMERA_DEVICE_APPROVED:
@@ -207,14 +214,20 @@ SDL_Window *SDL_GetWindowFromEvent(const SDL_Event *event)
case SDL_EVENTCATEGORY_TFINGER:
windowID = event->tfinger.windowID;
break;
case SDL_EVENTCATEGORY_PTIP:
windowID = event->ptip.windowID;
case SDL_EVENTCATEGORY_PPROXIMITY:
windowID = event->pproximity.windowID;
break;
case SDL_EVENTCATEGORY_PTOUCH:
windowID = event->ptouch.windowID;
break;
case SDL_EVENTCATEGORY_PBUTTON:
windowID = event->pbutton.windowID;
break;
case SDL_EVENTCATEGORY_PMOTION:
windowID = event->pmotion.windowID;
break;
case SDL_EVENTCATEGORY_PBUTTON:
windowID = event->pbutton.windowID;
case SDL_EVENTCATEGORY_PAXIS:
windowID = event->paxis.windowID;
break;
case SDL_EVENTCATEGORY_DROP:
windowID = event->drop.windowID;
+3 -1
View File
@@ -54,9 +54,11 @@ typedef enum SDL_EventCategory
SDL_EVENTCATEGORY_QUIT,
SDL_EVENTCATEGORY_USER,
SDL_EVENTCATEGORY_TFINGER,
SDL_EVENTCATEGORY_PTIP,
SDL_EVENTCATEGORY_PPROXIMITY,
SDL_EVENTCATEGORY_PTOUCH,
SDL_EVENTCATEGORY_PMOTION,
SDL_EVENTCATEGORY_PBUTTON,
SDL_EVENTCATEGORY_PAXIS,
SDL_EVENTCATEGORY_DROP,
SDL_EVENTCATEGORY_CLIPBOARD,
} SDL_EventCategory;
+33 -32
View File
@@ -378,6 +378,9 @@ static void SDLCALL SDL_EventLoggingChanged(void *userdata, const char *name, co
static void SDL_LogEvent(const SDL_Event *event)
{
static const char *pen_axisnames[] = { "PRESSURE", "XTILT", "YTILT", "DISTANCE", "ROTATION", "SLIDER" };
SDL_COMPILE_TIME_ASSERT(pen_axisnames_array_matches, SDL_arraysize(pen_axisnames) == SDL_PEN_NUM_AXES);
char name[64];
char details[128];
@@ -385,6 +388,7 @@ static void SDL_LogEvent(const SDL_Event *event)
if ((SDL_EventLoggingVerbosity < 2) &&
((event->type == SDL_EVENT_MOUSE_MOTION) ||
(event->type == SDL_EVENT_FINGER_MOTION) ||
(event->type == SDL_EVENT_PEN_AXIS) ||
(event->type == SDL_EVENT_PEN_MOTION) ||
(event->type == SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION) ||
(event->type == SDL_EVENT_GAMEPAD_SENSOR_UPDATE) ||
@@ -482,8 +486,6 @@ static void SDL_LogEvent(const SDL_Event *event)
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_RESTORED);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOUSE_ENTER);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOUSE_LEAVE);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PEN_ENTER);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PEN_LEAVE);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_FOCUS_GAINED);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_FOCUS_LOST);
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_CLOSE_REQUESTED);
@@ -699,45 +701,44 @@ static void SDL_LogEvent(const SDL_Event *event)
break;
#undef PRINT_FINGER_EVENT
#define PRINT_PTIP_EVENT(event) \
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u tip=%u state=%s x=%g y=%g)", \
(uint)event->ptip.timestamp, (uint)event->ptip.windowID, \
(uint)event->ptip.which, (uint)event->ptip.tip, \
event->ptip.state == SDL_PRESSED ? "down" : "up", \
event->ptip.x, event->ptip.y)
#define PRINT_PTOUCH_EVENT(event) \
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g eraser=%s state=%s)", \
(uint)event->ptouch.timestamp, (uint)event->ptouch.windowID, (uint)event->ptouch.which, (uint)event->ptouch.pen_state, event->ptouch.x, event->ptouch.y, \
event->ptouch.eraser ? "yes" : "no", event->ptouch.state == SDL_PRESSED ? "down" : "up");
SDL_EVENT_CASE(SDL_EVENT_PEN_DOWN)
PRINT_PTIP_EVENT(event);
PRINT_PTOUCH_EVENT(event);
break;
SDL_EVENT_CASE(SDL_EVENT_PEN_UP)
PRINT_PTIP_EVENT(event);
PRINT_PTOUCH_EVENT(event);
break;
#undef PRINT_PTOUCH_EVENT
#define PRINT_PPROXIMITY_EVENT(event) \
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u)", \
(uint)event->pproximity.timestamp, (uint)event->pproximity.windowID, (uint)event->pproximity.which);
SDL_EVENT_CASE(SDL_EVENT_PEN_PROXIMITY_IN)
PRINT_PPROXIMITY_EVENT(event);
break;
SDL_EVENT_CASE(SDL_EVENT_PEN_PROXIMITY_OUT)
PRINT_PPROXIMITY_EVENT(event);
break;
#undef PRINT_PPROXIMITY_EVENT
SDL_EVENT_CASE(SDL_EVENT_PEN_AXIS)
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g axis=%s value=%g)",
(uint)event->paxis.timestamp, (uint)event->paxis.windowID, (uint)event->paxis.which, (uint)event->paxis.pen_state, event->paxis.x, event->paxis.y,
((event->paxis.axis >= 0) && (event->paxis.axis < SDL_arraysize(pen_axisnames))) ? pen_axisnames[event->paxis.axis] : "[UNKNOWN]", event->paxis.value);
break;
#undef PRINT_PTIP_EVENT
SDL_EVENT_CASE(SDL_EVENT_PEN_MOTION)
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u state=%08x x=%g y=%g [%g, %g, %g, %g, %g, %g])",
(uint)event->pmotion.timestamp, (uint)event->pmotion.windowID,
(uint)event->pmotion.which, (uint)event->pmotion.pen_state,
event->pmotion.x, event->pmotion.y,
event->pmotion.axes[SDL_PEN_AXIS_PRESSURE],
event->pmotion.axes[SDL_PEN_AXIS_XTILT],
event->pmotion.axes[SDL_PEN_AXIS_YTILT],
event->pmotion.axes[SDL_PEN_AXIS_DISTANCE],
event->pmotion.axes[SDL_PEN_AXIS_ROTATION],
event->pmotion.axes[SDL_PEN_AXIS_SLIDER]);
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g)",
(uint)event->pmotion.timestamp, (uint)event->pmotion.windowID, (uint)event->pmotion.which, (uint)event->pmotion.pen_state, event->pmotion.x, event->pmotion.y);
break;
#define PRINT_PBUTTON_EVENT(event) \
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u tip=%u state=%s x=%g y=%g axes=[%g, %g, %g, %g, %g, %g])", \
(uint)event->pbutton.timestamp, (uint)event->pbutton.windowID, \
(uint)event->pbutton.which, (uint)event->pbutton.button, \
event->pbutton.state == SDL_PRESSED ? "pressed" : "released", \
event->pbutton.x, event->pbutton.y, \
event->pbutton.axes[SDL_PEN_AXIS_PRESSURE], \
event->pbutton.axes[SDL_PEN_AXIS_XTILT], \
event->pbutton.axes[SDL_PEN_AXIS_YTILT], \
event->pbutton.axes[SDL_PEN_AXIS_DISTANCE], \
event->pbutton.axes[SDL_PEN_AXIS_ROTATION], \
event->pbutton.axes[SDL_PEN_AXIS_SLIDER])
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g button=%u state=%s)", \
(uint)event->pbutton.timestamp, (uint)event->pbutton.windowID, (uint)event->pbutton.which, (uint)event->pbutton.pen_state, event->pbutton.x, event->pbutton.y, \
(uint)event->pbutton.button, event->pbutton.state == SDL_PRESSED ? "down" : "up");
SDL_EVENT_CASE(SDL_EVENT_PEN_BUTTON_DOWN)
PRINT_PBUTTON_EVENT(event);
break;
+1
View File
@@ -33,6 +33,7 @@
#include "SDL_keyboard_c.h"
#include "SDL_mouse_c.h"
#include "SDL_touch_c.h"
#include "SDL_pen_c.h"
#include "SDL_windowevents_c.h"
/* Start and stop the event processing loop */
+3 -6
View File
@@ -26,7 +26,6 @@
#include "../video/SDL_sysvideo.h"
#include "SDL_events_c.h"
#include "SDL_mouse_c.h"
#include "SDL_pen_c.h"
#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)
#include "../core/windows/SDL_windows.h" // For GetDoubleClickTime()
#endif
@@ -254,6 +253,7 @@ int SDL_PreInitMouse(void)
mouse->was_touch_mouse_events = SDL_FALSE; /* no touch to mouse movement event pending */
mouse->cursor_shown = SDL_TRUE;
return 0;
}
@@ -272,8 +272,6 @@ void SDL_PostInitMouse(void)
SDL_DestroySurface(surface);
}
}
SDL_PenInit();
}
SDL_bool SDL_IsMouse(Uint16 vendor, Uint16 product)
@@ -741,7 +739,7 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_
float xrel = 0.0f;
float yrel = 0.0f;
if ((!mouse->relative_mode || mouse->warp_emulation_active) && mouseID != SDL_TOUCH_MOUSEID && mouseID != SDL_PEN_MOUSEID) {
if ((!mouse->relative_mode || mouse->warp_emulation_active) && mouseID != SDL_TOUCH_MOUSEID) {
/* We're not in relative mode, so all mouse events are global mouse events */
mouseID = SDL_GLOBAL_MOUSE_ID;
}
@@ -935,7 +933,7 @@ static int SDL_PrivateSendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_
Uint32 buttonstate;
SDL_MouseInputSource *source;
if (!mouse->relative_mode && mouseID != SDL_TOUCH_MOUSEID && mouseID != SDL_PEN_MOUSEID) {
if (!mouse->relative_mode && mouseID != SDL_TOUCH_MOUSEID) {
/* We're not in relative mode, so all mouse events are global mouse events */
mouseID = SDL_GLOBAL_MOUSE_ID;
}
@@ -1101,7 +1099,6 @@ void SDL_QuitMouse(void)
}
SDL_SetRelativeMouseMode(SDL_FALSE);
SDL_ShowCursor();
SDL_PenQuit();
if (mouse->def_cursor) {
SDL_SetDefaultCursor(NULL);
+404 -1008
View File
File diff suppressed because it is too large Load Diff
+49 -294
View File
@@ -27,316 +27,71 @@
#include "../../include/SDL3/SDL_pen.h"
#include "SDL_mouse_c.h"
/* For testing alternate code paths: */
#define SDL_PEN_DEBUG_NOID 0 /* Pretend that pen device does not supply ID / ID is some default value \
affects: SDL_x11pen.c \
SDL_waylandevents.c */
#define SDL_PEN_DEBUG_NONWACOM 0 /* Pretend that no attached device is a Wacom device \
affects: SDL_x11pen.c \
SDL_waylandevents.c */
#define SDL_PEN_DEBUG_UNKNOWN_WACOM 0 /* Pretend that any attached Wacom device is of an unknown make \
affects: SDL_PenModifyFromWacomID() */
#define SDL_PEN_DEBUG_NOSERIAL_WACOM 0 /* Pretend that any attached Wacom device has serial number 0 \
affects: SDL_x11pen.c \
SDL_waylandevents.c */
typedef Uint32 SDL_PenCapabilityFlags;
#define SDL_PEN_CAPABILITY_PRESSURE (1u << 0) /**< Provides pressure information on SDL_PEN_AXIS_PRESSURE. */
#define SDL_PEN_CAPABILITY_XTILT (1u << 1) /**< Provides horizontal tilt information on SDL_PEN_AXIS_XTILT. */
#define SDL_PEN_CAPABILITY_YTILT (1u << 2) /**< Provides vertical tilt information on SDL_PEN_AXIS_YTILT. */
#define SDL_PEN_CAPABILITY_DISTANCE (1u << 3) /**< Provides distance to drawing tablet on SDL_PEN_AXIS_DISTANCE. */
#define SDL_PEN_CAPABILITY_ROTATION (1u << 4) /**< Provides barrel rotation info on SDL_PEN_AXIS_ROTATION. */
#define SDL_PEN_CAPABILITY_SLIDER (1u << 5) /**< Provides slider/finger wheel/etc on SDL_PEN_AXIS_SLIDER. */
#define SDL_PEN_CAPABILITY_ERASER (1u << 6) /**< Pen also has an eraser tip. */
#define SDL_PEN_TYPE_NONE 0 /**< Pen type for non-pens (use to cancel pen registration) */
#define SDL_PEN_MAX_NAME 64
#define SDL_PEN_FLAG_ERROR (1ul << 28) /* Printed an internal API usage error about this pen (used to prevent spamming) */
#define SDL_PEN_FLAG_NEW (1ul << 29) /* Pen was registered in most recent call to SDL_PenRegisterBegin() */
#define SDL_PEN_FLAG_DETACHED (1ul << 30) /* Detached (not re-registered before last SDL_PenGCSweep()) */
#define SDL_PEN_FLAG_STALE (1ul << 31) /* Not re-registered since last SDL_PenGCMark() */
typedef struct SDL_PenStatusInfo
typedef enum SDL_PenSubtype
{
float x, y;
float axes[SDL_PEN_NUM_AXES];
Uint16 buttons; /* SDL_BUTTON(1) | SDL_BUTTON(2) | ... | SDL_PEN_DOWN_MASK */
} SDL_PenStatusInfo;
SDL_PEN_TYPE_UNKNOWN, /**< Unknown pen device */
SDL_PEN_TYPE_ERASER, /**< Eraser */
SDL_PEN_TYPE_PEN, /**< Generic pen; this is the default. */
SDL_PEN_TYPE_PENCIL, /**< Pencil */
SDL_PEN_TYPE_BRUSH, /**< Brush-like device */
SDL_PEN_TYPE_AIRBRUSH /**< Airbrush device that "sprays" ink */
} SDL_PenSubtype;
typedef struct
typedef struct SDL_PenInfo
{
SDL_PenID id; /* id determines sort order unless SDL_PEN_FLAG_DETACHED is set */
Uint32 flags; /* SDL_PEN_FLAG_* | SDK_PEN_DOWN_MASK | SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_* */
SDL_Window *window; /* Current SDL window for this pen, or NULL */
} SDL_PenHeader;
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;
/**
* Internal (backend driver-independent) pen representation
*
* Implementation-specific backend drivers may read and write most of this structure, and
* are expected to initialise parts of it when registering a new pen. They must not write
* to the "header" section.
*/
typedef struct SDL_Pen
{
/* Backend driver MUST NOT not write to: */
SDL_PenHeader header;
// 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);
SDL_PenStatusInfo last; /* Last reported status, normally read-only for backend */
// Backend calls this when an existing pen device is disconnected during runtime. They must free their own stuff separately.
extern void SDL_RemovePenDevice(Uint64 timestamp, SDL_PenID instance_id);
/* Backend: MUST initialise this block when pen is first registered: */
SDL_GUID guid; /* GUID, MUST be set by backend.
MUST be unique (no other pen ID with same GUID).
SHOULD be persistent across sessions. */
// Backend can call this to remove all pens, probably during shutdown, with a callback to let them free their own handle.
extern void SDL_RemoveAllPenDevices(void (*callback)(SDL_PenID instance_id, void *handle, void *userdata), void *userdata);
/* Backend: SHOULD initialise this block when pen is first registered if it can
Otherwise: Set to sane default values during SDL_PenModifyEnd() */
SDL_PenCapabilityInfo info; /* Detail information about the pen (buttons, tilt) */
SDL_PenSubtype type;
Uint8 last_mouse_button; /* For mouse button emulation: last emulated button */
char *name; /* Preallocated; set via SDL_strlcpy(pen->name, src, SDL_PEN_MAX_NAME) */
/* We hand this exact pointer to client code, so it must not be modified after
creation. */
// Backend calls this when a pen's button changes, to generate events and update state.
extern int SDL_SendPenTouch(Uint64 timestamp, SDL_PenID instance_id, const SDL_Window *window, Uint8 state, Uint8 eraser);
void *deviceinfo; /* implementation-specific information */
} SDL_Pen;
// Backend calls this when a pen moves on the tablet, to generate events and update state.
extern int SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, const SDL_Window *window, float x, float y);
/* ---- API for backend driver only ---- */
// Backend calls this when a pen's axis changes, to generate events and update state.
extern int SDL_SendPenAxis(Uint64 timestamp, SDL_PenID instance_id, const SDL_Window *window, SDL_PenAxis axis, float value);
/**
* (Only for backend driver) Look up a pen by pen ID
*
* \param instance_id A Uint32 pen identifier (driver-dependent meaning). Must not be 0 = SDL_PEN_INVALID.
* The same ID is exposed to clients as SDL_PenID.
*
* The pen pointer is only valid until the next call to SDL_PenModifyEnd() or SDL_PenGCSweep()
*
* \return pen, if it exists, or NULL
*/
extern SDL_Pen *SDL_GetPenPtr(Uint32 instance_id);
// Backend calls this when a pen's button changes, to generate events and update state.
extern int SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, const SDL_Window *window, Uint8 state, Uint8 button);
/**
* (Only for backend driver) Start registering a new pen or updating an existing pen.
*
* Acquires the pen mutex, which is held until the next call to SDL_PenModifyEnd() .
*
* If the PenID already exists, returns the existing entry. Otherwise initialise fresh SDL_Pen.
* For new pens, sets SDL_PEN_FLAG_NEW.
*
* Usage:
* - SDL_PenModifyStart()
* - update pen object, in any order:
* - SDL_PenModifyAddCapabilities()
* - pen->guid (MUST be set for new pens, e.g. via ::SDL_PenUpdateGUIDForGeneric and related operations)
* - pen->info.num_buttons
* - pen->info.max_tilt
* - pen->type
* - pen->name
* - pen->deviceinfo (backend-specific)
* - SDL_PenModifyEnd()
*
* For new pens, sets defaults for:
* - num_buttons (SDL_PEN_INFO_UNKNOWN)
* - max_tilt (SDL_PEN_INFO_UNKNOWN)
* - pen_type (SDL_PEN_TYPE_PEN)
* - Zeroes all other (non-header) fields
*
* \param instance_id Pen ID to allocate (must not be 0 = SDL_PEN_ID_INVALID)
* \returns SDL_Pen pointer; only valid until the call to SDL_PenModifyEnd()
*/
extern SDL_Pen *SDL_PenModifyBegin(Uint32 instance_id);
// Backend can optionally use this to find the SDL_PenID for the `handle` that was passed to SDL_AddPenDevice.
extern SDL_PenID SDL_FindPenByHandle(void *handle);
/**
* (Only for backend driver) Add capabilities to a pen (cf. SDL_PenModifyBegin()).
*
* Adds capabilities to a pen obtained via SDL_PenModifyBegin(). Can be called more than once.
*
* \param pen The pen to update
* \param capabilities Capabilities flags, out of: SDL_PEN_AXIS_*, SDL_PEN_ERASER_MASK, SDL_PEN_INK_MASK
* Setting SDL_PEN_ERASER_MASK will clear SDL_PEN_INK_MASK, and vice versa.
*/
extern void SDL_PenModifyAddCapabilities(SDL_Pen *pen, Uint32 capabilities);
// Backend can optionally use this to find a SDL_PenID, selected by a callback examining all devices. Zero if not found.
extern SDL_PenID SDL_FindPenByCallback(SDL_bool (*callback)(void *handle, void *userdata), void *userdata);
/**
* Set up a pen structure for a Wacom device.
*
* Some backends (e.g., XInput2, Wayland) can only partially identify the capabilities of a given
* pen but can identify Wacom pens and obtain their Wacom-specific device type identifiers.
* This function partly automates device setup in those cases.
*
* This function does NOT set up the pen's GUID. Use ::SD_PenModifyGUIDForWacom instead.
*
* This function does NOT call SDL_PenModifyAddCapabilities() ifself, since some backends may
* not have access to all pen axes (e.g., Xinput2).
*
* \param pen The pen to initialise
* \param wacom_devicetype_id The Wacom-specific device type identifier
* \param[out] axis_flags The set of physically supported axes for this pen, suitable for passing to
* SDL_PenModifyAddCapabilities()
*
* \returns SDL_TRUE if the device ID could be identified, otherwise SDL_FALSE
*/
extern int SDL_PenModifyForWacomID(SDL_Pen *pen, Uint32 wacom_devicetype_id, Uint32 *axis_flags);
// Backend can use this to map an axis to a capability bit.
SDL_PenCapabilityFlags SDL_GetPenCapabilityFromAxis(SDL_PenAxis axis);
/**
* Updates a GUID for a generic pen device.
*
* Assumes that the GUID has been pre-initialised (typically to 0).
* Idempotent, and commutative with ::SDL_PenUpdateGUIDForWacom and ::SDL_PenUpdateGUIDForType
*
* \param[out] guid The GUID to update
* \param upper Upper half of the device ID (assume lower entropy than "lower"; pass 0 if not available)
* \param lower Lower half of the device ID (assume higher entropy than "upper")
*/
extern void SDL_PenUpdateGUIDForGeneric(SDL_GUID *guid, Uint32 upper, Uint32 lower);
// Higher-level SDL video subsystem code calls this when starting up. Backends shouldn't.
extern int SDL_InitPen(void);
/**
* Updates a GUID based on a pen type
*
* Assumes that the GUID has been pre-initialised (typically to 0).
* Idempotent, and commutative with ::SDL_PenUpdateGUIDForWacom and ::SDL_PenUpdateGUIDForGeneric
*
* \param[out] guid The GUID to update
* \param pentype The pen type to insert
*/
extern void SDL_PenUpdateGUIDForType(SDL_GUID *guid, SDL_PenSubtype pentype);
/**
* Updates a GUID for a Wacom pen device.
*
* Assumes that the GUID has been pre-initialised (typically to 0).
* Idempotent, and commutative with ::SDL_PenUpdateGUIDForType and ::SDL_PenUpdateGUIDForGeneric
*
* This update is identical to the one written by ::SDL_PenModifyFromWacomID .
*
* \param[out] guid The GUID to update
* \param wacom_devicetype_id The Wacom-specific device type identifier
* \param wacom_serial_id The Wacom-specific serial number
*/
extern void SDL_PenUpdateGUIDForWacom(SDL_GUID *guid, Uint32 wacom_devicetype_id, Uint32 wacom_serial_id);
/**
* (Only for backend driver) Finish updating a pen.
*
* Releases the pen mutex acquired by SDL_PenModifyBegin() .
*
* If pen->type == SDL_PEN_TYPE_NONE, removes the pen entirely (only
* for new pens). This allows backends to start registering a
* potential pen device and to abort if the device turns out to not be
* a pen.
*
* For new pens, this call will also set the following:
* - name (default name, if not yet set)
*
* \param pen The pen to register. That pointer is no longer valid after this call.
* \param attach Whether the pen should be attached (SDL_TRUE) or detached (SDL_FALSE).
*
* If the pen is detached or removed, it is the caller's responsibility to free
* and null "deviceinfo".
*/
extern void SDL_PenModifyEnd(SDL_Pen *pen, SDL_bool attach);
/**
* (Only for backend driver) Mark all current pens for garbage collection.
*
* Must not be called while the pen mutex is held (by SDL_PenModifyBegin() ).
*
* SDL_PenGCMark() / SDL_PenGCSweep() provide a simple mechanism for
* detaching all known pens that are not discoverable. This allows
* backends to use the same code for pen discovery and for
* hotplugging:
*
* - SDL_PenGCMark() and start backend-specific discovery
* - for each discovered pen: SDL_PenModifyBegin() + SDL_PenModifyEnd() (this will retain existing state)
* - SDL_PenGCSweep() (will now detach all pens that were not re-registered).
*/
extern void SDL_PenGCMark(void);
/**
* (Only for backend driver) Detach pens that haven't been reported attached since the last call to SDL_PenGCMark().
*
* Must not be called while the pen mutex is held (by SDL_PenModifyBegin() ).
*
* See SDL_PenGCMark() for details.
*
* \param context Extra parameter to pass through to "free_deviceinfo"
* \param free_deviceinfo Operation to call on any non-NULL "backend.deviceinfo".
*
* \sa SDL_PenGCMark()
*/
extern void SDL_PenGCSweep(void *context, void (*free_deviceinfo)(Uint32 instance_id, void *deviceinfo, void *context));
/**
* (Only for backend driver) Send a pen motion event.
*
* Suppresses pen motion events that do not change the current pen state.
* May also send a mouse motion event, if mouse emulation is enabled and the pen position has
* changed sufficiently for the motion to be visible to mouse event listeners.
*
* \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() .
* While 0 is safe to report, your backends may be able to report more precise
* timing information.
* Keep in mind that you should never report timestamps that are greater than
* SDL_GetTicksNS() . In particular, SDL_GetTicksNS() reports nanoseconds since the start
* of the SDL session, and your backend may use a different starting point as "timestamp zero".
* \param instance_id Pen
* \param window_relative Coordinates are already window-relative
* \param status Coordinates and axes (buttons are ignored)
*
* \returns SDL_TRUE if at least one event was sent
*/
extern int SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_bool window_relative, const SDL_PenStatusInfo *status);
/**
* (Only for backend driver) Send a pen button event
*
* \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() .
* See SDL_SendPenMotion() for a discussion about how to handle timestamps.
* \param instance_id Pen
* \param state SDL_PRESSED or SDL_RELEASED
* \param button Button number: 1 (first physical button) etc.
*
* \returns SDL_TRUE if at least one event was sent
*/
extern int SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, Uint8 state, Uint8 button);
/**
* (Only for backend driver) Send a pen tip event (touching or no longer touching the surface)
*
* Note: the backend should perform hit testing on window decoration elements to allow the pen
* to e.g. resize/move the window, just as for mouse events, unless ::SDL_SendPenTipEvent is false.
*
* \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() .
* See SDL_SendPenMotion() for a discussion about how to handle timestamps.
* \param instance_id Pen
* \param state SDL_PRESSED (for PEN_DOWN) or SDL_RELEASED (for PEN_UP)
*
* \returns SDL_TRUE if at least one event was sent
*/
extern int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state);
/**
* (Only for backend driver) Check if a PEN_DOWN event should perform hit box testing.
*
* \returns SDL_TRUE if and only if the backend should perform hit testing
*/
extern SDL_bool SDL_PenPerformHitTest(void);
/**
* (Only for backend driver) Send a pen window event.
*
* Tracks when a pen has entered/left a window.
* Don't call this when reporting new pens or removing known pens; those cases are handled automatically.
*
* \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() .
* See SDL_SendPenMotion() for a discussion about how to handle timestamps.
* \param instance_id Pen
* \param window Window to enter, or NULL to exit
*/
extern int SDL_SendPenWindowEvent(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window);
/**
* Initialises the pen subsystem.
*/
extern void SDL_PenInit(void);
/**
* De-initialises the pen subsystem.
*/
extern void SDL_PenQuit(void);
// Higher-level SDL video subsystem code calls this when shutting down. Backends shouldn't.
extern void SDL_QuitPen(void);
#endif /* SDL_pen_c_h_ */
+9
View File
@@ -563,6 +563,7 @@ int SDL_VideoInit(const char *driver_name)
SDL_bool init_keyboard = SDL_FALSE;
SDL_bool init_mouse = SDL_FALSE;
SDL_bool init_touch = SDL_FALSE;
SDL_bool init_pen = SDL_FALSE;
int i = 0;
/* Check to make sure we don't overwrite '_this' */
@@ -589,6 +590,10 @@ int SDL_VideoInit(const char *driver_name)
goto pre_driver_error;
}
init_touch = SDL_TRUE;
if (SDL_InitPen() < 0) {
goto pre_driver_error;
}
init_pen = SDL_TRUE;
/* Select the proper video driver */
video = NULL;
@@ -673,6 +678,9 @@ int SDL_VideoInit(const char *driver_name)
pre_driver_error:
SDL_assert(_this == NULL);
if (init_pen) {
SDL_QuitPen();
}
if (init_touch) {
SDL_QuitTouch();
}
@@ -4217,6 +4225,7 @@ void SDL_VideoQuit(void)
}
/* Halt event processing before doing anything else */
SDL_QuitPen();
SDL_QuitTouch();
SDL_QuitMouse();
SDL_QuitKeyboard();
File diff suppressed because it is too large Load Diff
+6 -41
View File
@@ -41,41 +41,11 @@ enum SDL_WaylandAxisEvent
struct SDL_WaylandTabletSeat;
struct SDL_WaylandTabletObjectListNode
typedef struct SDL_WaylandTabletInput
{
void *object;
struct SDL_WaylandTabletObjectListNode *next;
};
struct SDL_WaylandTabletInput
{
struct SDL_WaylandInput *sdlWaylandInput;
struct SDL_WaylandInput *input;
struct zwp_tablet_seat_v2 *seat;
struct SDL_WaylandTabletObjectListNode *tablets;
struct SDL_WaylandTabletObjectListNode *tools;
struct SDL_WaylandTabletObjectListNode *pads;
Uint32 id;
Uint32 num_pens; /* next pen ID is num_pens+1 */
struct SDL_WaylandCurrentPen
{
SDL_Pen *builder; /* pen that is being defined or receiving updates, if any */
SDL_bool builder_guid_complete; /* have complete/precise GUID information */
SDL_PenStatusInfo update_status; /* collects pen update information before sending event */
Uint16 buttons_pressed; /* Mask of newly pressed buttons, plus SDL_PEN_DOWN_MASK for PEN_DOWN */
Uint16 buttons_released; /* Mask of newly pressed buttons, plus SDL_PEN_DOWN_MASK for PEN_UP */
Uint32 serial; /* Most recent serial event number observed, or 0 */
SDL_WindowData *update_window; /* NULL while no event is in progress, otherwise the affected window */
} current_pen;
SDL_WindowData *tool_focus;
uint32_t tool_prox_serial;
/* Last motion end location (kept separate from sx_w, sy_w for the mouse pointer) */
wl_fixed_t sx_w;
wl_fixed_t sy_w;
};
} SDL_WaylandTabletInput;
typedef struct
{
@@ -169,7 +139,7 @@ struct SDL_WaylandInput
SDL_WaylandKeyboardRepeat keyboard_repeat;
struct SDL_WaylandTabletInput *tablet;
SDL_WaylandTabletInput *tablet_input;
SDL_bool keyboard_is_virtual;
@@ -178,11 +148,6 @@ struct SDL_WaylandInput
SDL_Keymod locked_modifiers;
};
struct SDL_WaylandTool
{
SDL_PenID penid;
struct SDL_WaylandTabletInput *tablet;
};
extern Uint64 Wayland_GetTouchTimestamp(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms);
@@ -209,8 +174,8 @@ extern int Wayland_input_unconfine_pointer(struct SDL_WaylandInput *input, SDL_W
extern int Wayland_input_grab_keyboard(SDL_Window *window, struct SDL_WaylandInput *input);
extern int Wayland_input_ungrab_keyboard(SDL_Window *window);
extern void Wayland_input_add_tablet(struct SDL_WaylandInput *input, struct SDL_WaylandTabletManager *tablet_manager);
extern void Wayland_input_destroy_tablet(struct SDL_WaylandInput *input);
extern void Wayland_input_init_tablet_support(struct SDL_WaylandInput *input, struct zwp_tablet_manager_v2 *tablet_manager);
extern void Wayland_input_quit_tablet_support(struct SDL_WaylandInput *input);
extern void Wayland_RegisterTimestampListeners(struct SDL_WaylandInput *input);
extern void Wayland_CreateCursorShapeDevice(struct SDL_WaylandInput *input);
+1 -1
View File
@@ -1167,7 +1167,7 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
d->decoration_manager = wl_registry_bind(d->registry, id, &zxdg_decoration_manager_v1_interface, 1);
} else if (SDL_strcmp(interface, "zwp_tablet_manager_v2") == 0) {
d->tablet_manager = wl_registry_bind(d->registry, id, &zwp_tablet_manager_v2_interface, 1);
Wayland_input_add_tablet(d->input, d->tablet_manager);
Wayland_input_init_tablet_support(d->input, d->tablet_manager);
} else if (SDL_strcmp(interface, "zxdg_output_manager_v1") == 0) {
version = SDL_min(version, 3); /* Versions 1 through 3 are supported. */
d->xdg_output_manager = wl_registry_bind(d->registry, id, &zxdg_output_manager_v1_interface, version);
+1 -2
View File
@@ -33,7 +33,6 @@
struct xkb_context;
struct SDL_WaylandInput;
struct SDL_WaylandTabletManager;
typedef struct
{
@@ -84,10 +83,10 @@ struct SDL_VideoData
struct wp_alpha_modifier_v1 *wp_alpha_modifier_v1;
struct kde_output_order_v1 *kde_output_order;
struct frog_color_management_factory_v1 *frog_color_management_factory_v1;
struct zwp_tablet_manager_v2 *tablet_manager;
struct xkb_context *xkb_context;
struct SDL_WaylandInput *input;
struct SDL_WaylandTabletManager *tablet_manager;
struct wl_list output_list;
struct wl_list output_order;
-3
View File
@@ -1996,9 +1996,6 @@ void X11_PumpEvents(SDL_VideoDevice *_this)
}
if (data->xinput_hierarchy_changed) {
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
X11_InitPen(_this);
#endif
X11_Xinput2UpdateDevices(_this, SDL_FALSE);
data->xinput_hierarchy_changed = SDL_FALSE;
}
+247 -523
View File
File diff suppressed because it is too large Load Diff
+32 -13
View File
@@ -23,32 +23,51 @@
#ifndef SDL_x11pen_h_
#define SDL_x11pen_h_
// Pressure-sensitive pen support for X11.
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
#include "SDL_x11video.h"
#include "../../events/SDL_pen_c.h"
/* Pressure-sensitive pen */
/* Forward definition for SDL_x11video.h */
// Forward definition for SDL_x11video.h
struct SDL_VideoData;
/* Function definitions */
#define SDL_X11_PEN_AXIS_VALUATOR_MISSING -1
/* Detect XINPUT2 devices that are pens / erasers, or update the list after hotplugging */
typedef struct X11_PenHandle
{
SDL_PenID pen;
SDL_bool is_eraser;
int x11_deviceid;
int valuator_for_axis[SDL_PEN_NUM_AXES];
float slider_bias; // shift value to add to PEN_AXIS_SLIDER (before normalisation)
float rotation_bias; // rotation to add to PEN_AXIS_ROTATION (after normalisation)
float axis_min[SDL_PEN_NUM_AXES];
float axis_max[SDL_PEN_NUM_AXES];
} X11_PenHandle;
// Prep pen support (never fails; pens simply won't be added if there's a problem).
extern void X11_InitPen(SDL_VideoDevice *_this);
/* Converts XINPUT2 valuators into pen axis information, including normalisation */
extern void X11_PenAxesFromValuators(const SDL_Pen *pen,
// Clean up pen support.
extern void X11_QuitPen(SDL_VideoDevice *_this);
// Converts XINPUT2 valuators into pen axis information, including normalisation.
extern void X11_PenAxesFromValuators(const X11_PenHandle *pen,
const double *input_values, const unsigned char *mask, const int mask_len,
/* out-mode parameters: */
float axis_values[SDL_PEN_NUM_AXES]);
/* Map X11 device ID to pen ID */
extern int X11_PenIDFromDeviceID(int deviceid);
// Add a pen (if this function's further checks validate it).
extern X11_PenHandle *X11_MaybeAddPenByDeviceID(SDL_VideoDevice *_this, int deviceid);
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
// Remove a pen. It's okay if deviceid is bogus or not a pen, we'll check it.
extern void X11_RemovePenByDeviceID(int deviceid);
#endif /* SDL_x11pen_h_ */
// Map X11 device ID to pen ID.
extern X11_PenHandle *X11_FindPenByDeviceID(int deviceid);
#endif // SDL_VIDEO_DRIVER_X11_XINPUT2
#endif // SDL_x11pen_h_
/* vi: set ts=4 sw=4 expandtab: */
+1 -2
View File
@@ -456,9 +456,7 @@ int X11_VideoInit(SDL_VideoDevice *_this)
X11_InitTouch(_this);
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
X11_InitPen(_this);
#endif
return 0;
}
@@ -485,6 +483,7 @@ void X11_VideoQuit(SDL_VideoDevice *_this)
X11_QuitKeyboard(_this);
X11_QuitMouse(_this);
X11_QuitTouch(_this);
X11_QuitPen(_this);
X11_QuitClipboard(_this);
X11_QuitXsettings(_this);
}
+8 -1
View File
@@ -104,6 +104,14 @@ struct SDL_VideoData
Atom XdndSelection;
Atom XKLAVIER_STATE;
/* Pen atoms (these have names that don't map well to C symbols) */
Atom pen_atom_device_product_id;
Atom pen_atom_abs_pressure;
Atom pen_atom_abs_tilt_x;
Atom pen_atom_abs_tilt_y;
Atom pen_atom_wacom_serial_ids;
Atom pen_atom_wacom_tool_type;
SDL_Scancode key_layout[256];
SDL_bool selection_waiting;
SDL_bool selection_incr_waiting;
@@ -141,7 +149,6 @@ struct SDL_VideoData
SDL_bool steam_keyboard_open;
SDL_bool is_xwayland;
};
extern SDL_bool X11_UseDirectColorVisuals(void);
+30 -71
View File
@@ -274,18 +274,6 @@ static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata,
return devinfo;
}
static void xinput2_pen_ensure_window(SDL_VideoDevice *_this, const SDL_Pen *pen, Window window)
{
/* When "flipping" a Wacom eraser pen, we get an XI_DeviceChanged event
* with the newly-activated pen, but this event is global for the display.
* We won't get a window until the pen starts triggering motion or
* button events, so we instead hook the pen to its window at that point. */
const SDL_WindowData *windowdata = X11_FindWindow(_this, window);
if (windowdata) {
SDL_SendPenWindowEvent(0, pen->header.id, windowdata->window);
}
}
#endif
void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
@@ -303,6 +291,14 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
const XIHierarchyEvent *hierev = (const XIHierarchyEvent *)cookie->data;
int i;
for (i = 0; i < hierev->num_info; i++) {
// pen stuff...
if ((hierev->info[i].flags & (XISlaveRemoved | XIDeviceDisabled)) != 0) {
X11_RemovePenByDeviceID(hierev->info[i].deviceid); // it's okay if this thing isn't actually a pen, it'll handle it.
} else if ((hierev->info[i].flags & (XISlaveAdded | XIDeviceEnabled)) != 0) {
X11_MaybeAddPenByDeviceID(_this, hierev->info[i].deviceid); // this will do more checks to make sure this is valid.
}
// not pen stuff...
if (hierev->info[i].flags & XISlaveRemoved) {
xinput2_remove_device_info(videodata, hierev->info[i].deviceid);
}
@@ -310,29 +306,14 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
videodata->xinput_hierarchy_changed = SDL_TRUE;
} break;
case XI_PropertyEvent:
case XI_DeviceChanged:
{
// FIXME: We shouldn't rescan all devices for pen changes every time a property or active slave changes
X11_InitPen(_this);
} break;
case XI_Enter:
case XI_Leave:
{
const XIEnterEvent *enterev = (const XIEnterEvent *)cookie->data;
const SDL_WindowData *windowdata = X11_FindWindow(_this, enterev->event);
const SDL_Pen *pen = SDL_GetPenPtr(X11_PenIDFromDeviceID(enterev->sourceid));
SDL_Window *window = (windowdata && (cookie->evtype == XI_Enter)) ? windowdata->window : NULL;
if (pen) {
SDL_SendPenWindowEvent(0, pen->header.id, window);
}
} break;
// !!! FIXME: the pen code used to rescan all devices here, but we can do this device-by-device with XI_HierarchyChanged. When do these events fire and why?
//case XI_PropertyEvent:
//case XI_DeviceChanged:
case XI_RawMotion:
{
const XIRawEvent *rawev = (const XIRawEvent *)cookie->data;
const SDL_bool is_pen = X11_PenIDFromDeviceID(rawev->sourceid) != SDL_PEN_INVALID;
const SDL_bool is_pen = X11_FindPenByDeviceID(rawev->sourceid) != NULL;
SDL_Mouse *mouse = SDL_GetMouse();
SDL_XInput2DeviceInfo *devinfo;
double coords[2];
@@ -341,11 +322,9 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
videodata->global_mouse_changed = SDL_TRUE;
if (is_pen) {
break; /* Pens check for XI_Motion instead */
break; // Pens check for XI_Motion instead
}
/* Non-pen: */
if (!mouse->relative_mode || mouse->relative_mode_warp) {
break;
}
@@ -426,31 +405,17 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
case XI_ButtonRelease:
{
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
const SDL_Pen *pen = SDL_GetPenPtr(X11_PenIDFromDeviceID(xev->deviceid));
X11_PenHandle *pen = X11_FindPenByDeviceID(xev->deviceid);
const int button = xev->detail;
const SDL_bool pressed = (cookie->evtype == XI_ButtonPress) ? SDL_TRUE : SDL_FALSE;
if (pen) {
xinput2_pen_ensure_window(_this, pen, xev->event);
/* Only report button event; if there was also pen movement / pressure changes, we expect
an XI_Motion event first anyway */
if (button == 1) {
/* button 1 is the pen tip */
if (pressed && SDL_PenPerformHitTest()) {
/* Check whether we should handle window resize / move events */
SDL_WindowData *windowdata = X11_FindWindow(_this, xev->event);
if (windowdata && X11_TriggerHitTestAction(_this, windowdata, pen->last.x, pen->last.y)) {
SDL_SendWindowEvent(windowdata->window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0);
break; /* Don't pass on this event */
}
}
SDL_SendPenTipEvent(0, pen->header.id,
pressed ? SDL_PRESSED : SDL_RELEASED);
// Only report button event; if there was also pen movement / pressure changes, we expect an XI_Motion event first anyway.
SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
if (button == 1) { // button 1 is the pen tip
SDL_SendPenTouch(0, pen->pen, window, pressed ? SDL_PRESSED : SDL_RELEASED, pen->is_eraser);
} else {
SDL_SendPenButton(0, pen->header.id,
pressed ? SDL_PRESSED : SDL_RELEASED,
button - 1);
SDL_SendPenButton(0, pen->pen, window, pressed ? SDL_PRESSED : SDL_RELEASED, button - 1);
}
} else {
/* Otherwise assume a regular mouse */
@@ -475,7 +440,6 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
case XI_Motion:
{
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
const SDL_Pen *pen = SDL_GetPenPtr(X11_PenIDFromDeviceID(xev->deviceid));
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
SDL_bool pointer_emulated = ((xev->flags & XIPointerEmulated) != 0);
#else
@@ -489,25 +453,20 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
break;
}
X11_PenHandle *pen = X11_FindPenByDeviceID(xev->deviceid);
if (pen) {
SDL_PenStatusInfo pen_status;
SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
SDL_SendPenMotion(0, pen->pen, window, (float) xev->event_x, (float) xev->event_y);
pen_status.x = (float)xev->event_x;
pen_status.y = (float)xev->event_y;
float axes[SDL_PEN_NUM_AXES];
X11_PenAxesFromValuators(pen, xev->valuators.values, xev->valuators.mask, xev->valuators.mask_len, axes);
X11_PenAxesFromValuators(pen,
xev->valuators.values, xev->valuators.mask, xev->valuators.mask_len,
&pen_status.axes[0]);
xinput2_pen_ensure_window(_this, pen, xev->event);
SDL_SendPenMotion(0, pen->header.id,
SDL_TRUE,
&pen_status);
break;
}
if (!pointer_emulated) {
for (int i = 0; i < SDL_arraysize(axes); i++) {
if (pen->valuator_for_axis[i] != SDL_X11_PEN_AXIS_VALUATOR_MISSING) {
SDL_SendPenAxis(0, pen->pen, window, (SDL_PenAxis) i, axes[i]);
}
}
} else if (!pointer_emulated) {
SDL_Mouse *mouse = SDL_GetMouse();
if (!mouse->relative_mode || mouse->relative_mode_warp) {
SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
-3
View File
@@ -34,9 +34,6 @@ static SDLTest_TestSuiteReference *testSuites[] = {
&mainTestSuite,
&mathTestSuite,
&mouseTestSuite,
#if !defined(SDL_PLATFORM_IOS) && !defined(SDL_PLATFORM_TVOS)
&penTestSuite,
#endif
&pixelsTestSuite,
&platformTestSuite,
&propertiesTestSuite,
File diff suppressed because it is too large Load Diff
-1
View File
@@ -25,7 +25,6 @@ extern SDLTest_TestSuiteReference logTestSuite;
extern SDLTest_TestSuiteReference mainTestSuite;
extern SDLTest_TestSuiteReference mathTestSuite;
extern SDLTest_TestSuiteReference mouseTestSuite;
extern SDLTest_TestSuiteReference penTestSuite;
extern SDLTest_TestSuiteReference pixelsTestSuite;
extern SDLTest_TestSuiteReference platformTestSuite;
extern SDLTest_TestSuiteReference propertiesTestSuite;
+258 -494
View File
File diff suppressed because it is too large Load Diff