From aff9eda4663bcbb277c683d1b45ff7c59296569f Mon Sep 17 00:00:00 2001 From: Susko3 Date: Wed, 7 Jan 2026 00:31:22 +0100 Subject: [PATCH] Cache pen device type Prevents crashes when alt-tabbing (pen is gone but we've yet to process events). --- osu.Framework/Platform/SDL3/SDL3Window.cs | 5 ++++ .../Platform/SDL3/SDL3Window_Input.cs | 28 +++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/osu.Framework/Platform/SDL3/SDL3Window.cs b/osu.Framework/Platform/SDL3/SDL3Window.cs index 5c76198af..fd5812cdb 100644 --- a/osu.Framework/Platform/SDL3/SDL3Window.cs +++ b/osu.Framework/Platform/SDL3/SDL3Window.cs @@ -597,6 +597,11 @@ namespace osu.Framework.Platform.SDL3 handleDropEvent(e.drop); break; + case SDL_EventType.SDL_EVENT_PEN_PROXIMITY_IN: + case SDL_EventType.SDL_EVENT_PEN_PROXIMITY_OUT: + handlePenProximityEvent(e.pproximity); + break; + case SDL_EventType.SDL_EVENT_PEN_DOWN: case SDL_EventType.SDL_EVENT_PEN_UP: handlePenTouchEvent(e.ptouch); diff --git a/osu.Framework/Platform/SDL3/SDL3Window_Input.cs b/osu.Framework/Platform/SDL3/SDL3Window_Input.cs index 823915fdf..8fa208af4 100644 --- a/osu.Framework/Platform/SDL3/SDL3Window_Input.cs +++ b/osu.Framework/Platform/SDL3/SDL3Window_Input.cs @@ -97,6 +97,8 @@ namespace osu.Framework.Platform.SDL3 private readonly Dictionary controllers = new Dictionary(); + private readonly Dictionary penDeviceTypes = new Dictionary(); + private void updateCursorVisibility(bool cursorVisible) => ScheduleCommand(() => { @@ -533,14 +535,36 @@ namespace osu.Framework.Platform.SDL3 private static TabletPenDeviceType getPenType(SDL_PenID instanceID) => SDL_GetPenDeviceType(instanceID).ThrowIfFailed().ToTabletPenDeviceType(); + private void handlePenProximityEvent(SDL_PenProximityEvent evtPenProximity) + { + if (evtPenProximity.type == SDL_EventType.SDL_EVENT_PEN_PROXIMITY_IN) + { + if (penDeviceTypes.ContainsKey(evtPenProximity.which)) + Logger.Log($"Unexpected SDL_EVENT_PEN_PROXIMITY_IN for pen id={evtPenProximity.which}. Pen already in proximity.", level: LogLevel.Important); + + penDeviceTypes[evtPenProximity.which] = getPenType(evtPenProximity.which); + } + else + { + if (!penDeviceTypes.Remove(evtPenProximity.which)) + Logger.Log($"Unexpected SDL_EVENT_PEN_PROXIMITY_OUT for pen id={evtPenProximity.which}. Pen not in proximity.", level: LogLevel.Important); + } + } + private void handlePenMotionEvent(SDL_PenMotionEvent evtPenMotion) { - PenMove?.Invoke(getPenType(evtPenMotion.which), new Vector2(evtPenMotion.x, evtPenMotion.y) * Scale, evtPenMotion.pen_state.HasFlagFast(SDL_PenInputFlags.SDL_PEN_INPUT_DOWN)); + if (penDeviceTypes.TryGetValue(evtPenMotion.which, out var type)) + PenMove?.Invoke(type, new Vector2(evtPenMotion.x, evtPenMotion.y) * Scale, evtPenMotion.pen_state.HasFlagFast(SDL_PenInputFlags.SDL_PEN_INPUT_DOWN)); + else + Logger.Log($"Unexpected SDL_EVENT_PEN_MOTION for pen id={evtPenMotion.which}. Pen not in proximity.", level: LogLevel.Important); } private void handlePenTouchEvent(SDL_PenTouchEvent evtPenTouch) { - PenTouch?.Invoke(getPenType(evtPenTouch.which), evtPenTouch.down, new Vector2(evtPenTouch.x, evtPenTouch.y) * Scale); + if (penDeviceTypes.TryGetValue(evtPenTouch.which, out var type)) + PenTouch?.Invoke(type, evtPenTouch.down, new Vector2(evtPenTouch.x, evtPenTouch.y) * Scale); + else + Logger.Log($"Unexpected {evtPenTouch.type} for pen id={evtPenTouch.which}. Pen not in proximity.", level: LogLevel.Important); } ///