Raw input related issues
I noticed a couple issues that seem to be related to the new raw input work as of 4d00706f57284b0072d18d7dc873012aa13f32a5
cc: @slouken
Busy Looping
First, the MsgWaitForMultipleObjects() call doesn't appear to actually be blocking to wait on new raw input messages (or more likely, we're somehow not reading them all off the queue to clear QS_RAWINPUT). https://github.com/libsdl-org/SDL/blob/e055a9fc2d98351bbfb9de553ee215a318da780f/src/video/windows/SDL_windowsrawinput.c#L81-L87
When I stepped through WIN_PollRawInput(), I saw it accumulate events on the first wakeup, then subsequent wakeups seemed to always receive 0 events from GetRawInputBuffer() without resetting QS_RAWINPUT. As a result, MsgWaitForMultipleObjects() instantly returns and we end up in a busy loop. I didn't see anything obviously wrong with any of the code there, so it probably needs more detailed investigation.
I used testgl2.exe from the sdl2-compat repo to reproduce this, but I think it impacts basically any SDL3 program using raw input.
Keyboard Grab
It looks like raw input also interferes with our keyboard hook. The hook is installed successfully, but it doesn't get called while we're registered for raw input. I tried using RIDEV_NOHOTKEYS which worked for blocking the Windows key, but doesn't properly intercept Alt+Tab (and [triggers use of the legacy Alt+Tab UI too).
We could try to carve out a specific exception for raw keyboard input in the case that keyboard grab is enabled and SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED=1 (with the caveat of Windows's RIDEV_NOHOTKEYS Alt+Tab handling not quite behaving as we document that hint should), but I think it's probably easier to just disable raw keyboard input as long as a keyboard grab is active.
To repro, I used testgl2.exe --keyboard-grab and pressed Alt+Tab and Windows key to ensure the grab was working.
The first part should be fixed by d99b732f0.
For the second part, it would be entirely surprising that keyboard grab would disable raw input, you'd think intuitively that raw input might imply a keyboard grab. Can you investigate a little more and see why raw keyboard input is interfering with the keyboard hook?
The first part should be fixed by d99b732f0.
Yeah, that fixes it. It's very strange though because MSDN says it should:
If all raw input messages have been successfully read from message queue then QS_RAWINPUT flag is cleared from the calling thread's message queue status.
It makes me wonder if there's something we're missing somehow.
Can you investigate a little more and see why raw keyboard input is interfering with the keyboard hook?
I think this incompatibility between raw input and low-level keyboard hooks is expected. There are several posts about it:
- https://stackoverflow.com/questions/55146753/raw-input-keyboard-with-ridev-nohotkeys-displays-a-classic-alttab-menu (legacy Alt+Tab UI)
- https://stackoverflow.com/questions/13128692/wh-keyboard-ll-hook-doesnt-capture-input-in-own-process (LL keyboard hook not invoked when raw input active)
- https://caseymuratori.com/blog_0006
FWIW, using RIDEV_NOHOTKEYS was the closest I could get to the behavior of the hook. At least as of Windows 11 23H2, non-Alt+Tab shortcuts seem to work fine (tried: Win, Win+Tab, Ctrl+Esc, Ctrl+Shift+Esc). Unfortunately, it has a couple of annoying issues that probably make it unsuitable for our keyboard grab feature:
- Alt+Tab is received by both the SDL app and Windows, so you get the legacy Alt+Tab UI on top of the SDL window
- The fallback Alt+Tab UI appears even when the app is in windowed mode, not just full-screen, so it doesn't match the documented behavior of
SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED
If we can find some way to disable that fallback Alt+Tab UI, I think we could totally throw out the keyboard hook in favor of just using raw input for keyboard grab, which would be awesome.
Edit: Actually Alt+Esc also isn't captured properly using RIDEV_NOHOTKEYS either. The same behavior happens as Alt+Tab where it's passed to both the OS and the app (though no UI is displayed for this feature).
Edit 2: Alt+Esc capture works if we use RIDEV_NOHOTKEYS | RIDEV_NOLEGACY | RIDEV_APPKEYS, but supporting RIDEV_NOLEGACY properly will require some more changes on the SDL side (it appears to break our keyboard modifier flags).
We use a low level keyboard hook in our game to block Windows keys when gameplay is active. This worked fine with SDL2, but in SDL3 with SDL_SetRelativeMouseMode(SDL_TRUE) or SDL_HINT_WINDOWS_RAW_KEYBOARD set to 1 (default) this no longer works.
I see that you've discussed blocking hotkeys when raw input handling is enabled. Is there an option to only block Windows keys? We'd still want Alt-Tab to work.
We default raw keyboard input off now, so it shouldn't impact keyboard hooks by default, so I'm moving this out of the 3.2.0 milestone.
Alt+Esc capture works if we use RIDEV_NOHOTKEYS | RIDEV_NOLEGACY | RIDEV_APPKEYS, but supporting RIDEV_NOLEGACY properly will require some more changes on the SDL side (it appears to break our keyboard modifier flags).
@cgutman, feel free to create a PR if you do more investigation on this.