From e2e8f86076a815303836514bb4ba661a84532d24 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 12 Nov 2025 21:40:05 -0800
Subject: [PATCH] Check for wine_get_version() to detect Wine/Proton
If this application is being run under Wine but Steam doesn't know that, Steam won't set STEAM_COMPAT_PROTON. So we'll use wine_get_version() to detect that we're running under Wine instead.
---
src/core/windows/SDL_windows.c | 18 ++++++++++++++++++
src/core/windows/SDL_windows.h | 3 +++
src/joystick/SDL_gamepad.c | 11 ++++++-----
3 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/src/core/windows/SDL_windows.c b/src/core/windows/SDL_windows.c
index 4621531ca545f..6bcc8f5ee3147 100644
--- a/src/core/windows/SDL_windows.c
+++ b/src/core/windows/SDL_windows.c
@@ -325,6 +325,24 @@ static BOOL IsWindowsBuildVersionAtLeast(DWORD dwBuildNumber)
return result;
#endif
+BOOL WIN_IsWine(void)
+{
+ static bool checked;
+ static bool is_wine;
+
+ if (!checked) {
+ HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll"));
+ if (ntdll) {
+ if (GetProcAddress(ntdll, "wine_get_version") != NULL) {
+ is_wine = true;
+ }
+ FreeLibrary(ntdll);
+ }
+ checked = true;
+ }
+ return is_wine;
+}
+
// this is the oldest thing we run on (and we may lose support for this in SDL3 at any time!),
// so there's no "OrGreater" as that would always be TRUE. The other functions are here to
// ask "can we support a specific feature?" but this function is here to ask "do we need to do
diff --git a/src/core/windows/SDL_windows.h b/src/core/windows/SDL_windows.h
index f26b653b92d61..7dfbc7daf6439 100644
--- a/src/core/windows/SDL_windows.h
+++ b/src/core/windows/SDL_windows.h
@@ -168,6 +168,9 @@ extern void WIN_CoUninitialize(void);
extern HRESULT WIN_RoInitialize(void);
extern void WIN_RoUninitialize(void);
+// Returns true if we're running on Wine
+extern BOOL WIN_IsWine(void);
+
// Returns true if we're running on Windows XP (any service pack). DOES NOT CHECK XP "OR GREATER"!
extern BOOL WIN_IsWindowsXP(void);
diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c
index b63a47a8791e2..cdb7714e4542a 100644
--- a/src/joystick/SDL_gamepad.c
+++ b/src/joystick/SDL_gamepad.c
@@ -34,10 +34,11 @@
#include "hidapi/SDL_hidapi_sinput.h"
#include "../events/SDL_events_c.h"
-
-#ifdef SDL_PLATFORM_ANDROID
+#ifdef SDL_PLATFORM_WIN32
+#include "../core/windows/SDL_windows.h"
#endif
+
// Many gamepads turn the center button into an instantaneous button press
#define SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS 250
@@ -3262,10 +3263,10 @@ bool SDL_ShouldIgnoreGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version
#ifdef SDL_PLATFORM_WIN32
if (SDL_GetHintBoolean("SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD", false) &&
- SDL_GetHintBoolean("STEAM_COMPAT_PROTON", false)) {
- // We are launched by Steam and running under Proton
+ WIN_IsWine()) {
+ // We are launched by Steam and running under Proton or Wine
// We can't tell whether this controller is a Steam Virtual Gamepad,
- // so assume that Proton is doing the appropriate filtering of controllers
+ // so assume that is doing the appropriate filtering of controllers
// and anything we see here is fine to use.
return false;
}