API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
/*
Simple DirectMedia Layer
2024-01-01 14:15:26 -07:00
Copyright ( C ) 1997 - 2024 Sam Lantinga < slouken @ libsdl . org >
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be
misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
*/
2023-08-02 08:03:32 -06:00
# ifndef NO_BUILD_CONFIG
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
# include <stddef.h>
/**
* Pen test suite
*/
# define SDL_internal_h_ /* Inhibit dynamic symbol redefinitions that clash with ours */
/* ================= System Under Test (SUT) ================== */
/* Renaming SUT operations to avoid link-time symbol clashes */
# define SDL_GetPens SDL_SUT_GetPens
# define SDL_GetPenStatus SDL_SUT_GetPenStatus
# define SDL_GetPenFromGUID SDL_SUT_GetPenFromGUID
# define SDL_GetPenGUID SDL_SUT_GetPenGUID
# define SDL_PenConnected SDL_SUT_PenConnected
# define SDL_GetPenName SDL_SUT_GetPenName
# define SDL_GetPenCapabilities SDL_SUT_GetPenCapabilities
# define SDL_GetPenType SDL_SUT_GetPenType
# define SDL_GetPenPtr SDL_SUT_GetPenPtr
# define SDL_PenModifyBegin SDL_SUT_PenModifyBegin
# define SDL_PenModifyAddCapabilities SDL_SUT_PenModifyAddCapabilities
# define SDL_PenModifyForWacomID SDL_SUT_PenModifyForWacomID
# define SDL_PenUpdateGUIDForWacom SDL_SUT_PenUpdateGUIDForWacom
# define SDL_PenUpdateGUIDForType SDL_SUT_PenUpdateGUIDForType
# define SDL_PenUpdateGUIDForGeneric SDL_SUT_PenUpdateGUIDForGeneric
# define SDL_PenModifyEnd SDL_SUT_PenModifyEnd
# define SDL_PenGCMark SDL_SUT_PenGCMark
# define SDL_PenGCSweep SDL_SUT_PenGCSweep
# define SDL_SendPenMotion SDL_SUT_SendPenMotion
# define SDL_SendPenButton SDL_SUT_SendPenButton
# define SDL_SendPenTipEvent SDL_SUT_SendPenTipEvent
# define SDL_SendPenWindowEvent SDL_SUT_SendPenWindowEvent
# define SDL_PenPerformHitTest SDL_SUT_PenPerformHitTest
# define SDL_PenInit SDL_SUT_PenInit
2023-11-27 13:37:02 -07:00
# define SDL_PenQuit SDL_SUT_PenQuit
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
/* ================= Mock API ================== */
# include <stdlib.h>
# include <SDL3/SDL.h>
# include <SDL3/SDL_test.h>
/* For SDL_Window, SDL_Mouse, SDL_MouseID: */
# include "../src/events/SDL_mouse_c.h"
/* Divert calls to mock mouse API: */
# define SDL_SendMouseMotion SDL_Mock_SendMouseMotion
# define SDL_SendMouseButton SDL_Mock_SendMouseButton
# define SDL_GetMouse SDL_Mock_GetMouse
# define SDL_MousePositionInWindow SDL_Mock_MousePositionInWindow
# define SDL_SetMouseFocus SDL_Mock_SetMouseFocus
/* Mock mouse API */
2024-03-21 10:27:12 -06:00
static int SDL_SendMouseMotion ( Uint64 timestamp , SDL_Window * window , SDL_MouseID mouseID , SDL_bool relative , float x , float y ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
static int SDL_SendMouseButton ( Uint64 timestamp , SDL_Window * window , SDL_MouseID mouseID , Uint8 state , Uint8 button ) ;
static SDL_Mouse * SDL_GetMouse ( void ) ;
2024-03-21 10:27:12 -06:00
static SDL_bool SDL_MousePositionInWindow ( SDL_Window * window , float x , float y ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
static void SDL_SetMouseFocus ( SDL_Window * window ) ;
/* Import SUT code with macro-renamed function names */
# define SDL_waylanddyn_h_ /* hack: suppress spurious build problem with libdecor.h on Wayland */
# include "../src/events/SDL_pen.c"
# include "../src/events/SDL_pen_c.h"
/* ================= Internal SDL API Compatibility ================== */
/* Mock implementations of Pen -> Mouse calls */
/* Not thread-safe! */
2024-03-21 10:27:12 -06:00
static SDL_bool SDL_MousePositionInWindow ( SDL_Window * window , float x , float y )
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
{
return SDL_TRUE ;
}
static int _mouseemu_last_event = 0 ;
static float _mouseemu_last_x = 0.0f ;
static float _mouseemu_last_y = 0.0f ;
static int _mouseemu_last_mouseid = 0 ;
static int _mouseemu_last_button = 0 ;
2024-03-21 10:27:12 -06:00
static SDL_bool _mouseemu_last_relative = SDL_FALSE ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
static int _mouseemu_last_focus = - 1 ;
static int SDL_SendMouseButton ( Uint64 timestamp , SDL_Window * window , SDL_MouseID mouseID , Uint8 state , Uint8 button )
{
if ( mouseID = = SDL_PEN_MOUSEID ) {
_mouseemu_last_event = ( state = = SDL_PRESSED ) ? SDL_EVENT_MOUSE_BUTTON_DOWN : SDL_EVENT_MOUSE_BUTTON_UP ;
_mouseemu_last_button = button ;
_mouseemu_last_mouseid = mouseID ;
}
return 1 ;
}
2024-03-21 10:27:12 -06:00
static int SDL_SendMouseMotion ( Uint64 timestamp , SDL_Window * window , SDL_MouseID mouseID , SDL_bool relative , float x , float y )
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
{
if ( mouseID = = SDL_PEN_MOUSEID ) {
_mouseemu_last_event = SDL_EVENT_MOUSE_MOTION ;
_mouseemu_last_x = x ;
_mouseemu_last_y = y ;
_mouseemu_last_mouseid = mouseID ;
_mouseemu_last_relative = relative ;
}
return 1 ;
}
static SDL_Mouse * SDL_GetMouse ( void )
{
static SDL_Mouse dummy_mouse ;
return & dummy_mouse ;
}
static void SDL_SetMouseFocus ( SDL_Window * window )
{
_mouseemu_last_focus = window ? 1 : 0 ;
}
/* ================= Test Case Support ================== */
# define PEN_NUM_TEST_IDS 8
/* Helper functions */
/* Iterate over all pens to find index for pen ID, otherwise -1 */
static int _pen_iterationFindsPenIDAt ( SDL_PenID needle )
{
int i ;
int num_pens = - 1 ;
SDL_PenID * pens = SDL_GetPens ( & num_pens ) ;
/* Check for (a) consistency and (b) ability to handle NULL parameter */
SDL_PenID * pens2 = SDL_GetPens ( NULL ) ;
SDLTest_AssertCheck ( num_pens > = 0 ,
" SDL_GetPens() yielded %d pens " , num_pens ) ;
SDLTest_AssertCheck ( pens [ num_pens ] = = 0 ,
" SDL_GetPens() not 0 terminated (num_pens = %d) " , num_pens ) ;
SDLTest_AssertCheck ( pens2 [ num_pens ] = = 0 ,
" SDL_GetPens(NULL) not 0 terminated (num_pens = %d) " , num_pens ) ;
for ( i = 0 ; i < num_pens ; + + i ) {
SDLTest_AssertCheck ( pens [ i ] = = pens2 [ i ] ,
" SDL_GetPens(&i) and SDL_GetPens(NULL) disagree at index %d/%d " , i , num_pens ) ;
SDLTest_AssertCheck ( pens [ i ] ! = SDL_PEN_INVALID ,
" Invalid pen ID %08lx at index %d/%d after SDL_GetPens() " , ( unsigned long ) pens [ i ] , i , num_pens ) ;
}
SDL_free ( pens2 ) ;
for ( i = 0 ; pens [ i ] ; + + i ) {
SDL_PenID pen_id = pens [ i ] ;
SDLTest_AssertCheck ( pen_id ! = SDL_PEN_INVALID ,
" Invalid pen ID %08lx at index %d/%d after SDL_GetPens() " , ( unsigned long ) pen_id , i , num_pens ) ;
if ( pen_id = = needle ) {
SDL_free ( pens ) ;
return i ;
}
}
SDL_free ( pens ) ;
return - 1 ;
}
/* Retrieve number of pens and sanity-check SDL_GetPens() */
static int
_num_pens ( void )
{
int num_pens = - 1 ;
SDL_PenID * pens = SDL_GetPens ( & num_pens ) ;
SDLTest_AssertCheck ( pens ! = NULL ,
" SDL_GetPens() => NULL " ) ;
SDLTest_AssertCheck ( num_pens > = 0 ,
" SDL_GetPens() reports %d pens " , num_pens ) ;
SDLTest_AssertCheck ( pens [ num_pens ] = = 0 ,
" SDL_GetPens()[%d] != 0 " , num_pens ) ;
SDL_free ( pens ) ;
return num_pens ;
}
/* Assert number of pens is as expected */
static void _AssertCheck_num_pens ( int expected , char * location )
{
int num_pens = _num_pens ( ) ;
SDLTest_AssertCheck ( expected = = num_pens ,
" Expected SDL_GetPens() =>count = %d, actual = %d: %s " , expected , num_pens , location ) ;
}
/* ---------------------------------------- */
/* Test device deallocation */
typedef struct /* Collection of pen (de)allocation information */
{
unsigned int deallocated_id_flags ; /* ith bits set to 1 if the ith test_id is deallocated */
unsigned int deallocated_deviceinfo_flags ; /* ith bits set to 1 if deviceinfo as *int with value i was deallocated */
SDL_PenID ids [ PEN_NUM_TEST_IDS ] ;
SDL_GUID guids [ PEN_NUM_TEST_IDS ] ;
SDL_Window * window ;
int num_ids ;
int initial_pen_count ;
} pen_testdata ;
/* SDL_PenGCSweep(): callback for tracking pen deallocation */
static void _pen_testdata_callback ( Uint32 deviceid , void * deviceinfo , void * tracker_ref )
{
pen_testdata * tracker = ( pen_testdata * ) tracker_ref ;
int offset = - 1 ;
int i ;
for ( i = 0 ; i < tracker - > num_ids ; + + i ) {
if ( deviceid = = tracker - > ids [ i ] ) {
tracker - > deallocated_id_flags | = ( 1 < < i ) ;
}
}
SDLTest_AssertCheck ( deviceinfo ! = NULL ,
" Device %lu has deviceinfo " ,
( unsigned long ) deviceid ) ;
offset = * ( ( int * ) deviceinfo ) ;
SDLTest_AssertCheck ( offset > = 0 & & offset < = 31 ,
" Device %lu has well-formed deviceinfo %d " ,
( unsigned long ) deviceid , offset ) ;
tracker - > deallocated_deviceinfo_flags | = 1 < < offset ;
SDL_free ( deviceinfo ) ;
}
/* GC Sweep tracking: update "tracker->deallocated_id_flags" and "tracker->deallocated_deviceinfo_flags" to record deallocations */
static void _pen_trackGCSweep ( pen_testdata * tracker )
{
tracker - > deallocated_id_flags = 0 ;
tracker - > deallocated_deviceinfo_flags = 0 ;
SDL_PenGCSweep ( tracker , _pen_testdata_callback ) ;
}
/* Finds a number of unused pen IDs (does not allocate them). Also initialises GUIDs. */
static void _pen_unusedIDs ( pen_testdata * tracker , int count )
{
2024-02-03 12:23:16 -07:00
static Uint8 guidmod = 0 ; /* Ensure uniqueness as long as we use no more than 256 test pens */
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
Uint32 synthetic_penid = 1000u ;
int index = 0 ;
tracker - > num_ids = count ;
SDLTest_AssertCheck ( count < PEN_NUM_TEST_IDS , " Test setup: Valid number of test IDs requested: %d " , ( int ) count ) ;
while ( count - - ) {
int k ;
while ( SDL_GetPenPtr ( synthetic_penid ) ) {
+ + synthetic_penid ;
}
tracker - > ids [ index ] = synthetic_penid ;
for ( k = 0 ; k < 15 ; + + k ) {
2024-02-03 12:23:16 -07:00
tracker - > guids [ index ] . data [ k ] = ( Uint8 ) ( ( 16 * k ) + index ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
}
tracker - > guids [ index ] . data [ 15 ] = + + guidmod ;
+ + synthetic_penid ;
+ + index ;
}
}
# define DEVICEINFO_UNCHANGED -17
/* Allocate deviceinfo for pen */
static void _pen_setDeviceinfo ( SDL_Pen * pen , int deviceinfo )
{
if ( deviceinfo = = DEVICEINFO_UNCHANGED ) {
SDLTest_AssertCheck ( pen - > deviceinfo ! = NULL ,
" pen->deviceinfo was already set for %p (%lu), as expected " ,
pen , ( unsigned long ) pen - > header . id ) ;
} else {
int * data = ( int * ) SDL_malloc ( sizeof ( int ) ) ;
* data = deviceinfo ;
SDLTest_AssertCheck ( pen - > deviceinfo = = NULL ,
" pen->deviceinfo was NULL for %p (%lu) when requesting deviceinfo %d " ,
pen , ( unsigned long ) pen - > header . id , deviceinfo ) ;
pen - > deviceinfo = data ;
}
SDL_PenModifyEnd ( pen , SDL_TRUE ) ;
}
/* ---------------------------------------- */
/* Back up and restore device information */
typedef struct deviceinfo_backup
{
Uint32 deviceid ;
void * deviceinfo ;
struct deviceinfo_backup * next ;
} deviceinfo_backup ;
/* SDL_PenGCSweep(): Helper callback for collecting all deviceinfo records */
static void _pen_accumulate_gc_sweep ( Uint32 deviceid , void * deviceinfo , void * backup_ref )
{
deviceinfo_backup * * db_ref = ( deviceinfo_backup * * ) backup_ref ;
deviceinfo_backup * next = * db_ref ;
* db_ref = SDL_calloc ( sizeof ( deviceinfo_backup ) , 1 ) ;
( * db_ref ) - > deviceid = deviceid ;
( * db_ref ) - > deviceinfo = deviceinfo ;
( * db_ref ) - > next = next ;
}
/* SDL_PenGCSweep(): Helper callback that must never be called */
static void _pen_assert_impossible ( Uint32 deviceid , void * deviceinfo , void * backup_ref )
{
SDLTest_AssertCheck ( 0 , " Deallocation for deviceid %lu during enableAndRestore: not expected " ,
( unsigned long ) deviceid ) ;
}
/* Disable all pens and store their status */
static deviceinfo_backup * _pen_disableAndBackup ( void )
{
deviceinfo_backup * backup = NULL ;
SDL_PenGCMark ( ) ;
SDL_PenGCSweep ( & backup , _pen_accumulate_gc_sweep ) ;
return backup ;
}
/* Restore all pens to their previous status */
static void _pen_enableAndRestore ( deviceinfo_backup * backup , int test_marksweep )
{
if ( test_marksweep ) {
SDL_PenGCMark ( ) ;
}
while ( backup ) {
SDL_Pen * disabledpen = SDL_GetPenPtr ( backup - > deviceid ) ;
deviceinfo_backup * next = backup - > next ;
SDL_PenModifyEnd ( SDL_PenModifyBegin ( disabledpen - > header . id ) ,
SDL_TRUE ) ;
disabledpen - > deviceinfo = backup - > deviceinfo ;
SDL_free ( backup ) ;
backup = next ;
}
if ( test_marksweep ) {
SDL_PenGCSweep ( NULL , _pen_assert_impossible ) ;
}
}
static struct SDL_Window _test_window = { 0 } ;
/* ---------------------------------------- */
/* Default set-up and tear down routines */
/* Back up existing pens, allocate fresh ones but don't assign them yet */
static deviceinfo_backup * _setup_test ( pen_testdata * ptest , int pens_for_testing )
{
int i ;
deviceinfo_backup * backup ;
/* Get number of pens */
SDL_free ( SDL_GetPens ( & ptest - > initial_pen_count ) ) ;
/* Provide fake window for window enter/exit simulation */
_test_window . id = 0x7e57da7a ;
_test_window . w = 1600 ;
_test_window . h = 1200 ;
ptest - > window = & _test_window ;
/* Grab unused pen IDs for testing */
_pen_unusedIDs ( ptest , pens_for_testing ) ;
for ( i = 0 ; i < pens_for_testing ; + + i ) {
int index = _pen_iterationFindsPenIDAt ( ptest - > ids [ i ] ) ;
SDLTest_AssertCheck ( - 1 = = index ,
" Registered PenID(%lu) since index %d == -1 " ,
( unsigned long ) ptest - > ids [ i ] , index ) ;
}
/* Remove existing pens, but back up */
backup = _pen_disableAndBackup ( ) ;
_AssertCheck_num_pens ( 0 , " after disabling and backing up all current pens " ) ;
SDLTest_AssertPass ( " Removed existing pens " ) ;
return backup ;
}
static void _teardown_test_general ( pen_testdata * ptest , deviceinfo_backup * backup , int with_gc_test )
{
/* Restore previously existing pens */
_pen_enableAndRestore ( backup , with_gc_test ) ;
/* validate */
SDLTest_AssertPass ( " Restored pens to pre-test state " ) ;
_AssertCheck_num_pens ( ptest - > initial_pen_count , " after restoring all initial pens " ) ;
}
static void _teardown_test ( pen_testdata * ptest , deviceinfo_backup * backup )
{
_teardown_test_general ( ptest , backup , 0 ) ;
}
static void _teardown_test_with_gc ( pen_testdata * ptest , deviceinfo_backup * backup )
{
_teardown_test_general ( ptest , backup , 1 ) ;
}
/* ---------------------------------------- */
/* Pen simulation */
# define SIMPEN_ACTION_DONE 0
# define SIMPEN_ACTION_MOVE_X 1
# define SIMPEN_ACTION_MOVE_Y 2
# define SIMPEN_ACTION_AXIS 3
# define SIMPEN_ACTION_MOTION_EVENT 4 /* epxlicit motion event */
# define SIMPEN_ACTION_MOTION_EVENT_S 5 /* send motion event but expect it to be suppressed */
# define SIMPEN_ACTION_PRESS 6 /* implicit update event */
# define SIMPEN_ACTION_RELEASE 7 /* implicit update event */
# define SIMPEN_ACTION_DOWN 8 /* implicit update event */
# define SIMPEN_ACTION_UP 9 /* implicit update event */
# define SIMPEN_ACTION_ERASER_MODE 10
/* Individual action in pen simulation script */
typedef struct simulated_pen_action
{
int type ;
int pen_index ; /* index into the list of simulated pens */
int index ; /* button or axis number, if needed */
float update ; /* x,y; for AXIS, update[0] is the updated axis */
} simulated_pen_action ;
static simulated_pen_action _simpen_event ( int type , int pen_index , int index , float v , int line_nr )
{
simulated_pen_action action ;
action . type = type ;
action . pen_index = pen_index ;
action . index = index ;
action . update = v ;
/* Sanity check-- turned out to be necessary */
if ( ( type = = SIMPEN_ACTION_PRESS | | type = = SIMPEN_ACTION_RELEASE ) & & index = = 0 ) {
SDL_Log ( " Error: SIMPEN_EVENT_BUTTON must have button > 0 (first button has number 1!), in line %d! " , line_nr ) ;
exit ( 1 ) ;
}
return action ;
}
/* STEP is passed in later (C macros use dynamic scoping) */
# define SIMPEN_DONE() \
STEP _simpen_event ( SIMPEN_ACTION_DONE , 0 , 0 , 0.0f , __LINE__ )
# define SIMPEN_MOVE(pen_index, x, y) \
STEP _simpen_event ( SIMPEN_ACTION_MOVE_X , ( pen_index ) , 0 , ( x ) , __LINE__ ) ; \
STEP _simpen_event ( SIMPEN_ACTION_MOVE_Y , ( pen_index ) , 0 , ( y ) , __LINE__ )
# define SIMPEN_AXIS(pen_index, axis, y) \
STEP _simpen_event ( SIMPEN_ACTION_AXIS , ( pen_index ) , ( axis ) , ( y ) , __LINE__ )
# define SIMPEN_EVENT_MOTION(pen_index) \
STEP _simpen_event ( SIMPEN_ACTION_MOTION_EVENT , ( pen_index ) , 0 , 0.0f , __LINE__ )
# define SIMPEN_EVENT_MOTION_SUPPRESSED(pen_index) \
STEP _simpen_event ( SIMPEN_ACTION_MOTION_EVENT_S , ( pen_index ) , 0 , 0.0f , __LINE__ )
# define SIMPEN_EVENT_BUTTON(pen_index, push, button) \
STEP _simpen_event ( ( push ) ? SIMPEN_ACTION_PRESS : SIMPEN_ACTION_RELEASE , ( pen_index ) , ( button ) , 0.0f , __LINE__ )
# define SIMPEN_EVENT_TIP(pen_index, touch, tip) \
STEP _simpen_event ( ( touch ) ? SIMPEN_ACTION_DOWN : SIMPEN_ACTION_UP , ( pen_index ) , tip , 0.0f , __LINE__ )
# define SIMPEN_SET_ERASER(pen_index, eraser_mode) \
STEP _simpen_event ( SIMPEN_ACTION_ERASER_MODE , ( pen_index ) , eraser_mode , 0.0f , __LINE__ )
static void
_pen_dump ( const char * prefix , SDL_Pen * pen )
{
int i ;
char * axes_str ;
if ( ! pen ) {
SDL_Log ( " (NULL pen) " ) ;
return ;
}
axes_str = SDL_strdup ( " " ) ;
for ( i = 0 ; i < SDL_PEN_NUM_AXES ; + + i ) {
char * old_axes_str = axes_str ;
SDL_asprintf ( & axes_str , " %s \t %f " , old_axes_str , pen - > last . axes [ i ] ) ;
SDL_free ( old_axes_str ) ;
}
SDL_Log ( " %s: pen %lu (%s): status=%04lx, flags=%lx, x,y=(%f, %f) axes = %s " ,
prefix ,
( unsigned long ) pen - > header . id ,
pen - > name ,
( unsigned long ) pen - > last . buttons ,
( unsigned long ) pen - > header . flags ,
pen - > last . x , pen - > last . y ,
axes_str ) ;
SDL_free ( axes_str ) ;
}
/* Runs until the next event has been issued or we are done and returns pointer to it.
Returns NULL once we hit SIMPEN_ACTION_DONE .
Updates simulated_pens accordingly . There must be as many simulated_pens as the highest pen_index used in
any of the " steps " .
Also validates the internal state with expectations ( via SDL_GetPenStatus ( ) ) and updates the , but does not poll SDL events . */
static simulated_pen_action *
_pen_simulate ( simulated_pen_action * steps , int * step_counter , SDL_Pen * simulated_pens , int num_pens )
{
SDL_bool done = SDL_FALSE ;
SDL_bool dump_pens = SDL_FALSE ;
unsigned int mask ;
int pen_nr ;
do {
simulated_pen_action step = steps [ * step_counter ] ;
SDL_Pen * simpen = & simulated_pens [ step . pen_index ] ;
if ( step . pen_index > = num_pens ) {
SDLTest_AssertCheck ( 0 ,
" Unexpected pen index %d at step %d, action %d " , step . pen_index , * step_counter , step . type ) ;
return NULL ;
}
switch ( step . type ) {
case SIMPEN_ACTION_DONE :
SDLTest_AssertPass ( " SIMPEN_ACTION_DONE " ) ;
return NULL ;
case SIMPEN_ACTION_MOVE_X :
SDLTest_AssertPass ( " SIMPEN_ACTION_MOVE_X [pen %d] : y <- %f " , step . pen_index , step . update ) ;
simpen - > last . x = step . update ;
break ;
case SIMPEN_ACTION_MOVE_Y :
SDLTest_AssertPass ( " SIMPEN_ACTION_MOVE_Y [pen %d] : x <- %f " , step . pen_index , step . update ) ;
simpen - > last . y = step . update ;
break ;
case SIMPEN_ACTION_AXIS :
SDLTest_AssertPass ( " SIMPEN_ACTION_AXIS [pen %d] : axis[%d] <- %f " , step . pen_index , step . index , step . update ) ;
simpen - > last . axes [ step . index ] = step . update ;
break ;
case SIMPEN_ACTION_MOTION_EVENT :
done = SDL_TRUE ;
SDLTest_AssertCheck ( SDL_SendPenMotion ( 0 , simpen - > header . id , SDL_TRUE ,
& simpen - > last ) ,
" SIMPEN_ACTION_MOTION_EVENT [pen %d] " , step . pen_index ) ;
break ;
case SIMPEN_ACTION_MOTION_EVENT_S :
SDLTest_AssertCheck ( ! SDL_SendPenMotion ( 0 , simpen - > header . id , SDL_TRUE ,
& simpen - > last ) ,
" SIMPEN_ACTION_MOTION_EVENT_SUPPRESSED [pen %d] " , step . pen_index ) ;
break ;
case SIMPEN_ACTION_PRESS :
mask = ( 1 < < ( step . index - 1 ) ) ;
simpen - > last . buttons | = mask ;
2024-02-03 12:23:16 -07:00
SDLTest_AssertCheck ( SDL_SendPenButton ( 0 , simpen - > header . id , SDL_PRESSED , ( Uint8 ) step . index ) ,
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
" SIMPEN_ACTION_PRESS [pen %d]: button %d (mask %x) " , step . pen_index , step . index , mask ) ;
done = SDL_TRUE ;
break ;
case SIMPEN_ACTION_RELEASE :
mask = ~ ( 1 < < ( step . index - 1 ) ) ;
simpen - > last . buttons & = mask ;
2024-02-03 12:23:16 -07:00
SDLTest_AssertCheck ( SDL_SendPenButton ( 0 , simpen - > header . id , SDL_RELEASED , ( Uint8 ) step . index ) ,
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
" SIMPEN_ACTION_RELEASE [pen %d]: button %d (mask %x) " , step . pen_index , step . index , mask ) ;
done = SDL_TRUE ;
break ;
case SIMPEN_ACTION_DOWN :
simpen - > last . buttons | = SDL_PEN_DOWN_MASK ;
SDLTest_AssertCheck ( SDL_SendPenTipEvent ( 0 , simpen - > header . id , SDL_PRESSED ) ,
" SIMPEN_ACTION_DOWN [pen %d]: (mask %lx) " , step . pen_index , SDL_PEN_DOWN_MASK ) ;
done = SDL_TRUE ;
break ;
case SIMPEN_ACTION_UP :
simpen - > last . buttons & = ~ SDL_PEN_DOWN_MASK ;
SDLTest_AssertCheck ( SDL_SendPenTipEvent ( 0 , simpen - > header . id , SDL_RELEASED ) ,
" SIMPEN_ACTION_UP [pen %d]: (mask %lx) " , step . pen_index , ~ SDL_PEN_DOWN_MASK ) ;
done = SDL_TRUE ;
break ;
case SIMPEN_ACTION_ERASER_MODE : {
Uint32 pmask ;
SDL_Pen * pen = SDL_PenModifyBegin ( simpen - > header . id ) ;
if ( step . index ) {
pmask = SDL_PEN_ERASER_MASK ;
} else {
pmask = SDL_PEN_INK_MASK ;
}
SDL_PenModifyAddCapabilities ( pen , pmask ) ;
SDL_PenModifyEnd ( pen , SDL_TRUE ) ;
simpen - > header . flags & = ~ ( SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK ) ;
simpen - > header . flags | = pmask ;
break ;
}
default :
SDLTest_AssertCheck ( 0 ,
" Unexpected pen simulation action %d " , step . type ) ;
return NULL ;
}
+ + ( * step_counter ) ;
} while ( ! done ) ;
for ( pen_nr = 0 ; pen_nr < num_pens ; + + pen_nr ) {
SDL_Pen * simpen = & simulated_pens [ pen_nr ] ;
float x = - 1.0f , y = - 1.0f ;
float axes [ SDL_PEN_NUM_AXES ] ;
Uint32 actual_flags = SDL_GetPenStatus ( simpen - > header . id , & x , & y , axes , SDL_PEN_NUM_AXES ) ;
int i ;
if ( simpen - > last . x ! = x | | simpen - > last . y ! = y ) {
SDLTest_AssertCheck ( 0 , " Coordinate mismatch in pen %d " , pen_nr ) ;
dump_pens = SDL_TRUE ;
}
if ( ( actual_flags & ~ ( SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK ) ) ! = ( simpen - > last . buttons & ~ ( SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK ) ) ) {
SDLTest_AssertCheck ( 0 , " Status mismatch in pen %d (reported: %08x) " , pen_nr , ( unsigned int ) actual_flags ) ;
dump_pens = SDL_TRUE ;
}
if ( ( actual_flags & ( SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK ) ) ! = ( simpen - > header . flags & ( SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK ) ) ) {
SDLTest_AssertCheck ( 0 , " Flags mismatch in pen %d (reported: %08x) " , pen_nr , ( unsigned int ) actual_flags ) ;
dump_pens = SDL_TRUE ;
}
for ( i = 0 ; i < SDL_PEN_NUM_AXES ; + + i ) {
if ( axes [ i ] ! = simpen - > last . axes [ i ] ) {
SDLTest_AssertCheck ( 0 , " Axis %d mismatch in pen %d " , pen_nr , i ) ;
dump_pens = SDL_TRUE ;
}
}
}
if ( dump_pens ) {
int i ;
for ( i = 0 ; i < num_pens ; + + i ) {
SDL_Log ( " ==== pen #%d " , i ) ;
_pen_dump ( " expect " , simulated_pens + i ) ;
_pen_dump ( " actual " , SDL_GetPenPtr ( simulated_pens [ i ] . header . id ) ) ;
}
}
return & steps [ ( * step_counter ) - 1 ] ;
}
/* Init simulated_pens with suitable initial state */
static void
_pen_simulate_init ( pen_testdata * ptest , SDL_Pen * simulated_pens , int num_pens )
{
int i ;
for ( i = 0 ; i < num_pens ; + + i ) {
simulated_pens [ i ] = * SDL_GetPenPtr ( ptest - > ids [ i ] ) ;
}
}
/* ---------------------------------------- */
/* Other helper functions */
/* "standard" pen registration process */
static SDL_Pen *
_pen_register ( SDL_PenID penid , SDL_GUID guid , char * name , Uint32 flags )
{
SDL_Pen * pen = SDL_PenModifyBegin ( penid ) ;
pen - > guid = guid ;
SDL_strlcpy ( pen - > name , name , SDL_PEN_MAX_NAME ) ;
SDL_PenModifyAddCapabilities ( pen , flags ) ;
return pen ;
}
/* Test whether EXPECTED and ACTUAL of type TY agree. Their C format string must be FMT.
MESSAGE is a string with one format string , passed as ARG0 . */
# define SDLTest_AssertEq1(TY, FMT, EXPECTED, ACTUAL, MESSAGE, ARG0) \
{ \
TY _t_expect = ( EXPECTED ) ; \
TY _t_actual = ( ACTUAL ) ; \
SDLTest_AssertCheck ( _t_expect = = _t_actual , " L%d: " MESSAGE " : expected " # EXPECTED " = " FMT " , actual = " FMT , __LINE__ , ( ARG0 ) , _t_expect , _t_actual ) ; \
}
/* ================= Test Case Implementation ================== */
/**
* @ brief Check basic pen device introduction and iteration , as well as basic queries
*
* @ sa SDL_GetPens , SDL_GetPenName , SDL_GetPenCapabilities
*/
static int
pen_iteration ( void * arg )
{
pen_testdata ptest ;
int i ;
char long_pen_name [ SDL_PEN_MAX_NAME + 10 ] ;
const char * name ;
deviceinfo_backup * backup ;
/* Check initial pens */
SDL_PumpEvents ( ) ;
SDLTest_AssertPass ( " SDL_GetPens() => count = %d " , _num_pens ( ) ) ;
/* Grab unused pen IDs for testing */
backup = _setup_test ( & ptest , 3 ) ; /* validates that we have zero pens */
/* Re-run GC, track deallocations */
SDL_PenGCMark ( ) ;
_pen_trackGCSweep ( & ptest ) ;
_AssertCheck_num_pens ( 0 , " after second GC pass " ) ;
SDLTest_AssertCheck ( ptest . deallocated_id_flags = = 0 , " No unexpected device deallocations " ) ;
SDLTest_AssertCheck ( ptest . deallocated_deviceinfo_flags = = 0 , " No unexpected deviceinfo deallocations " ) ;
SDLTest_AssertPass ( " Validated that GC on empty pen set is idempotent " ) ;
/* Add three pens, validate */
SDL_PenGCMark ( ) ;
SDL_memset ( long_pen_name , ' x ' , sizeof ( long_pen_name ) ) ; /* Include pen name that is too long */
long_pen_name [ sizeof ( long_pen_name ) - 1 ] = 0 ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 0 ] , ptest . guids [ 0 ] , " pen 0 " ,
SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) ,
16 ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 2 ] , ptest . guids [ 2 ] , long_pen_name ,
SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK ) ,
20 ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 1 ] , ptest . guids [ 1 ] , " pen 1 " ,
SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_YTILT_MASK ) ,
24 ) ;
_pen_trackGCSweep ( & ptest ) ;
_AssertCheck_num_pens ( 3 , " after allocating three pens " ) ;
SDLTest_AssertCheck ( ptest . deallocated_id_flags = = 0 , " No unexpected device deallocations " ) ;
SDLTest_AssertCheck ( ptest . deallocated_deviceinfo_flags = = 0 , " No unexpected deviceinfo deallocations " ) ;
for ( i = 0 ; i < 3 ; + + i ) {
/* Check that all pens are accounted for */
int index = _pen_iterationFindsPenIDAt ( ptest . ids [ i ] ) ;
SDLTest_AssertCheck ( - 1 ! = index , " Found PenID(%lu) " , ( unsigned long ) ptest . ids [ i ] ) ;
}
SDLTest_AssertPass ( " Validated that all three pens are indexable " ) ;
/* Check pen properties */
SDLTest_AssertCheck ( 0 = = SDL_strcmp ( " pen 0 " , SDL_GetPenName ( ptest . ids [ 0 ] ) ) ,
" Pen #0 name " ) ;
SDLTest_AssertCheck ( ( SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) = = SDL_GetPenCapabilities ( ptest . ids [ 0 ] , NULL ) ,
" Pen #0 capabilities " ) ;
SDLTest_AssertCheck ( 0 = = SDL_strcmp ( " pen 1 " , SDL_GetPenName ( ptest . ids [ 1 ] ) ) ,
" Pen #1 name " ) ;
SDLTest_AssertCheck ( ( SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_YTILT_MASK ) = = SDL_GetPenCapabilities ( ptest . ids [ 1 ] , NULL ) ,
" Pen #1 capabilities " ) ;
name = SDL_GetPenName ( ptest . ids [ 2 ] ) ;
SDLTest_AssertCheck ( SDL_PEN_MAX_NAME - 1 = = SDL_strlen ( name ) ,
" Pen #2 name length " ) ;
SDLTest_AssertCheck ( 0 = = SDL_memcmp ( name , long_pen_name , SDL_PEN_MAX_NAME - 1 ) ,
" Pen #2 name contents " ) ;
SDLTest_AssertCheck ( ( SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK ) = = SDL_GetPenCapabilities ( ptest . ids [ 2 ] , NULL ) ,
" Pen #2 capabilities " ) ;
SDLTest_AssertPass ( " Pen registration and basic queries " ) ;
/* Re-run GC, track deallocations */
SDL_PenGCMark ( ) ;
_pen_trackGCSweep ( & ptest ) ;
_AssertCheck_num_pens ( 0 , " after third GC pass " ) ;
SDLTest_AssertCheck ( ptest . deallocated_id_flags = = 0x07 ,
" No unexpected device deallocation : %08x " , ptest . deallocated_id_flags ) ;
SDLTest_AssertCheck ( ptest . deallocated_deviceinfo_flags = = 0x01110000 ,
" No unexpected deviceinfo deallocation : %08x " , ptest . deallocated_deviceinfo_flags ) ;
SDLTest_AssertPass ( " Validated that GC on empty pen set is idempotent " ) ;
/* tear down and finish */
_teardown_test ( & ptest , backup ) ;
return TEST_COMPLETED ;
}
static void
_expect_pen_attached ( SDL_PenID penid )
{
SDLTest_AssertCheck ( - 1 ! = _pen_iterationFindsPenIDAt ( penid ) ,
" Found PenID(%lu) " , ( unsigned long ) penid ) ;
SDLTest_AssertCheck ( SDL_PenConnected ( penid ) ,
" Pen %lu was attached, as expected " , ( unsigned long ) penid ) ;
}
static void
_expect_pen_detached ( SDL_PenID penid )
{
SDLTest_AssertCheck ( - 1 = = _pen_iterationFindsPenIDAt ( penid ) ,
" Did not find PenID(%lu), as expected " , ( unsigned long ) penid ) ;
SDLTest_AssertCheck ( ! SDL_PenConnected ( penid ) ,
" Pen %lu was detached, as expected " , ( unsigned long ) penid ) ;
}
# define ATTACHED(i) (1 << (i))
static void
_expect_pens_attached_or_detached ( SDL_PenID * pen_ids , int ids , Uint32 mask )
{
int i ;
int attached_count = 0 ;
for ( i = 0 ; i < ids ; + + i ) {
if ( mask & ( 1 < < i ) ) {
+ + attached_count ;
_expect_pen_attached ( pen_ids [ i ] ) ;
} else {
_expect_pen_detached ( pen_ids [ i ] ) ;
}
}
_AssertCheck_num_pens ( attached_count , " While checking attached/detached status " ) ;
}
/**
* @ brief Check pen device hotplugging
*
* @ sa SDL_GetPens , SDL_GetPenName , SDL_GetPenCapabilities , SDL_PenConnected
*/
static int
pen_hotplugging ( void * arg )
{
pen_testdata ptest ;
deviceinfo_backup * backup = _setup_test ( & ptest , 3 ) ;
SDL_GUID checkguid ;
/* Add two pens */
SDL_PenGCMark ( ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 0 ] , ptest . guids [ 0 ] , " pen 0 " , SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) ,
16 ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 2 ] , ptest . guids [ 2 ] , " pen 2 " , SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) ,
24 ) ;
_pen_trackGCSweep ( & ptest ) ;
_AssertCheck_num_pens ( 2 , " after allocating two pens (pass 1) " ) ;
SDLTest_AssertCheck ( ptest . deallocated_id_flags = = 0 , " No unexpected device deallocation (pass 1) " ) ;
SDLTest_AssertCheck ( ptest . deallocated_deviceinfo_flags = = 0 , " No unexpected deviceinfo deallocation (pass 1) " ) ;
_expect_pens_attached_or_detached ( ptest . ids , 3 , ATTACHED ( 0 ) | ATTACHED ( 2 ) ) ;
SDLTest_AssertPass ( " Validated hotplugging (pass 1): attachmend of two pens " ) ;
/* Introduce pen #1, remove pen #2 */
SDL_PenGCMark ( ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 0 ] , ptest . guids [ 0 ] , " pen 0 " , SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) ,
DEVICEINFO_UNCHANGED ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 1 ] , ptest . guids [ 1 ] , " pen 1 " , SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) ,
20 ) ;
_pen_trackGCSweep ( & ptest ) ;
_AssertCheck_num_pens ( 2 , " after allocating two pens (pass 2) " ) ;
SDLTest_AssertCheck ( ptest . deallocated_id_flags = = 0x04 , " No unexpected device deallocation (pass 2): %x " , ptest . deallocated_id_flags ) ;
SDLTest_AssertCheck ( ptest . deallocated_deviceinfo_flags = = 0x01000000 , " No unexpected deviceinfo deallocation (pass 2): %x " , ptest . deallocated_deviceinfo_flags ) ;
_expect_pens_attached_or_detached ( ptest . ids , 3 , ATTACHED ( 0 ) | ATTACHED ( 1 ) ) ;
SDLTest_AssertPass ( " Validated hotplugging (pass 2): unplug one, attach another " ) ;
/* Return to previous state (#0 and #2 attached) */
SDL_PenGCMark ( ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 0 ] , ptest . guids [ 0 ] , " pen 0 " , SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_YTILT ) ,
DEVICEINFO_UNCHANGED ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 2 ] , ptest . guids [ 2 ] , " pen 2 " , SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) ,
24 ) ;
_pen_trackGCSweep ( & ptest ) ;
_AssertCheck_num_pens ( 2 , " after allocating two pens (pass 3) " ) ;
SDLTest_AssertCheck ( ptest . deallocated_id_flags = = 0x02 , " No unexpected device deallocation (pass 3) " ) ;
SDLTest_AssertCheck ( ptest . deallocated_deviceinfo_flags = = 0x00100000 , " No unexpected deviceinfo deallocation (pass 3) " ) ;
_expect_pens_attached_or_detached ( ptest . ids , 3 , ATTACHED ( 0 ) | ATTACHED ( 2 ) ) ;
SDLTest_AssertPass ( " Validated hotplugging (pass 3): return to state of pass 1 " ) ;
/* Introduce pen #1, remove pen #0 */
SDL_PenGCMark ( ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 1 ] , ptest . guids [ 1 ] , " pen 1 " , SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) ,
20 ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 2 ] , ptest . guids [ 2 ] , " pen 2 " , SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) ,
DEVICEINFO_UNCHANGED ) ;
_pen_trackGCSweep ( & ptest ) ;
_AssertCheck_num_pens ( 2 , " after allocating two pens (pass 4) " ) ;
SDLTest_AssertCheck ( ptest . deallocated_id_flags = = 0x01 , " No unexpected device deallocation (pass 4): %x " , ptest . deallocated_id_flags ) ;
SDLTest_AssertCheck ( ptest . deallocated_deviceinfo_flags = = 0x00010000 , " No unexpected deviceinfo deallocation (pass 4): %x " , ptest . deallocated_deviceinfo_flags ) ;
_expect_pens_attached_or_detached ( ptest . ids , 3 , ATTACHED ( 1 ) | ATTACHED ( 2 ) ) ;
SDLTest_AssertPass ( " Validated hotplugging (pass 5) " ) ;
/* Check detached pen */
SDLTest_AssertCheck ( 0 = = SDL_strcmp ( " pen 0 " , SDL_GetPenName ( ptest . ids [ 0 ] ) ) ,
" Pen #0 name " ) ;
checkguid = SDL_GetPenGUID ( ptest . ids [ 0 ] ) ;
SDLTest_AssertCheck ( 0 = = SDL_memcmp ( ptest . guids [ 0 ] . data , checkguid . data , sizeof ( ptest . guids [ 0 ] . data ) ) ,
" Pen #0 guid " ) ;
SDLTest_AssertCheck ( ( SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_YTILT ) = = SDL_GetPenCapabilities ( ptest . ids [ 0 ] , NULL ) ,
" Pen #0 capabilities " ) ;
SDLTest_AssertPass ( " Validated that detached pens retained name, GUID, axis info after pass 5 " ) ;
/* Individually detach #1 dn #2 */
_expect_pens_attached_or_detached ( ptest . ids , 3 , ATTACHED ( 1 ) | ATTACHED ( 2 ) ) ;
SDL_PenModifyEnd ( SDL_PenModifyBegin ( ptest . ids [ 1 ] ) , SDL_FALSE ) ;
_expect_pens_attached_or_detached ( ptest . ids , 3 , ATTACHED ( 2 ) ) ;
SDL_PenModifyEnd ( SDL_PenModifyBegin ( ptest . ids [ 2 ] ) , SDL_FALSE ) ;
_expect_pens_attached_or_detached ( ptest . ids , 3 , 0 ) ;
SDLTest_AssertPass ( " Validated individual hotplugging (pass 6) " ) ;
/* Individually attach all */
SDL_PenModifyEnd ( SDL_PenModifyBegin ( ptest . ids [ 2 ] ) , SDL_TRUE ) ;
_expect_pens_attached_or_detached ( ptest . ids , 3 , ATTACHED ( 2 ) ) ;
SDL_PenModifyEnd ( SDL_PenModifyBegin ( ptest . ids [ 0 ] ) , SDL_TRUE ) ;
_expect_pens_attached_or_detached ( ptest . ids , 3 , ATTACHED ( 0 ) | ATTACHED ( 2 ) ) ;
SDL_PenModifyEnd ( SDL_PenModifyBegin ( ptest . ids [ 1 ] ) , SDL_TRUE ) ;
_expect_pens_attached_or_detached ( ptest . ids , 3 , ATTACHED ( 0 ) | ATTACHED ( 1 ) | ATTACHED ( 2 ) ) ;
SDLTest_AssertPass ( " Validated individual hotplugging (pass 7) " ) ;
SDL_PenGCMark ( ) ;
_pen_trackGCSweep ( & ptest ) ;
_AssertCheck_num_pens ( 0 , " after hotplugging test (cleanup) " ) ;
SDLTest_AssertCheck ( ptest . deallocated_id_flags = = 0x06 , " No unexpected device deallocation (cleanup): %x " , ptest . deallocated_id_flags ) ;
SDLTest_AssertCheck ( ptest . deallocated_deviceinfo_flags = = 0x01100000 , " No unexpected deviceinfo deallocation (pass 4): %x " , ptest . deallocated_deviceinfo_flags ) ;
_teardown_test_with_gc ( & ptest , backup ) ;
return TEST_COMPLETED ;
}
/**
* @ brief Check pen device GUID handling
*
* @ sa SDL_GetPenGUID
*/
static int
pen_GUIDs ( void * arg )
{
int i ;
char * names [ 4 ] = { " pen 0 " , " pen 1 " , " pen 2 " , " pen 3 " } ;
pen_testdata ptest ;
deviceinfo_backup * backup ;
backup = _setup_test ( & ptest , 4 ) ;
/* Define four pens */
SDL_PenGCMark ( ) ;
for ( i = 0 ; i < 4 ; + + i ) {
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ i ] , ptest . guids [ i ] , names [ i ] , SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) ,
20 ) ;
}
_pen_trackGCSweep ( & ptest ) ;
/* Detach pens 0 and 2 */
SDL_PenGCMark ( ) ;
for ( i = 1 ; i < 4 ; i + = 2 ) {
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ i ] , ptest . guids [ i ] , names [ i ] , SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) ,
DEVICEINFO_UNCHANGED ) ;
}
_pen_trackGCSweep ( & ptest ) ;
for ( i = 0 ; i < 4 ; + + i ) {
SDLTest_AssertCheck ( ptest . ids [ i ] = = SDL_GetPenFromGUID ( ptest . guids [ i ] ) ,
" GUID search succeeded for %d " , i ) ;
}
/* detach all */
SDL_PenGCMark ( ) ;
_pen_trackGCSweep ( & ptest ) ;
_teardown_test ( & ptest , backup ) ;
SDLTest_AssertPass ( " Pen ID lookup by GUID " ) ;
return TEST_COMPLETED ;
}
/**
* @ brief Check pen device button reporting
*
*/
static int
pen_buttonReporting ( void * arg )
{
int i ;
int button_nr , pen_nr ;
pen_testdata ptest ;
SDL_Event event ;
SDL_PenStatusInfo update ;
float axes [ SDL_PEN_NUM_AXES + 1 ] ;
const float expected_x [ 2 ] = { 10.0f , 20.0f } ;
const float expected_y [ 2 ] = { 11.0f , 21.0f } ;
const Uint32 all_axes = SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_ROTATION_MASK | SDL_PEN_AXIS_SLIDER_MASK ;
/* Register pen */
deviceinfo_backup * backup = _setup_test ( & ptest , 2 ) ;
SDL_PenGCMark ( ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 0 ] , ptest . guids [ 0 ] , " test pen " ,
SDL_PEN_INK_MASK | all_axes ) ,
20 ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 1 ] , ptest . guids [ 1 ] , " test eraser " ,
SDL_PEN_ERASER_MASK | all_axes ) ,
24 ) ;
_pen_trackGCSweep ( & ptest ) ;
/* Position mouse suitably before we start */
for ( i = 0 ; i < = SDL_PEN_NUM_AXES ; + + i ) {
axes [ i ] = 0.0625f * i ; /* initialise with numbers that can be represented precisely in IEEE 754 and
are > 0.0f and < = 1.0f */
}
/* Let pens enter the test window */
SDL_SendPenWindowEvent ( 0 , ptest . ids [ 0 ] , ptest . window ) ;
SDL_SendPenWindowEvent ( 0 , ptest . ids [ 1 ] , ptest . window ) ;
update . x = expected_x [ 0 ] ;
update . y = expected_y [ 0 ] ;
SDL_memcpy ( update . axes , axes , sizeof ( float ) * SDL_PEN_NUM_AXES ) ;
SDL_SendPenMotion ( 0 , ptest . ids [ 0 ] , SDL_TRUE , & update ) ;
update . x = expected_x [ 1 ] ;
update . y = expected_y [ 1 ] ;
SDL_memcpy ( update . axes , axes + 1 , sizeof ( float ) * SDL_PEN_NUM_AXES ) ;
SDL_SendPenMotion ( 0 , ptest . ids [ 1 ] , SDL_TRUE , & update ) ;
while ( SDL_PollEvent ( & event ) )
; /* Flush event queue */
/* Trigger pen tip events for PEN_DOWN */
SDLTest_AssertPass ( " Touch pens to surface " ) ;
for ( pen_nr = 0 ; pen_nr < 2 ; + + pen_nr ) {
float * expected_axes = axes + pen_nr ;
SDL_bool found_event = SDL_FALSE ;
Uint16 pen_state = 0x0000 | SDL_PEN_DOWN_MASK ;
Uint8 tip = SDL_PEN_TIP_INK ;
if ( pen_nr = = 1 ) {
pen_state | = SDL_PEN_ERASER_MASK ;
tip = SDL_PEN_TIP_ERASER ;
}
SDL_SendPenTipEvent ( 0 , ptest . ids [ pen_nr ] , SDL_PRESSED ) ;
while ( SDL_PollEvent ( & event ) ) {
if ( event . type = = SDL_EVENT_PEN_DOWN ) {
SDLTest_AssertCheck ( event . ptip . which = = ptest . ids [ pen_nr ] ,
" Received SDL_EVENT_PEN_DOWN from correct pen " ) ;
SDLTest_AssertCheck ( event . ptip . tip = = ( pen_nr = = 0 ) ? SDL_PEN_TIP_INK : SDL_PEN_TIP_ERASER ,
" Received SDL_EVENT_PEN_DOWN for correct tip " ) ;
SDLTest_AssertCheck ( event . ptip . state = = SDL_PRESSED ,
" Received SDL_EVENT_PEN_DOWN but and marked SDL_PRESSED " ) ;
SDLTest_AssertCheck ( event . ptip . tip = = tip ,
" Received tip %x but expected %x " , event . ptip . tip , tip ) ;
SDLTest_AssertCheck ( event . ptip . pen_state = = pen_state ,
" Received SDL_EVENT_PEN_DOWN, and state %04x == %04x (expected) " ,
event . pbutton . pen_state , pen_state ) ;
SDLTest_AssertCheck ( ( event . ptip . x = = expected_x [ pen_nr ] ) & & ( event . ptip . y = = expected_y [ pen_nr ] ) ,
" Received SDL_EVENT_PEN_DOWN event at correct coordinates: (%f, %f) vs (%f, %f) (expected) " ,
event . pbutton . x , event . pbutton . y , expected_x [ pen_nr ] , expected_y [ pen_nr ] ) ;
SDLTest_AssertCheck ( 0 = = SDL_memcmp ( expected_axes , event . pbutton . axes , sizeof ( float ) * SDL_PEN_NUM_AXES ) ,
" Received SDL_EVENT_PEN_DOWN event with correct axis values " ) ;
found_event = SDL_TRUE ;
}
SDLTest_AssertCheck ( found_event ,
" Received the expected SDL_EVENT_PEN_DOWN event " ) ;
}
}
SDLTest_AssertPass ( " Pen and eraser set up for button testing " ) ;
/* Actual tests start: pen, then eraser */
for ( pen_nr = 0 ; pen_nr < 2 ; + + pen_nr ) {
Uint16 pen_state = 0x0000 | SDL_PEN_DOWN_MASK ;
float * expected_axes = axes + pen_nr ;
if ( pen_nr = = 1 ) {
pen_state | = SDL_PEN_ERASER_MASK ;
}
for ( button_nr = 1 ; button_nr < = 8 ; + + button_nr ) {
SDL_bool found_event = SDL_FALSE ;
pen_state | = ( 1 < < ( button_nr - 1 ) ) ;
2024-02-03 12:23:16 -07:00
SDL_SendPenButton ( 0 , ptest . ids [ pen_nr ] , SDL_PRESSED , ( Uint8 ) button_nr ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
while ( SDL_PollEvent ( & event ) ) {
if ( event . type = = SDL_EVENT_PEN_BUTTON_DOWN ) {
SDLTest_AssertCheck ( event . pbutton . which = = ptest . ids [ pen_nr ] ,
" Received SDL_EVENT_PEN_BUTTON_DOWN from correct pen " ) ;
SDLTest_AssertCheck ( event . pbutton . button = = button_nr ,
" Received SDL_EVENT_PEN_BUTTON_DOWN from correct button " ) ;
SDLTest_AssertCheck ( event . pbutton . state = = SDL_PRESSED ,
" Received SDL_EVENT_PEN_BUTTON_DOWN but and marked SDL_PRESSED " ) ;
SDLTest_AssertCheck ( event . pbutton . pen_state = = pen_state ,
" Received SDL_EVENT_PEN_BUTTON_DOWN, and state %04x == %04x (expected) " ,
event . pbutton . pen_state , pen_state ) ;
SDLTest_AssertCheck ( ( event . pbutton . x = = expected_x [ pen_nr ] ) & & ( event . pbutton . y = = expected_y [ pen_nr ] ) ,
" Received SDL_EVENT_PEN_BUTTON_DOWN event at correct coordinates: (%f, %f) vs (%f, %f) (expected) " ,
event . pbutton . x , event . pbutton . y , expected_x [ pen_nr ] , expected_y [ pen_nr ] ) ;
SDLTest_AssertCheck ( 0 = = SDL_memcmp ( expected_axes , event . pbutton . axes , sizeof ( float ) * SDL_PEN_NUM_AXES ) ,
" Received SDL_EVENT_PEN_BUTTON_DOWN event with correct axis values " ) ;
if ( 0 ! = SDL_memcmp ( expected_axes , event . pbutton . axes , sizeof ( float ) * SDL_PEN_NUM_AXES ) ) {
int ax ;
for ( ax = 0 ; ax < SDL_PEN_NUM_AXES ; + + ax ) {
SDL_Log ( " \t ax %d \t %.5f \t %.5f expected (equal=%d) " ,
ax ,
event . pbutton . axes [ ax ] , expected_axes [ ax ] ,
event . pbutton . axes [ ax ] = = expected_axes [ ax ] ) ;
}
}
found_event = SDL_TRUE ;
}
}
SDLTest_AssertCheck ( found_event ,
" Received the expected SDL_EVENT_PEN_BUTTON_DOWN event " ) ;
}
}
SDLTest_AssertPass ( " Pressed all buttons " ) ;
/* Release every other button */
for ( pen_nr = 0 ; pen_nr < 2 ; + + pen_nr ) {
Uint16 pen_state = 0x00ff | SDL_PEN_DOWN_MASK ; /* 8 buttons pressed */
float * expected_axes = axes + pen_nr ;
if ( pen_nr = = 1 ) {
pen_state | = SDL_PEN_ERASER_MASK ;
}
for ( button_nr = pen_nr + 1 ; button_nr < = 8 ; button_nr + = 2 ) {
SDL_bool found_event = SDL_FALSE ;
pen_state & = ~ ( 1 < < ( button_nr - 1 ) ) ;
2024-02-03 12:23:16 -07:00
SDL_SendPenButton ( 0 , ptest . ids [ pen_nr ] , SDL_RELEASED , ( Uint8 ) button_nr ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
while ( SDL_PollEvent ( & event ) ) {
if ( event . type = = SDL_EVENT_PEN_BUTTON_UP ) {
SDLTest_AssertCheck ( event . pbutton . which = = ptest . ids [ pen_nr ] ,
" Received SDL_EVENT_PEN_BUTTON_UP from correct pen " ) ;
SDLTest_AssertCheck ( event . pbutton . button = = button_nr ,
" Received SDL_EVENT_PEN_BUTTON_UP from correct button " ) ;
SDLTest_AssertCheck ( event . pbutton . state = = SDL_RELEASED ,
" Received SDL_EVENT_PEN_BUTTON_UP and is marked SDL_RELEASED " ) ;
SDLTest_AssertCheck ( event . pbutton . pen_state = = pen_state ,
" Received SDL_EVENT_PEN_BUTTON_UP, and state %04x == %04x (expected) " ,
event . pbutton . pen_state , pen_state ) ;
SDLTest_AssertCheck ( ( event . pbutton . x = = expected_x [ pen_nr ] ) & & ( event . pbutton . y = = expected_y [ pen_nr ] ) ,
" Received SDL_EVENT_PEN_BUTTON_UP event at correct coordinates " ) ;
SDLTest_AssertCheck ( 0 = = SDL_memcmp ( expected_axes , event . pbutton . axes , sizeof ( float ) * SDL_PEN_NUM_AXES ) ,
" Received SDL_EVENT_PEN_BUTTON_UP event with correct axis values " ) ;
found_event = SDL_TRUE ;
}
}
SDLTest_AssertCheck ( found_event ,
" Received the expected SDL_EVENT_PEN_BUTTON_UP event " ) ;
}
}
SDLTest_AssertPass ( " Released every other button " ) ;
/* Trigger pen tip events for PEN_UP */
SDLTest_AssertPass ( " Remove pens from surface " ) ;
for ( pen_nr = 0 ; pen_nr < 2 ; + + pen_nr ) {
float * expected_axes = axes + pen_nr ;
SDL_bool found_event = SDL_FALSE ;
Uint16 pen_state = 0x0000 ;
Uint8 tip = SDL_PEN_TIP_INK ;
if ( pen_nr = = 1 ) {
pen_state | = SDL_PEN_ERASER_MASK ;
tip = SDL_PEN_TIP_ERASER ;
}
SDL_SendPenTipEvent ( 0 , ptest . ids [ pen_nr ] , SDL_RELEASED ) ;
while ( SDL_PollEvent ( & event ) ) {
if ( event . type = = SDL_EVENT_PEN_UP ) {
SDLTest_AssertCheck ( event . ptip . which = = ptest . ids [ pen_nr ] ,
" Received SDL_EVENT_PEN_UP from correct pen " ) ;
SDLTest_AssertCheck ( event . ptip . tip = = ( pen_nr = = 0 ) ? SDL_PEN_TIP_INK : SDL_PEN_TIP_ERASER ,
" Received SDL_EVENT_PEN_UP for correct tip " ) ;
SDLTest_AssertCheck ( event . ptip . state = = SDL_RELEASED ,
" Received SDL_EVENT_PEN_UP but and marked SDL_RELEASED " ) ;
SDLTest_AssertCheck ( event . ptip . tip = = tip ,
" Received tip %x but expected %x " , event . ptip . tip , tip ) ;
SDLTest_AssertCheck ( ( event . ptip . pen_state & 0xff00 ) = = ( pen_state & 0xff00 ) ,
" Received SDL_EVENT_PEN_UP, and state %04x == %04x (expected) " ,
event . pbutton . pen_state , pen_state ) ;
SDLTest_AssertCheck ( ( event . ptip . x = = expected_x [ pen_nr ] ) & & ( event . ptip . y = = expected_y [ pen_nr ] ) ,
" Received SDL_EVENT_PEN_UP event at correct coordinates: (%f, %f) vs (%f, %f) (expected) " ,
event . pbutton . x , event . pbutton . y , expected_x [ pen_nr ] , expected_y [ pen_nr ] ) ;
SDLTest_AssertCheck ( 0 = = SDL_memcmp ( expected_axes , event . pbutton . axes , sizeof ( float ) * SDL_PEN_NUM_AXES ) ,
" Received SDL_EVENT_PEN_UP event with correct axis values " ) ;
found_event = SDL_TRUE ;
}
SDLTest_AssertCheck ( found_event ,
" Received the expected SDL_EVENT_PEN_UP event " ) ;
}
}
/* Cleanup */
SDL_PenGCMark ( ) ;
_pen_trackGCSweep ( & ptest ) ;
_teardown_test ( & ptest , backup ) ;
return TEST_COMPLETED ;
}
/**
* @ brief Check pen device movement and axis update reporting
*
* Also tests SDL_GetPenStatus for agreement with the most recently reported events
*
* @ sa SDL_GetPenStatus
*/
static int
pen_movementAndAxes ( void * arg )
{
pen_testdata ptest ;
SDL_Event event ;
# define MAX_STEPS 80
/* Pen simulation */
simulated_pen_action steps [ MAX_STEPS ] ;
size_t num_steps = 0 ;
SDL_Pen simulated_pens [ 2 ] ;
int sim_pc = 0 ;
simulated_pen_action * last_action ;
/* Register pen */
deviceinfo_backup * backup = _setup_test ( & ptest , 2 ) ;
/* Pen simulation program */
# define STEP steps[num_steps++] =
/* #1: Check basic reporting */
/* Hover eraser, tilt axes */
SIMPEN_MOVE ( 0 , 30.0f , 31.0f ) ;
SIMPEN_AXIS ( 0 , SDL_PEN_AXIS_PRESSURE , 0.0f ) ;
SIMPEN_AXIS ( 0 , SDL_PEN_AXIS_XTILT , 22.5f ) ;
SIMPEN_AXIS ( 0 , SDL_PEN_AXIS_YTILT , 45.0f ) ;
SIMPEN_EVENT_MOTION ( 0 ) ;
/* #2: Check that motion events without motion aren't reported */
SIMPEN_EVENT_MOTION_SUPPRESSED ( 0 ) ;
SIMPEN_EVENT_MOTION_SUPPRESSED ( 0 ) ;
/* #3: Check multiple pens being reported */
/* Move pen and touch surface, don't tilt */
SIMPEN_MOVE ( 1 , 40.0f , 41.0f ) ;
SIMPEN_AXIS ( 1 , SDL_PEN_AXIS_PRESSURE , 0.25f ) ;
SIMPEN_EVENT_MOTION ( 1 ) ;
/* $4: Multi-buttons */
/* Press eraser buttons */
SIMPEN_EVENT_TIP ( 0 , " down " , SDL_PEN_TIP_ERASER ) ;
SIMPEN_EVENT_BUTTON ( 0 , " push " , 2 ) ;
SIMPEN_EVENT_BUTTON ( 0 , " push " , 1 ) ;
SIMPEN_EVENT_BUTTON ( 0 , 0 , 2 ) ; /* release again */
SIMPEN_EVENT_BUTTON ( 0 , " push " , 3 ) ;
/* #5: Check move + button actions connecting */
/* Move and tilt pen, press some pen buttons */
SIMPEN_MOVE ( 1 , 3.0f , 8.0f ) ;
SIMPEN_AXIS ( 1 , SDL_PEN_AXIS_PRESSURE , 0.5f ) ;
SIMPEN_AXIS ( 1 , SDL_PEN_AXIS_XTILT , - 21.0f ) ;
SIMPEN_AXIS ( 1 , SDL_PEN_AXIS_YTILT , - 25.0f ) ;
SIMPEN_EVENT_MOTION ( 1 ) ;
SIMPEN_EVENT_BUTTON ( 1 , " push " , 2 ) ;
SIMPEN_EVENT_TIP ( 1 , " down " , SDL_PEN_TIP_INK ) ;
/* #6: Check nonterference between pens */
/* Eraser releases buttons */
SIMPEN_EVENT_BUTTON ( 0 , 0 , 1 ) ;
SIMPEN_EVENT_TIP ( 0 , 0 , SDL_PEN_TIP_ERASER ) ;
/* #7: Press-move-release action */
/* Eraser press-move-release */
SIMPEN_EVENT_BUTTON ( 0 , " push " , 1 ) ;
SIMPEN_MOVE ( 0 , 99.0f , 88.0f ) ;
SIMPEN_AXIS ( 0 , SDL_PEN_AXIS_PRESSURE , 0.625f ) ;
SIMPEN_EVENT_MOTION ( 0 ) ;
SIMPEN_MOVE ( 0 , 44.5f , 42.25f ) ;
SIMPEN_EVENT_MOTION ( 0 ) ;
SIMPEN_EVENT_BUTTON ( 0 , 0 , 1 ) ;
/* #8: Intertwining button release actions some more */
/* Pen releases button */
SIMPEN_EVENT_BUTTON ( 1 , 0 , 2 ) ;
SIMPEN_EVENT_TIP ( 1 , 0 , SDL_PEN_TIP_INK ) ;
/* Push one more pen button, then release all ereaser buttons */
SIMPEN_EVENT_TIP ( 1 , " down " , SDL_PEN_TIP_INK ) ;
SIMPEN_EVENT_BUTTON ( 0 , 0 , 2 ) ;
SIMPEN_EVENT_BUTTON ( 0 , 0 , 3 ) ;
/* Lift up pen, flip it so it becomes an eraser, and touch it again */
SIMPEN_EVENT_TIP ( 1 , 0 , SDL_PEN_TIP_INK ) ;
SIMPEN_SET_ERASER ( 1 , 1 ) ;
SIMPEN_EVENT_TIP ( 1 , " push " , SDL_PEN_TIP_ERASER ) ;
/* And back again */
SIMPEN_EVENT_TIP ( 1 , 0 , SDL_PEN_TIP_ERASER ) ;
SIMPEN_SET_ERASER ( 1 , 0 ) ;
SIMPEN_EVENT_TIP ( 1 , " push " , SDL_PEN_TIP_INK ) ;
/* #9: Suppress move on unsupported axis */
SIMPEN_AXIS ( 1 , SDL_PEN_AXIS_DISTANCE , 0.25f ) ;
SIMPEN_EVENT_MOTION_SUPPRESSED ( 0 ) ;
SIMPEN_DONE ( ) ;
# undef STEP
/* End of pen simulation program */
SDLTest_AssertCheck ( num_steps < MAX_STEPS , " Pen simulation program does not exceed buffer size " ) ;
# undef MAX_STEPS
SDL_PenGCMark ( ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 0 ] , ptest . guids [ 0 ] , " test eraser " ,
SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK ) ,
20 ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 1 ] , ptest . guids [ 1 ] , " test pen " ,
SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK ) ,
24 ) ;
_pen_trackGCSweep ( & ptest ) ;
SDL_SendPenWindowEvent ( 0 , ptest . ids [ 0 ] , ptest . window ) ;
SDL_SendPenWindowEvent ( 0 , ptest . ids [ 1 ] , ptest . window ) ;
while ( SDL_PollEvent ( & event ) )
; /* Flush event queue */
SDLTest_AssertPass ( " Pen and eraser set up for testing " ) ;
_pen_simulate_init ( & ptest , simulated_pens , 2 ) ;
/* Simulate pen movements */
2024-02-03 12:25:29 -07:00
while ( ( last_action = _pen_simulate ( steps , & sim_pc , & simulated_pens [ 0 ] , 2 ) ) ! = 0 ) {
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
int attempts = 0 ;
SDL_Pen * simpen = & simulated_pens [ last_action - > pen_index ] ;
2024-02-03 12:23:16 -07:00
SDL_PenID reported_which = 0 ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
float reported_x = - 1.0f , reported_y = - 1.0f ;
float * reported_axes = NULL ;
Uint32 reported_pen_state = 0 ;
Uint32 expected_pen_state = simpen - > header . flags & SDL_PEN_ERASER_MASK ;
SDL_bool dump_pens = SDL_FALSE ;
do {
SDL_PumpEvents ( ) ;
SDL_PollEvent ( & event ) ;
if ( + + attempts > 10000 ) {
SDLTest_AssertCheck ( 0 , " Never got the anticipated event " ) ;
return TEST_ABORTED ;
}
} while ( event . type ! = SDL_EVENT_PEN_DOWN
& & event . type ! = SDL_EVENT_PEN_UP
& & event . type ! = SDL_EVENT_PEN_MOTION
& & event . type ! = SDL_EVENT_PEN_BUTTON_UP
& & event . type ! = SDL_EVENT_PEN_BUTTON_DOWN ) ; /* skip boring events */
expected_pen_state | = simpen - > last . buttons ;
SDLTest_AssertCheck ( 0 ! = event . type ,
" Received the anticipated event " ) ;
switch ( last_action - > type ) {
case SIMPEN_ACTION_MOTION_EVENT :
SDLTest_AssertCheck ( event . type = = SDL_EVENT_PEN_MOTION , " Expected pen motion event (but got 0x%lx) " , ( unsigned long ) event . type ) ;
reported_which = event . pmotion . which ;
reported_x = event . pmotion . x ;
reported_y = event . pmotion . y ;
reported_pen_state = event . pmotion . pen_state ;
reported_axes = & event . pmotion . axes [ 0 ] ;
break ;
case SIMPEN_ACTION_PRESS :
SDLTest_AssertCheck ( event . type = = SDL_EVENT_PEN_BUTTON_DOWN , " Expected PENBUTTONDOWN event (but got 0x%lx) " , ( unsigned long ) event . type ) ;
SDLTest_AssertCheck ( event . pbutton . state = = SDL_PRESSED , " Expected PRESSED button " ) ;
2024-03-18 10:56:22 -06:00
SDL_FALLTHROUGH ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
case SIMPEN_ACTION_RELEASE :
if ( last_action - > type = = SIMPEN_ACTION_RELEASE ) {
SDLTest_AssertCheck ( event . type = = SDL_EVENT_PEN_BUTTON_UP , " Expected PENBUTTONUP event (but got 0x%lx) " , ( unsigned long ) event . type ) ;
SDLTest_AssertCheck ( event . pbutton . state = = SDL_RELEASED , " Expected RELEASED button " ) ;
}
SDLTest_AssertCheck ( event . pbutton . button = = last_action - > index , " Expected button %d, but got %d " ,
last_action - > index , event . pbutton . button ) ;
reported_which = event . pbutton . which ;
reported_x = event . pbutton . x ;
reported_y = event . pbutton . y ;
reported_pen_state = event . pbutton . pen_state ;
reported_axes = & event . pbutton . axes [ 0 ] ;
break ;
case SIMPEN_ACTION_DOWN :
SDLTest_AssertCheck ( event . type = = SDL_EVENT_PEN_DOWN , " Expected PENBUTTONDOWN event (but got 0x%lx) " , ( unsigned long ) event . type ) ;
SDLTest_AssertCheck ( event . ptip . state = = SDL_PRESSED , " Expected PRESSED button " ) ;
2024-03-18 10:56:22 -06:00
SDL_FALLTHROUGH ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
case SIMPEN_ACTION_UP :
if ( last_action - > type = = SIMPEN_ACTION_UP ) {
SDLTest_AssertCheck ( event . type = = SDL_EVENT_PEN_UP , " Expected PENBUTTONUP event (but got 0x%lx) " , ( unsigned long ) event . type ) ;
SDLTest_AssertCheck ( event . ptip . state = = SDL_RELEASED , " Expected RELEASED button " ) ;
}
SDLTest_AssertCheck ( event . ptip . tip = = last_action - > index , " Expected tip %d, but got %d " ,
last_action - > index , event . ptip . tip ) ;
reported_which = event . ptip . which ;
reported_x = event . ptip . x ;
reported_y = event . ptip . y ;
reported_pen_state = event . ptip . pen_state ;
reported_axes = & event . ptip . axes [ 0 ] ;
break ;
case SIMPEN_ACTION_ERASER_MODE :
break ;
default :
SDLTest_AssertCheck ( 0 , " Error in pen simulator: unexpected action %d " , last_action - > type ) ;
return TEST_ABORTED ;
}
if ( reported_which ! = simpen - > header . id ) {
dump_pens = SDL_TRUE ;
SDLTest_AssertCheck ( 0 , " Expected report for pen %lu but got report for pen %lu " ,
( unsigned long ) simpen - > header . id ,
( unsigned long ) reported_which ) ;
}
if ( reported_x ! = simpen - > last . x | | reported_y ! = simpen - > last . y ) {
dump_pens = SDL_TRUE ;
SDLTest_AssertCheck ( 0 , " Mismatch in pen coordinates " ) ;
}
if ( reported_x ! = simpen - > last . x | | reported_y ! = simpen - > last . y ) {
dump_pens = SDL_TRUE ;
SDLTest_AssertCheck ( 0 , " Mismatch in pen coordinates " ) ;
}
if ( reported_pen_state ! = expected_pen_state ) {
dump_pens = SDL_TRUE ;
SDLTest_AssertCheck ( 0 , " Mismatch in pen state: %lx vs %lx (expected) " ,
( unsigned long ) reported_pen_state ,
( unsigned long ) expected_pen_state ) ;
}
if ( 0 ! = SDL_memcmp ( reported_axes , simpen - > last . axes , sizeof ( float ) * SDL_PEN_NUM_AXES ) ) {
dump_pens = SDL_TRUE ;
SDLTest_AssertCheck ( 0 , " Mismatch in axes " ) ;
}
if ( dump_pens ) {
SDL_Log ( " ----- Pen #%d: " , last_action - > pen_index ) ;
_pen_dump ( " expect " , simpen ) ;
_pen_dump ( " actual " , SDL_GetPenPtr ( simpen - > header . id ) ) ;
}
}
SDLTest_AssertPass ( " Pen and eraser move and report events correctly and independently " ) ;
/* Cleanup */
SDL_PenGCMark ( ) ;
_pen_trackGCSweep ( & ptest ) ;
_teardown_test ( & ptest , backup ) ;
return TEST_COMPLETED ;
}
static void
_expect_pen_config ( SDL_PenID penid ,
SDL_GUID expected_guid ,
SDL_bool expected_attached ,
char * expected_name ,
int expected_type ,
int expected_num_buttons ,
float expected_max_tilt ,
int expected_axes )
{
SDL_PenCapabilityInfo actual_info = { 0 } ;
const char * actual_name = SDL_GetPenName ( penid ) ;
if ( penid = = SDL_PEN_INVALID ) {
SDLTest_Assert ( 0 , " Invalid pen ID " ) ;
return ;
}
SDLTest_AssertEq1 ( int , " %d " , 0 , SDL_GUIDCompare ( expected_guid , SDL_GetPenGUID ( penid ) ) ,
" Pen %lu guid equality " , ( unsigned long ) penid ) ;
SDLTest_AssertCheck ( 0 = = SDL_strcmp ( expected_name , actual_name ) ,
" Expected name='%s' vs actual='%s' " , expected_name , actual_name ) ;
SDLTest_AssertEq1 ( int , " %d " , expected_attached , SDL_PenConnected ( penid ) ,
" Pen %lu is attached " , ( unsigned long ) penid ) ;
SDLTest_AssertEq1 ( int , " %d " , expected_type , SDL_GetPenType ( penid ) ,
" Pen %lu type " , ( unsigned long ) penid ) ;
SDLTest_AssertEq1 ( int , " %x " , expected_axes , SDL_GetPenCapabilities ( penid , & actual_info ) ,
" Pen %lu axis flags " , ( unsigned long ) penid ) ;
SDLTest_AssertEq1 ( int , " %d " , expected_num_buttons , actual_info . num_buttons ,
" Pen %lu number of buttons " , ( unsigned long ) penid ) ;
SDLTest_AssertEq1 ( float , " %f " , expected_max_tilt , actual_info . max_tilt ,
" Pen %lu max tilt " , ( unsigned long ) penid ) ;
}
/**
* @ brief Check backend pen iniitalisation and pen meta - information
*
* @ sa SDL_GetPenCapabilities , SDL_PenAxisInfo
*/
static int
pen_initAndInfo ( void * arg )
{
pen_testdata ptest ;
SDL_Pen * pen ;
Uint32 mask ;
char strbuf [ SDL_PEN_MAX_NAME ] ;
/* Init */
deviceinfo_backup * backup = _setup_test ( & ptest , 7 ) ;
/* Register default pen */
_expect_pens_attached_or_detached ( ptest . ids , 7 , 0 ) ;
/* Register completely default pen */
pen = SDL_PenModifyBegin ( ptest . ids [ 0 ] ) ;
SDL_memcpy ( pen - > guid . data , ptest . guids [ 0 ] . data , sizeof ( ptest . guids [ 0 ] . data ) ) ;
SDL_PenModifyEnd ( pen , SDL_TRUE ) ;
SDL_snprintf ( strbuf , sizeof ( strbuf ) ,
" Pen %lu " , ( unsigned long ) ptest . ids [ 0 ] ) ;
_expect_pen_config ( ptest . ids [ 0 ] , ptest . guids [ 0 ] , SDL_TRUE ,
strbuf , SDL_PEN_TYPE_PEN , SDL_PEN_INFO_UNKNOWN , 0.0f ,
SDL_PEN_INK_MASK ) ;
_expect_pens_attached_or_detached ( ptest . ids , 7 , ATTACHED ( 0 ) ) ;
SDLTest_AssertPass ( " Pass #1: default pen " ) ;
/* Register mostly-default pen with buttons and custom name */
pen = SDL_PenModifyBegin ( ptest . ids [ 1 ] ) ;
SDL_PenModifyAddCapabilities ( pen , SDL_PEN_AXIS_PRESSURE_MASK ) ;
SDL_memcpy ( pen - > guid . data , ptest . guids [ 1 ] . data , sizeof ( ptest . guids [ 1 ] . data ) ) ;
SDL_strlcpy ( strbuf , " My special test pen " , SDL_PEN_MAX_NAME ) ;
SDL_strlcpy ( pen - > name , strbuf , SDL_PEN_MAX_NAME ) ;
pen - > info . num_buttons = 7 ;
SDL_PenModifyEnd ( pen , SDL_TRUE ) ;
_expect_pen_config ( ptest . ids [ 1 ] , ptest . guids [ 1 ] , SDL_TRUE ,
strbuf , SDL_PEN_TYPE_PEN , 7 , 0.0f ,
SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) ;
_expect_pens_attached_or_detached ( ptest . ids , 7 , ATTACHED ( 0 ) | ATTACHED ( 1 ) ) ;
SDLTest_AssertPass ( " Pass #2: default pen with button and name info " ) ;
/* Register eraser with default name, but keep initially detached */
pen = SDL_PenModifyBegin ( ptest . ids [ 2 ] ) ;
SDL_memcpy ( pen - > guid . data , ptest . guids [ 2 ] . data , sizeof ( ptest . guids [ 2 ] . data ) ) ;
pen - > type = SDL_PEN_TYPE_ERASER ;
SDL_PenModifyAddCapabilities ( pen , SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK ) ;
SDL_PenModifyEnd ( pen , SDL_FALSE ) ;
SDL_snprintf ( strbuf , sizeof ( strbuf ) ,
" Eraser %lu " , ( unsigned long ) ptest . ids [ 2 ] ) ;
_expect_pen_config ( ptest . ids [ 2 ] , ptest . guids [ 2 ] , SDL_FALSE ,
strbuf , SDL_PEN_TYPE_ERASER , SDL_PEN_INFO_UNKNOWN , SDL_PEN_INFO_UNKNOWN ,
SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK ) ;
_expect_pens_attached_or_detached ( ptest . ids , 7 , ATTACHED ( 0 ) | ATTACHED ( 1 ) ) ;
/* now make available */
SDL_PenModifyEnd ( SDL_PenModifyBegin ( ptest . ids [ 2 ] ) , SDL_TRUE ) ;
_expect_pen_config ( ptest . ids [ 2 ] , ptest . guids [ 2 ] , SDL_TRUE ,
strbuf , SDL_PEN_TYPE_ERASER , SDL_PEN_INFO_UNKNOWN , SDL_PEN_INFO_UNKNOWN ,
SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK ) ;
_expect_pens_attached_or_detached ( ptest . ids , 7 , ATTACHED ( 0 ) | ATTACHED ( 1 ) | ATTACHED ( 2 ) ) ;
SDLTest_AssertPass ( " Pass #3: eraser-type pen initially detached, then attached " ) ;
/* Abort pen registration */
pen = SDL_PenModifyBegin ( ptest . ids [ 3 ] ) ;
SDL_memcpy ( pen - > guid . data , ptest . guids [ 3 ] . data , sizeof ( ptest . guids [ 3 ] . data ) ) ;
SDL_PenModifyAddCapabilities ( pen , SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK ) ;
pen - > type = SDL_PEN_TYPE_NONE ;
SDL_PenModifyEnd ( pen , SDL_TRUE ) ;
_expect_pens_attached_or_detached ( ptest . ids , 7 , ATTACHED ( 0 ) | ATTACHED ( 1 ) | ATTACHED ( 2 ) ) ;
SDLTest_AssertCheck ( NULL = = SDL_GetPenName ( ptest . ids [ 3 ] ) , " Pen with aborted registration remains unknown " ) ;
SDLTest_AssertPass ( " Pass #4: aborted pen registration " ) ;
/* Brush with custom axes */
pen = SDL_PenModifyBegin ( ptest . ids [ 4 ] ) ;
SDL_memcpy ( pen - > guid . data , ptest . guids [ 4 ] . data , sizeof ( ptest . guids [ 4 ] . data ) ) ;
SDL_strlcpy ( pen - > name , " Testish Brush " , SDL_PEN_MAX_NAME ) ;
pen - > type = SDL_PEN_TYPE_BRUSH ;
pen - > info . num_buttons = 1 ;
SDL_PenModifyAddCapabilities ( pen , SDL_PEN_AXIS_ROTATION_MASK ) ;
pen - > info . max_tilt = 72.5f ;
SDL_PenModifyAddCapabilities ( pen , SDL_PEN_AXIS_XTILT_MASK ) ;
SDL_PenModifyAddCapabilities ( pen , SDL_PEN_AXIS_PRESSURE_MASK ) ;
SDL_PenModifyEnd ( pen , SDL_TRUE ) ;
_expect_pen_config ( ptest . ids [ 4 ] , ptest . guids [ 4 ] , SDL_TRUE ,
" Testish Brush " , SDL_PEN_TYPE_BRUSH , 1 , 72.5f ,
SDL_PEN_INK_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_ROTATION_MASK | SDL_PEN_AXIS_PRESSURE_MASK ) ;
_expect_pens_attached_or_detached ( ptest . ids , 7 , ATTACHED ( 0 ) | ATTACHED ( 1 ) | ATTACHED ( 2 ) | ATTACHED ( 4 ) ) ;
SDLTest_AssertPass ( " Pass #5: brush-type pen with unusual axis layout " ) ;
/* Wacom airbrush pen */
{
const Uint32 wacom_type_id = 0x0912 ;
const Uint32 wacom_serial_id = 0xa0b1c2d3 ;
SDL_GUID guid = {
{ 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 }
} ;
guid . data [ 0 ] = ( wacom_serial_id > > 0 ) & 0xff ;
guid . data [ 1 ] = ( wacom_serial_id > > 8 ) & 0xff ;
guid . data [ 2 ] = ( wacom_serial_id > > 16 ) & 0xff ;
guid . data [ 3 ] = ( wacom_serial_id > > 24 ) & 0xff ;
guid . data [ 4 ] = ( wacom_type_id > > 0 ) & 0xff ;
guid . data [ 5 ] = ( wacom_type_id > > 8 ) & 0xff ;
guid . data [ 6 ] = ( wacom_type_id > > 16 ) & 0xff ;
guid . data [ 7 ] = ( wacom_type_id > > 24 ) & 0xff ;
pen = SDL_PenModifyBegin ( ptest . ids [ 5 ] ) ;
SDL_PenModifyForWacomID ( pen , wacom_type_id , & mask ) ;
SDL_PenUpdateGUIDForWacom ( & pen - > guid , wacom_type_id , wacom_serial_id ) ;
SDL_PenModifyAddCapabilities ( pen , mask ) ;
SDL_PenModifyEnd ( pen , SDL_TRUE ) ;
_expect_pen_config ( ptest . ids [ 5 ] , guid , SDL_TRUE ,
" Wacom Airbrush Pen " , SDL_PEN_TYPE_AIRBRUSH , 1 , 64.0f , /* Max tilt angle */
SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_SLIDER_MASK ) ;
_expect_pens_attached_or_detached ( ptest . ids , 7 , ATTACHED ( 0 ) | ATTACHED ( 1 ) | ATTACHED ( 2 ) | ATTACHED ( 4 ) | ATTACHED ( 5 ) ) ;
}
SDLTest_AssertPass ( " Pass #6: wacom airbrush pen " ) ;
/* Cleanup */
SDL_PenGCMark ( ) ;
_pen_trackGCSweep ( & ptest ) ;
_teardown_test ( & ptest , backup ) ;
return TEST_COMPLETED ;
}
# define SET_POS(update, xpos, ypos) \
( update ) . x = ( xpos ) ; \
( update ) . y = ( ypos ) ;
static void
_penmouse_expect_button ( int type , int button )
{
SDL_bool press = type = = SDL_PRESSED ;
SDLTest_AssertCheck ( ( press ? SDL_EVENT_MOUSE_BUTTON_DOWN : SDL_EVENT_MOUSE_BUTTON_UP ) = = _mouseemu_last_event ,
" Mouse button %s: %x " ,
( press ? " press " : " release " ) , _mouseemu_last_event ) ;
SDLTest_AssertCheck ( button = = _mouseemu_last_button ,
" Observed the expected simulated button: %d " , _mouseemu_last_button ) ;
SDLTest_AssertCheck ( SDL_PEN_MOUSEID = = _mouseemu_last_mouseid ,
" Observed the expected mouse ID: 0x%x " , _mouseemu_last_mouseid ) ;
_mouseemu_last_event = 0 ;
}
/**
* @ brief Check pen device mouse emulation and event suppression without SDL_HINT_PEN_DELAY_MOUSE_BUTTON
*
* Since we include SDL_pen . c , we link it against our own mock implementations of SDL_PSendMouseButton
* and SDL_SendMouseMotion ; see tehere for details .
*/
static int
pen_mouseEmulation ( void * arg )
{
pen_testdata ptest ;
SDL_Event event ;
int i ;
SDL_PenStatusInfo update ;
deviceinfo_backup * backup ;
pen_delay_mouse_button_mode = 0 ;
pen_mouse_emulation_mode = PEN_MOUSE_EMULATE ; /* to trigger our own SDL_SendMouseButton */
/* Register pen */
backup = _setup_test ( & ptest , 1 ) ;
SDL_PenGCMark ( ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 0 ] , ptest . guids [ 0 ] , " testpen " ,
SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT | SDL_PEN_AXIS_YTILT ) ,
20 ) ;
_pen_trackGCSweep ( & ptest ) ;
/* Move pen into window */
SDL_SendPenWindowEvent ( 0 , ptest . ids [ 0 ] , ptest . window ) ;
/* Initialise pen location */
SDL_memset ( update . axes , 0 , sizeof ( update . axes ) ) ;
SET_POS ( update , 100.0f , 100.0f ) ;
SDL_SendPenMotion ( 0 , ptest . ids [ 0 ] , SDL_TRUE , & update ) ;
while ( SDL_PollEvent ( & event ) )
; /* Flush event queue */
/* Test motion forwarding */
_mouseemu_last_event = 0 ;
SET_POS ( update , 121.25f , 110.75f ) ;
SDL_SendPenMotion ( 0 , ptest . ids [ 0 ] , SDL_TRUE , & update ) ;
SDLTest_AssertCheck ( SDL_EVENT_MOUSE_MOTION = = _mouseemu_last_event ,
" Mouse motion event: %d " , _mouseemu_last_event ) ;
SDLTest_AssertCheck ( 121.25f = = _mouseemu_last_x & & 110.75f = = _mouseemu_last_y ,
" Motion to correct position: %f,%f " , _mouseemu_last_x , _mouseemu_last_y ) ;
SDLTest_AssertCheck ( SDL_PEN_MOUSEID = = _mouseemu_last_mouseid ,
" Observed the expected mouse ID: 0x%x " , _mouseemu_last_mouseid ) ;
SDLTest_AssertCheck ( 0 = = _mouseemu_last_relative ,
" Absolute motion event " ) ;
SDLTest_AssertPass ( " Motion emulation " ) ;
/* Test redundant motion report suppression */
_mouseemu_last_event = 0 ;
SET_POS ( update , 121.25f , 110.75f ) ;
SDL_SendPenMotion ( 0 , ptest . ids [ 0 ] , SDL_TRUE , & update ) ;
SET_POS ( update , 121.25f , 110.75f ) ;
SDL_SendPenMotion ( 0 , ptest . ids [ 0 ] , SDL_TRUE , & update ) ;
update . axes [ 0 ] = 1.0f ;
SDL_SendPenMotion ( 0 , ptest . ids [ 0 ] , SDL_TRUE , & update ) ;
SET_POS ( update , 121.25f , 110.75f ) ;
update . axes [ 0 ] = 0.0f ;
update . axes [ 1 ] = 0.75f ;
SDL_SendPenMotion ( 0 , ptest . ids [ 0 ] , SDL_TRUE , & update ) ;
SDLTest_AssertCheck ( 0 = = _mouseemu_last_event ,
" Redundant mouse motion suppressed: %d " , _mouseemu_last_event ) ;
SDLTest_AssertPass ( " Redundant motion suppression " ) ;
/* Test button press reporting */
SDL_SendPenTipEvent ( 0 , ptest . ids [ 0 ] , SDL_PRESSED ) ;
_penmouse_expect_button ( SDL_PRESSED , 1 ) ;
for ( i = 1 ; i < = 3 ; + + i ) {
2024-02-03 12:23:16 -07:00
SDL_SendPenButton ( 0 , ptest . ids [ 0 ] , SDL_PRESSED , ( Uint8 ) i ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
_penmouse_expect_button ( SDL_PRESSED , i + 1 ) ;
}
SDLTest_AssertPass ( " Button press mouse emulation " ) ;
/* Test button release reporting */
SDL_SendPenTipEvent ( 0 , ptest . ids [ 0 ] , SDL_RELEASED ) ;
_penmouse_expect_button ( SDL_RELEASED , 1 ) ;
for ( i = 1 ; i < = 3 ; + + i ) {
2024-02-03 12:23:16 -07:00
SDL_SendPenButton ( 0 , ptest . ids [ 0 ] , SDL_RELEASED , ( Uint8 ) i ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
_penmouse_expect_button ( SDL_RELEASED , i + 1 ) ;
}
SDLTest_AssertPass ( " Button release mouse emulation " ) ;
/* Cleanup */
SDL_PenGCMark ( ) ;
_pen_trackGCSweep ( & ptest ) ;
_teardown_test ( & ptest , backup ) ;
return TEST_COMPLETED ;
}
/**
* @ brief Check pen device mouse emulation when SDL_HINT_PEN_DELAY_MOUSE_BUTTON is enabled ( default )
*/
static int
pen_mouseEmulationDelayed ( void * arg )
{
pen_testdata ptest ;
SDL_Event event ;
int i ;
SDL_PenStatusInfo update ;
deviceinfo_backup * backup ;
pen_delay_mouse_button_mode = 1 ;
pen_mouse_emulation_mode = PEN_MOUSE_EMULATE ; /* to trigger our own SDL_SendMouseButton */
/* Register pen */
backup = _setup_test ( & ptest , 1 ) ;
SDL_PenGCMark ( ) ;
_pen_setDeviceinfo ( _pen_register ( ptest . ids [ 0 ] , ptest . guids [ 0 ] , " testpen " ,
SDL_PEN_INK_MASK | SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT | SDL_PEN_AXIS_YTILT ) ,
20 ) ;
_pen_trackGCSweep ( & ptest ) ;
/* Move pen into window */
SDL_SendPenWindowEvent ( 0 , ptest . ids [ 0 ] , ptest . window ) ;
/* Initialise pen location */
SDL_memset ( update . axes , 0 , sizeof ( update . axes ) ) ;
SET_POS ( update , 100.0f , 100.0f ) ;
SDL_SendPenMotion ( 0 , ptest . ids [ 0 ] , SDL_TRUE , & update ) ;
while ( SDL_PollEvent ( & event ) )
; /* Flush event queue */
/* Test motion forwarding */
_mouseemu_last_event = 0 ;
SET_POS ( update , 121.25f , 110.75f ) ;
SDL_SendPenMotion ( 0 , ptest . ids [ 0 ] , SDL_TRUE , & update ) ;
SDLTest_AssertCheck ( SDL_EVENT_MOUSE_MOTION = = _mouseemu_last_event ,
" Mouse motion event: %d " , _mouseemu_last_event ) ;
SDLTest_AssertCheck ( 121.25f = = _mouseemu_last_x & & 110.75f = = _mouseemu_last_y ,
" Motion to correct position: %f,%f " , _mouseemu_last_x , _mouseemu_last_y ) ;
SDLTest_AssertCheck ( SDL_PEN_MOUSEID = = _mouseemu_last_mouseid ,
" Observed the expected mouse ID: 0x%x " , _mouseemu_last_mouseid ) ;
SDLTest_AssertCheck ( 0 = = _mouseemu_last_relative ,
" Absolute motion event " ) ;
SDLTest_AssertPass ( " Motion emulation " ) ;
_mouseemu_last_event = 0 ;
/* Test button press reporting */
for ( i = 1 ; i < = 2 ; + + i ) {
2024-02-03 12:23:16 -07:00
SDL_SendPenButton ( 0 , ptest . ids [ 0 ] , SDL_PRESSED , ( Uint8 ) i ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
SDLTest_AssertCheck ( 0 = = _mouseemu_last_event ,
" Non-touching button press suppressed: %d " , _mouseemu_last_event ) ;
2024-02-03 12:23:16 -07:00
SDL_SendPenButton ( 0 , ptest . ids [ 0 ] , SDL_RELEASED , ( Uint8 ) i ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
SDLTest_AssertCheck ( 0 = = _mouseemu_last_event ,
" Non-touching button release suppressed: %d " , _mouseemu_last_event ) ;
}
/* Touch surface */
SDL_SendPenTipEvent ( 0 , ptest . ids [ 0 ] , SDL_PRESSED ) ;
_penmouse_expect_button ( SDL_PRESSED , 1 ) ;
SDL_SendPenTipEvent ( 0 , ptest . ids [ 0 ] , SDL_RELEASED ) ;
_penmouse_expect_button ( SDL_RELEASED , 1 ) ;
/* Test button press reporting, releasing extra button AFTER lifting pen */
for ( i = 1 ; i < = 2 ; + + i ) {
2024-02-03 12:23:16 -07:00
SDL_SendPenButton ( 0 , ptest . ids [ 0 ] , SDL_PRESSED , ( Uint8 ) i ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
SDLTest_AssertCheck ( 0 = = _mouseemu_last_event ,
" Non-touching button press suppressed (A.1): %d " , _mouseemu_last_event ) ;
SDL_SendPenTipEvent ( 0 , ptest . ids [ 0 ] , SDL_PRESSED ) ;
_penmouse_expect_button ( SDL_PRESSED , i + 1 ) ;
SDL_SendPenTipEvent ( 0 , ptest . ids [ 0 ] , SDL_RELEASED ) ;
_penmouse_expect_button ( SDL_RELEASED , i + 1 ) ;
2024-02-03 12:23:16 -07:00
SDL_SendPenButton ( 0 , ptest . ids [ 0 ] , SDL_RELEASED , ( Uint8 ) i ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
SDLTest_AssertCheck ( 0 = = _mouseemu_last_event ,
" Non-touching button press suppressed (A.2): %d " , _mouseemu_last_event ) ;
}
SDLTest_AssertPass ( " Delayed button press mouse emulation, touching without releasing button " ) ;
/* Test button press reporting, releasing extra button BEFORE lifting pen */
for ( i = 1 ; i < = 2 ; + + i ) {
2024-02-03 12:23:16 -07:00
SDL_SendPenButton ( 0 , ptest . ids [ 0 ] , SDL_PRESSED , ( Uint8 ) i ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
SDLTest_AssertCheck ( 0 = = _mouseemu_last_event ,
" Non-touching button press suppressed (B.1): %d " , _mouseemu_last_event ) ;
SDL_SendPenTipEvent ( 0 , ptest . ids [ 0 ] , SDL_PRESSED ) ;
_penmouse_expect_button ( SDL_PRESSED , i + 1 ) ;
2024-02-03 12:23:16 -07:00
SDL_SendPenButton ( 0 , ptest . ids [ 0 ] , SDL_RELEASED , ( Uint8 ) i ) ;
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
SDLTest_AssertCheck ( 0 = = _mouseemu_last_event ,
" Non-touching button press suppressed (B.2): %d " , _mouseemu_last_event ) ;
SDL_SendPenTipEvent ( 0 , ptest . ids [ 0 ] , SDL_RELEASED ) ;
_penmouse_expect_button ( SDL_RELEASED , i + 1 ) ;
}
SDLTest_AssertPass ( " Delayed button press mouse emulation, touching and then releasing button " ) ;
/* Cleanup */
SDL_PenGCMark ( ) ;
_pen_trackGCSweep ( & ptest ) ;
_teardown_test ( & ptest , backup ) ;
return TEST_COMPLETED ;
}
/**
* @ brief Ensure that all SDL_Pen * Event structures have compatible memory layout , as expected by SDL_pen . c
*/
static int
pen_memoryLayout ( void * arg )
{
# define LAYOUT_COMPATIBLE(field) \
SDLTest_AssertCheck ( offsetof ( SDL_PenTipEvent , field ) = = offsetof ( SDL_PenMotionEvent , field ) , \
" Memory layout SDL_PenTipEvent and SDL_PenMotionEvent compatibility: ' " # field " ' " ) ; \
SDLTest_AssertCheck ( offsetof ( SDL_PenTipEvent , field ) = = offsetof ( SDL_PenButtonEvent , field ) , \
" Memory layout SDL_PenTipEvent and SDL_PenBUttonEvent compatibility: ' " # field " ' " ) ;
LAYOUT_COMPATIBLE ( which ) ;
LAYOUT_COMPATIBLE ( x ) ;
LAYOUT_COMPATIBLE ( y ) ;
LAYOUT_COMPATIBLE ( axes ) ;
return TEST_COMPLETED ;
}
2024-03-18 02:40:23 -06:00
/* ================= Test Setup and Teardown ================== */
static void
pen_test_setup ( void * arg ) {
SDL_PenInit ( ) ;
}
static void
pen_test_teardown ( void * arg ) {
SDL_PenQuit ( ) ;
}
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
/* ================= Test References ================== */
2024-03-18 02:40:23 -06:00
/* Pen test cases */
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
static const SDLTest_TestCaseReference penTest1 = { ( SDLTest_TestCaseFp ) pen_iteration , " pen_iteration " , " Iterate over all pens with SDL_PenIDForIndex " , TEST_ENABLED } ;
static const SDLTest_TestCaseReference penTest2 = { ( SDLTest_TestCaseFp ) pen_hotplugging , " pen_hotplugging " , " Hotplug pens and validate their status, including SDL_PenConnected " , TEST_ENABLED } ;
static const SDLTest_TestCaseReference penTest3 = { ( SDLTest_TestCaseFp ) pen_GUIDs , " pen_GUIDs " , " Check Pen SDL_GUID operations " , TEST_ENABLED } ;
static const SDLTest_TestCaseReference penTest4 = { ( SDLTest_TestCaseFp ) pen_buttonReporting , " pen_buttonReporting " , " Check pen button presses " , TEST_ENABLED } ;
static const SDLTest_TestCaseReference penTest5 = { ( SDLTest_TestCaseFp ) pen_movementAndAxes , " pen_movementAndAxes " , " Check pen movement and axis update reporting " , TEST_ENABLED } ;
static const SDLTest_TestCaseReference penTest6 = { ( SDLTest_TestCaseFp ) pen_initAndInfo , " pen_info " , " Check pen self-description and initialisation " , TEST_ENABLED } ;
static const SDLTest_TestCaseReference penTest7 = { ( SDLTest_TestCaseFp ) pen_mouseEmulation , " pen_mouseEmulation " , " Check pen-as-mouse event forwarding (direct) " , TEST_ENABLED } ;
static const SDLTest_TestCaseReference penTest8 = { ( SDLTest_TestCaseFp ) pen_mouseEmulationDelayed , " pen_mouseEmulationDelayed " , " Check pen-as-mouse event forwarding (delayed) " , TEST_ENABLED } ;
static const SDLTest_TestCaseReference penTest9 = { ( SDLTest_TestCaseFp ) pen_memoryLayout , " pen_memoryLayout " , " Check that all pen events have compatible layout (required by SDL_pen.c) " , TEST_ENABLED } ;
2024-03-18 02:40:23 -06:00
/* Sequence of Pen test cases */
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
static const SDLTest_TestCaseReference * penTests [ ] = {
& penTest1 , & penTest2 , & penTest3 , & penTest4 , & penTest5 , & penTest6 , & penTest7 , & penTest8 , & penTest9 , NULL
} ;
2024-03-18 02:40:23 -06:00
/* Pen test suite (global) */
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
SDLTest_TestSuiteReference penTestSuite = {
" Pen " ,
2024-03-18 02:40:23 -06:00
( SDLTest_TestCaseSetUpFp ) pen_test_setup ,
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
penTests ,
2024-03-18 02:40:23 -06:00
( SDLTest_TestCaseTearDownFp ) pen_test_teardown
API for pressure-sensitive pens + XInput2/Wayland
This patch adds an API for querying pressure-
sensitive pens, cf. SDL_pen.h:
- Enumerate all pens
- Get pen capabilities, names, GUIDs
- Distinguishes pens and erasers
- Distinguish attached and detached pens
- Pressure and tilt support
- Rotation, distance, throttle wheel support
(throttle wheel untested)
- Pen type and meta-information reporting
(partially tested)
Pen event reporting:
- Three new event structures: PenTip, PenMotion, and
PenButton
- Report location with sub-pixel precision
- Include axis and button status, is-eraser flag
Internal pen tracker, intended to be independent
of platform APIs, cf. SDL_pen_c.h:
- Track known pens
- Handle pen hotplugging
Automatic test:
- testautomation_pen.c
Other features:
- XInput2 implementation, incl. hotplugging
- Wayland implementation, incl. hotplugging
- Backward compatibility: pen events default to
emulating pens with mouse ID SDL_PEN_MOUSEID
- Can be toggled via SDL_HINT_PEN_NOT_MOUSE
- Test/demo program (testpen)
- Wacom pen feature identification by pen ID
Acknowledgements:
- Ping Cheng (Wacom) provided extensive feedback
on Wacom pen features and detection so that
hopefully untested Wacom devices have a
realistic chance of working out of the box.
2023-08-27 00:20:29 -06:00
} ;
2023-08-02 08:03:32 -06:00
# else
# include <SDL3/SDL_test.h>
# include "testautomation_suites.h"
/* Sequence of Mouse test cases */
static const SDLTest_TestCaseReference * penTests [ ] = {
NULL
} ;
/* Mouse test suite (global) */
SDLTest_TestSuiteReference penTestSuite = {
" Pen " ,
NULL ,
penTests ,
NULL
} ;
# endif