From 2d602e67263bfb287d470f0bb6397ba2601409fd Mon Sep 17 00:00:00 2001 From: Susko3 Date: Tue, 27 Jan 2026 00:45:07 +0100 Subject: [PATCH] Add workaround to fix pen clicks not working on Android --- .../Platform/SDL3/SDL3Window_Input.cs | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/osu.Framework/Platform/SDL3/SDL3Window_Input.cs b/osu.Framework/Platform/SDL3/SDL3Window_Input.cs index 73cb15526..4f10522e6 100644 --- a/osu.Framework/Platform/SDL3/SDL3Window_Input.cs +++ b/osu.Framework/Platform/SDL3/SDL3Window_Input.cs @@ -533,11 +533,36 @@ namespace osu.Framework.Platform.SDL3 private void handleKeymapChangedEvent() => KeymapChanged?.Invoke(); + private readonly bool penProximityWorkaround = RuntimeInfo.OS == RuntimeInfo.Platform.Android; + + private bool tryGetPenDeviceType(SDL_PenID penID, out TabletPenDeviceType deviceType) + { + if (penDeviceTypes.TryGetValue(penID, out deviceType)) + return true; + + // Workaround for Android: after clicking with a pen, it can send motion and touch events even though we've received SDL_EVENT_PEN_PROXIMITY_OUT. + // It's either a bug in Android or SDL. + // Instead of ignoring those events, fetch the type and store it. + if (penProximityWorkaround) + { + var sdlType = SDL_GetPenDeviceType(penID); + + if (sdlType == SDL_PenDeviceType.SDL_PEN_DEVICE_TYPE_INVALID) + return false; + + deviceType = sdlType.ToTabletPenDeviceType(); + penDeviceTypes[penID] = deviceType; + return true; + } + + return false; + } + private void handlePenProximityEvent(SDL_PenProximityEvent evtPenProximity) { if (evtPenProximity.type == SDL_EventType.SDL_EVENT_PEN_PROXIMITY_IN) { - if (penDeviceTypes.ContainsKey(evtPenProximity.which)) + if (!penProximityWorkaround && 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] = SDL_GetPenDeviceType(evtPenProximity.which).ThrowIfFailed().ToTabletPenDeviceType(); @@ -551,7 +576,7 @@ namespace osu.Framework.Platform.SDL3 private void handlePenMotionEvent(SDL_PenMotionEvent evtPenMotion) { - if (penDeviceTypes.TryGetValue(evtPenMotion.which, out var type)) + if (tryGetPenDeviceType(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); @@ -559,7 +584,7 @@ namespace osu.Framework.Platform.SDL3 private void handlePenTouchEvent(SDL_PenTouchEvent evtPenTouch) { - if (penDeviceTypes.TryGetValue(evtPenTouch.which, out var type)) + if (tryGetPenDeviceType(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);