Skip to content

Commit c7b69ed

Browse files
committed
Initial pressure-sensitive pen API + XInput2 implementation
- Adds new event types "PenMotion" and "PenButton" - Adds internal pipeline for reporting pen events, tee-ing them into mouse events with mouse ID SDL_PEN_MOUSEID - XInput2 pen support, incl. pressure, horizontal / vertical tilt - Test program: test/testpen bool -> SDL_bool fixes by @sezero
1 parent 1c9299b commit c7b69ed

File tree

11 files changed

+171
-26
lines changed

11 files changed

+171
-26
lines changed

include/SDL_events.h

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ typedef enum
157157
/* Sensor events */
158158
SDL_SENSORUPDATE = 0x1200, /**< A sensor was updated */
159159

160+
/* Pressure-sensitive pen events */
161+
SDL_PENMOTION = 0x1300, /**< Pressure-sensitive pen moved, or change in angle/pressure changed */
162+
SDL_PENBUTTONDOWN, /**< Pressure-sensitive pen button pressed */
163+
SDL_PENBUTTONUP, /**< Pressure-sensitive pen button released */
164+
160165
/* Render events */
161166
SDL_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */
162167
SDL_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */
@@ -278,7 +283,7 @@ typedef struct SDL_MouseMotionEvent
278283
Uint32 type; /**< ::SDL_MOUSEMOTION */
279284
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
280285
Uint32 windowID; /**< The window with mouse focus, if any */
281-
Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
286+
Uint32 which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */
282287
Uint32 state; /**< The current button state */
283288
Sint32 x; /**< X coordinate, relative to window */
284289
Sint32 y; /**< Y coordinate, relative to window */
@@ -294,7 +299,7 @@ typedef struct SDL_MouseButtonEvent
294299
Uint32 type; /**< ::SDL_MOUSEBUTTONDOWN or ::SDL_MOUSEBUTTONUP */
295300
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
296301
Uint32 windowID; /**< The window with mouse focus, if any */
297-
Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
302+
Uint32 which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */
298303
Uint8 button; /**< The mouse button index */
299304
Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
300305
Uint8 clicks; /**< 1 for single-click, 2 for double-click, etc. */
@@ -311,7 +316,7 @@ typedef struct SDL_MouseWheelEvent
311316
Uint32 type; /**< ::SDL_MOUSEWHEEL */
312317
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
313318
Uint32 windowID; /**< The window with mouse focus, if any */
314-
Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
319+
Uint32 which; /**< The mouse instance id, SDL_TOUCH_MOUSEID, or SDL_PEN_MOUSEID */
315320
Sint32 x; /**< The amount scrolled horizontally, positive to the right and negative to the left */
316321
Sint32 y; /**< The amount scrolled vertically, positive away from the user and negative toward the user */
317322
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 */
@@ -530,6 +535,43 @@ typedef struct SDL_DollarGestureEvent
530535
float y; /**< Normalized center of gesture */
531536
} SDL_DollarGestureEvent;
532537

538+
/**
539+
* \brief Pressure-sensitive pen motion / pressure / angle event structure (event.pmotion.*)
540+
*/
541+
typedef struct SDL_PenMotionEvent
542+
{
543+
Uint32 type; /**< ::SDL_PENMOTION */
544+
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
545+
Uint32 windowID; /**< The window with pen focus, if any */
546+
Uint32 which; /**< The pen instance id */
547+
Uint16 state; /**< The current button state */
548+
Uint8 eraser; /**< Nonzero iff this pen is an eraser */
549+
float x; /**< X coordinate, relative to window */
550+
float y; /**< Y coordinate, relative to window */
551+
float pressure; /**< Pen pressure, normalised to the range 0..1.0 */
552+
float xtilt; /**< Pen horizontal tilt, normalised to the range -1.0..1.0 */
553+
float ytilt; /**< Pen vertical tilt, normalised to the range -1.0..1.0 */
554+
} SDL_PenMotionEvent;
555+
556+
/**
557+
* \brief Pressure-sensitive pen button event structure (event.pbutton.*)
558+
*/
559+
typedef struct SDL_PenButtonEvent
560+
{
561+
Uint32 type; /**< ::SDL_PENBUTTONDOWN or ::SDL_PENBUTTONUP */
562+
Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
563+
Uint32 windowID; /**< The window with pen focus, if any */
564+
Uint32 which; /**< The pen instance id */
565+
Uint8 button; /**< The pen button index */
566+
Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
567+
Uint8 eraser; /**< Nonzero iff this pen is an eraser */
568+
Uint8 padding1;
569+
float x; /**< X coordinate, relative to window */
570+
float y; /**< Y coordinate, relative to window */
571+
float pressure; /**< Pen pressure, normalised to the range 0..1.0 */
572+
float xtilt; /**< Pen horizontal tilt, normalised to the range -1.0..1.0 */
573+
float ytilt; /**< Pen vertical tilt, normalised to the range -1.0..1.0 */
574+
} SDL_PenButtonEvent;
533575

