We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 5496 - [PATCH] Implement keyboard grab support for Windows
Summary: [PATCH] Implement keyboard grab support for Windows
Status: RESOLVED FIXED
Alias: None
Product: SDL
Classification: Unclassified
Component: video (show other bugs)
Version: HG 2.0
Hardware: x86 Windows 10
: P2 normal
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-01-23 01:52 UTC by Cameron Gutman
Modified: 2021-01-24 19:25 UTC (History)
0 users

See Also:


Attachments
Patch (5.40 KB, patch)
2021-01-23 01:52 UTC, Cameron Gutman
Details | Diff
Patch v2 (5.65 KB, patch)
2021-01-23 15:58 UTC, Cameron Gutman
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Cameron Gutman 2021-01-23 01:52:24 UTC
This patch implements support for SDL_HINT_GRAB_KEYBOARD on Windows using a keyboard hook. I've shipped a version of this in Moonlight, but there were a lot more hoops to jump through due to the fact that I had to keep manually synchronizing SDL's modifier state because I was eating some of the keyboard events prior to them reaching SDL. The code is much simpler in SDL itself where we can just call SDL_SendKeyboardKey() and it will do the magic for us.

The only gotcha is that SetWindowHookEx() needs an HMODULE and that's challenging for us since we support DLL and static builds of SDL. Right now the code assumes that SDL2.dll is where our code will reside, but it will just gracefully fail if SDL2.dll is not loaded. We could enumerate loaded modules and look for the address of our window hook, but I didn't want to overcomplicate the initial implementation.

The commit message has a bunch of detail that I'll lazily paste below:


This is implemented via a low-level keyboard hook. Unfortunately, this is
rather invasive, but it's how Microsoft recommends that it be done [0].
We want to do as little as possible in the hook, so we only intercept a few
crucial modifier keys there, while leaving other keys to the normal event
processing flow.

We will only install this hook if SDL_HINT_GRAB_KEYBOARD=1, which is not
the default. This will reduce any compatibility concerns to just the SDL
applications that explicitly ask for this behavior.

We also remove the hook when the grab is terminated to ensure that we're
not unnecessarily staying involved in key event processing when it's not
required anymore.

The current implementation requires that the SDL code be running in a DLL
called SDL2.dll (the default SDL DLL name). If SDL2.dll is not loaded, the
hook will not be enabled.

[0]: https://docs.microsoft.com/en-us/windows/win32/dxtecharts/disabling-shortcut-keys-in-games
Comment 1 Cameron Gutman 2021-01-23 01:52:57 UTC
Created attachment 4692 [details]
Patch
Comment 2 Cameron Gutman 2021-01-23 15:58:40 UTC
Created attachment 4693 [details]
Patch v2

It turns out Windows provides a nice API to do the address->HMODULE lookup for us, so it's trivial to support both static and dynamic linked versions of SDL (and those who use don't use the default name of SDL2.dll for their DLL).
Comment 3 Sam Lantinga 2021-01-23 17:31:08 UTC
Patch added, thanks!
https://hg.libsdl.org/SDL/rev/3f700918b9f6

It might need some tweaking for XP support. I haven't checked the functions you call to see if they're supported there.
Comment 4 Cameron Gutman 2021-01-23 20:44:09 UTC
It should be okay on XP. The hooking APIs are documented as W2K+ and GetModuleHandleEx() is XP+.

I'll try it though.
Comment 5 Cameron Gutman 2021-01-24 19:25:28 UTC
It works on XP. Capture of Alt+Tab doesn't work prior to Windows 8 for some reason, but all the Super key combos seem to be captured properly.