diff --git a/vrclient_x64/gen_wrapper.py b/vrclient_x64/gen_wrapper.py index 74c942f3..2525a1d3 100755 --- a/vrclient_x64/gen_wrapper.py +++ b/vrclient_x64/gen_wrapper.py @@ -288,6 +288,9 @@ class_versions = {} def get_params(f): return [p for p in f.get_children() if p.kind == clang.cindex.CursorKind.PARM_DECL] +def ivrclientcore_is_hmd_present(cppname, method): + return "ivrclientcore_is_hmd_present" + def ivrclientcore_init(cppname, method): if "002" in cppname: return "ivrclientcore_002_init" @@ -382,6 +385,7 @@ def ivroverlay_set_overlay_texture(cppname, method): return "ivroverlay_set_overlay_texture" method_overrides = [ + ("IVRClientCore", "BIsHmdPresent", ivrclientcore_is_hmd_present), ("IVRClientCore", "Init", ivrclientcore_init), ("IVRClientCore", "GetGenericInterface", ivrclientcore_get_generic_interface), ("IVRClientCore", "Cleanup", ivrclientcore_cleanup), diff --git a/vrclient_x64/vrclient_x64/vrclient_main.c b/vrclient_x64/vrclient_x64/vrclient_main.c index dc7568af..7c4b36d7 100644 --- a/vrclient_x64/vrclient_x64/vrclient_main.c +++ b/vrclient_x64/vrclient_x64/vrclient_main.c @@ -357,6 +357,93 @@ static void load_vk_unwrappers(void) get_native_VkQueue = (void*)GetProcAddress(h, "__wine_get_native_VkQueue"); } +static bool is_hmd_present_reg(void) +{ + DWORD type, value, wait_status, size; + DWORD is_hmd_present = 0; + LSTATUS status; + HANDLE event; + HKEY vr_key; + + if ((status = RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\VR", 0, KEY_READ, &vr_key))) + { + WINE_ERR("Could not create key, status %#x.\n", status); + return FALSE; + } + + size = sizeof(value); + if ((status = RegQueryValueExA(vr_key, "state", NULL, &type, (BYTE *)&value, &size))) + { + WINE_ERR("Could not query value, status %#x.\n", status); + RegCloseKey(vr_key); + return FALSE; + } + if (type != REG_DWORD) + { + WINE_ERR("Unexpected value type %#x.\n", type); + RegCloseKey(vr_key); + return FALSE; + } + + if (value) + { + RegCloseKey(vr_key); + return value == 1; + } + + event = CreateEventA( NULL, FALSE, FALSE, NULL ); + while (1) + { + if (RegNotifyChangeKeyValue(vr_key, FALSE, REG_NOTIFY_CHANGE_LAST_SET, event, TRUE)) + { + WINE_ERR("Error registering registry change notification.\n"); + goto done; + } + size = sizeof(value); + if ((status = RegQueryValueExA(vr_key, "state", NULL, &type, (BYTE *)&value, &size))) + { + WINE_ERR("Could not query value, status %#x.\n", status); + goto done; + } + if (value) + break; + while ((wait_status = WaitForSingleObject(event, 1000)) == WAIT_TIMEOUT) + WINE_ERR("VR state wait timeout.\n"); + + if (wait_status != WAIT_OBJECT_0) + { + WINE_ERR("Got unexpected wait status %#x.\n", wait_status); + break; + } + } + + if (value != 1) + goto done; + + size = sizeof(is_hmd_present); + if ((status = RegQueryValueExA(vr_key, "is_hmd_present", NULL, &type, (BYTE *)&is_hmd_present, &size))) + WINE_ERR("Could not query is_hmd_present value, status %#x.\n", status); + +done: + CloseHandle(event); + RegCloseKey(vr_key); + return is_hmd_present; +} + +bool ivrclientcore_is_hmd_present(bool (*cpp_func)(void *), void *linux_side, unsigned int version, + struct client_core_data *user_data) +{ + TRACE("linux_side %p, compositor_data.client_core_linux_side %p.\n", + linux_side, compositor_data.client_core_linux_side); + + /* BIsHmdPresent() currently always returns FALSE on Linux if called before Init(). + * Return true if the value stored by steam.exe helper in registry says the HMD is presnt. */ + if (compositor_data.client_core_linux_side || !is_hmd_present_reg()) + return cpp_func(linux_side); + + return TRUE; +} + EVRInitError ivrclientcore_002_init(EVRInitError (*cpp_func)(void *, EVRApplicationType), void *linux_side, EVRApplicationType application_type, unsigned int version, struct client_core_data *user_data) diff --git a/vrclient_x64/vrclient_x64/vrclient_private.h b/vrclient_x64/vrclient_x64/vrclient_private.h index b4e0af0e..53e44c03 100644 --- a/vrclient_x64/vrclient_x64/vrclient_private.h +++ b/vrclient_x64/vrclient_x64/vrclient_private.h @@ -72,6 +72,8 @@ struct client_core_data SIZE_T created_interfaces_size; }; +bool ivrclientcore_is_hmd_present(bool (*cpp_func)(void *), void *linux_side, unsigned int version, + struct client_core_data *user_data); EVRInitError ivrclientcore_002_init(EVRInitError (*cpp_func)(void *, EVRApplicationType), void *linux_side, EVRApplicationType application_type, unsigned int version, struct client_core_data *user_data); diff --git a/vrclient_x64/vrclient_x64/winIVRClientCore.c b/vrclient_x64/vrclient_x64/winIVRClientCore.c index 6e5ede6a..91e78c6c 100644 --- a/vrclient_x64/vrclient_x64/winIVRClientCore.c +++ b/vrclient_x64/vrclient_x64/winIVRClientCore.c @@ -58,7 +58,7 @@ DEFINE_THISCALL_WRAPPER(winIVRClientCore_IVRClientCore_003_BIsHmdPresent, 4) bool __thiscall winIVRClientCore_IVRClientCore_003_BIsHmdPresent(winIVRClientCore_IVRClientCore_003 *_this) { TRACE("%p\n", _this); - return cppIVRClientCore_IVRClientCore_003_BIsHmdPresent(_this->linux_side); + return ivrclientcore_is_hmd_present(cppIVRClientCore_IVRClientCore_003_BIsHmdPresent, _this->linux_side, 3, &_this->user_data); } DEFINE_THISCALL_WRAPPER(winIVRClientCore_IVRClientCore_003_GetEnglishStringForHmdError, 8) @@ -179,7 +179,7 @@ DEFINE_THISCALL_WRAPPER(winIVRClientCore_IVRClientCore_002_BIsHmdPresent, 4) bool __thiscall winIVRClientCore_IVRClientCore_002_BIsHmdPresent(winIVRClientCore_IVRClientCore_002 *_this) { TRACE("%p\n", _this); - return cppIVRClientCore_IVRClientCore_002_BIsHmdPresent(_this->linux_side); + return ivrclientcore_is_hmd_present(cppIVRClientCore_IVRClientCore_002_BIsHmdPresent, _this->linux_side, 2, &_this->user_data); } DEFINE_THISCALL_WRAPPER(winIVRClientCore_IVRClientCore_002_GetEnglishStringForHmdError, 8)