From 9780425540b22a1f035965ce70c6abdba1401d73 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Thu, 1 Oct 2026 15:01:19 -0400
Subject: [PATCH] events: Send pen device type with each event.
It's the only thing you would need to query with an external function, and the
pen ID could be invalid by the time you run the event queue, so it's easier to
just include it with the events.
Fixes #16316.
---
include/SDL3/SDL_events.h | 5 +++++
src/events/SDL_pen.c | 22 ++++++++++++++++++----
2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h
index 990e16a38b653..524a1858ed2b5 100644
--- a/include/SDL3/SDL_events.h
+++ b/include/SDL3/SDL_events.h
@@ -914,6 +914,7 @@ typedef struct SDL_PenProximityEvent
SDL_WindowID windowID; /**< The window with pen focus, if any */
SDL_PenID which; /**< The pen instance id */
SDL_PenInputFlags pen_state; /**< Complete pen input state at time of event (added in 3.4.16). */
+ SDL_PenDeviceType device_type; /**< the device type of the pen, if known (added in 3.4.18). */
} SDL_PenProximityEvent;
/**
@@ -937,6 +938,7 @@ typedef struct SDL_PenMotionEvent
SDL_PenInputFlags pen_state; /**< Complete pen input state at time of event */
float x; /**< X coordinate, relative to window */
float y; /**< Y coordinate, relative to window */
+ SDL_PenDeviceType device_type; /**< the device type of the pen, if known (added in 3.4.18). */
} SDL_PenMotionEvent;
/**
@@ -959,6 +961,7 @@ typedef struct SDL_PenTouchEvent
float y; /**< Y coordinate, relative to window */
bool eraser; /**< true if eraser end is used (not all pens support this). */
bool down; /**< true if the pen is touching or false if the pen is lifted off */
+ SDL_PenDeviceType device_type; /**< the device type of the pen, if known (added in 3.4.18). */
} SDL_PenTouchEvent;
/**
@@ -981,6 +984,7 @@ typedef struct SDL_PenButtonEvent
float y; /**< Y coordinate, relative to window */
Uint8 button; /**< The pen button index (first button is 1). */
bool down; /**< true if the button is pressed */
+ SDL_PenDeviceType device_type; /**< the device type of the pen, if known (added in 3.4.18). */
} SDL_PenButtonEvent;
/**
@@ -1003,6 +1007,7 @@ typedef struct SDL_PenAxisEvent
float y; /**< Y coordinate, relative to window */
SDL_PenAxis axis; /**< Axis that has changed */
float value; /**< New value of axis */
+ SDL_PenDeviceType device_type; /**< the device type of the pen, if known (added in 3.4.18). */
} SDL_PenAxisEvent;
/**
diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c
index 7202559ffb1c7..af4c9fc11b753 100644
--- a/src/events/SDL_pen.c
+++ b/src/events/SDL_pen.c
@@ -355,6 +355,7 @@ void SDL_SendPenTouch(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *windo
{
bool send_event = false;
SDL_PenInputFlags input_state = 0;
+ SDL_PenDeviceType device_type = SDL_PEN_DEVICE_TYPE_UNKNOWN;
float x = 0.0f;
float y = 0.0f;
@@ -366,6 +367,7 @@ void SDL_SendPenTouch(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *windo
SDL_Pen *pen = FindPenByInstanceId(instance_id);
if (pen) {
input_state = pen->input_state;
+ device_type = pen->info.device_type;
x = pen->x;
y = pen->y;
@@ -403,6 +405,7 @@ void SDL_SendPenTouch(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *windo
event.ptouch.y = y;
event.ptouch.eraser = eraser;
event.ptouch.down = down;
+ event.ptouch.device_type = device_type;
SDL_PushEvent(&event);
}
@@ -449,6 +452,7 @@ void SDL_SendPenAxis(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window
bool send_event = false;
SDL_PenInputFlags input_state = 0;
+ SDL_PenDeviceType device_type = SDL_PEN_DEVICE_TYPE_UNKNOWN;
float x = 0.0f;
float y = 0.0f;
@@ -462,6 +466,7 @@ void SDL_SendPenAxis(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window
if (pen->axes[axis] != value) {
pen->axes[axis] = value; // we could do an SDL_SetAtomicInt here if we run into trouble...
input_state = pen->input_state;
+ device_type = pen->info.device_type;
x = pen->x;
y = pen->y;
send_event = true;
@@ -481,6 +486,7 @@ void SDL_SendPenAxis(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window
event.paxis.y = y;
event.paxis.axis = axis;
event.paxis.value = value;
+ event.paxis.device_type = device_type;
SDL_PushEvent(&event);
if (window && (axis == SDL_PEN_AXIS_PRESSURE) && (pen_touching == instance_id)) {
@@ -507,6 +513,7 @@ void SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *wind
{
bool send_event = false;
SDL_PenInputFlags input_state = 0;
+ SDL_PenDeviceType device_type = SDL_PEN_DEVICE_TYPE_UNKNOWN;
// note that this locks for _reading_ because the lock protects the
// pen_devices array from being reallocated from under us, not the data in it;
@@ -521,6 +528,7 @@ void SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *wind
pen->x = x; // we could do an SDL_SetAtomicInt here if we run into trouble...
pen->y = y; // we could do an SDL_SetAtomicInt here if we run into trouble...
input_state = pen->input_state;
+ device_type = pen->info.device_type;
send_event = true;
}
}
@@ -536,6 +544,7 @@ void SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *wind
event.pmotion.pen_state = input_state;
event.pmotion.x = x;
event.pmotion.y = y;
+ event.pmotion.device_type = device_type;
SDL_PushEvent(&event);
if (window) {
@@ -562,7 +571,7 @@ void SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *wind
}
}
-static void SendPenButtonEvents(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, Uint8 button, bool down, SDL_PenInputFlags input_state, float x, float y)
+static void SendPenButtonEvents(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window, Uint8 button, bool down, SDL_PenInputFlags input_state, float x, float y, SDL_PenDeviceType device_type)
{
const SDL_EventType evtype = down ? SDL_EVENT_PEN_BUTTON_DOWN : SDL_EVENT_PEN_BUTTON_UP;
if (SDL_EventEnabled(evtype)) {
@@ -577,6 +586,7 @@ static void SendPenButtonEvents(Uint64 timestamp, SDL_PenID instance_id, SDL_Win
event.pbutton.y = y;
event.pbutton.button = button;
event.pbutton.down = down;
+ event.pbutton.device_type = device_type;
SDL_PushEvent(&event);
if (window && (!pen_touching || (pen_touching == instance_id))) {
@@ -595,6 +605,7 @@ void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *wind
{
bool send_event = false;
SDL_PenInputFlags input_state = 0;
+ SDL_PenDeviceType device_type = SDL_PEN_DEVICE_TYPE_UNKNOWN;
float x = 0.0f;
float y = 0.0f;
@@ -610,8 +621,8 @@ void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *wind
SDL_Pen *pen = FindPenByInstanceId(instance_id);
if (pen) {
EnsurePenProximity(timestamp, pen, window);
-
input_state = pen->input_state;
+ device_type = pen->info.device_type;
const SDL_PenInputFlags flag = (SDL_PenInputFlags) (1u << button);
const bool current = ((input_state & flag) != 0);
x = pen->x;
@@ -628,7 +639,7 @@ void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *wind
SDL_UnlockRWLock(pen_device_rwlock);
if (send_event) {
- SendPenButtonEvents(timestamp, instance_id, window, button, down, input_state, x, y);
+ SendPenButtonEvents(timestamp, instance_id, window, button, down, input_state, x, y, device_type);
}
}
@@ -637,6 +648,7 @@ void SDL_SendPenProximity(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *w
bool send_event = false;
SDL_PenInputFlags input_state = 0;
SDL_PenInputFlags orig_input_state = 0;
+ SDL_PenDeviceType device_type = SDL_PEN_DEVICE_TYPE_UNKNOWN;
float x = 0.0f;
float y = 0.0f;
@@ -647,6 +659,7 @@ void SDL_SendPenProximity(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *w
SDL_LockRWLockForReading(pen_device_rwlock);
SDL_Pen *pen = FindPenByInstanceId(instance_id);
if (pen) {
+ device_type = pen->info.device_type;
if (in || immediate) {
orig_input_state = input_state = pen->input_state;
const bool in_proximity = ((input_state & SDL_PEN_INPUT_IN_PROXIMITY) != 0);
@@ -681,7 +694,7 @@ void SDL_SendPenProximity(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *w
const SDL_PenInputFlags flag = (SDL_PenInputFlags) (1u << button);
if (orig_input_state & flag) { // orig_input_state continues to report we're in proximity.
orig_input_state &= ~flag; // drop the button we're reporting on.
- SendPenButtonEvents(timestamp, instance_id, window, button, false, orig_input_state, x, y);
+ SendPenButtonEvents(timestamp, instance_id, window, button, false, orig_input_state, x, y, device_type);
}
}
}
@@ -695,6 +708,7 @@ void SDL_SendPenProximity(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *w
event.pproximity.windowID = window ? window->id : 0;
event.pproximity.which = instance_id;
event.pproximity.pen_state = input_state;
+ event.pproximity.device_type = device_type;
SDL_PushEvent(&event);
}
}