534576
/**
535577
* \brief An event used to request a file open by the system (event.drop.*)
@@ -638,6 +680,8 @@ typedef union SDL_Event
638680
SDL_TouchFingerEvent tfinger; /**< Touch finger event data */
639681
SDL_MultiGestureEvent mgesture; /**< Gesture event data */
640682
SDL_DollarGestureEvent dgesture; /**< Gesture event data */
683+
SDL_PenMotionEvent pmotion; /**< Pen change in position, pressure, or angle */
684+
SDL_PenButtonEvent pbutton; /**< Pen button press */
641685
SDL_DropEvent drop; /**< Drag and drop event data */
642686

643687
/* This is necessary for ABI compatibility between Visual C++ and GCC.

include/SDL_mouse.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ typedef enum
6969
SDL_MOUSEWHEEL_FLIPPED /**< The scroll direction is flipped / natural */
7070
} SDL_MouseWheelDirection;
7171

72+
/* Used as the device ID for mouse events triggered by pen events */
73+
#define SDL_PEN_MOUSEID ((Uint32)-2)
74+
75+
7276
/* Function prototypes */
7377

7478
/**

src/events/SDL_mouse.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -279,20 +279,29 @@ SDL_SetMouseFocus(SDL_Window * window)
279279
SDL_SetCursor(NULL);
280280
}
281281

282-
/* Check to see if we need to synthesize focus events */
283-
static SDL_bool
284-
SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate, SDL_bool send_mouse_motion)
282+
SDL_bool
283+
SDL_IsMousePositionInWindow(SDL_Window * window, SDL_MouseID mouseID, int x, int y)
285284
{
286-
SDL_Mouse *mouse = SDL_GetMouse();
287-
SDL_bool inWindow = SDL_TRUE;
285+
if (!window) {
286+
return SDL_FALSE;
287+
}
288288

289-
if (window && ((window->flags & SDL_WINDOW_MOUSE_CAPTURE) == 0)) {
289+
if (0 == (window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
290290
int w, h;
291291
SDL_GetWindowSize(window, &w, &h);
292292
if (x < 0 || y < 0 || x >= w || y >= h) {
293-
inWindow = SDL_FALSE;
293+
return SDL_FALSE;
294294
}
295295
}
296+
return SDL_TRUE;
297+
}
298+
299+
/* Check to see if we need to synthesize focus events */
300+
static SDL_bool
301+
SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate, SDL_bool send_mouse_motion)
302+
{
303+
SDL_Mouse *mouse = SDL_GetMouse();
304+
SDL_bool inWindow = SDL_IsMousePositionInWindow(window, mouse->mouseID, x, y);
296305

297306
if (!inWindow) {
298307
if (window == mouse->focus) {

src/events/SDL_mouse_c.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ extern int SDL_SendMouseButtonClicks(SDL_Window * window, SDL_MouseID mouseID, U
147147
/* Send a mouse wheel event */
148148
extern int SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction);
149149

150+
/* Check if mouse position is within window or captured by window */
151+
extern SDL_bool SDL_IsMousePositionInWindow(SDL_Window * window, SDL_MouseID mouseID, int x, int y);
152+
150153
/* Shutdown the mouse subsystem */
151154
extern void SDL_MouseQuit(void);
152155

src/video/x11/SDL_x11events.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
605605
int seln_format, mime_formats;
606606
unsigned long nbytes;
607607
unsigned long overflow;
608-
unsigned char *seln_data;
608+
unsigned char *seln_data;
609609
Atom supportedFormats[SDL_X11_CLIPBOARD_MIME_TYPE_MAX+1];
610610
Atom XA_TARGETS = X11_XInternAtom(display, "TARGETS", 0);
611611

@@ -625,7 +625,7 @@ X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
625625
/* !!! FIXME: We were probably storing this on the root window
626626
because an SDL window might go away...? but we don't have to do
627627
this now (or ever, really). */
628-
628+
629629
if (req->target == XA_TARGETS) {
630630
supportedFormats[0] = XA_TARGETS;
631631
mime_formats = 1;
@@ -908,7 +908,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
908908
if (xevent->xcrossing.mode != NotifyGrab &&
909909
xevent->xcrossing.mode != NotifyUngrab &&
910910
xevent->xcrossing.detail != NotifyInferior) {
911-
911+
912912
/* In order for interaction with the window decorations and menu to work properly
913913
on Mutter, we need to ungrab the keyboard when the the mouse leaves. */
914914
if (!(data->window->flags & SDL_WINDOW_FULLSCREEN)) {
@@ -1124,7 +1124,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
11241124
&xevent->xconfigure.x, &xevent->xconfigure.y,
11251125
&ChildReturn);
11261126
}
1127-
1127+
11281128
if (xevent->xconfigure.x != data->last_xconfigure.x ||
11291129
xevent->xconfigure.y != data->last_xconfigure.y) {
11301130
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED,

src/video/x11/SDL_x11video.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,8 @@ X11_VideoInit(_THIS)
471471

472472
X11_InitTouch(_this);
473473

474+
X11_InitPen(_this);
475+
474476
return 0;
475477
}
476478

src/video/x11/SDL_x11video.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include "SDL_x11modes.h"
6868
#include "SDL_x11mouse.h"
6969
#include "SDL_x11opengl.h"
70+
#include "SDL_x11pen.h"
7071
#include "SDL_x11window.h"
7172
#include "SDL_x11vulkan.h"
7273

@@ -154,6 +155,11 @@ typedef struct SDL_VideoData
154155
PFN_XGetXCBConnection vulkan_XGetXCBConnection;
155156
#endif
156157

158+
#if SDL_VIDEO_DRIVER_X11_XINPUT2
159+
Uint32 num_pens;
160+
SDL_X11Pen pens[SDL_MAX_PEN_DEVICES];
161+
#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
162+
157163
} SDL_VideoData;
158164

159165
extern SDL_bool X11_UseDirectColorVisuals(void);

src/video/x11/SDL_x11window.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
422422
#if SDL_VIDEO_OPENGL_EGL
423423
if (((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) ||
424424
SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE))
425-
#if SDL_VIDEO_OPENGL_GLX
425+
#if SDL_VIDEO_OPENGL_GLX
426426
&& ( !_this->gl_data || X11_GL_UseEGL(_this) )
427427
#endif
428428
) {
@@ -635,14 +635,14 @@ X11_CreateWindow(_THIS, SDL_Window * window)
635635
windowdata = (SDL_WindowData *) window->driverdata;
636636

637637
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2 || SDL_VIDEO_OPENGL_EGL
638-
if ((window->flags & SDL_WINDOW_OPENGL) &&
638+
if ((window->flags & SDL_WINDOW_OPENGL) &&
639639
((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) ||
640640
SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE))
641-
#if SDL_VIDEO_OPENGL_GLX
641+
#if SDL_VIDEO_OPENGL_GLX
642642
&& ( !_this->gl_data || X11_GL_UseEGL(_this) )
643-
#endif
643+
#endif
644644
) {
645-
#if SDL_VIDEO_OPENGL_EGL
645+
#if SDL_VIDEO_OPENGL_EGL
646646
if (!_this->egl_data) {
647647
return -1;
648648
}
@@ -658,7 +658,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
658658
#endif /* SDL_VIDEO_OPENGL_EGL */
659659
}
660660
#endif
661-
661+
662662

663663
#ifdef X_HAVE_UTF8_STRING
664664
if (SDL_X11_HAVE_UTF8 && windowdata->ic) {
@@ -675,6 +675,8 @@ X11_CreateWindow(_THIS, SDL_Window * window)
675675
PropertyChangeMask | StructureNotifyMask |
676676
KeymapStateMask | fevent));
677677

678+
X11_PenXinput2SelectEvents(_this);
679+
678680
/* For _ICC_PROFILE. */
679681
X11_XSelectInput(display, RootWindow(display, screen), PropertyChangeMask);
680682

0 commit comments

Comments
 (0)