mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-22 23:36:20 +08:00
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.
This commit is contained in:
committed by
Sam Lantinga
parent
d3e43668d0
commit
7c80ac6df7
@@ -330,6 +330,7 @@
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_opengles2_gl2ext.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_opengles2_gl2platform.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_opengles2_khrplatform.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_pen.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_pixels.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_platform.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_platform_defines.h" />
|
||||
@@ -586,6 +587,7 @@
|
||||
<ClCompile Include="..\..\src\events\SDL_events.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_keyboard.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_mouse.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_pen.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_quit.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_touch.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_windowevents.c" />
|
||||
|
||||
@@ -300,6 +300,9 @@
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_opengles2_khrplatform.h">
|
||||
<Filter>API Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_pen.h">
|
||||
<Filter>API Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_pixels.h">
|
||||
<Filter>API Headers</Filter>
|
||||
</ClInclude>
|
||||
@@ -940,6 +943,9 @@
|
||||
<ClCompile Include="..\..\src\events\SDL_mouse.c">
|
||||
<Filter>events</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\events\SDL_pen.c">
|
||||
<Filter>events</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\events\SDL_quit.c">
|
||||
<Filter>events</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
<ClInclude Include="..\include\SDL3\SDL_mouse.h" />
|
||||
<ClInclude Include="..\include\SDL3\SDL_mutex.h" />
|
||||
<ClInclude Include="..\include\SDL3\SDL_opengles2.h" />
|
||||
<ClInclude Include="..\include\SDL3\SDL_pen.h" />
|
||||
<ClInclude Include="..\include\SDL3\SDL_pixels.h" />
|
||||
<ClInclude Include="..\include\SDL3\SDL_platform.h" />
|
||||
<ClInclude Include="..\include\SDL3\SDL_platform_defines.h" />
|
||||
@@ -306,6 +307,7 @@
|
||||
<ClCompile Include="..\src\events\SDL_events.c" />
|
||||
<ClCompile Include="..\src\events\SDL_keyboard.c" />
|
||||
<ClCompile Include="..\src\events\SDL_mouse.c" />
|
||||
<ClCompile Include="..\src\events\SDL_pen.c" />
|
||||
<ClCompile Include="..\src\events\SDL_quit.c" />
|
||||
<ClCompile Include="..\src\events\SDL_touch.c" />
|
||||
<ClCompile Include="..\src\events\SDL_windowevents.c" />
|
||||
|
||||
@@ -105,6 +105,9 @@
|
||||
<ClInclude Include="..\include\SDL3\SDL_opengles2.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\SDL3\SDL_pen.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\SDL3\SDL_pixels.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -552,6 +555,9 @@
|
||||
<ClCompile Include="..\src\events\SDL_mouse.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\events\SDL_pen.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\events\SDL_quit.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -280,6 +280,7 @@
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_opengles2_gl2ext.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_opengles2_gl2platform.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_opengles2_khrplatform.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_pen.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_pixels.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_platform.h" />
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_platform_defines.h" />
|
||||
@@ -507,6 +508,7 @@
|
||||
<ClCompile Include="..\..\src\events\SDL_events.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_keyboard.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_mouse.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_pen.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_quit.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_touch.c" />
|
||||
<ClCompile Include="..\..\src\events\SDL_windowevents.c" />
|
||||
|
||||
@@ -294,6 +294,9 @@
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_opengles2_khrplatform.h">
|
||||
<Filter>API Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_pen.h">
|
||||
<Filter>API Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_pixels.h">
|
||||
<Filter>API Headers</Filter>
|
||||
</ClInclude>
|
||||
@@ -921,6 +924,9 @@
|
||||
<ClCompile Include="..\..\src\events\SDL_mouse.c">
|
||||
<Filter>events</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\events\SDL_pen.c">
|
||||
<Filter>events</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\events\SDL_quit.c">
|
||||
<Filter>events</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -209,6 +209,12 @@
|
||||
<ClCompile Include="..\..\..\test\testautomation_main.c" />
|
||||
<ClCompile Include="..\..\..\test\testautomation_math.c" />
|
||||
<ClCompile Include="..\..\..\test\testautomation_mouse.c" />
|
||||
<ClCompile Include="..\..\..\test\testautomation_pen.c">
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\test\testautomation_pixels.c" />
|
||||
<ClCompile Include="..\..\..\test\testautomation_platform.c" />
|
||||
<ClCompile Include="..\..\..\test\testautomation_properties.c" />
|
||||
|
||||
@@ -43,6 +43,27 @@
|
||||
00D0D0D810675E46004B05EF /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007317C10858E15000B2BC32 /* Carbon.framework */; platformFilters = (macos, ); };
|
||||
557D0CFA254586CA003913E3 /* CoreHaptics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F37DC5F225350EBC0002E6F7 /* CoreHaptics.framework */; platformFilters = (ios, maccatalyst, macos, tvos, ); };
|
||||
557D0CFB254586D7003913E3 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A75FDABD23E28B6200529352 /* GameController.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
63125C002A790B12008EF011 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125BFF2A790B12008EF011 /* SDL_pen.h */; };
|
||||
63125C012A790B12008EF011 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125BFF2A790B12008EF011 /* SDL_pen.h */; };
|
||||
63125C022A790B12008EF011 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125BFF2A790B12008EF011 /* SDL_pen.h */; };
|
||||
63125C0A2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; };
|
||||
63125C0B2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; };
|
||||
63125C0C2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; };
|
||||
63125C0D2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; };
|
||||
63125C0E2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; };
|
||||
63125C0F2A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; };
|
||||
63125C102A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; };
|
||||
63125C112A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; };
|
||||
63125C122A790B69008EF011 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63125C092A790B69008EF011 /* SDL_pen.c */; };
|
||||
63125C142A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; };
|
||||
63125C152A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; };
|
||||
63125C162A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; };
|
||||
63125C172A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; };
|
||||
63125C182A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; };
|
||||
63125C192A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; };
|
||||
63125C1A2A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; };
|
||||
63125C1B2A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; };
|
||||
63125C1C2A790B9A008EF011 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63125C132A790B9A008EF011 /* SDL_pen_c.h */; };
|
||||
5616CA4C252BB2A6005D5928 /* SDL_url.c in Sources */ = {isa = PBXBuildFile; fileRef = 5616CA49252BB2A5005D5928 /* SDL_url.c */; };
|
||||
5616CA4D252BB2A6005D5928 /* SDL_sysurl.h in Headers */ = {isa = PBXBuildFile; fileRef = 5616CA4A252BB2A6005D5928 /* SDL_sysurl.h */; };
|
||||
5616CA4E252BB2A6005D5928 /* SDL_sysurl.m in Sources */ = {isa = PBXBuildFile; fileRef = 5616CA4B252BB2A6005D5928 /* SDL_sysurl.m */; };
|
||||
@@ -52,6 +73,9 @@
|
||||
566E26D8246274CC00718109 /* SDL_locale.c in Sources */ = {isa = PBXBuildFile; fileRef = 566E26CD246274CB00718109 /* SDL_locale.c */; };
|
||||
566E26E1246274CC00718109 /* SDL_syslocale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26CE246274CC00718109 /* SDL_syslocale.h */; };
|
||||
56A2373329F9C113003CCA5F /* SDL_sysrwlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 56A2373229F9C113003CCA5F /* SDL_sysrwlock.c */; };
|
||||
63134A222A7902CF0021E9A6 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63134A212A7902CF0021E9A6 /* SDL_pen.h */; };
|
||||
63134A252A7902FD0021E9A6 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63134A232A7902FD0021E9A6 /* SDL_pen_c.h */; };
|
||||
63134A262A7902FD0021E9A6 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63134A242A7902FD0021E9A6 /* SDL_pen.c */; };
|
||||
75E0915A241EA924004729E1 /* SDL_virtualjoystick.c in Sources */ = {isa = PBXBuildFile; fileRef = 75E09158241EA924004729E1 /* SDL_virtualjoystick.c */; };
|
||||
75E09163241EA924004729E1 /* SDL_virtualjoystick_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 75E09159241EA924004729E1 /* SDL_virtualjoystick_c.h */; };
|
||||
9846B07C287A9020000C35C8 /* SDL_hidapi_shield.c in Sources */ = {isa = PBXBuildFile; fileRef = 9846B07B287A9020000C35C8 /* SDL_hidapi_shield.c */; };
|
||||
@@ -534,6 +558,9 @@
|
||||
566E26CD246274CB00718109 /* SDL_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_locale.c; path = locale/SDL_locale.c; sourceTree = "<group>"; };
|
||||
566E26CE246274CC00718109 /* SDL_syslocale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_syslocale.h; path = locale/SDL_syslocale.h; sourceTree = "<group>"; };
|
||||
56A2373229F9C113003CCA5F /* SDL_sysrwlock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_sysrwlock.c; sourceTree = "<group>"; };
|
||||
63134A212A7902CF0021E9A6 /* SDL_pen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_pen.h; path = SDL3/SDL_pen.h; sourceTree = "<group>"; };
|
||||
63134A232A7902FD0021E9A6 /* SDL_pen_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_pen_c.h; sourceTree = "<group>"; };
|
||||
63134A242A7902FD0021E9A6 /* SDL_pen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_pen.c; sourceTree = "<group>"; };
|
||||
75E09158241EA924004729E1 /* SDL_virtualjoystick.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_virtualjoystick.c; sourceTree = "<group>"; };
|
||||
75E09159241EA924004729E1 /* SDL_virtualjoystick_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_virtualjoystick_c.h; sourceTree = "<group>"; };
|
||||
9846B07B287A9020000C35C8 /* SDL_hidapi_shield.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_shield.c; sourceTree = "<group>"; };
|
||||
@@ -1093,6 +1120,7 @@
|
||||
F3F7D8C92933074B00816151 /* SDL_opengles2_gl2platform.h */,
|
||||
F3F7D8B12933074900816151 /* SDL_opengles2_khrplatform.h */,
|
||||
F3F7D8C72933074B00816151 /* SDL_opengles2.h */,
|
||||
63134A212A7902CF0021E9A6 /* SDL_pen.h */,
|
||||
F3F7D8B52933074A00816151 /* SDL_pixels.h */,
|
||||
F3B38CCB296E2E52005DA6D3 /* SDL_platform_defines.h */,
|
||||
F3F7D8AB2933074900816151 /* SDL_platform.h */,
|
||||
@@ -2059,6 +2087,8 @@
|
||||
A7D8A93823E2514000DCD162 /* SDL_keyboard.c */,
|
||||
A7D8A92B23E2514000DCD162 /* SDL_mouse_c.h */,
|
||||
A7D8A92A23E2514000DCD162 /* SDL_mouse.c */,
|
||||
63134A232A7902FD0021E9A6 /* SDL_pen_c.h */,
|
||||
63134A242A7902FD0021E9A6 /* SDL_pen.c */,
|
||||
A7D8A93C23E2514000DCD162 /* SDL_quit.c */,
|
||||
A7D8A93723E2514000DCD162 /* SDL_touch_c.h */,
|
||||
A7D8A93E23E2514000DCD162 /* SDL_touch.c */,
|
||||
@@ -2365,6 +2395,8 @@
|
||||
A7D8B3D423E2514300DCD162 /* yuv_rgb.h in Headers */,
|
||||
A7D8B3C823E2514200DCD162 /* yuv_rgb_sse_func.h in Headers */,
|
||||
A7D8B3CE23E2514300DCD162 /* yuv_rgb_std_func.h in Headers */,
|
||||
63134A222A7902CF0021E9A6 /* SDL_pen.h in Headers */,
|
||||
63134A252A7902FD0021E9A6 /* SDL_pen_c.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2685,6 +2717,7 @@
|
||||
A7D8AEA023E2514100DCD162 /* SDL_cocoavulkan.m in Sources */,
|
||||
A7D8AB6123E2514100DCD162 /* SDL_offscreenwindow.c in Sources */,
|
||||
566E26D8246274CC00718109 /* SDL_locale.c in Sources */,
|
||||
63134A262A7902FD0021E9A6 /* SDL_pen.c in Sources */,
|
||||
000040E76FDC6AE48CBF0000 /* SDL_hashtable.c in Sources */,
|
||||
0000A4DA2F45A31DC4F00000 /* SDL_sysmain_callbacks.m in Sources */,
|
||||
000028F8113A53F4333E0000 /* SDL_main_callbacks.c in Sources */,
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <SDL3/SDL_joystick.h>
|
||||
#include <SDL3/SDL_keyboard.h>
|
||||
#include <SDL3/SDL_mouse.h>
|
||||
#include <SDL3/SDL_pen.h>
|
||||
#include <SDL3/SDL_quit.h>
|
||||
#include <SDL3/SDL_stdinc.h>
|
||||
#include <SDL3/SDL_touch.h>
|
||||
@@ -113,6 +114,8 @@ typedef enum
|
||||
SDL_EVENT_WINDOW_RESTORED, /**< Window has been restored to normal size and position */
|
||||
SDL_EVENT_WINDOW_MOUSE_ENTER, /**< Window has gained mouse focus */
|
||||
SDL_EVENT_WINDOW_MOUSE_LEAVE, /**< Window has lost mouse focus */
|
||||
SDL_EVENT_WINDOW_PEN_ENTER, /**< Window has gained focus of the pressure-sensitive pen with ID "data1" */
|
||||
SDL_EVENT_WINDOW_PEN_LEAVE, /**< Window has lost focus of the pressure-sensitive pen with ID "data1" */
|
||||
SDL_EVENT_WINDOW_FOCUS_GAINED, /**< Window has gained keyboard focus */
|
||||
SDL_EVENT_WINDOW_FOCUS_LOST, /**< Window has lost keyboard focus */
|
||||
SDL_EVENT_WINDOW_CLOSE_REQUESTED, /**< The window manager requests that the window be closed */
|
||||
@@ -191,6 +194,13 @@ typedef enum
|
||||
/* Sensor events */
|
||||
SDL_EVENT_SENSOR_UPDATE = 0x1200, /**< A sensor was updated */
|
||||
|
||||
/* Pressure-sensitive pen events */
|
||||
SDL_EVENT_PEN_DOWN = 0x1300, /**< Pressure-sensitive pen touched drawing surface */
|
||||
SDL_EVENT_PEN_UP, /**< Pressure-sensitive pen stopped touching drawing surface */
|
||||
SDL_EVENT_PEN_MOTION, /**< Pressure-sensitive pen moved, or angle/pressure changed */
|
||||
SDL_EVENT_PEN_BUTTON_DOWN, /**< Pressure-sensitive pen button pressed */
|
||||
SDL_EVENT_PEN_BUTTON_UP, /**< Pressure-sensitive pen button released */
|
||||
|
||||
/* Render events */
|
||||
SDL_EVENT_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */
|
||||
SDL_EVENT_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */
|
||||
@@ -296,7 +306,7 @@ typedef struct SDL_MouseMotionEvent
|
||||
Uint32 type; /**< ::SDL_EVENT_MOUSE_MOTION */
|
||||
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
|
||||
SDL_WindowID windowID; /**< The window with mouse focus, if any */
|
||||
SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
|
||||
SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */
|
||||
Uint32 state; /**< The current button state */
|
||||
float x; /**< X coordinate, relative to window */
|
||||
float y; /**< Y coordinate, relative to window */
|
||||
@@ -312,7 +322,7 @@ typedef struct SDL_MouseButtonEvent
|
||||
Uint32 type; /**< ::SDL_EVENT_MOUSE_BUTTON_DOWN or ::SDL_EVENT_MOUSE_BUTTON_UP */
|
||||
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
|
||||
SDL_WindowID windowID; /**< The window with mouse focus, if any */
|
||||
SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
|
||||
SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */
|
||||
Uint8 button; /**< The mouse button index */
|
||||
Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
|
||||
Uint8 clicks; /**< 1 for single-click, 2 for double-click, etc. */
|
||||
@@ -329,7 +339,7 @@ typedef struct SDL_MouseWheelEvent
|
||||
Uint32 type; /**< ::SDL_EVENT_MOUSE_WHEEL */
|
||||
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
|
||||
SDL_WindowID windowID; /**< The window with mouse focus, if any */
|
||||
SDL_MouseID which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
|
||||
SDL_MouseID which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */
|
||||
float x; /**< The amount scrolled horizontally, positive to the right and negative to the left */
|
||||
float y; /**< The amount scrolled vertically, positive away from the user and negative toward the user */
|
||||
Uint32 direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
|
||||
@@ -512,6 +522,63 @@ typedef struct SDL_TouchFingerEvent
|
||||
|
||||
|
||||
#define SDL_DROPEVENT_DATA_SIZE 64
|
||||
/**
|
||||
* Pressure-sensitive pen touched or stopped touching surface (event.ptip.*)
|
||||
*/
|
||||
typedef struct SDL_PenTipEvent
|
||||
{
|
||||
Uint32 type; /**< ::SDL_EVENT_PEN_DOWN or ::SDL_EVENT_PEN_UP */
|
||||
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
|
||||
Uint32 windowID; /**< The window with pen focus, if any */
|
||||
SDL_PenID which; /**< The pen instance id */
|
||||
Uint8 tip; /**< ::SDL_PEN_TIP_INK when using a regular pen tip, or ::SDL_PEN_TIP_ERASER if the pen is being used as an eraser (e.g., flipped to use the eraser tip) */
|
||||
Uint8 state; /**< ::SDL_PRESSED on ::SDL_EVENT_PEN_DOWN and ::SDL_RELEASED on ::SDL_EVENT_PEN_UP */
|
||||
Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.),
|
||||
::SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and
|
||||
::SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */
|
||||
float x; /**< X coordinate, relative to window */
|
||||
float y; /**< Y coordinate, relative to window */
|
||||
float axes[SDL_PEN_NUM_AXES]; /**< Pen axes such as pressure and tilt (ordered as per ::SDL_PenAxis) */
|
||||
} SDL_PenTipEvent;
|
||||
|
||||
/**
|
||||
* Pressure-sensitive pen motion / pressure / angle event structure (event.pmotion.*)
|
||||
*/
|
||||
typedef struct SDL_PenMotionEvent
|
||||
{
|
||||
Uint32 type; /**< ::SDL_EVENT_PEN_MOTION */
|
||||
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
|
||||
Uint32 windowID; /**< The window with pen focus, if any */
|
||||
SDL_PenID which; /**< The pen instance id */
|
||||
Uint8 padding1;
|
||||
Uint8 padding2;
|
||||
Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.),
|
||||
::SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and
|
||||
::SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */
|
||||
float x; /**< X coordinate, relative to window */
|
||||
float y; /**< Y coordinate, relative to window */
|
||||
float axes[SDL_PEN_NUM_AXES]; /**< Pen axes such as pressure and tilt (ordered as per ::SDL_PenAxis) */
|
||||
} SDL_PenMotionEvent;
|
||||
|
||||
/**
|
||||
* Pressure-sensitive pen button event structure (event.pbutton.*)
|
||||
*/
|
||||
typedef struct SDL_PenButtonEvent
|
||||
{
|
||||
Uint32 type; /**< ::SDL_EVENT_PEN_BUTTON_DOWN or ::SDL_EVENT_PEN_BUTTON_UP */
|
||||
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
|
||||
Uint32 windowID; /**< The window with pen focus, if any */
|
||||
SDL_PenID which; /**< The pen instance id */
|
||||
Uint8 button; /**< The pen button index (1 represents the pen tip for compatibility with mouse events) */
|
||||
Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
|
||||
Uint16 pen_state; /**< Pen button masks (where SDL_BUTTON(1) is the first button, SDL_BUTTON(2) is the second button etc.),
|
||||
::SDL_PEN_DOWN_MASK is set if the pen is touching the surface, and
|
||||
::SDL_PEN_ERASER_MASK is set if the pen is (used as) an eraser. */
|
||||
float x; /**< X coordinate, relative to window */
|
||||
float y; /**< Y coordinate, relative to window */
|
||||
float axes[SDL_PEN_NUM_AXES]; /**< Pen axes such as pressure and tilt (ordered as per ::SDL_PenAxis) */
|
||||
} SDL_PenButtonEvent;
|
||||
|
||||
/**
|
||||
* An event used to drop text or request a file open by the system (event.drop.*)
|
||||
*
|
||||
@@ -603,6 +670,9 @@ typedef union SDL_Event
|
||||
SDL_QuitEvent quit; /**< Quit request event data */
|
||||
SDL_UserEvent user; /**< Custom event data */
|
||||
SDL_TouchFingerEvent tfinger; /**< Touch finger event data */
|
||||
SDL_PenTipEvent ptip; /**< Pen tip touching or leaving drawing surface */
|
||||
SDL_PenMotionEvent pmotion; /**< Pen change in position, pressure, or angle */
|
||||
SDL_PenButtonEvent pbutton; /**< Pen button press */
|
||||
SDL_DropEvent drop; /**< Drag and drop event data */
|
||||
SDL_ClipboardEvent clipboard; /**< Clipboard event data */
|
||||
|
||||
|
||||
@@ -1220,6 +1220,40 @@ extern "C" {
|
||||
*/
|
||||
#define SDL_HINT_MOUSE_AUTO_CAPTURE "SDL_MOUSE_AUTO_CAPTURE"
|
||||
|
||||
/**
|
||||
* Treat pen movement as separate from mouse movement
|
||||
*
|
||||
* By default, pens report both ::SDL_MouseMotionEvent and ::SDL_PenMotionEvent updates
|
||||
* (analogously for button presses). This hint allows decoupling mouse and pen updates.
|
||||
*
|
||||
* This variable toggles between the following behaviour:
|
||||
* "0" - (Default) Pen acts as a mouse with mouse ID ::SDL_PEN_MOUSEID.
|
||||
* Use case: client application is not pen aware, user wants to
|
||||
* use pen instead of mouse to interact.
|
||||
* "1" - Pen reports mouse clicks and movement events but does not update
|
||||
* SDL-internal mouse state (buttons pressed, current mouse location).
|
||||
* Use case: client application is not pen aware, user frequently
|
||||
* alternates between pen and "real" mouse.
|
||||
* "2" - Pen reports no mouse events.
|
||||
* Use case: pen-aware client application uses this hint to allow user to
|
||||
* toggle between pen+mouse mode ("2") and pen-only mode ("1" or "0").
|
||||
*/
|
||||
#define SDL_HINT_PEN_NOT_MOUSE "SDL_HINT_PEN_NOT_MOUSE"
|
||||
|
||||
/**
|
||||
* Pen mouse button emulation triggers only when the pen touches the tablet surface
|
||||
*
|
||||
* "0" - The pen reports mouse button press/release immediately when the pen
|
||||
* button is pressed/released, and the pen tip touching the surface counts
|
||||
* as left mouse button press.
|
||||
* "1" - (Default) Mouse button presses are sent when the pen first touches
|
||||
* the tablet (analogously for releases). Not pressing a pen button
|
||||
* simulates mouse button 1, pressing the first pen button simulates
|
||||
* mouse button 2 etc.; it is not possible to report multiple buttons
|
||||
* as pressed at the same time.
|
||||
*/
|
||||
#define SDL_HINT_PEN_DELAY_MOUSE_BUTTON "SDL_HINT_PEN_DELAY_MOUSE_BUTTON"
|
||||
|
||||
/**
|
||||
* Tell SDL not to catch the SIGINT or SIGTERM signals.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file SDL_pen.h
|
||||
*
|
||||
* Include file for SDL pen event handling.
|
||||
*
|
||||
* This file describes operations for pressure-sensitive pen (stylus and/or eraser) handling, e.g., for input
|
||||
* and drawing tablets or suitably equipped mobile / tablet devices.
|
||||
*
|
||||
* To get started with pens:
|
||||
* - Listen to ::SDL_PenMotionEvent and ::SDL_PenButtonEvent
|
||||
* - To avoid treating pen events as mouse events, ignore ::SDL_MouseMotionEvent and ::SDL_MouseButtonEvent
|
||||
* whenever "which" == ::SDL_PEN_MOUSEID.
|
||||
*
|
||||
* This header file describes advanced functionality that can be useful for managing user configuration
|
||||
* and understanding the capabilities of the attached pens.
|
||||
*
|
||||
* We primarily identify pens by ::SDL_PenID. The implementation makes a best effort to relate each :SDL_PenID
|
||||
* to the same physical device during a session. Formerly valid ::SDL_PenID values remain valid
|
||||
* even if a device disappears.
|
||||
*
|
||||
* For identifying pens across sessions, the API provides the type ::SDL_GUID .
|
||||
*/
|
||||
|
||||
#ifndef SDL_pen_h_
|
||||
#define SDL_pen_h_
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_guid.h"
|
||||
#include "SDL_stdinc.h"
|
||||
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef Uint32 SDL_PenID; /**< SDL_PenIDs identify pens uniquely within a session */
|
||||
|
||||
#define SDL_PEN_INVALID ((Uint32)0) /**< Reserved invalid ::SDL_PenID is valid */
|
||||
|
||||
#define SDL_PEN_MOUSEID ((Uint32)-2) /**< Device ID for mouse events triggered by pen events */
|
||||
|
||||
#define SDL_PEN_INFO_UNKNOWN (-1) /**< Marks unknown information when querying the pen */
|
||||
|
||||
/**
|
||||
* Pen axis indices
|
||||
*
|
||||
* Below are the valid indices to the "axis" array from ::SDL_PenMotionEvent and ::SDL_PenButtonEvent.
|
||||
* The axis indices form a contiguous range of ints from 0 to ::SDL_PEN_AXIS_LAST, inclusive.
|
||||
* All "axis[]" entries are either normalised to 0..1 or report a (positive or negative)
|
||||
* angle in degrees, with 0.0 representing the centre.
|
||||
* Not all pens/backends support all axes: unsupported entries are always "0.0f".
|
||||
*
|
||||
* To convert angles for tilt and rotation into vector representation, use
|
||||
* \link SDL_sinf \endlink on the XTILT, YTILT, or ROTATION component, e.g., "SDL_sinf(xtilt * SDL_PI_F / 180.0)".
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SDL_PEN_AXIS_PRESSURE = 0, /**< Pen pressure. Unidirectional: 0..1.0 */
|
||||
SDL_PEN_AXIS_XTILT, /**< Pen horizontal tilt angle. Bidirectional: -90.0..90.0 (left-to-right).
|
||||
The physical max/min tilt may be smaller than -90.0 / 90.0, cf. \link SDL_PenCapabilityInfo \endlink */
|
||||
SDL_PEN_AXIS_YTILT, /**< Pen vertical tilt angle. Bidirectional: -90.0..90.0 (top-to-down).
|
||||
The physical max/min tilt may be smaller than -90.0 / 90.0, cf. \link SDL_PenCapabilityInfo \endlink */
|
||||
SDL_PEN_AXIS_DISTANCE, /**< Pen distance to drawing surface. Unidirectional: 0.0..1.0 */
|
||||
SDL_PEN_AXIS_ROTATION, /**< Pen barrel rotation. Bidirectional: -180..179.9 (clockwise, 0 is facing up, -180.0 is facing down). */
|
||||
SDL_PEN_AXIS_SLIDER, /**< Pen finger wheel or slider (e.g., Airbrush Pen). Unidirectional: 0..1.0 */
|
||||
SDL_PEN_NUM_AXES, /**< Last valid axis index */
|
||||
SDL_PEN_AXIS_LAST = SDL_PEN_NUM_AXES - 1 /**< Last axis index plus 1 */
|
||||
} SDL_PenAxis;
|
||||
|
||||
/* Pen flags. These share a bitmask space with ::SDL_BUTTON_LEFT and friends. */
|
||||
#define SDL_PEN_FLAG_DOWN_BIT_INDEX 13 /* Bit for storing that pen is touching the surface */
|
||||
#define SDL_PEN_FLAG_INK_BIT_INDEX 14 /* Bit for storing has-non-eraser-capability status */
|
||||
#define SDL_PEN_FLAG_ERASER_BIT_INDEX 15 /* Bit for storing is-eraser or has-eraser-capability property */
|
||||
#define SDL_PEN_FLAG_AXIS_BIT_OFFSET 16 /* Bit for storing has-axis-0 property */
|
||||
|
||||
#define SDL_PEN_CAPABILITY(capbit) (1ul << (capbit))
|
||||
#define SDL_PEN_AXIS_CAPABILITY(axis) SDL_PEN_CAPABILITY((axis) + SDL_PEN_FLAG_AXIS_BIT_OFFSET)
|
||||
|
||||
/**
|
||||
* Pen tips
|
||||
* @{
|
||||
*/
|
||||
#define SDL_PEN_TIP_INK SDL_PEN_FLAG_INK_BIT_INDEX /**< Regular pen tip (for drawing) touched the surface */
|
||||
#define SDL_PEN_TIP_ERASER SDL_PEN_FLAG_ERASER_BIT_INDEX /**< Eraser pen tip touched the surface */
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* \defgroup SDL_PEN_CAPABILITIES Pen capabilities
|
||||
* Pen capabilities reported by ::SDL_GetPenCapabilities
|
||||
* @{
|
||||
*/
|
||||
#define SDL_PEN_DOWN_MASK SDL_PEN_CAPABILITY(SDL_PEN_FLAG_DOWN_BIT_INDEX) /**< Pen tip is currently touching the drawing surface. */
|
||||
#define SDL_PEN_INK_MASK SDL_PEN_CAPABILITY(SDL_PEN_FLAG_INK_BIT_INDEX) /**< Pen has a regular drawing tip (::SDL_GetPenCapabilities). For events (::SDL_PenButtonEvent, ::SDL_PenMotionEvent, ::SDL_GetPenStatus) this flag is mutually exclusive with ::SDL_PEN_ERASER_MASK . */
|
||||
#define SDL_PEN_ERASER_MASK SDL_PEN_CAPABILITY(SDL_PEN_FLAG_ERASER_BIT_INDEX) /**< Pen has an eraser tip (::SDL_GetPenCapabilities) or is being used as eraser (::SDL_PenButtonEvent , ::SDL_PenMotionEvent , ::SDL_GetPenStatus) */
|
||||
#define SDL_PEN_AXIS_PRESSURE_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_PRESSURE) /**< Pen provides pressure information in axis ::SDL_PEN_AXIS_PRESSURE */
|
||||
#define SDL_PEN_AXIS_XTILT_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_XTILT) /**< Pen provides horizontal tilt information in axis ::SDL_PEN_AXIS_XTILT */
|
||||
#define SDL_PEN_AXIS_YTILT_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_YTILT) /**< Pen provides vertical tilt information in axis ::SDL_PEN_AXIS_YTILT */
|
||||
#define SDL_PEN_AXIS_DISTANCE_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_DISTANCE) /**< Pen provides distance to drawing tablet in ::SDL_PEN_AXIS_DISTANCE */
|
||||
#define SDL_PEN_AXIS_ROTATION_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_ROTATION) /**< Pen provides barrel rotation information in axis ::SDL_PEN_AXIS_ROTATION */
|
||||
#define SDL_PEN_AXIS_SLIDER_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_SLIDER) /**< Pen provides slider / finger wheel or similar in axis ::SDL_PEN_AXIS_SLIDER */
|
||||
|
||||
#define SDL_PEN_AXIS_BIDIRECTIONAL_MASKS (SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK)
|
||||
/**< Masks for all axes that may be bidirectional */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Pen types
|
||||
*
|
||||
* Some pens identify as a particular type of drawing device (e.g., an airbrush or a pencil).
|
||||
*
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SDL_PEN_TYPE_ERASER = 1, /**< Eraser */
|
||||
SDL_PEN_TYPE_PEN, /**< Generic pen; this is the default. */
|
||||
SDL_PEN_TYPE_PENCIL, /**< Pencil */
|
||||
SDL_PEN_TYPE_BRUSH, /**< Brush-like device */
|
||||
SDL_PEN_TYPE_AIRBRUSH, /**< Airbrush device that "sprays" ink */
|
||||
SDL_PEN_TYPE_LAST = SDL_PEN_TYPE_AIRBRUSH /**< Last valid pen type */
|
||||
} SDL_PenSubtype;
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
/**
|
||||
* Retrieves all pens that are connected to the system.
|
||||
*
|
||||
* Yields an array of ::SDL_PenID values. These identify and track pens throughout a session.
|
||||
* To track pens across sessions (program restart), use ::SDL_GUID .
|
||||
*
|
||||
* \param[out] count The number of pens in the array (number of array elements minus 1, i.e., not
|
||||
* counting the terminator 0).
|
||||
*
|
||||
* \returns A 0 terminated array of ::SDL_PenID values, or NULL on error.
|
||||
* The array must be freed with ::SDL_free().
|
||||
* On a NULL return, ::SDL_GetError() is set.
|
||||
*
|
||||
* \since This function is available since SDL 3.TBD
|
||||
*/
|
||||
extern DECLSPEC SDL_PenID *SDLCALL SDL_GetPens(int *count);
|
||||
|
||||
/**
|
||||
* Retrieves the pen's current status.
|
||||
*
|
||||
* If the pen is detached (cf. ::SDL_PenConnected), this operation may return
|
||||
* default values.
|
||||
*
|
||||
* \param instance_id The pen to query.
|
||||
* \param[out] x Out-mode parameter for pen x coordinate. May be NULL.
|
||||
* \param[out] y Out-mode parameter for pen y coordinate. May be NULL.
|
||||
* \param[out] axes Out-mode parameter for axis information. May be null. The axes are in the same order as for
|
||||
* ::SDL_PenAxis .
|
||||
* \param num_axes Maximum number of axes to write to "axes".
|
||||
*
|
||||
* \returns a bit mask with the current pen button states (::SDL_BUTTON_LMASK etc.),
|
||||
* possibly ::SDL_PEN_DOWN_MASK, and exactly one of
|
||||
* ::SDL_PEN_INK_MASK or ::SDL_PEN_ERASER_MASK , or 0 on error (see ::SDL_GetError()).
|
||||
*
|
||||
* \since This function is available since SDL 3.TBD
|
||||
*/
|
||||
extern DECLSPEC Uint32 SDLCALL SDL_GetPenStatus(SDL_PenID instance_id, float *x, float *y, float *axes, size_t num_axes);
|
||||
|
||||
/**
|
||||
* Retrieves an ::SDL_PenID for the given ::SDL_GUID.
|
||||
*
|
||||
* \param guid A pen GUID.
|
||||
*
|
||||
* \returns A valid ::SDL_PenID, or ::SDL_PEN_INVALID if there is no matching SDL_PenID.
|
||||
*
|
||||
* \since This function is available since SDL 3.TBD
|
||||
*
|
||||
* \sa SDL_GUID()
|
||||
*/
|
||||
extern DECLSPEC SDL_PenID SDLCALL SDL_GetPenFromGUID(SDL_GUID guid);
|
||||
|
||||
/**
|
||||
* Retrieves the ::SDL_GUID for a given ::SDL_PenID.
|
||||
*
|
||||
* \param instance_id The pen to query.
|
||||
*
|
||||
* \returns The corresponding pen GUID; persistent across multiple sessions.
|
||||
* If "instance_id" is ::SDL_PEN_INVALID, returns an all-zeroes GUID.
|
||||
*
|
||||
* \since This function is available since SDL 3.TBD
|
||||
*
|
||||
* \sa SDL_PenForID()
|
||||
*/
|
||||
extern DECLSPEC SDL_GUID SDLCALL SDL_GetPenGUID(SDL_PenID instance_id);
|
||||
|
||||
/**
|
||||
* Checks whether a pen is still attached.
|
||||
*
|
||||
* If a pen is detached, it will not show up for ::SDL_GetPens().
|
||||
* Other operations will still be available but may return default values.
|
||||
*
|
||||
* \param instance_id A pen ID.
|
||||
* \returns SDL_TRUE if "instance_id" is valid and the corresponding pen is attached, or
|
||||
* SDL_FALSE otherwise.
|
||||
*
|
||||
* \since This function is available since SDL 3.TBD
|
||||
*/
|
||||
extern DECLSPEC SDL_bool SDLCALL SDL_PenConnected(SDL_PenID instance_id);
|
||||
|
||||
/**
|
||||
* Retrieves a human-readable description for a ::SDL_PenID.
|
||||
*
|
||||
* \param instance_id The pen to query.
|
||||
*
|
||||
* \returns A string that contains the name of the pen, intended for human consumption.
|
||||
* The string might or might not be localised, depending on platform settings.
|
||||
* It is not guaranteed to be unique; use ::SDL_GetPenGUID() for (best-effort)
|
||||
* unique identifiers.
|
||||
* The pointer is managed by the SDL pen subsystem and must not be deallocated.
|
||||
* The pointer remains valid until SDL is shut down.
|
||||
* Returns NULL on error (cf. ::SDL_GetError())
|
||||
*
|
||||
* \since This function is available since SDL 3.TBD
|
||||
*/
|
||||
extern DECLSPEC const char *SDLCALL SDL_GetPenName(SDL_PenID instance_id);
|
||||
|
||||
/**
|
||||
* Pen capabilities, as reported by ::SDL_GetPenCapabilities()
|
||||
*/
|
||||
typedef struct SDL_PenCapabilityInfo
|
||||
{
|
||||
float max_tilt; /**< Physical maximum tilt angle, for XTILT and YTILT, or SDL_PEN_INFO_UNKNOWN . Pens cannot typically tilt all the way to 90 degrees, so this value is usually less than 90.0. */
|
||||
Uint32 wacom_id; /**< For Wacom devices: wacom tool type ID, otherwise 0 (useful e.g. with libwacom) */
|
||||
Sint8 num_buttons; /**< Number of pen buttons (not counting the pen tip), or SDL_PEN_INFO_UNKNOWN */
|
||||
} SDL_PenCapabilityInfo;
|
||||
|
||||
/**
|
||||
* Retrieves capability flags for a given ::SDL_PenID.
|
||||
*
|
||||
* \param instance_id The pen to query.
|
||||
* \param[out] capabilities Detail information about pen capabilities, such as the number of buttons
|
||||
*
|
||||
* \returns a set of capability flags, cf. \link SDL_PEN_CAPABILITIES \endlink. Returns 0 on error
|
||||
* (cf. ::SDL_GetError())
|
||||
*
|
||||
* \since This function is available since SDL 3.TBD
|
||||
*/
|
||||
extern DECLSPEC Uint32 SDLCALL SDL_GetPenCapabilities(SDL_PenID instance_id, SDL_PenCapabilityInfo *capabilities);
|
||||
|
||||
/**
|
||||
* Retrieves the pen type for a given ::SDL_PenID.
|
||||
*
|
||||
* \param instance_id The pen to query.
|
||||
* \returns The corresponding pen type (cf. ::SDL_PenSubtype) or 0 on error. Note that the pen type does not
|
||||
* dictate whether the pen tip is ::SDL_PEN_TIP_INK or ::SDL_PEN_TIP_ERASER; to determine whether a pen
|
||||
* is being used for drawing or in eraser mode, check either the pen tip on ::SDL_EVENT_PEN_DOWN, or the
|
||||
* flag ::SDL_PEN_ERASER_MASK in the pen state.
|
||||
* \since This function is available since SDL 3.TBD
|
||||
*/
|
||||
extern DECLSPEC SDL_PenSubtype SDLCALL SDL_GetPenType(SDL_PenID instance_id);
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SDL_pen_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -940,6 +940,22 @@ SDL3_0.0.0 {
|
||||
SDL_GetVideoCaptureDevices;
|
||||
SDL_GetGamepadButtonLabelForType;
|
||||
SDL_GetGamepadButtonLabel;
|
||||
SDL_GetPens;
|
||||
SDL_GetPenStatus;
|
||||
SDL_GetPenFromGUID;
|
||||
SDL_GetPenGUID;
|
||||
SDL_PenConnected;
|
||||
SDL_GetPenName;
|
||||
SDL_GetPenCapabilities;
|
||||
SDL_GetPenType;
|
||||
SDL_GetPens;
|
||||
SDL_GetPenStatus;
|
||||
SDL_GetPenFromGUID;
|
||||
SDL_GetPenGUID;
|
||||
SDL_PenConnected;
|
||||
SDL_GetPenName;
|
||||
SDL_GetPenCapabilities;
|
||||
SDL_GetPenType;
|
||||
# extra symbols go here (don't modify this line)
|
||||
local: *;
|
||||
};
|
||||
|
||||
@@ -965,3 +965,19 @@
|
||||
#define SDL_GetVideoCaptureDevices SDL_GetVideoCaptureDevices_REAL
|
||||
#define SDL_GetGamepadButtonLabelForType SDL_GetGamepadButtonLabelForType_REAL
|
||||
#define SDL_GetGamepadButtonLabel SDL_GetGamepadButtonLabel_REAL
|
||||
#define SDL_GetPens SDL_GetPens_REAL
|
||||
#define SDL_GetPenStatus SDL_GetPenStatus_REAL
|
||||
#define SDL_GetPenFromGUID SDL_GetPenFromGUID_REAL
|
||||
#define SDL_GetPenGUID SDL_GetPenGUID_REAL
|
||||
#define SDL_PenConnected SDL_PenConnected_REAL
|
||||
#define SDL_GetPenName SDL_GetPenName_REAL
|
||||
#define SDL_GetPenCapabilities SDL_GetPenCapabilities_REAL
|
||||
#define SDL_GetPenType SDL_GetPenType_REAL
|
||||
#define SDL_GetPens SDL_GetPens_REAL
|
||||
#define SDL_GetPenStatus SDL_GetPenStatus_REAL
|
||||
#define SDL_GetPenFromGUID SDL_GetPenFromGUID_REAL
|
||||
#define SDL_GetPenGUID SDL_GetPenGUID_REAL
|
||||
#define SDL_PenConnected SDL_PenConnected_REAL
|
||||
#define SDL_GetPenName SDL_GetPenName_REAL
|
||||
#define SDL_GetPenCapabilities SDL_GetPenCapabilities_REAL
|
||||
#define SDL_GetPenType SDL_GetPenType_REAL
|
||||
|
||||
@@ -998,3 +998,11 @@ SDL_DYNAPI_PROC(void,SDL_CloseVideoCapture,(SDL_VideoCaptureDevice *a),(a),)
|
||||
SDL_DYNAPI_PROC(SDL_VideoCaptureDeviceID*,SDL_GetVideoCaptureDevices,(int *a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_GamepadButtonLabel,SDL_GetGamepadButtonLabelForType,(SDL_GamepadType a, SDL_GamepadButton b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(SDL_GamepadButtonLabel,SDL_GetGamepadButtonLabel,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(SDL_PenID*,SDL_GetPens,(int *a),(a),return)
|
||||
SDL_DYNAPI_PROC(Uint32,SDL_GetPenStatus,(SDL_PenID a, float *b, float *c, float *d, size_t e),(a,b,c,d,e),return)
|
||||
SDL_DYNAPI_PROC(SDL_PenID,SDL_GetPenFromGUID,(SDL_GUID a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_GUID,SDL_GetPenGUID,(SDL_PenID a),(a),return)
|
||||
SDL_DYNAPI_PROC(SDL_bool,SDL_PenConnected,(SDL_PenID a),(a),return)
|
||||
SDL_DYNAPI_PROC(const char*,SDL_GetPenName,(SDL_PenID a),(a),return)
|
||||
SDL_DYNAPI_PROC(Uint32,SDL_GetPenCapabilities,(SDL_PenID a, SDL_PenCapabilityInfo *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(SDL_PenSubtype,SDL_GetPenType,(SDL_PenID a),(a),return)
|
||||
|
||||
@@ -379,7 +379,7 @@ def check_comment():
|
||||
if header != 'SDL_stdinc.h':
|
||||
parameter_name = i['parameter_name']
|
||||
for n in parameter_name:
|
||||
if n != "" and "\\param " + n not in comment:
|
||||
if n != "" and "\\param " + n not in comment and "\\param[out] " + n not in comment:
|
||||
check_comment_header()
|
||||
print(" In file %s: function %s() missing '\\param %s'" % (header, name, n));
|
||||
|
||||
|
||||
+52
-2
@@ -192,7 +192,7 @@ static void SDLCALL SDL_PollSentinelChanged(void *userdata, const char *name, co
|
||||
* Verbosity of logged events as defined in SDL_HINT_EVENT_LOGGING:
|
||||
* - 0: (default) no logging
|
||||
* - 1: logging of most events
|
||||
* - 2: as above, plus mouse and finger motion
|
||||
* - 2: as above, plus mouse, pen, and finger motion
|
||||
*/
|
||||
static int SDL_EventLoggingVerbosity = 0;
|
||||
|
||||
@@ -206,10 +206,11 @@ static void SDL_LogEvent(const SDL_Event *event)
|
||||
char name[64];
|
||||
char details[128];
|
||||
|
||||
/* sensor/mouse/finger motion are spammy, ignore these if they aren't demanded. */
|
||||
/* sensor/mouse/pen/finger motion are spammy, ignore these if they aren't demanded. */
|
||||
if ((SDL_EventLoggingVerbosity < 2) &&
|
||||
((event->type == SDL_EVENT_MOUSE_MOTION) ||
|
||||
(event->type == SDL_EVENT_FINGER_MOTION) ||
|
||||
(event->type == SDL_EVENT_PEN_MOTION) ||
|
||||
(event->type == SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION) ||
|
||||
(event->type == SDL_EVENT_GAMEPAD_SENSOR_UPDATE) ||
|
||||
(event->type == SDL_EVENT_SENSOR_UPDATE))) {
|
||||
@@ -302,6 +303,8 @@ static void SDL_LogEvent(const SDL_Event *event)
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_RESTORED);
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOUSE_ENTER);
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOUSE_LEAVE);
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PEN_ENTER);
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PEN_LEAVE);
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_FOCUS_GAINED);
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_FOCUS_LOST);
|
||||
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_CLOSE_REQUESTED);
|
||||
@@ -470,6 +473,53 @@ static void SDL_LogEvent(const SDL_Event *event)
|
||||
break;
|
||||
#undef PRINT_FINGER_EVENT
|
||||
|
||||
#define PRINT_PTIP_EVENT(event) \
|
||||
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u tip=%u state=%s x=%g y=%g)", \
|
||||
(uint)event->ptip.timestamp, (uint)event->ptip.windowID, \
|
||||
(uint)event->ptip.which, (uint)event->ptip.tip, \
|
||||
event->ptip.state == SDL_PRESSED ? "down" : "up", \
|
||||
event->ptip.x, event->ptip.y)
|
||||
SDL_EVENT_CASE(SDL_EVENT_PEN_DOWN)
|
||||
PRINT_PTIP_EVENT(event);
|
||||
break;
|
||||
SDL_EVENT_CASE(SDL_EVENT_PEN_UP)
|
||||
PRINT_PTIP_EVENT(event);
|
||||
break;
|
||||
#undef PRINT_PTIP_EVENT
|
||||
|
||||
SDL_EVENT_CASE(SDL_EVENT_PEN_MOTION)
|
||||
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u state=%08x x=%g y=%g [%g, %g, %g, %g, %g, %g])",
|
||||
(uint)event->pmotion.timestamp, (uint)event->pmotion.windowID,
|
||||
(uint)event->pmotion.which, (uint)event->pmotion.pen_state,
|
||||
event->pmotion.x, event->pmotion.y,
|
||||
event->pmotion.axes[SDL_PEN_AXIS_PRESSURE],
|
||||
event->pmotion.axes[SDL_PEN_AXIS_XTILT],
|
||||
event->pmotion.axes[SDL_PEN_AXIS_YTILT],
|
||||
event->pmotion.axes[SDL_PEN_AXIS_DISTANCE],
|
||||
event->pmotion.axes[SDL_PEN_AXIS_ROTATION],
|
||||
event->pmotion.axes[SDL_PEN_AXIS_SLIDER]);
|
||||
break;
|
||||
|
||||
#define PRINT_PBUTTON_EVENT(event) \
|
||||
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u tip=%u state=%s x=%g y=%g axes=[%g, %g, %g, %g, %g, %g])", \
|
||||
(uint)event->pbutton.timestamp, (uint)event->pbutton.windowID, \
|
||||
(uint)event->pbutton.which, (uint)event->pbutton.button, \
|
||||
event->pbutton.state == SDL_PRESSED ? "pressed" : "released", \
|
||||
event->pbutton.x, event->pbutton.y, \
|
||||
event->pbutton.axes[SDL_PEN_AXIS_PRESSURE], \
|
||||
event->pbutton.axes[SDL_PEN_AXIS_XTILT], \
|
||||
event->pbutton.axes[SDL_PEN_AXIS_YTILT], \
|
||||
event->pbutton.axes[SDL_PEN_AXIS_DISTANCE], \
|
||||
event->pbutton.axes[SDL_PEN_AXIS_ROTATION], \
|
||||
event->pbutton.axes[SDL_PEN_AXIS_SLIDER])
|
||||
SDL_EVENT_CASE(SDL_EVENT_PEN_BUTTON_DOWN)
|
||||
PRINT_PBUTTON_EVENT(event);
|
||||
break;
|
||||
SDL_EVENT_CASE(SDL_EVENT_PEN_BUTTON_UP)
|
||||
PRINT_PBUTTON_EVENT(event);
|
||||
break;
|
||||
#undef PRINT_PBUTTON_EVENT
|
||||
|
||||
#define PRINT_DROP_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (data='%s' timestamp=%u windowid=%u x=%f y=%f)", event->drop.data, (uint)event->drop.timestamp, (uint)event->drop.windowID, event->drop.x, event->drop.y)
|
||||
SDL_EVENT_CASE(SDL_EVENT_DROP_FILE)
|
||||
PRINT_DROP_EVENT(event);
|
||||
|
||||
+20
-8
@@ -22,9 +22,11 @@
|
||||
|
||||
/* General mouse handling code for SDL */
|
||||
|
||||
#include "SDL_events_c.h"
|
||||
#include "../SDL_hints_c.h"
|
||||
#include "../video/SDL_sysvideo.h"
|
||||
#include "SDL_events_c.h"
|
||||
#include "SDL_mouse_c.h"
|
||||
#include "SDL_pen_c.h"
|
||||
#if defined(__WIN32__) || defined(__GDK__)
|
||||
#include "../core/windows/SDL_windows.h" // For GetDoubleClickTime()
|
||||
#endif
|
||||
@@ -221,6 +223,8 @@ void SDL_PostInitMouse(void)
|
||||
SDL_DestroySurface(surface);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_PenInit();
|
||||
}
|
||||
|
||||
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
|
||||
@@ -351,17 +355,25 @@ void SDL_SetMouseFocus(SDL_Window *window)
|
||||
SDL_SetCursor(NULL);
|
||||
}
|
||||
|
||||
SDL_bool SDL_MousePositionInWindow(SDL_Window *window, SDL_MouseID mouseID, float x, float y)
|
||||
{
|
||||
if (!window) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (window && !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
|
||||
if (x < 0.0f || y < 0.0f || x >= (float)window->w || y >= (float)window->h) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* Check to see if we need to synthesize focus events */
|
||||
static SDL_bool SDL_UpdateMouseFocus(SDL_Window *window, float x, float y, Uint32 buttonstate, SDL_bool send_mouse_motion)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_bool inWindow = SDL_TRUE;
|
||||
|
||||
if (window && !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
|
||||
if (x < 0.0f || y < 0.0f || x >= (float)window->w || y >= (float)window->h) {
|
||||
inWindow = SDL_FALSE;
|
||||
}
|
||||
}
|
||||
SDL_bool inWindow = SDL_MousePositionInWindow(window, mouse->mouseID, x, y);
|
||||
|
||||
if (!inWindow) {
|
||||
if (window == mouse->focus) {
|
||||
|
||||
@@ -163,6 +163,9 @@ extern void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, S
|
||||
extern void SDL_ResetMouse(void);
|
||||
#endif /* 0 */
|
||||
|
||||
/* Check if mouse position is within window or captured by window */
|
||||
extern SDL_bool SDL_MousePositionInWindow(SDL_Window *window, SDL_MouseID mouseID, float x, float y);
|
||||
|
||||
/* Shutdown the mouse subsystem */
|
||||
extern void SDL_QuitMouse(void);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_pen_c_h_
|
||||
#define SDL_pen_c_h_
|
||||
|
||||
#include "../../include/SDL3/SDL_pen.h"
|
||||
#include "SDL_mouse_c.h"
|
||||
|
||||
/* For testing alternate code paths: */
|
||||
#define SDL_PEN_DEBUG_NOID 0 /* Pretend that pen device does not supply ID / ID is some default value \
|
||||
affects: SDL_x11pen.c \
|
||||
SDL_waylandevents.c */
|
||||
#define SDL_PEN_DEBUG_NONWACOM 0 /* Pretend that no attached device is a Wacom device \
|
||||
affects: SDL_x11pen.c \
|
||||
SDL_waylandevents.c */
|
||||
#define SDL_PEN_DEBUG_UNKNOWN_WACOM 0 /* Pretend that any attached Wacom device is of an unknown make \
|
||||
affects: SDL_PenModifyFromWacomID() */
|
||||
#define SDL_PEN_DEBUG_NOSERIAL_WACOM 0 /* Pretend that any attached Wacom device has serial number 0 \
|
||||
affects: SDL_x11pen.c \
|
||||
SDL_waylandevents.c */
|
||||
|
||||
#define SDL_PEN_TYPE_NONE 0 /**< Pen type for non-pens (use to cancel pen registration) */
|
||||
|
||||
#define SDL_PEN_MAX_NAME 64
|
||||
|
||||
#define SDL_PEN_FLAG_ERROR (1ul << 28) /* Printed an internal API usage error about this pen (used to prevent spamming) */
|
||||
#define SDL_PEN_FLAG_NEW (1ul << 29) /* Pen was registered in most recent call to SDL_PenRegisterBegin() */
|
||||
#define SDL_PEN_FLAG_DETACHED (1ul << 30) /* Detached (not re-registered before last SDL_PenGCSweep()) */
|
||||
#define SDL_PEN_FLAG_STALE (1ul << 31) /* Not re-registered since last SDL_PenGCMark() */
|
||||
|
||||
typedef struct SDL_PenStatusInfo
|
||||
{
|
||||
float x, y;
|
||||
float axes[SDL_PEN_NUM_AXES];
|
||||
Uint32 buttons; /* SDL_BUTTON(1) | SDL_BUTTON(2) | ... | SDL_PEN_DOWN_MASK */
|
||||
} SDL_PenStatusInfo;
|
||||
|
||||
/**
|
||||
* Internal (backend driver-independent) pen representation
|
||||
*
|
||||
* Implementation-specific backend drivers may read and write most of this structure, and
|
||||
* are expected to initialise parts of it when registering a new pen. They must not write
|
||||
* to the "header" section.
|
||||
*/
|
||||
typedef struct SDL_Pen
|
||||
{
|
||||
/* Backend driver MUST NOT not write to: */
|
||||
struct SDL_Pen_header
|
||||
{
|
||||
SDL_PenID id; /* id determines sort order unless SDL_PEN_FLAG_DETACHED is set */
|
||||
Uint32 flags; /* SDL_PEN_FLAG_* | SDK_PEN_DOWN_MASK | SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_* */
|
||||
SDL_Window *window; /* Current SDL window for this pen, or NULL */
|
||||
} header;
|
||||
|
||||
SDL_PenStatusInfo last; /* Last reported status, normally read-only for backend */
|
||||
|
||||
/* Backend: MUST initialise this block when pen is first registered: */
|
||||
SDL_GUID guid; /* GUID, MUST be set by backend.
|
||||
MUST be unique (no other pen ID with same GUID).
|
||||
SHOULD be persistent across sessions. */
|
||||
|
||||
/* Backend: SHOULD initialise this block when pen is first registered if it can
|
||||
Otherwise: Set to sane default values during SDL_PenModifyEnd() */
|
||||
SDL_PenCapabilityInfo info; /* Detail information about the pen (buttons, tilt) */
|
||||
SDL_PenSubtype type;
|
||||
Uint8 last_mouse_button; /* For mouse button emulation: last emulated button */
|
||||
char *name; /* Preallocated; set via SDL_strlcpy(pen->name, src, SDL_PEN_MAX_NAME) */
|
||||
/* We hand this exact pointer to client code, so it must not be modified after
|
||||
creation. */
|
||||
|
||||
void *deviceinfo; /* implementation-specific information */
|
||||
} SDL_Pen;
|
||||
|
||||
/* ---- API for backend driver only ---- */
|
||||
|
||||
/**
|
||||
* (Only for backend driver) Look up a pen by pen ID
|
||||
*
|
||||
* \param instance_id A Uint32 pen identifier (driver-dependent meaning). Must not be 0 = SDL_PEN_INVALID.
|
||||
* The same ID is exposed to clients as SDL_PenID.
|
||||
*
|
||||
* The pen pointer is only valid until the next call to SDL_PenModifyEnd() or SDL_PenGCSweep()
|
||||
*
|
||||
* \return pen, if it exists, or NULL
|
||||
*/
|
||||
extern SDL_Pen *SDL_GetPenPtr(Uint32 instance_id);
|
||||
|
||||
/**
|
||||
* (Only for backend driver) Start registering a new pen or updating an existing pen.
|
||||
*
|
||||
* Acquires the pen mutex, which is held until the next call to SDL_PenModifyEnd() .
|
||||
*
|
||||
* If the PenID already exists, returns the existing entry. Otherwise initialise fresh SDL_Pen.
|
||||
* For new pens, sets SDL_PEN_FLAG_NEW.
|
||||
*
|
||||
* Usage:
|
||||
* - SDL_PenModifyStart()
|
||||
* - update pen object, in any order:
|
||||
* - SDL_PenModifyAddCapabilities()
|
||||
* - pen->guid (MUST be set for new pens, e.g. via ::SDL_PenUpdateGUIDForGeneric and related operations)
|
||||
* - pen->info.num_buttons
|
||||
* - pen->info.max_tilt
|
||||
* - pen->type
|
||||
* - pen->name
|
||||
* - pen->deviceinfo (backend-specific)
|
||||
* - SDL_PenModifyEnd()
|
||||
*
|
||||
* For new pens, sets defaults for:
|
||||
* - num_buttons (SDL_PEN_INFO_UNKNOWN)
|
||||
* - max_tilt (SDL_PEN_INFO_UNKNOWN)
|
||||
* - pen_type (SDL_PEN_TYPE_PEN)
|
||||
* - Zeroes all other (non-header) fields
|
||||
*
|
||||
* \param instance_id Pen ID to allocate (must not be 0 = SDL_PEN_ID_INVALID)
|
||||
* \returns SDL_Pen pointer; only valid until the call to SDL_PenModifyEnd()
|
||||
*/
|
||||
extern SDL_Pen *SDL_PenModifyBegin(Uint32 instance_id);
|
||||
|
||||
/**
|
||||
* (Only for backend driver) Add capabilities to a pen (cf. SDL_PenModifyBegin()).
|
||||
*
|
||||
* Adds capabilities to a pen obtained via SDL_PenModifyBegin(). Can be called more than once.
|
||||
*
|
||||
* \param pen The pen to update
|
||||
* \param capabilities Capabilities flags, out of: SDL_PEN_AXIS_*, SDL_PEN_ERASER_MASK, SDL_PEN_INK_MASK
|
||||
* Setting SDL_PEN_ERASER_MASK will clear SDL_PEN_INK_MASK, and vice versa.
|
||||
*/
|
||||
extern void SDL_PenModifyAddCapabilities(SDL_Pen *pen, Uint32 capabilities);
|
||||
|
||||
/**
|
||||
* Set up a pen structure for a Wacom device.
|
||||
*
|
||||
* Some backends (e.g., XInput2, Wayland) can only partially identify the capabilities of a given
|
||||
* pen but can identify Wacom pens and obtain their Wacom-specific device type identifiers.
|
||||
* This function partly automates device setup in those cases.
|
||||
*
|
||||
* This function does NOT set up the pen's GUID. Use ::SD_PenModifyGUIDForWacom instead.
|
||||
*
|
||||
* This function does NOT call SDL_PenModifyAddCapabilities() ifself, since some backends may
|
||||
* not have access to all pen axes (e.g., Xinput2).
|
||||
*
|
||||
* \param pen The pen to initialise
|
||||
* \param wacom_devicetype_id The Wacom-specific device type identifier
|
||||
* \param[out] axis_flags The set of physically supported axes for this pen, suitable for passing to
|
||||
* SDL_PenModifyAddCapabilities()
|
||||
*
|
||||
* \returns SDL_TRUE if the device ID could be identified, otherwise SDL_FALSE
|
||||
*/
|
||||
extern int SDL_PenModifyForWacomID(SDL_Pen *pen, Uint32 wacom_devicetype_id, Uint32 *axis_flags);
|
||||
|
||||
/**
|
||||
* Updates a GUID for a generic pen device.
|
||||
*
|
||||
* Assumes that the GUID has been pre-initialised (typically to 0).
|
||||
* Idempotent, and commutative with ::SDL_PenUpdateGUIDForWacom and ::SDL_PenUpdateGUIDForType
|
||||
*
|
||||
* \param[out] guid The GUID to update
|
||||
* \param upper Upper half of the device ID (assume lower entropy than "lower"; pass 0 if not available)
|
||||
* \param lower Lower half of the device ID (assume higher entropy than "upper")
|
||||
*/
|
||||
extern void SDL_PenUpdateGUIDForGeneric(SDL_GUID *guid, Uint32 upper, Uint32 lower);
|
||||
|
||||
/**
|
||||
* Updates a GUID based on a pen type
|
||||
*
|
||||
* Assumes that the GUID has been pre-initialised (typically to 0).
|
||||
* Idempotent, and commutative with ::SDL_PenUpdateGUIDForWacom and ::SDL_PenUpdateGUIDForGeneric
|
||||
*
|
||||
* \param[out] guid The GUID to update
|
||||
* \param pentype The pen type to insert
|
||||
*/
|
||||
extern void SDL_PenUpdateGUIDForType(SDL_GUID *guid, SDL_PenSubtype pentype);
|
||||
|
||||
/**
|
||||
* Updates a GUID for a Wacom pen device.
|
||||
*
|
||||
* Assumes that the GUID has been pre-initialised (typically to 0).
|
||||
* Idempotent, and commutative with ::SDL_PenUpdateGUIDForType and ::SDL_PenUpdateGUIDForGeneric
|
||||
*
|
||||
* This update is identical to the one written by ::SDL_PenModifyFromWacomID .
|
||||
*
|
||||
* \param[out] guid The GUID to update
|
||||
* \param wacom_devicetype_id The Wacom-specific device type identifier
|
||||
* \param wacom_serial_id The Wacom-specific serial number
|
||||
*/
|
||||
extern void SDL_PenUpdateGUIDForWacom(SDL_GUID *guid, Uint32 wacom_devicetype_id, Uint32 wacom_serial_id);
|
||||
|
||||
/**
|
||||
* (Only for backend driver) Finish updating a pen.
|
||||
*
|
||||
* Releases the pen mutex acquired by SDL_PenModifyBegin() .
|
||||
*
|
||||
* If pen->type == SDL_PEN_TYPE_NONE, removes the pen entirely (only
|
||||
* for new pens). This allows backends to start registering a
|
||||
* potential pen device and to abort if the device turns out to not be
|
||||
* a pen.
|
||||
*
|
||||
* For new pens, this call will also set the following:
|
||||
* - name (default name, if not yet set)
|
||||
*
|
||||
* \param pen The pen to register. That pointer is no longer valid after this call.
|
||||
* \param attach Whether the pen should be attached (SDL_TRUE) or detached (SDL_FALSE).
|
||||
*
|
||||
* If the pen is detached or removed, it is the caller's responsibility to free
|
||||
* and null "deviceinfo".
|
||||
*/
|
||||
extern void SDL_PenModifyEnd(SDL_Pen *pen, SDL_bool attach);
|
||||
|
||||
/**
|
||||
* (Only for backend driver) Mark all current pens for garbage collection.
|
||||
*
|
||||
* Must not be called while the pen mutex is held (by SDL_PenModifyBegin() ).
|
||||
*
|
||||
* SDL_PenGCMark() / SDL_PenGCSweep() provide a simple mechanism for
|
||||
* detaching all known pens that are not discoverable. This allows
|
||||
* backends to use the same code for pen discovery and for
|
||||
* hotplugging:
|
||||
*
|
||||
* - SDL_PenGCMark() and start backend-specific discovery
|
||||
* - for each discovered pen: SDL_PenModifyBegin() + SDL_PenModifyEnd() (this will retain existing state)
|
||||
* - SDL_PenGCSweep() (will now detach all pens that were not re-registered).
|
||||
*/
|
||||
extern void SDL_PenGCMark(void);
|
||||
|
||||
/**
|
||||
* (Only for backend driver) Detach pens that haven't been reported attached since the last call to SDL_PenGCMark().
|
||||
*
|
||||
* Must not be called while the pen mutex is held (by SDL_PenModifyBegin() ).
|
||||
*
|
||||
* See SDL_PenGCMark() for details.
|
||||
*
|
||||
* \param context Extra parameter to pass through to "free_deviceinfo"
|
||||
* \param free_deviceinfo Operation to call on any non-NULL "backend.deviceinfo".
|
||||
*
|
||||
* \sa SDL_PenGCMark()
|
||||
*/
|
||||
extern void SDL_PenGCSweep(void *context, void (*free_deviceinfo)(Uint32 instance_id, void *deviceinfo, void *context));
|
||||
|
||||
/**
|
||||
* (Only for backend driver) Send a pen motion event.
|
||||
*
|
||||
* Suppresses pen motion events that do not change the current pen state.
|
||||
* May also send a mouse motion event, if mouse emulation is enabled and the pen position has
|
||||
* changed sufficiently for the motion to be visible to mouse event listeners.
|
||||
*
|
||||
* \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() .
|
||||
* While 0 is safe to report, your backends may be able to report more precise
|
||||
* timing information.
|
||||
* Keep in mind that you should never report timestamps that are greater than
|
||||
* SDL_GetTicksNS() . In particular, SDL_GetTicksNS() reports nanoseconds since the start
|
||||
* of the SDL session, and your backend may use a different starting point as "timestamp zero".
|
||||
* \param instance_id Pen
|
||||
* \param window_relative Coordinates are already window-relative
|
||||
* \param status Coordinates and axes (buttons are ignored)
|
||||
*
|
||||
* \returns SDL_TRUE if at least one event was sent
|
||||
*/
|
||||
extern int SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_bool window_relative, const SDL_PenStatusInfo *status);
|
||||
|
||||
/**
|
||||
* (Only for backend driver) Send a pen button event
|
||||
*
|
||||
* \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() .
|
||||
* See SDL_SendPenMotion() for a discussion about how to handle timestamps.
|
||||
* \param instance_id Pen
|
||||
* \param state SDL_PRESSED or SDL_RELEASED
|
||||
* \param button Button number: 1 (first physical button) etc.
|
||||
*
|
||||
* \returns SDL_TRUE if at least one event was sent
|
||||
*/
|
||||
extern int SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, Uint8 state, Uint8 button);
|
||||
|
||||
/**
|
||||
* (Only for backend driver) Send a pen tip event (touching or no longer touching the surface)
|
||||
*
|
||||
* Note: the backend should perform hit testing on window decoration elements to allow the pen
|
||||
* to e.g. resize/move the window, just as for mouse events, unless ::SDL_SendPenTipEvent is false.
|
||||
*
|
||||
* \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() .
|
||||
* See SDL_SendPenMotion() for a discussion about how to handle timestamps.
|
||||
* \param instance_id Pen
|
||||
* \param state SDL_PRESSED (for PEN_DOWN) or SDL_RELEASED (for PEN_UP)
|
||||
*
|
||||
* \returns SDL_TRUE if at least one event was sent
|
||||
*/
|
||||
extern int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state);
|
||||
|
||||
/**
|
||||
* (Only for backend driver) Check if a PEN_DOWN event should perform hit box testing.
|
||||
*
|
||||
* \returns SDL_TRUE if and only if the backend should perform hit testing
|
||||
*/
|
||||
extern SDL_bool SDL_PenPerformHitTest(void);
|
||||
|
||||
/**
|
||||
* (Only for backend driver) Send a pen window event.
|
||||
*
|
||||
* Tracks when a pen has entered/left a window.
|
||||
* Don't call this when reporting new pens or removing known pens; those cases are handled automatically.
|
||||
*
|
||||
* \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() .
|
||||
* See SDL_SendPenMotion() for a discussion about how to handle timestamps.
|
||||
* \param instance_id Pen
|
||||
* \param window Window to enter, or NULL to exit
|
||||
*/
|
||||
extern int SDL_SendPenWindowEvent(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window);
|
||||
|
||||
/**
|
||||
* Initialises the pen subsystem.
|
||||
*/
|
||||
extern void SDL_PenInit(void);
|
||||
|
||||
#endif /* SDL_pen_c_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@
|
||||
#define SDL_waylandevents_h_
|
||||
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_pen_c.h"
|
||||
|
||||
#include "SDL_waylandvideo.h"
|
||||
#include "SDL_waylandwindow.h"
|
||||
@@ -55,31 +56,38 @@ struct SDL_WaylandTabletInput
|
||||
struct SDL_WaylandTabletObjectListNode *tools;
|
||||
struct SDL_WaylandTabletObjectListNode *pads;
|
||||
|
||||
Uint32 id;
|
||||
Uint32 num_pens; /* next pen ID is num_pens+1 */
|
||||
struct SDL_WaylandCurrentPen
|
||||
{
|
||||
SDL_Pen *builder; /* pen that is being defined or receiving updates, if any */
|
||||
SDL_bool builder_guid_complete; /* have complete/precise GUID information */
|
||||
SDL_PenStatusInfo update_status; /* collects pen update information before sending event */
|
||||
Uint16 buttons_pressed; /* Mask of newly pressed buttons, plus SDL_PEN_DOWN_MASK for PEN_DOWN */
|
||||
Uint16 buttons_released; /* Mask of newly pressed buttons, plus SDL_PEN_DOWN_MASK for PEN_UP */
|
||||
Uint32 serial; /* Most recent serial event number observed, or 0 */
|
||||
SDL_WindowData *update_window; /* NULL while no event is in progress, otherwise the affected window */
|
||||
} current_pen;
|
||||
|
||||
SDL_WindowData *tool_focus;
|
||||
uint32_t tool_prox_serial;
|
||||
|
||||
/* Last motion location */
|
||||
/* Last motion end location (kept separate from sx_w, sy_w for the mouse pointer) */
|
||||
wl_fixed_t sx_w;
|
||||
wl_fixed_t sy_w;
|
||||
|
||||
SDL_bool is_down;
|
||||
|
||||
SDL_bool btn_stylus;
|
||||
SDL_bool btn_stylus2;
|
||||
SDL_bool btn_stylus3;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32_t repeat_rate; /* Repeat rate in range of [1, 1000] character(s) per second */
|
||||
int32_t repeat_delay_ms; /* Time to first repeat event in milliseconds */
|
||||
int32_t repeat_rate; /* Repeat rate in range of [1, 1000] character(s) per second */
|
||||
int32_t repeat_delay_ms; /* Time to first repeat event in milliseconds */
|
||||
SDL_bool is_initialized;
|
||||
|
||||
SDL_bool is_key_down;
|
||||
uint32_t key;
|
||||
Uint64 wl_press_time_ns; /* Key press time as reported by the Wayland API */
|
||||
Uint64 sdl_press_time_ns; /* Key press time expressed in SDL ticks */
|
||||
Uint64 next_repeat_ns; /* Next repeat event in nanoseconds */
|
||||
Uint64 wl_press_time_ns; /* Key press time as reported by the Wayland API */
|
||||
Uint64 sdl_press_time_ns; /* Key press time expressed in SDL ticks */
|
||||
Uint64 next_repeat_ns; /* Next repeat event in nanoseconds */
|
||||
uint32_t scancode;
|
||||
char text[8];
|
||||
} SDL_WaylandKeyboardRepeat;
|
||||
@@ -169,6 +177,12 @@ struct SDL_WaylandInput
|
||||
SDL_Keymod locked_modifiers;
|
||||
};
|
||||
|
||||
struct SDL_WaylandTool
|
||||
{
|
||||
SDL_PenID penid;
|
||||
struct SDL_WaylandTabletInput *tablet;
|
||||
};
|
||||
|
||||
extern Uint64 Wayland_GetTouchTimestamp(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms);
|
||||
|
||||
extern void Wayland_PumpEvents(SDL_VideoDevice *_this);
|
||||
|
||||
+109
-76
@@ -179,14 +179,14 @@ static SDL_bool X11_KeyRepeat(Display *display, XEvent *event)
|
||||
return d.found;
|
||||
}
|
||||
|
||||
static SDL_bool X11_IsWheelEvent(Display *display, XEvent *event, int *xticks, int *yticks)
|
||||
static SDL_bool X11_IsWheelEvent(Display *display, int button, int *xticks, int *yticks)
|
||||
{
|
||||
/* according to the xlib docs, no specific mouse wheel events exist.
|
||||
However, the defacto standard is that the vertical wheel is X buttons
|
||||
4 (up) and 5 (down) and a horizontal wheel is 6 (left) and 7 (right). */
|
||||
|
||||
/* Xlib defines "Button1" through 5, so we just use literals here. */
|
||||
switch (event->xbutton.button) {
|
||||
switch (button) {
|
||||
case 4:
|
||||
*yticks = 1;
|
||||
return SDL_TRUE;
|
||||
@@ -333,13 +333,15 @@ void SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata)
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
|
||||
static void X11_HandleGenericEvent(SDL_VideoData *videodata, XEvent *xev)
|
||||
static void X11_HandleGenericEvent(SDL_VideoDevice *_this, XEvent *xev)
|
||||
{
|
||||
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
|
||||
|
||||
/* event is a union, so cookie == &event, but this is type safe. */
|
||||
XGenericEventCookie *cookie = &xev->xcookie;
|
||||
if (X11_XGetEventData(videodata->display, cookie)) {
|
||||
if (!g_X11EventHook || g_X11EventHook(g_X11EventHookData, xev)) {
|
||||
X11_HandleXinput2Event(videodata, cookie);
|
||||
X11_HandleXinput2Event(_this, cookie);
|
||||
}
|
||||
X11_XFreeEventData(videodata->display, cookie);
|
||||
}
|
||||
@@ -557,12 +559,12 @@ static void InitiateWindowResize(SDL_VideoDevice *_this, const SDL_WindowData *d
|
||||
X11_XSync(display, 0);
|
||||
}
|
||||
|
||||
static SDL_bool ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, const XEvent *xev)
|
||||
SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y)
|
||||
{
|
||||
SDL_Window *window = data->window;
|
||||
|
||||
if (window->hit_test) {
|
||||
const SDL_Point point = { xev->xbutton.x, xev->xbutton.y };
|
||||
const SDL_Point point = { x, y };
|
||||
const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
|
||||
static const int directions[] = {
|
||||
_NET_WM_MOVERESIZE_SIZE_TOPLEFT, _NET_WM_MOVERESIZE_SIZE_TOP,
|
||||
@@ -761,14 +763,14 @@ static Bool isReparentNotify(Display *display, XEvent *ev, XPointer arg)
|
||||
|
||||
static SDL_bool IsHighLatin1(const char *string, int length)
|
||||
{
|
||||
while (length-- > 0) {
|
||||
Uint8 ch = (Uint8)*string;
|
||||
if (ch >= 0x80) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
++string;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
while (length-- > 0) {
|
||||
Uint8 ch = (Uint8)*string;
|
||||
if (ch >= 0x80) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
++string;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static int XLookupStringAsUTF8(XKeyEvent *event_struct, char *buffer_return, int bytes_buffer, KeySym *keysym_return, XComposeStatus *status_in_out)
|
||||
@@ -787,6 +789,78 @@ static int XLookupStringAsUTF8(XKeyEvent *event_struct, char *buffer_return, int
|
||||
return result;
|
||||
}
|
||||
|
||||
SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window)
|
||||
{
|
||||
const SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
|
||||
int i;
|
||||
|
||||
if (videodata && videodata->windowlist) {
|
||||
for (i = 0; i < videodata->numwindows; ++i) {
|
||||
if ((videodata->windowlist[i] != NULL) &&
|
||||
(videodata->windowlist[i]->xwindow == window)) {
|
||||
return videodata->windowlist[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, int button, const float x, const float y, const unsigned long time)
|
||||
{
|
||||
SDL_Window *window = windowdata->window;
|
||||
const SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
|
||||
Display *display = videodata->display;
|
||||
int xticks = 0, yticks = 0;
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: ButtonPress (X11 button = %d)\n", window, button);
|
||||
#endif
|
||||
if (X11_IsWheelEvent(display, button, &xticks, &yticks)) {
|
||||
SDL_SendMouseWheel(0, window, 0, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL);
|
||||
} else {
|
||||
SDL_bool ignore_click = SDL_FALSE;
|
||||
if (button == Button1) {
|
||||
if (X11_ProcessHitTest(_this, windowdata, x, y)) {
|
||||
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0);
|
||||
return; /* don't pass this event on to app. */
|
||||
}
|
||||
} else if (button > 7) {
|
||||
/* X button values 4-7 are used for scrolling, so X1 is 8, X2 is 9, ...
|
||||
=> subtract (8-SDL_BUTTON_X1) to get value SDL expects */
|
||||
button -= (8 - SDL_BUTTON_X1);
|
||||
}
|
||||
if (windowdata->last_focus_event_time) {
|
||||
const int X11_FOCUS_CLICK_TIMEOUT = 10;
|
||||
if (SDL_GetTicks() < (windowdata->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) {
|
||||
ignore_click = !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE);
|
||||
}
|
||||
windowdata->last_focus_event_time = 0;
|
||||
}
|
||||
if (!ignore_click) {
|
||||
SDL_SendMouseButton(0, window, 0, SDL_PRESSED, button);
|
||||
}
|
||||
}
|
||||
X11_UpdateUserTime(windowdata, time);
|
||||
}
|
||||
|
||||
void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, int button)
|
||||
{
|
||||
SDL_Window *window = windowdata->window;
|
||||
const SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
|
||||
Display *display = videodata->display;
|
||||
/* The X server sends a Release event for each Press for wheels. Ignore them. */
|
||||
int xticks = 0, yticks = 0;
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent->xbutton.button);
|
||||
#endif
|
||||
if (!X11_IsWheelEvent(display, button, &xticks, &yticks)) {
|
||||
if (button > 7) {
|
||||
/* see explanation at case ButtonPress */
|
||||
button -= (8 - SDL_BUTTON_X1);
|
||||
}
|
||||
SDL_SendMouseButton(0, window, 0, SDL_RELEASED, button);
|
||||
}
|
||||
}
|
||||
|
||||
void X11_GetBorderValues(SDL_WindowData *data)
|
||||
{
|
||||
SDL_VideoData *videodata = data->videodata;
|
||||
@@ -861,7 +935,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
|
||||
if (xevent->type == GenericEvent) {
|
||||
X11_HandleGenericEvent(videodata, xevent);
|
||||
X11_HandleGenericEvent(_this, xevent);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -886,19 +960,19 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XFIXES
|
||||
if (SDL_X11_HAVE_XFIXES &&
|
||||
xevent->type == X11_GetXFixesSelectionNotifyEvent()) {
|
||||
XFixesSelectionNotifyEvent *ev = (XFixesSelectionNotifyEvent *) xevent;
|
||||
xevent->type == X11_GetXFixesSelectionNotifyEvent()) {
|
||||
XFixesSelectionNotifyEvent *ev = (XFixesSelectionNotifyEvent *)xevent;
|
||||
|
||||
/* !!! FIXME: cache atoms */
|
||||
Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0);
|
||||
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window CLIPBOARD: XFixesSelectionNotify (selection = %s)\n",
|
||||
X11_XGetAtomName(display, ev->selection));
|
||||
X11_XGetAtomName(display, ev->selection));
|
||||
#endif
|
||||
|
||||
if (ev->selection == XA_PRIMARY ||
|
||||
(XA_CLIPBOARD != None && ev->selection == XA_CLIPBOARD)) {
|
||||
(XA_CLIPBOARD != None && ev->selection == XA_CLIPBOARD)) {
|
||||
SDL_SendClipboardUpdate();
|
||||
return;
|
||||
}
|
||||
@@ -911,16 +985,8 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
return;
|
||||
}
|
||||
|
||||
data = NULL;
|
||||
if (videodata && videodata->windowlist) {
|
||||
for (i = 0; i < videodata->numwindows; ++i) {
|
||||
if ((videodata->windowlist[i] != NULL) &&
|
||||
(videodata->windowlist[i]->xwindow == xevent->xany.window)) {
|
||||
data = videodata->windowlist[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
data = X11_FindWindow(_this, xevent->xany.window);
|
||||
|
||||
if (!data) {
|
||||
/* The window for KeymapNotify, etc events is 0 */
|
||||
if (xevent->type == KeymapNotify) {
|
||||
@@ -1227,8 +1293,9 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
xevent->xconfigure.x, xevent->xconfigure.y,
|
||||
xevent->xconfigure.width, xevent->xconfigure.height);
|
||||
#endif
|
||||
/* Real configure notify events are relative to the parent, synthetic events are absolute. */
|
||||
if (!xevent->xconfigure.send_event) {
|
||||
/* Real configure notify events are relative to the parent, synthetic events are absolute. */
|
||||
if (!xevent->xconfigure.send_event)
|
||||
{
|
||||
unsigned int NumChildren;
|
||||
Window ChildReturn, Root, Parent;
|
||||
Window *Children;
|
||||
@@ -1318,7 +1385,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
root_y = xevent->xclient.data.l[2] & 0xffff;
|
||||
/* Translate from root to current window position */
|
||||
X11_XTranslateCoordinates(display, DefaultRootWindow(display), data->xwindow,
|
||||
root_x, root_y, &window_x, &window_y, &ChildReturn);
|
||||
root_x, root_y, &window_x, &window_y, &ChildReturn);
|
||||
|
||||
SDL_SendDropPosition(data->window, (float)window_x, (float)window_y);
|
||||
}
|
||||
@@ -1402,6 +1469,12 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_EXPOSED, 0, 0);
|
||||
} break;
|
||||
|
||||
/* Use XInput2 instead of the xevents API if possible, for:
|
||||
- MotionNotify
|
||||
- ButtonPress
|
||||
- ButtonRelease
|
||||
XInput2 has more precise information, e.g., to distinguish different input devices. */
|
||||
#ifndef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
case MotionNotify:
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
@@ -1416,55 +1489,15 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
|
||||
|
||||
case ButtonPress:
|
||||
{
|
||||
int xticks = 0, yticks = 0;
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: ButtonPress (X11 button = %d)\n", data, xevent->xbutton.button);
|
||||
#endif
|
||||
if (X11_IsWheelEvent(display, xevent, &xticks, &yticks)) {
|
||||
SDL_SendMouseWheel(0, data->window, 0, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL);
|
||||
} else {
|
||||
SDL_bool ignore_click = SDL_FALSE;
|
||||
int button = xevent->xbutton.button;
|
||||
if (button == Button1) {
|
||||
if (ProcessHitTest(_this, data, xevent)) {
|
||||
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0);
|
||||
break; /* don't pass this event on to app. */
|
||||
}
|
||||
} else if (button > 7) {
|
||||
/* X button values 4-7 are used for scrolling, so X1 is 8, X2 is 9, ...
|
||||
=> subtract (8-SDL_BUTTON_X1) to get value SDL expects */
|
||||
button -= (8 - SDL_BUTTON_X1);
|
||||
}
|
||||
if (data->last_focus_event_time) {
|
||||
const int X11_FOCUS_CLICK_TIMEOUT = 10;
|
||||
if (SDL_GetTicks() < (data->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) {
|
||||
ignore_click = !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE);
|
||||
}
|
||||
data->last_focus_event_time = 0;
|
||||
}
|
||||
if (!ignore_click) {
|
||||
SDL_SendMouseButton(0, data->window, 0, SDL_PRESSED, button);
|
||||
}
|
||||
}
|
||||
X11_UpdateUserTime(data, xevent->xbutton.time);
|
||||
X11_HandleButtonPress(_this, data, xevent->xbutton.button,
|
||||
xevent->xbutton.x, xevent->xbutton.y, xevent->xbutton.time);
|
||||
} break;
|
||||
|
||||
case ButtonRelease:
|
||||
{
|
||||
int button = xevent->xbutton.button;
|
||||
/* The X server sends a Release event for each Press for wheels. Ignore them. */
|
||||
int xticks = 0, yticks = 0;
|
||||
#ifdef DEBUG_XEVENTS
|
||||
printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent->xbutton.button);
|
||||
#endif
|
||||
if (!X11_IsWheelEvent(display, xevent, &xticks, &yticks)) {
|
||||
if (button > 7) {
|
||||
/* see explanation at case ButtonPress */
|
||||
button -= (8 - SDL_BUTTON_X1);
|
||||
}
|
||||
SDL_SendMouseButton(0, data->window, 0, SDL_RELEASED, button);
|
||||
}
|
||||
X11_HandleButtonRelease(_this, data, xevent->xbutton.button);
|
||||
} break;
|
||||
#endif /* !SDL_VIDEO_DRIVER_X11_XINPUT2 */
|
||||
|
||||
case PropertyNotify:
|
||||
{
|
||||
|
||||
@@ -29,5 +29,9 @@ extern void X11_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern int X11_SuspendScreenSaver(SDL_VideoDevice *_this);
|
||||
extern void X11_ReconcileKeyboardState(SDL_VideoDevice *_this);
|
||||
extern void X11_GetBorderValues(SDL_WindowData *data);
|
||||
extern void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button, const float x, const float y, const unsigned long time);
|
||||
extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *wdata, int button);
|
||||
extern SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window);
|
||||
extern SDL_bool X11_ProcessHitTest(SDL_VideoDevice *_this, const SDL_WindowData *data, const float x, const float y);
|
||||
|
||||
#endif /* SDL_x11events_h_ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef SDL_x11pen_h_
|
||||
#define SDL_x11pen_h_
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
|
||||
#include "SDL_x11video.h"
|
||||
#include "../../events/SDL_pen_c.h"
|
||||
|
||||
/* Pressure-sensitive pen */
|
||||
|
||||
/* Forward definition for SDL_x11video.h */
|
||||
struct SDL_VideoData;
|
||||
|
||||
/* Function definitions */
|
||||
|
||||
/* Detect XINPUT2 devices that are pens / erasers, or update the list after hotplugging */
|
||||
extern void X11_InitPen(SDL_VideoDevice *_this);
|
||||
|
||||
/* Converts XINPUT2 valuators into pen axis information, including normalisation */
|
||||
extern void X11_PenAxesFromValuators(const SDL_Pen *pen,
|
||||
const double *input_values, const unsigned char *mask, const int mask_len,
|
||||
/* out-mode parameters: */
|
||||
float axis_values[SDL_PEN_NUM_AXES]);
|
||||
|
||||
/* Map X11 device ID to pen ID */
|
||||
extern int X11_PenIDFromDeviceID(int deviceid);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
|
||||
|
||||
#endif /* SDL_x11pen_h_ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -289,6 +289,7 @@ SDL_X11_SYM(Status,XIQueryVersion,(Display *a,int *b,int *c),(a,b,c),return)
|
||||
SDL_X11_SYM(XIEventMask*,XIGetSelectedEvents,(Display *a,Window b,int *c),(a,b,c),return)
|
||||
SDL_X11_SYM(Bool,XIGetClientPointer,(Display *a,Window b,int *c),(a,b,c),return)
|
||||
SDL_X11_SYM(Bool,XIWarpPointer,(Display *a,int b,Window c,Window d,double e,double f,int g,int h,double i,double j),(a,b,c,d,e,f,g,h,i,j),return)
|
||||
SDL_X11_SYM(Status,XIGetProperty,(Display *a,int b,Atom c,long d,long e,Bool f, Atom g, Atom *h, int *i, unsigned long *j, unsigned long *k, unsigned char **l),(a,b,c,d,e,f,g,h,i,j,k,l),return);
|
||||
#endif
|
||||
|
||||
/* XRandR support */
|
||||
|
||||
@@ -24,16 +24,17 @@
|
||||
|
||||
#include <unistd.h> /* For getpid() and readlink() */
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../SDL_pixels_c.h"
|
||||
#include "../../core/linux/SDL_system_theme.h"
|
||||
#include "../SDL_pixels_c.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#include "SDL_x11video.h"
|
||||
#include "SDL_x11framebuffer.h"
|
||||
#include "SDL_x11pen.h"
|
||||
#include "SDL_x11shape.h"
|
||||
#include "SDL_x11touch.h"
|
||||
#include "SDL_x11xinput2.h"
|
||||
#include "SDL_x11video.h"
|
||||
#include "SDL_x11xfixes.h"
|
||||
#include "SDL_x11xinput2.h"
|
||||
|
||||
#ifdef SDL_VIDEO_OPENGL_EGL
|
||||
#include "SDL_x11opengles.h"
|
||||
@@ -432,6 +433,10 @@ int X11_VideoInit(SDL_VideoDevice *_this)
|
||||
|
||||
X11_InitTouch(_this);
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
X11_InitPen(_this);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -592,8 +592,8 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
X11_ConstrainPopup(window);
|
||||
}
|
||||
SDL_RelativeToGlobalForWindow(window,
|
||||
window->windowed.x, window->windowed.y,
|
||||
&win_x, &win_y);
|
||||
window->windowed.x, window->windowed.y,
|
||||
&win_x, &win_y);
|
||||
|
||||
/* Always create this with the window->windowed.* fields; if we're
|
||||
creating a windowed mode window, that's fine. If we're creating a
|
||||
@@ -754,12 +754,20 @@ int X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
|
||||
X11_Xinput2SelectTouch(_this, window);
|
||||
|
||||
X11_XSelectInput(display, w,
|
||||
(FocusChangeMask | EnterWindowMask | LeaveWindowMask |
|
||||
ExposureMask | ButtonPressMask | ButtonReleaseMask |
|
||||
PointerMotionMask | KeyPressMask | KeyReleaseMask |
|
||||
PropertyChangeMask | StructureNotifyMask |
|
||||
KeymapStateMask | fevent));
|
||||
{
|
||||
unsigned int x11_pointer_events = ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
|
||||
if (X11_Xinput2SelectMouse(_this, window)) {
|
||||
/* If XInput2 can handle pointer events, we don't track them here */
|
||||
x11_pointer_events = 0;
|
||||
}
|
||||
|
||||
X11_XSelectInput(display, w,
|
||||
(FocusChangeMask | EnterWindowMask | LeaveWindowMask | ExposureMask |
|
||||
x11_pointer_events |
|
||||
KeyPressMask | KeyReleaseMask |
|
||||
PropertyChangeMask | StructureNotifyMask |
|
||||
KeymapStateMask | fevent));
|
||||
}
|
||||
|
||||
/* For _ICC_PROFILE. */
|
||||
X11_XSelectInput(display, RootWindow(display, screen), PropertyChangeMask);
|
||||
@@ -832,7 +840,8 @@ static int X11_CatchAnyError(Display *d, XErrorEvent *e)
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum check_method {
|
||||
enum check_method
|
||||
{
|
||||
COMPARE_POSITION = 1,
|
||||
COMPARE_SIZE = 2,
|
||||
COMPARE_DOUBLE_ATTEMPT = 3,
|
||||
@@ -842,8 +851,8 @@ enum check_method {
|
||||
/* Wait a brief time, or not, to see if the window manager decided to move/resize the window.
|
||||
* Send MOVED and RESIZED window events */
|
||||
static void X11_WaitAndSendWindowEvents(SDL_Window *window, int param_timeout, enum check_method method,
|
||||
int orig_x, int orig_y, int dest_x, int dest_y,
|
||||
int orig_w, int orig_h, int dest_w, int dest_h)
|
||||
int orig_x, int orig_y, int dest_x, int dest_y,
|
||||
int orig_w, int orig_h, int dest_w, int dest_h)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
Display *display = data->videodata->display;
|
||||
@@ -934,7 +943,6 @@ static void X11_WaitAndSendWindowEvents(SDL_Window *window, int param_timeout, e
|
||||
caught_x11_error = SDL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
int X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon)
|
||||
{
|
||||
SDL_WindowData *data = window->driverdata;
|
||||
@@ -974,8 +982,8 @@ int X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *i
|
||||
}
|
||||
|
||||
X11_XChangeProperty(display, data->xwindow, _NET_WM_ICON, XA_CARDINAL,
|
||||
32, PropModeReplace, (unsigned char *)propdata,
|
||||
propsize);
|
||||
32, PropModeReplace, (unsigned char *)propdata,
|
||||
propsize);
|
||||
SDL_free(propdata);
|
||||
|
||||
if (caught_x11_error) {
|
||||
@@ -1351,7 +1359,6 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
if (data->border_left == 0 && data->border_right == 0 && data->border_top == 0 && data->border_bottom == 0) {
|
||||
X11_GetBorderValues(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void X11_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
@@ -1485,7 +1492,6 @@ static void X11_SetWindowMaximized(SDL_VideoDevice *_this, SDL_Window *window, S
|
||||
/* Send MOVED/RESIZED event, if needed. Compare with initial position and size. Timeout 1000 */
|
||||
X11_WaitAndSendWindowEvents(window, 1000, COMPARE_ORIG, orig_x, orig_y, 0, 0, orig_w, orig_h, 0, 0);
|
||||
|
||||
|
||||
} else {
|
||||
X11_SetNetWMState(_this, data->xwindow, window->flags);
|
||||
}
|
||||
|
||||
+169
-11
@@ -22,9 +22,12 @@
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11
|
||||
|
||||
#include "SDL_x11pen.h"
|
||||
#include "SDL_x11video.h"
|
||||
#include "SDL_x11xinput2.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "../../events/SDL_pen_c.h"
|
||||
#include "../../events/SDL_touch_c.h"
|
||||
|
||||
#define MAX_AXIS 16
|
||||
@@ -74,19 +77,25 @@ static SDL_bool xinput2_version_atleast(const int version, const int wantmajor,
|
||||
return version >= ((wantmajor * 1000) + wantminor);
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
static SDL_Window *xinput2_get_sdlwindow(SDL_VideoData *videodata, Window window)
|
||||
static SDL_WindowData *xinput2_get_sdlwindowdata(SDL_VideoData *videodata, Window window)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < videodata->numwindows; i++) {
|
||||
SDL_WindowData *d = videodata->windowlist[i];
|
||||
if (d->xwindow == window) {
|
||||
return d->window;
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static SDL_Window *xinput2_get_sdlwindow(SDL_VideoData *videodata, Window window)
|
||||
{
|
||||
const SDL_WindowData *windowdata = xinput2_get_sdlwindowdata(videodata, window);
|
||||
return windowdata ? windowdata->window : NULL;
|
||||
}
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
static void xinput2_normalize_touch_coordinates(SDL_Window *window, double in_x, double in_y, float *out_x, float *out_y)
|
||||
{
|
||||
if (window) {
|
||||
@@ -262,18 +271,51 @@ static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata,
|
||||
|
||||
return devinfo;
|
||||
}
|
||||
|
||||
static void xinput2_pen_ensure_window(SDL_VideoDevice *_this, const SDL_Pen *pen, Window window)
|
||||
{
|
||||
/* When "flipping" a Wacom eraser pen, we get an XI_DeviceChanged event
|
||||
* with the newly-activated pen, but this event is global for the display.
|
||||
* We won't get a window until the pen starts triggering motion or
|
||||
* button events, so we instead hook the pen to its window at that point. */
|
||||
const SDL_WindowData *windowdata = X11_FindWindow(_this, window);
|
||||
if (windowdata) {
|
||||
SDL_SendPenWindowEvent(0, pen->header.id, windowdata->window);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie)
|
||||
int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
|
||||
{
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
|
||||
|
||||
if (cookie->extension != xinput2_opcode) {
|
||||
return 0;
|
||||
}
|
||||
switch (cookie->evtype) {
|
||||
case XI_PropertyEvent:
|
||||
case XI_DeviceChanged:
|
||||
{
|
||||
X11_InitPen(_this);
|
||||
} break;
|
||||
|
||||
case XI_Enter:
|
||||
case XI_Leave:
|
||||
{
|
||||
const XIEnterEvent *enterev = (const XIEnterEvent *)cookie->data;
|
||||
const SDL_WindowData *windowdata = X11_FindWindow(_this, enterev->event);
|
||||
const SDL_Pen *pen = SDL_GetPenPtr(X11_PenIDFromDeviceID(enterev->sourceid));
|
||||
SDL_Window *window = (windowdata && (cookie->evtype == XI_Enter)) ? windowdata->window : NULL;
|
||||
if (pen) {
|
||||
SDL_SendPenWindowEvent(0, pen->header.id, window);
|
||||
}
|
||||
} break;
|
||||
|
||||
case XI_RawMotion:
|
||||
{
|
||||
const XIRawEvent *rawev = (const XIRawEvent *)cookie->data;
|
||||
const SDL_bool is_pen = X11_PenIDFromDeviceID(rawev->sourceid) != SDL_PEN_INVALID;
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_XInput2DeviceInfo *devinfo;
|
||||
double coords[2];
|
||||
@@ -281,6 +323,11 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie
|
||||
int i;
|
||||
|
||||
videodata->global_mouse_changed = SDL_TRUE;
|
||||
if (is_pen) {
|
||||
return 0; /* Pens check for XI_Motion instead */
|
||||
}
|
||||
|
||||
/* Non-pen: */
|
||||
|
||||
if (!mouse->relative_mode || mouse->relative_mode_warp) {
|
||||
return 0;
|
||||
@@ -317,6 +364,7 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie
|
||||
xinput2_remove_device_info(videodata, hierev->info[i].deviceid);
|
||||
}
|
||||
}
|
||||
X11_InitPen(_this);
|
||||
} break;
|
||||
|
||||
case XI_RawButtonPress:
|
||||
@@ -326,17 +374,94 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie
|
||||
case XI_RawTouchUpdate:
|
||||
case XI_RawTouchEnd:
|
||||
#endif
|
||||
{
|
||||
videodata->global_mouse_changed = SDL_TRUE;
|
||||
break;
|
||||
} break;
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
/* With multitouch, register to receive XI_Motion (which desctivates MotionNotify),
|
||||
* so that we can distinguish real mouse motions from synthetic one. */
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
{
|
||||
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
|
||||
const SDL_Pen *pen = SDL_GetPenPtr(X11_PenIDFromDeviceID(xev->deviceid));
|
||||
const int button = xev->detail;
|
||||
const SDL_bool pressed = (cookie->evtype == XI_ButtonPress) ? SDL_TRUE : SDL_FALSE;
|
||||
|
||||
if (pen) {
|
||||
xinput2_pen_ensure_window(_this, pen, xev->event);
|
||||
|
||||
/* Only report button event; if there was also pen movement / pressure changes, we expect
|
||||
an XI_Motion event first anyway */
|
||||
if (button == 1) {
|
||||
/* button 1 is the pen tip */
|
||||
if (pressed && SDL_PenPerformHitTest()) {
|
||||
/* Check whether we should handle window resize / move events */
|
||||
const SDL_WindowData *windowdata = X11_FindWindow(_this, xev->event);
|
||||
|
||||
if (X11_ProcessHitTest(_this, windowdata, pen->last.x, pen->last.y)) {
|
||||
SDL_SendWindowEvent(windowdata->window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0);
|
||||
return 1; /* Don't pass on this event */
|
||||
}
|
||||
}
|
||||
SDL_SendPenTipEvent(0, pen->header.id,
|
||||
pressed ? SDL_PRESSED : SDL_RELEASED);
|
||||
} else {
|
||||
SDL_SendPenButton(0, pen->header.id,
|
||||
pressed ? SDL_PRESSED : SDL_RELEASED,
|
||||
button - 1);
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
/* Otherwise assume a regular mouse */
|
||||
SDL_WindowData *windowdata = xinput2_get_sdlwindowdata(videodata, xev->event);
|
||||
|
||||
if (xev->deviceid != xev->sourceid) {
|
||||
/* Discard events from "Master" devices to avoid duplicates. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pressed) {
|
||||
X11_HandleButtonPress(_this, windowdata, button,
|
||||
xev->event_x, xev->event_y, xev->time);
|
||||
} else {
|
||||
X11_HandleButtonRelease(_this, windowdata, button);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
/* Register to receive XI_Motion (which deactivates MotionNotify), so that we can distinguish
|
||||
real mouse motions from synthetic ones, for multitouch and pen support. */
|
||||
case XI_Motion:
|
||||
{
|
||||
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
|
||||
const SDL_Pen *pen = SDL_GetPenPtr(X11_PenIDFromDeviceID(xev->deviceid));
|
||||
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
int pointer_emulated = (xev->flags & XIPointerEmulated);
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */
|
||||
|
||||
if (xev->deviceid != xev->sourceid) {
|
||||
/* Discard events from "Master" devices to avoid duplicates. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pen) {
|
||||
SDL_PenStatusInfo pen_status;
|
||||
|
||||
pen_status.x = xev->event_x;
|
||||
pen_status.y = xev->event_y;
|
||||
|
||||
X11_PenAxesFromValuators(pen,
|
||||
xev->valuators.values, xev->valuators.mask, xev->valuators.mask_len,
|
||||
&pen_status.axes[0]);
|
||||
|
||||
xinput2_pen_ensure_window(_this, pen, xev->event);
|
||||
|
||||
SDL_SendPenMotion(0, pen->header.id,
|
||||
SDL_TRUE,
|
||||
&pen_status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
if (!pointer_emulated) {
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
if (!mouse->relative_mode || mouse->relative_mode_warp) {
|
||||
@@ -347,8 +472,10 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */
|
||||
} break;
|
||||
|
||||
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
case XI_TouchBegin:
|
||||
{
|
||||
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
|
||||
@@ -376,10 +503,9 @@ int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie
|
||||
SDL_SendTouchMotion(0, xev->sourceid, xev->detail, window, x, y, 1.0);
|
||||
return 1;
|
||||
} break;
|
||||
|
||||
#endif
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */
|
||||
}
|
||||
#endif
|
||||
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -460,6 +586,38 @@ int X11_Xinput2IsInitialized(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
SDL_bool X11_Xinput2SelectMouse(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
|
||||
const SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
|
||||
XIEventMask eventmask;
|
||||
unsigned char mask[4] = { 0, 0, 0, 0 };
|
||||
SDL_WindowData *window_data = (SDL_WindowData *)window->driverdata;
|
||||
|
||||
eventmask.mask_len = sizeof(mask);
|
||||
eventmask.mask = mask;
|
||||
eventmask.deviceid = XIAllDevices;
|
||||
|
||||
XISetMask(mask, XI_ButtonPress);
|
||||
XISetMask(mask, XI_ButtonRelease);
|
||||
XISetMask(mask, XI_Motion);
|
||||
XISetMask(mask, XI_Enter);
|
||||
XISetMask(mask, XI_Leave);
|
||||
/* Hotplugging: */
|
||||
XISetMask(mask, XI_DeviceChanged);
|
||||
XISetMask(mask, XI_HierarchyChanged);
|
||||
XISetMask(mask, XI_PropertyEvent); /* E.g., when swapping tablet pens */
|
||||
|
||||
if (X11_XISelectEvents(data->display,
|
||||
window_data->xwindow,
|
||||
&eventmask, 1) == Success) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, "Could not enable XInput2 mouse event handling\n");
|
||||
#endif
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
int X11_Xinput2IsMultitouchSupported(void)
|
||||
{
|
||||
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
|
||||
|
||||
@@ -32,11 +32,12 @@ typedef struct XGenericEventCookie XGenericEventCookie;
|
||||
|
||||
extern void X11_InitXinput2(SDL_VideoDevice *_this);
|
||||
extern void X11_InitXinput2Multitouch(SDL_VideoDevice *_this);
|
||||
extern int X11_HandleXinput2Event(SDL_VideoData *videodata, XGenericEventCookie *cookie);
|
||||
extern int X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie);
|
||||
extern int X11_Xinput2IsInitialized(void);
|
||||
extern int X11_Xinput2IsMultitouchSupported(void);
|
||||
extern void X11_Xinput2SelectTouch(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void X11_Xinput2GrabTouch(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern void X11_Xinput2UngrabTouch(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
extern SDL_bool X11_Xinput2SelectMouse(SDL_VideoDevice *_this, SDL_Window *window);
|
||||
|
||||
#endif /* SDL_x11xinput2_h_ */
|
||||
|
||||
@@ -328,6 +328,7 @@ add_sdl_test_executable(testgles2 SOURCES testgles2.c)
|
||||
add_sdl_test_executable(testgles2_sdf NEEDS_RESOURCES TESTUTILS SOURCES testgles2_sdf.c)
|
||||
add_sdl_test_executable(testhaptic SOURCES testhaptic.c)
|
||||
add_sdl_test_executable(testhotplug SOURCES testhotplug.c)
|
||||
add_sdl_test_executable(testpen SOURCES testpen.c)
|
||||
add_sdl_test_executable(testrumble SOURCES testrumble.c)
|
||||
add_sdl_test_executable(testthread NONINTERACTIVE NONINTERACTIVE_TIMEOUT 40 SOURCES testthread.c)
|
||||
add_sdl_test_executable(testiconv NEEDS_RESOURCES TESTUTILS SOURCES testiconv.c)
|
||||
|
||||
@@ -33,6 +33,7 @@ static SDLTest_TestSuiteReference *testSuites[] = {
|
||||
&mainTestSuite,
|
||||
&mathTestSuite,
|
||||
&mouseTestSuite,
|
||||
&penTestSuite,
|
||||
&pixelsTestSuite,
|
||||
&platformTestSuite,
|
||||
&propertiesTestSuite,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,7 @@ extern SDLTest_TestSuiteReference keyboardTestSuite;
|
||||
extern SDLTest_TestSuiteReference mainTestSuite;
|
||||
extern SDLTest_TestSuiteReference mathTestSuite;
|
||||
extern SDLTest_TestSuiteReference mouseTestSuite;
|
||||
extern SDLTest_TestSuiteReference penTestSuite;
|
||||
extern SDLTest_TestSuiteReference pixelsTestSuite;
|
||||
extern SDLTest_TestSuiteReference platformTestSuite;
|
||||
extern SDLTest_TestSuiteReference propertiesTestSuite;
|
||||
|
||||
+496
@@ -0,0 +1,496 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_main.h>
|
||||
#include <SDL3/SDL_test.h>
|
||||
#include <SDL3/SDL_test_common.h>
|
||||
|
||||
#define WIDTH 1600
|
||||
#define HEIGHT 1200
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#define ALWAYS_SHOW_PRESSURE_BOX 1
|
||||
|
||||
static SDLTest_CommonState *state;
|
||||
static int quitting = 0;
|
||||
|
||||
static float last_x, last_y;
|
||||
static float last_xtilt, last_ytilt, last_pressure, last_distance, last_rotation;
|
||||
static int last_button;
|
||||
static int last_touching; /* tip touches surface */
|
||||
static int last_was_eraser;
|
||||
|
||||
static SDL_Texture *offscreen_texture = NULL;
|
||||
|
||||
static void DrawScreen(SDL_Renderer *renderer)
|
||||
{
|
||||
float xdelta, ydelta, endx, endy;
|
||||
/* off-screen texture to render into */
|
||||
SDL_Texture *window_texture;
|
||||
const float X = 128.0f, Y = 128.0f; /* mid-point in the off-screen texture */
|
||||
SDL_FRect dest_rect;
|
||||
float tilt_vec_x = SDL_sinf(last_xtilt * SDL_PI_F / 180.0f);
|
||||
float tilt_vec_y = SDL_sinf(last_ytilt * SDL_PI_F / 180.0f);
|
||||
int color = last_button + 1;
|
||||
|
||||
if (!renderer) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(renderer, 0x40, 0x40, 0x40, 0xff);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
if (offscreen_texture == NULL) {
|
||||
offscreen_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, (int)(X * 2.0f), (int)(Y * 2.0f));
|
||||
}
|
||||
|
||||
/* Render into off-screen texture so we can do pixel-precise rendering later */
|
||||
window_texture = SDL_GetRenderTarget(renderer);
|
||||
SDL_SetRenderTarget(renderer, offscreen_texture);
|
||||
|
||||
/* Rendering starts here */
|
||||
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(renderer, 0x40, 0x40, 0x40, 0xff);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0xa0, 0xa0, 0xa0, 0xff);
|
||||
if (last_touching) {
|
||||
SDL_FRect rect;
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.w = 2.0f * X - 1.0f;
|
||||
rect.h = 2.0f * Y - 1.0f;
|
||||
|
||||
SDL_RenderRect(renderer, &rect);
|
||||
} else {
|
||||
/* Show where the pen is rotating when it isn't touching the surface.
|
||||
Otherwise we draw the rotation angle below together with pressure information. */
|
||||
float rot_vecx = SDL_sinf(last_rotation / 180.0f * SDL_PI_F);
|
||||
float rot_vecy = -SDL_cosf(last_rotation / 180.0f * SDL_PI_F);
|
||||
float px = X + rot_vecx * 100.0f;
|
||||
float py = Y + rot_vecy * 100.0f;
|
||||
float px2 = X + rot_vecx * 80.0f;
|
||||
float py2 = Y + rot_vecy * 80.0f;
|
||||
|
||||
SDL_RenderLine(renderer,
|
||||
px, py,
|
||||
px2 + rot_vecy * 20.0f,
|
||||
py2 - rot_vecx * 20.0f);
|
||||
SDL_RenderLine(renderer,
|
||||
px, py,
|
||||
px2 - rot_vecy * 20.0f,
|
||||
py2 + rot_vecx * 20.0f);
|
||||
}
|
||||
|
||||
if (last_was_eraser) {
|
||||
SDL_FRect rect;
|
||||
|
||||
rect.x = X - 10.0f;
|
||||
rect.y = Y - 10.0f;
|
||||
rect.w = 21.0f;
|
||||
rect.h = 21.0f;
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0x00, 0xff, 0xff, 0xff);
|
||||
SDL_RenderFillRect(renderer, &rect);
|
||||
} else {
|
||||
float distance = last_distance * 50.0f;
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 0xff, 0, 0, 0xff);
|
||||
SDL_RenderLine(renderer,
|
||||
X - 10.0f - distance, Y,
|
||||
X - distance, Y);
|
||||
SDL_RenderLine(renderer,
|
||||
X + 10.0f + distance, Y,
|
||||
X + distance, Y);
|
||||
SDL_RenderLine(renderer,
|
||||
X, Y - 10.0f - distance,
|
||||
X, Y - distance);
|
||||
SDL_RenderLine(renderer,
|
||||
X, Y + 10.0f + distance,
|
||||
X, Y + distance);
|
||||
|
||||
}
|
||||
|
||||
/* Draw a cone based on the direction the pen is leaning as if it were shining a light. */
|
||||
/* Colour derived from pens, intensity based on pressure: */
|
||||
SDL_SetRenderDrawColor(renderer,
|
||||
(color & 0x01) ? 0xff : 0,
|
||||
(color & 0x02) ? 0xff : 0,
|
||||
(color & 0x04) ? 0xff : 0,
|
||||
(int)(0xff));
|
||||
|
||||
xdelta = -tilt_vec_x * 100.0f;
|
||||
ydelta = -tilt_vec_y * 100.0f;
|
||||
endx = X + xdelta;
|
||||
endy = Y + ydelta;
|
||||
SDL_RenderLine(renderer, X, Y, endx, endy);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer,
|
||||
(color & 0x01) ? 0xff : 0,
|
||||
(color & 0x02) ? 0xff : 0,
|
||||
(color & 0x04) ? 0xff : 0,
|
||||
(int)(0xff * last_pressure));
|
||||
/* Cone base width based on pressure: */
|
||||
SDL_RenderLine(renderer, X, Y, endx + (ydelta * last_pressure / 3.0f), endy - (xdelta * last_pressure / 3.0f));
|
||||
SDL_RenderLine(renderer, X, Y, endx - (ydelta * last_pressure / 3.0f), endy + (xdelta * last_pressure / 3.0f));
|
||||
|
||||
/* If tilt is very small (or zero, for pens that don't have tilt), add some extra lines, rotated by the current rotation value */
|
||||
if (ALWAYS_SHOW_PRESSURE_BOX || (fabs(tilt_vec_x) < 0.2f && fabs(tilt_vec_y) < 0.2f)) {
|
||||
int rot;
|
||||
float pressure = last_pressure * 80.0f;
|
||||
|
||||
/* Four times, rotated 90 degrees, so that we get a box */
|
||||
for (rot = 0; rot < 4; ++rot) {
|
||||
|
||||
float vecx = SDL_cosf((last_rotation + (rot * 90.0f)) / 180.0f * SDL_PI_F);
|
||||
float vecy = SDL_sinf((last_rotation + (rot * 90.0f)) / 180.0f * SDL_PI_F);
|
||||
|
||||
float px = X + vecx * pressure;
|
||||
float py = Y + vecy * pressure;
|
||||
|
||||
SDL_RenderLine(renderer,
|
||||
px + vecy * 10.0f, py - vecx * 10.0f,
|
||||
px - vecy * 10.0f, py + vecx * 10.0f);
|
||||
|
||||
if (rot == 3) {
|
||||
int r = 0;
|
||||
for (; r >= 0; r -= 2) {
|
||||
float delta = 10.0f - ((float) r);
|
||||
|
||||
SDL_RenderLine(renderer,
|
||||
px + vecy * delta, py - vecx * delta,
|
||||
px + (vecx * pressure * 0.4f),
|
||||
py + (vecy * pressure * 0.4f));
|
||||
SDL_RenderLine(renderer,
|
||||
px - vecy * delta, py + vecx * delta,
|
||||
px + (vecx * pressure * 0.4f),
|
||||
py + (vecy * pressure * 0.4f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SetRenderTarget(renderer, window_texture);
|
||||
/* Now render to pixel-precise position */
|
||||
dest_rect.x = last_x - X;
|
||||
dest_rect.y = last_y - Y;
|
||||
dest_rect.w = X * 2.0f;
|
||||
dest_rect.h = Y * 2.0f;
|
||||
SDL_RenderTexture(renderer, offscreen_texture, NULL, &dest_rect);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
static void dump_state(void)
|
||||
{
|
||||
int i;
|
||||
int pens_nr;
|
||||
|
||||
/* Make sure this also works with a NULL parameter */
|
||||
SDL_PenID* pens = SDL_GetPens(NULL);
|
||||
if (pens) {
|
||||
SDL_free(pens);
|
||||
}
|
||||
|
||||
pens = SDL_GetPens(&pens_nr);
|
||||
if (!pens) {
|
||||
SDL_Log("Couldn't get pens: %s\n", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
SDL_Log("Found %d pens (terminated by %u)\n", pens_nr, (unsigned) pens[pens_nr]);
|
||||
|
||||
for (i = 0; i < pens_nr; ++i) {
|
||||
SDL_PenID penid = pens[i];
|
||||
SDL_GUID guid = SDL_GetPenGUID(penid);
|
||||
char guid_str[33];
|
||||
float axes[SDL_PEN_NUM_AXES];
|
||||
float x, y;
|
||||
int k;
|
||||
SDL_PenCapabilityInfo info;
|
||||
Uint32 status = SDL_GetPenStatus(penid, &x, &y, axes, SDL_PEN_NUM_AXES);
|
||||
Uint32 capabilities = SDL_GetPenCapabilities(penid, &info);
|
||||
char *type;
|
||||
char *buttons_str;
|
||||
|
||||
SDL_GUIDToString(guid, guid_str, 33);
|
||||
|
||||
switch (SDL_GetPenType(penid)) {
|
||||
case SDL_PEN_TYPE_ERASER:
|
||||
type = "Eraser";
|
||||
break;
|
||||
case SDL_PEN_TYPE_PEN:
|
||||
type = "Pen";
|
||||
break;
|
||||
case SDL_PEN_TYPE_PENCIL:
|
||||
type = "Pencil";
|
||||
break;
|
||||
case SDL_PEN_TYPE_BRUSH:
|
||||
type = "Brush";
|
||||
break;
|
||||
case SDL_PEN_TYPE_AIRBRUSH:
|
||||
type = "Airbrush";
|
||||
break;
|
||||
default:
|
||||
type = "Unknown (bug?)";
|
||||
}
|
||||
|
||||
switch (info.num_buttons) {
|
||||
case SDL_PEN_INFO_UNKNOWN:
|
||||
SDL_asprintf(&buttons_str, "? buttons");
|
||||
break;
|
||||
case 1:
|
||||
SDL_asprintf(&buttons_str, "1 button");
|
||||
break;
|
||||
default:
|
||||
SDL_asprintf(&buttons_str, "%d button", info.num_buttons);
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_Log("%s %lu: [%s] attached=%d, %s [cap= %08lx:%08lx =status] '%s'\n",
|
||||
type,
|
||||
(unsigned long) penid, guid_str,
|
||||
SDL_PenConnected(penid), /* should always be SDL_TRUE during iteration */
|
||||
buttons_str,
|
||||
(unsigned long) capabilities,
|
||||
(unsigned long) status,
|
||||
SDL_GetPenName(penid));
|
||||
SDL_free(buttons_str);
|
||||
SDL_Log(" pos=(%.2f, %.2f)", x, y);
|
||||
for (k = 0; k < SDL_PEN_NUM_AXES; ++k) {
|
||||
SDL_bool supported = capabilities & SDL_PEN_AXIS_CAPABILITY(k);
|
||||
if (supported) {
|
||||
if (k == SDL_PEN_AXIS_XTILT || k == SDL_PEN_AXIS_YTILT) {
|
||||
if (info.max_tilt == SDL_PEN_INFO_UNKNOWN) {
|
||||
SDL_Log(" axis %d: %.3f (max tilt unknown)", k, axes[k]);
|
||||
} else {
|
||||
SDL_Log(" axis %d: %.3f (tilt -%.1f..%.1f)", k, axes[k],
|
||||
info.max_tilt, info.max_tilt);
|
||||
}
|
||||
} else {
|
||||
SDL_Log(" axis %d: %.3f", k, axes[k]);
|
||||
}
|
||||
} else {
|
||||
SDL_Log(" axis %d: unsupported (%.3f)", k, axes[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_free(pens);
|
||||
}
|
||||
|
||||
static void update_axes(float *axes)
|
||||
{
|
||||
last_xtilt = axes[SDL_PEN_AXIS_XTILT];
|
||||
last_ytilt = axes[SDL_PEN_AXIS_YTILT];
|
||||
last_pressure = axes[SDL_PEN_AXIS_PRESSURE];
|
||||
last_distance = axes[SDL_PEN_AXIS_DISTANCE];
|
||||
last_rotation = axes[SDL_PEN_AXIS_ROTATION];
|
||||
}
|
||||
|
||||
static void process_event(SDL_Event event)
|
||||
{
|
||||
SDLTest_CommonEvent(state, &event, &quitting);
|
||||
|
||||
switch (event.type) {
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
{
|
||||
dump_state();
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
#if VERBOSE
|
||||
{
|
||||
float x, y;
|
||||
SDL_GetMouseState(&x, &y);
|
||||
if (event.type == SDL_EVENT_MOUSE_MOTION) {
|
||||
SDL_Log("[%lu] mouse motion: mouse ID %d is at (%.2f, %.2f) (state: %.2f,%.2f) delta (%.2f, %.2f)\n",
|
||||
event.motion.timestamp,
|
||||
event.motion.which,
|
||||
event.motion.x, event.motion.y,
|
||||
event.motion.xrel, event.motion.yrel,
|
||||
x, y);
|
||||
} else {
|
||||
SDL_Log("[%lu] mouse button: mouse ID %d is at (%.2f, %.2f) (state: %.2f,%.2f)\n",
|
||||
event.button.timestamp,
|
||||
event.button.which,
|
||||
event.button.x, event.button.y,
|
||||
x, y);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (event.motion.which != SDL_PEN_MOUSEID) {
|
||||
SDL_ShowCursor();
|
||||
} break;
|
||||
|
||||
case SDL_EVENT_PEN_MOTION:
|
||||
{
|
||||
SDL_PenMotionEvent *ev = &event.pmotion;
|
||||
|
||||
SDL_HideCursor();
|
||||
last_x = ev->x;
|
||||
last_y = ev->y;
|
||||
update_axes(ev->axes);
|
||||
last_was_eraser = ev->pen_state & SDL_PEN_ERASER_MASK;
|
||||
#if VERBOSE
|
||||
SDL_Log("[%lu] pen motion: %s %u at (%.4f, %.4f); pressure=%.3f, tilt=%.3f/%.3f, dist=%.3f [buttons=%02x]\n",
|
||||
(unsigned long) ev->timestamp,
|
||||
last_was_eraser ? "eraser" : "pen",
|
||||
(unsigned int)ev->which, ev->x, ev->y, last_pressure, last_xtilt, last_ytilt, last_distance,
|
||||
ev->pen_state);
|
||||
#endif
|
||||
} break;
|
||||
|
||||
case SDL_EVENT_PEN_UP:
|
||||
case SDL_EVENT_PEN_DOWN: {
|
||||
SDL_PenTipEvent *ev = &event.ptip;
|
||||
last_x = ev->x;
|
||||
last_y = ev->y;
|
||||
update_axes(ev->axes);
|
||||
last_was_eraser = ev->tip == SDL_PEN_TIP_ERASER;
|
||||
last_button = ev->pen_state & 0xf; /* button mask */
|
||||
last_touching = (event.type == SDL_EVENT_PEN_DOWN);
|
||||
} break;
|
||||
|
||||
case SDL_EVENT_PEN_BUTTON_UP:
|
||||
case SDL_EVENT_PEN_BUTTON_DOWN:
|
||||
{
|
||||
SDL_PenButtonEvent *ev = &event.pbutton;
|
||||
|
||||
SDL_HideCursor();
|
||||
last_x = ev->x;
|
||||
last_y = ev->y;
|
||||
update_axes(ev->axes);
|
||||
if (last_pressure > 0.0f && !last_touching) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_TEST,
|
||||
"[%lu] : reported pressure %.5f even though pen is not touching surface",
|
||||
(unsigned long) ev->timestamp, last_pressure);
|
||||
|
||||
}
|
||||
last_was_eraser = ev->pen_state & SDL_PEN_ERASER_MASK;
|
||||
last_button = ev->pen_state & 0xf; /* button mask */
|
||||
if ((ev->pen_state & SDL_PEN_DOWN_MASK) && !last_touching) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_TEST,
|
||||
"[%lu] : reported flags %x (SDL_PEN_FLAG_DOWN_MASK) despite not receiving SDL_EVENT_PEN_DOWN",
|
||||
(unsigned long) ev->timestamp, ev->pen_state);
|
||||
|
||||
}
|
||||
if (!(ev->pen_state & SDL_PEN_DOWN_MASK) && last_touching) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_TEST,
|
||||
"[%lu] : reported flags %x (no SDL_PEN_FLAG_DOWN_MASK) despite receiving SDL_EVENT_PEN_DOWN without SDL_EVENT_PEN_UP afterwards",
|
||||
(unsigned long) ev->timestamp, ev->pen_state);
|
||||
|
||||
}
|
||||
#if VERBOSE
|
||||
SDL_Log("[%lu] pen button: %s %u at (%.4f, %.4f); BUTTON %d reported %s with event %s [pressure=%.3f, tilt=%.3f/%.3f, dist=%.3f]\n",
|
||||
(unsigned long) ev->timestamp,
|
||||
last_was_eraser ? "eraser" : "pen",
|
||||
(unsigned int)ev->which, ev->x, ev->y,
|
||||
ev->button,
|
||||
(ev->state == SDL_PRESSED) ? "PRESSED"
|
||||
: ((ev->state == SDL_RELEASED) ? "RELEASED" : "--invalid--"),
|
||||
event.type == SDL_EVENT_PEN_BUTTON_UP ? "PENBUTTONUP" : "PENBUTTONDOWN",
|
||||
last_pressure, last_xtilt, last_ytilt, last_distance);
|
||||
#endif
|
||||
} break;
|
||||
|
||||
case SDL_EVENT_WINDOW_PEN_ENTER:
|
||||
SDL_Log("[%lu] Pen %lu entered window %lx",
|
||||
(unsigned long) event.window.timestamp,
|
||||
(unsigned long) event.window.data1,
|
||||
(unsigned long) event.window.windowID);
|
||||
break;
|
||||
|
||||
case SDL_EVENT_WINDOW_PEN_LEAVE:
|
||||
SDL_Log("[%lu] Pen %lu left window %lx",
|
||||
(unsigned long) event.window.timestamp,
|
||||
(unsigned long) event.window.data1,
|
||||
(unsigned long) event.window.windowID);
|
||||
break;
|
||||
|
||||
#if VERBOSE
|
||||
case SDL_EVENT_WINDOW_MOUSE_ENTER:
|
||||
SDL_Log("[%lu] Mouse entered window %lx",
|
||||
(unsigned long) event.window.timestamp,
|
||||
(unsigned long) event.window.windowID);
|
||||
break;
|
||||
|
||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||
SDL_Log("[%lu] Mouse left window %lx",
|
||||
(unsigned long) event.window.timestamp,
|
||||
(unsigned long) event.window.windowID);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void loop(void)
|
||||
{
|
||||
SDL_Event event;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < state->num_windows; ++i) {
|
||||
if (state->renderers[i]) {
|
||||
DrawScreen(state->renderers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_WaitEventTimeout(&event, 10)) {
|
||||
process_event(event);
|
||||
}
|
||||
while (SDL_PollEvent(&event)) {
|
||||
process_event(event);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
|
||||
if (!state) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
|
||||
|
||||
state->window_title = "Pressure-Sensitive Pen Test";
|
||||
state->window_w = WIDTH;
|
||||
state->window_h = HEIGHT;
|
||||
state->skip_renderer = SDL_FALSE;
|
||||
|
||||
if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) {
|
||||
SDLTest_CommonQuit(state);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (!quitting) {
|
||||
loop();
|
||||
}
|
||||
|
||||
SDLTest_CommonQuit(state);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user