From b4eaf9d96f59a4155673143282b0419bd06899a6 Mon Sep 17 00:00:00 2001 From: expikr <77922942+expikr@users.noreply.github.com> Date: Mon, 27 Oct 2025 00:27:33 +0800 Subject: [PATCH] Add hint for blocking win key when using raw keyboard (#13066) Co-authored-by: Susko3 --- include/SDL3/SDL_hints.h | 22 ++++++++++++++ src/video/windows/SDL_windowsrawinput.c | 40 +++++++++++++++++++++++++ src/video/windows/SDL_windowsrawinput.h | 2 +- src/video/windows/SDL_windowsvideo.c | 9 ++++++ src/video/windows/SDL_windowsvideo.h | 1 + 5 files changed, 73 insertions(+), 1 deletion(-) diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index b5565b5496..a53ae96828 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -4384,6 +4384,28 @@ extern "C" { */ #define SDL_HINT_WINDOWS_RAW_KEYBOARD "SDL_WINDOWS_RAW_KEYBOARD" +/** + * A variable controlling whether or not the RIDEV_NOHOTKEYS flag is set when + * enabling Windows raw keyboard events. + * + * This blocks any hotkeys that have been registered by applications from + * having any effect beyond generating raw WM_INPUT events. + * + * This flag does not affect system-hotkeys like ALT-TAB or CTRL-ALT-DEL, + * but does affect the Windows Logo key since it is a userland hotkey registered + * by explorer.exe. + * + * The variable can be set to the following values: + * + * - "0": Hotkeys are not excluded. (default) + * - "1": Hotkeys are excluded. + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_WINDOWS_RAW_KEYBOARD_EXCLUDE_HOTKEYS "SDL_WINDOWS_RAW_KEYBOARD_EXCLUDE_HOTKEYS" + /** * A variable controlling whether SDL uses Kernel Semaphores on Windows. * diff --git a/src/video/windows/SDL_windowsrawinput.c b/src/video/windows/SDL_windowsrawinput.c index 5f32b373c5..46da4a158b 100644 --- a/src/video/windows/SDL_windowsrawinput.c +++ b/src/video/windows/SDL_windowsrawinput.c @@ -34,6 +34,7 @@ #define ENABLE_RAW_MOUSE_INPUT 0x01 #define ENABLE_RAW_KEYBOARD_INPUT 0x02 +#define RAW_KEYBOARD_FLAG_NOHOTKEYS 0x04 typedef struct { @@ -81,6 +82,9 @@ static DWORD WINAPI WIN_RawInputThread(LPVOID param) devices[count].usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP; devices[count].usUsage = USB_USAGE_GENERIC_KEYBOARD; devices[count].dwFlags = 0; + if (data->flags & RAW_KEYBOARD_FLAG_NOHOTKEYS) { + devices[count].dwFlags |= RIDEV_NOHOTKEYS; + } devices[count].hwndTarget = window; ++count; } @@ -203,6 +207,9 @@ static bool WIN_UpdateRawInputEnabled(SDL_VideoDevice *_this) } if (data->raw_keyboard_enabled) { flags |= ENABLE_RAW_KEYBOARD_INPUT; + if (data->raw_keyboard_flag_nohotkeys) { + flags |= RAW_KEYBOARD_FLAG_NOHOTKEYS; + } } if (flags != data->raw_input_enabled) { if (WIN_SetRawInputEnabled(_this, flags)) { @@ -250,6 +257,34 @@ bool WIN_SetRawKeyboardEnabled(SDL_VideoDevice *_this, bool enabled) return true; } +typedef enum WIN_RawKeyboardFlag { + NOHOTKEYS +} WIN_RawKeyboardFlag; + +static bool WIN_SetRawKeyboardFlag(SDL_VideoDevice *_this, WIN_RawKeyboardFlag flag, bool enabled) +{ + SDL_VideoData *data = _this->internal; + + switch(flag) { + case NOHOTKEYS: + data->raw_keyboard_flag_nohotkeys = enabled; + break; + default: + return false; + } + + if (data->gameinput_context) { + return true; + } + + return WIN_UpdateRawInputEnabled(_this); +} + +bool WIN_SetRawKeyboardFlag_NoHotkeys(SDL_VideoDevice *_this, bool enabled) +{ + return WIN_SetRawKeyboardFlag(_this, NOHOTKEYS, enabled); +} + #else bool WIN_SetRawMouseEnabled(SDL_VideoDevice *_this, bool enabled) @@ -262,6 +297,11 @@ bool WIN_SetRawKeyboardEnabled(SDL_VideoDevice *_this, bool enabled) return SDL_Unsupported(); } +bool WIN_SetRawKeyboardFlag_NoHotkeys(SDL_VideoDevice *_this, bool enabled) +{ + return SDL_Unsupported(); +} + #endif // !SDL_PLATFORM_XBOXONE && !SDL_PLATFORM_XBOXSERIES #endif // SDL_VIDEO_DRIVER_WINDOWS diff --git a/src/video/windows/SDL_windowsrawinput.h b/src/video/windows/SDL_windowsrawinput.h index 25ae7054eb..dc2e28fe33 100644 --- a/src/video/windows/SDL_windowsrawinput.h +++ b/src/video/windows/SDL_windowsrawinput.h @@ -25,6 +25,6 @@ extern bool WIN_SetRawMouseEnabled(SDL_VideoDevice *_this, bool enabled); extern bool WIN_SetRawKeyboardEnabled(SDL_VideoDevice *_this, bool enabled); -extern bool WIN_RefreshRawInputEnabled(SDL_VideoDevice *_this); +extern bool WIN_SetRawKeyboardFlag_NoHotkeys(SDL_VideoDevice *_this, bool enabled); #endif // SDL_windowsrawinput_h_ diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index e840b0507e..6b459138f7 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -149,6 +149,13 @@ static void SDLCALL UpdateWindowsRawKeyboard(void *userdata, const char *name, c WIN_SetRawKeyboardEnabled(_this, enabled); } +static void SDLCALL UpdateWindowsRawKeyboardNoHotkeys(void *userdata, const char *name, const char *oldValue, const char *newValue) +{ + SDL_VideoDevice *_this = (SDL_VideoDevice *)userdata; + bool enabled = SDL_GetStringBoolean(newValue, false); + WIN_SetRawKeyboardFlag_NoHotkeys(_this, enabled); +} + static void SDLCALL UpdateWindowsEnableMessageLoop(void *userdata, const char *name, const char *oldValue, const char *newValue) { g_WindowsEnableMessageLoop = SDL_GetStringBoolean(newValue, true); @@ -632,6 +639,7 @@ static bool WIN_VideoInit(SDL_VideoDevice *_this) #endif SDL_AddHintCallback(SDL_HINT_WINDOWS_RAW_KEYBOARD, UpdateWindowsRawKeyboard, _this); + SDL_AddHintCallback(SDL_HINT_WINDOWS_RAW_KEYBOARD_EXCLUDE_HOTKEYS, UpdateWindowsRawKeyboardNoHotkeys, _this); SDL_AddHintCallback(SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP, UpdateWindowsEnableMessageLoop, NULL); SDL_AddHintCallback(SDL_HINT_WINDOWS_ENABLE_MENU_MNEMONICS, UpdateWindowsEnableMenuMnemonics, NULL); SDL_AddHintCallback(SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN, UpdateWindowFrameUsableWhileCursorHidden, NULL); @@ -649,6 +657,7 @@ void WIN_VideoQuit(SDL_VideoDevice *_this) SDL_VideoData *data = _this->internal; SDL_RemoveHintCallback(SDL_HINT_WINDOWS_RAW_KEYBOARD, UpdateWindowsRawKeyboard, _this); + SDL_RemoveHintCallback(SDL_HINT_WINDOWS_RAW_KEYBOARD_EXCLUDE_HOTKEYS, UpdateWindowsRawKeyboardNoHotkeys, _this); SDL_RemoveHintCallback(SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP, UpdateWindowsEnableMessageLoop, NULL); SDL_RemoveHintCallback(SDL_HINT_WINDOWS_ENABLE_MENU_MNEMONICS, UpdateWindowsEnableMenuMnemonics, NULL); SDL_RemoveHintCallback(SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN, UpdateWindowFrameUsableWhileCursorHidden, NULL); diff --git a/src/video/windows/SDL_windowsvideo.h b/src/video/windows/SDL_windowsvideo.h index b192fb664c..4ed1a42b58 100644 --- a/src/video/windows/SDL_windowsvideo.h +++ b/src/video/windows/SDL_windowsvideo.h @@ -590,6 +590,7 @@ struct SDL_VideoData SDL_Point last_raw_mouse_position; bool raw_mouse_enabled; bool raw_keyboard_enabled; + bool raw_keyboard_flag_nohotkeys; bool pending_E1_key_sequence; Uint32 raw_input_enabled;