osu-framework icon indicating copy to clipboard operation
osu-framework copied to clipboard

SDL3: Handle keyboard input asynchronously when text input is disabled

Open Susko3 opened this issue 11 months ago • 5 comments

  • Related: https://github.com/ppy/osu-framework/issues/6141
  • Companion to https://github.com/ppy/osu-framework/pull/6235

This PR updates keyboard events to be handled asynchronously in the SDL event filter iff text input is disabled.

For now, keyboard input is handled synchronously when text input is enabled to prevent timing problems. If keyboard events are handled asynchronously, a keyboard event might come before a text input event. This is opposite to the current order and may break TextBox consuming key events that produce text. TextBox expects and is tested to first receive text, and then key input:

https://github.com/ppy/osu-framework/blob/54a23fb71d273d48d4936c84492e2a48ec1e6dce/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBoxKeyEvents.cs#L68-L78

Threading concerns

There is a possibility for a key to get stuck in a pressed state if it's quickly tapped around the time text input is disabled.

Assume a key is quickly pressed and released, generating SDL_EVENT_KEY_DOWN and a SDL_EVENT_KEY_UP.

Raw keyboard thread Main thread Update thread
Text input enabled (initial state)
Receive SDL_EVENT_KEY_DOWN
Ignored as text input is enabled
Request text input disable
Run new frame
commandScheduler.Update()
SDL_StopTextInput()
Receive SDL_EVENT_KEY_UP
Handled, added to input queue
Receive the same SDL_EVENT_KEY_DOWN
Handled, added to input queue
Check input queue:
Handle key up event (no state change)
Handle key down event

The key is now stuck. But the user can just press and release it to fix this.

The opposite is also possible: a key is pressed, but the game thinks it's released. Can happen if a held key is quickly released and pressed again.

This is only a concern if keyboard input is handled on a different thread, as things currently stand with SDL on Windows (SDL_HINT_WINDOWS_RAW_KEYBOARD is disabled by default), keyboard events are added to the SDL event queue and handled by our filter on the main thread.

Susko3 avatar Jan 23 '25 18:01 Susko3

Just to confirm before I make a start on testing this, the "stuck key" issue is only an issue until https://github.com/ppy/osu-framework/pull/6507 is merged, correct?

peppy avatar Jan 24 '25 07:01 peppy

Just to confirm before I make a start on testing this, the "stuck key" issue is only an issue until #6507 is merged, correct?

On windows, stuck key is not an issue until #6507 is merged.

On android, stuck key is an issue with this PR as android already uses different threads. The Android-managed UI thread generates input events, while the main thread is started separately, by SDL. No idea about other platforms.

Susko3 avatar Jan 24 '25 14:01 Susko3

I am a bit worried that if this is combined with https://github.com/ppy/osu-framework/pull/6507, osu!framework key events are going to get handled in the raw keyboard hook thread, right?

If that's the case, osu! may become the cause of the issue we are trying to solve. I think it's fine to enable raw keyboard on Windows, but I'd rather keep the key event handling as-is for now.

EDIT: I read SDL code, and it seems that rawinput is implemented differently to what I did with my program before. The code should be then probably fine except for the issue in OP, but I still don't want o!f key handling to run on an SDL thread.

hwsmm avatar Jan 25 '25 07:01 hwsmm

I still don't want o!f key handling to run on an SDL thread.

What's your main concern with that? Keep in mind that osu!framework UI events are still handled on the update thread. This PR just changes the way SDL events are collected – directly when SDL generates them. The idea is to avoid the SDL event queue, as we already have a thread-safe InputHandler.PendingInputs queue.

Susko3 avatar Jan 25 '25 14:01 Susko3

What I meant is that this solution sounds a bit roundabout than fixing SDL_PumpEvent to me, but I am not against of it as a workaround until an actual solution is found.

Edited because my comment was literally repeating yours. 😅 I really should have written it better.

hwsmm avatar Jan 25 '25 14:01 hwsmm