From ed70ce85c1a574f77602f71cbbc4c3ae29dd7801 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 29 Apr 2026 17:51:26 -0500 Subject: [PATCH] pen: Fix enabling touch emulation while a pen is connected (cherry picked from commit 41f079491a0e79b22441fd32a7c8ad91db237744) --- src/events/SDL_mouse.c | 18 -------------- src/events/SDL_pen.c | 55 +++++++++++++++++++++++++++--------------- 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index e389e47a16..5dd25d713a 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -188,18 +188,6 @@ static void SDLCALL SDL_PenMouseEventsChanged(void *userdata, const char *name, mouse->pen_mouse_events = SDL_GetStringBoolean(hint, true); } -static void SDLCALL SDL_PenTouchEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint) -{ - SDL_Mouse *mouse = (SDL_Mouse *)userdata; - - mouse->pen_touch_events = SDL_GetStringBoolean(hint, true); - - if (!mouse->pen_touch_events && mouse->added_pen_touch_device) { - SDL_DelTouch(SDL_PEN_TOUCHID); - mouse->added_pen_touch_device = false; - } -} - static void SDLCALL SDL_MouseAutoCaptureChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { SDL_Mouse *mouse = (SDL_Mouse *)userdata; @@ -282,9 +270,6 @@ bool SDL_PreInitMouse(void) SDL_AddHintCallback(SDL_HINT_PEN_MOUSE_EVENTS, SDL_PenMouseEventsChanged, mouse); - SDL_AddHintCallback(SDL_HINT_PEN_TOUCH_EVENTS, - SDL_PenTouchEventsChanged, mouse); - SDL_AddHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE, SDL_MouseAutoCaptureChanged, mouse); @@ -1149,9 +1134,6 @@ void SDL_QuitMouse(void) SDL_RemoveHintCallback(SDL_HINT_PEN_MOUSE_EVENTS, SDL_PenMouseEventsChanged, mouse); - SDL_RemoveHintCallback(SDL_HINT_PEN_TOUCH_EVENTS, - SDL_PenTouchEventsChanged, mouse); - SDL_RemoveHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE, SDL_MouseAutoCaptureChanged, mouse); diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c index 83543a695e..d70542b9f9 100644 --- a/src/events/SDL_pen.c +++ b/src/events/SDL_pen.c @@ -93,6 +93,33 @@ SDL_PenID SDL_FindPenByCallback(bool (*callback)(void *handle, void *userdata), return result; } +static void UpdateTouchEmulationDevicePresence(void) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + + SDL_LockRWLockForReading(pen_device_rwlock); + bool has_pen = (pen_device_count != 0); + SDL_UnlockRWLock(pen_device_rwlock); + + if (!mouse->pen_touch_events || !has_pen) { + if (mouse->added_pen_touch_device) { + SDL_DelTouch(SDL_PEN_TOUCHID); + mouse->added_pen_touch_device = false; + } + } else if (!mouse->added_pen_touch_device) { + SDL_AddTouch(SDL_PEN_TOUCHID, SDL_TOUCH_DEVICE_DIRECT, "pen_input"); + mouse->added_pen_touch_device = true; + } +} + +static void SDLCALL SDL_PenTouchEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + + mouse->pen_touch_events = SDL_GetStringBoolean(hint, true); + + UpdateTouchEmulationDevicePresence(); +} // public API ... @@ -106,11 +133,18 @@ bool SDL_InitPen(void) if (!pen_device_rwlock) { return false; } + + SDL_AddHintCallback(SDL_HINT_PEN_TOUCH_EVENTS, + SDL_PenTouchEventsChanged, NULL); + return true; } void SDL_QuitPen(void) { + SDL_RemoveHintCallback(SDL_HINT_PEN_TOUCH_EVENTS, + SDL_PenTouchEventsChanged, NULL); + SDL_RemoveAllPenDevices(NULL, NULL); SDL_DestroyRWLock(pen_device_rwlock); pen_device_rwlock = NULL; @@ -228,7 +262,6 @@ SDL_PenID SDL_AddPenDevice(Uint64 timestamp, const char *name, SDL_Window *windo SDL_LockRWLockForWriting(pen_device_rwlock); - bool first_device = false; SDL_Pen *pen = NULL; void *ptr = SDL_realloc(pen_devices, (pen_device_count + 1) * sizeof (*pen)); if (ptr) { @@ -237,8 +270,6 @@ SDL_PenID SDL_AddPenDevice(Uint64 timestamp, const char *name, SDL_Window *windo pen = &pen_devices[pen_device_count]; pen_device_count++; - first_device = (pen_device_count == 1); - SDL_zerop(pen); pen->instance_id = result; pen->name = namecpy; @@ -254,13 +285,7 @@ SDL_PenID SDL_AddPenDevice(Uint64 timestamp, const char *name, SDL_Window *windo SDL_free(namecpy); } - if (first_device) { - SDL_Mouse *mouse = SDL_GetMouse(); - if (mouse->pen_touch_events && !mouse->added_pen_touch_device) { - SDL_AddTouch(SDL_PEN_TOUCHID, SDL_TOUCH_DEVICE_DIRECT, "pen_input"); - mouse->added_pen_touch_device = true; - } - } + UpdateTouchEmulationDevicePresence(); if (result && in_proximity) { SDL_SendPenProximity(timestamp, result, window, true, true); @@ -278,7 +303,6 @@ void SDL_RemovePenDevice(Uint64 timestamp, SDL_Window *window, SDL_PenID instanc SDL_SendPenProximity(timestamp, instance_id, window, false, true); // bye bye SDL_LockRWLockForWriting(pen_device_rwlock); - bool last_device = false; SDL_Pen *pen = FindPenByInstanceId(instance_id); if (pen) { SDL_free(pen->name); @@ -300,18 +324,11 @@ void SDL_RemovePenDevice(Uint64 timestamp, SDL_Window *window, SDL_PenID instanc } else { SDL_free(pen_devices); pen_devices = NULL; - last_device = true; } } SDL_UnlockRWLock(pen_device_rwlock); - if (last_device) { - SDL_Mouse *mouse = SDL_GetMouse(); - if (mouse->added_pen_touch_device) { - SDL_DelTouch(SDL_PEN_TOUCHID); - mouse->added_pen_touch_device = false; - } - } + UpdateTouchEmulationDevicePresence(); } // This presumably is happening during video quit, so we don't send PROXIMITY_OUT events here.