From 01cfe92215a288e67d519497f12fbb04be6f31f2 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sun, 30 Aug 2026 18:41:06 -0400 Subject: [PATCH 1/2] chore(deps): bump libvirtualhid --- third-party/libvirtualhid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third-party/libvirtualhid b/third-party/libvirtualhid index e4317b28c6b..45db9957e55 160000 --- a/third-party/libvirtualhid +++ b/third-party/libvirtualhid @@ -1 +1 @@ -Subproject commit e4317b28c6bf9cbf080e78ec0e7d1e1fec4384d5 +Subproject commit 45db9957e55f030cba9b4d56feef4d2248eceea8 From 98e91c41228808d862ace76847c5752c0bb0c169 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sat, 5 Sep 2026 19:01:56 -0400 Subject: [PATCH 2/2] Improve Virtual HID version compatibility UX Centralized the minimum supported Virtual HID Driver version in CMake and wired it through runtime checks, docs, and tests to keep version requirements consistent. Updated driver-version logic to treat `0.0.*` builds as development versions, surfaced a `development_version` status flag, added a dedicated web info notice for dev builds, and added a Windows tray warning when an installed driver is unsupported (including a troubleshooting link). Added/updated unit and integration coverage for version parsing, status payload fields, tray behavior, and documentation consistency. --- CMakeLists.txt | 4 ++ docs/getting_started.md | 4 +- docs/troubleshooting.md | 4 +- src/confighttp.cpp | 20 +++---- src/confighttp.h | 15 +++++- src/main.cpp | 1 + src/system_tray.cpp | 54 +++++++++++++++++++ src/system_tray.h | 23 ++++++++ src_assets/common/assets/web/index.html | 13 ++++- .../assets/web/public/assets/locale/en.json | 2 + tests/CMakeLists.txt | 2 + .../test_virtualhid_version_consistency.cpp | 41 ++++++++++++++ tests/unit/test_confighttp.cpp | 21 ++++++-- tests/unit/test_system_tray.cpp | 41 ++++++++++++++ third-party/libvirtualhid | 2 +- 15 files changed, 225 insertions(+), 22 deletions(-) create mode 100644 tests/integration/test_virtualhid_version_consistency.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d75954efe0..6adf3fe6799 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,10 @@ project(Sunshine VERSION 0.0.0 DESCRIPTION "Self-hosted game stream host for Moonlight" HOMEPAGE_URL "https://app.lizardbyte.dev/Sunshine") +# Minimum separately installed Virtual HID Driver version supported by this build. +set(LIBVIRTUALHID_MINIMUM_VERSION "2026.905.2300.20") +list(APPEND SUNSHINE_DEFINITIONS LIBVIRTUALHID_MINIMUM_VERSION="${LIBVIRTUALHID_MINIMUM_VERSION}") + set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) if(NOT DEFINED CMAKE_CUDA_STANDARD) diff --git a/docs/getting_started.md b/docs/getting_started.md index 83b72dff44d..79fdc07e0e3 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -539,9 +539,7 @@ Sunshine uses libvirtualhid for virtual input on Windows. You must install the Input keyboard and mouse plus full virtual gamepad support. ViGEmBus is detected only as a limited fallback for Xbox 360 and DualShock 4 gamepads when libvirtualhid is unavailable. -Sunshine requires Virtual HID Driver version `2026.829.2338.54` or newer. Earlier releases use incompatible Windows -control and broker protocols and must be upgraded together with Sunshine's embedded libvirtualhid library. Local -development driver builds using a `0.0.0.*` version remain supported. +Sunshine requires Virtual HID Driver version `2026.905.2300.20` or newer. Compared with the ViGEmBus fallback, Virtual HID Driver can create Xbox One, Xbox Series, DualSense, Nintendo Switch Pro, and Generic gamepads in addition to Xbox 360 and DualShock 4. It can also expose controller-specific features such diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 22a20c50305..13b0d9a6cc2 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -308,9 +308,7 @@ Input keyboard and mouse plus full virtual gamepad support. ViGEmBus is detected 360 and DualShock 4 gamepads when libvirtualhid is unavailable. If you use the [ViGEmBus fallback](https://github.com/nefarius/ViGEmBus/releases/latest), you must use version 1.17 or newer. -Sunshine requires Virtual HID Driver version `2026.829.2338.54` or newer. Earlier releases use incompatible Windows -control and broker protocols. The Troubleshooting page reports an older installed package as unsupported and links -to the current driver release. Local development driver builds using a `0.0.0.*` version remain supported. +Sunshine requires Virtual HID Driver version `2026.905.2300.20` or newer. Virtual HID Driver adds Xbox One, Xbox Series, DualSense, Nintendo Switch Pro, and Generic gamepads, plus advanced controller features such as motion, touchpads, LEDs, and adaptive triggers when supported. Unlike the discontinued diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 7376b4da155..1e00fc76eb1 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -175,7 +175,7 @@ namespace confighttp { */ constexpr auto CSRF_TOKEN_LIFETIME = std::chrono::hours(1); // Tokens valid for 1 hour - constexpr auto LIBVIRTUALHID_MINIMUM_VERSION = "2026.829.2338.54"sv; ///< Minimum supported libvirtualhid driver version. // NOSONAR(cpp:S1313): not an IP address + constexpr std::string_view libvirtualhid_minimum_version = LIBVIRTUALHID_MINIMUM_VERSION; ///< Minimum supported libvirtualhid driver version. constexpr auto VIGEMBUS_MINIMUM_VERSION = "1.17.0.0"sv; ///< Minimum supported ViGEmBus fallback driver version. // NOSONAR(cpp:S1313): not an IP address /** @@ -231,8 +231,13 @@ namespace confighttp { return parts; } + bool is_driver_version_development(std::string_view version) { + const auto version_parts = parse_driver_version(version); + return version_parts && version_parts->size() >= 3U && (*version_parts)[0] == 0U && (*version_parts)[1] == 0U; + } + bool is_driver_version_supported(std::string_view version, std::string_view minimum_version) { - if (minimum_version.empty()) { + if (minimum_version.empty() || is_driver_version_development(version)) { return true; } @@ -242,10 +247,6 @@ namespace confighttp { return false; } - if (version_parts->size() >= 3U && (*version_parts)[0] == 0U && (*version_parts)[1] == 0U && (*version_parts)[2] == 0U) { - return true; - } - const auto part_count = std::max(version_parts->size(), minimum_parts->size()); for (std::size_t i = 0; i < part_count; ++i) { const auto version_part = i < version_parts->size() ? (*version_parts)[i] : 0U; @@ -266,6 +267,7 @@ namespace confighttp { output_tree["version"] = version; output_tree["minimum_version"] = minimum_version_text; output_tree["supported_versions"] = minimum_version.empty() ? "Any" : std::format(">= {}", minimum_version_text); + output_tree["development_version"] = installed && is_driver_version_development(version); output_tree["version_compatible"] = installed && is_driver_version_supported(version, minimum_version); return output_tree; @@ -1886,7 +1888,7 @@ namespace confighttp { #ifdef _WIN32 const auto version_str = read_libvirtualhid_driver_version(); const auto driver_detected = !version_str.empty(); - auto output_tree = build_driver_status(driver_detected, version_str, LIBVIRTUALHID_MINIMUM_VERSION); + auto output_tree = build_driver_status(driver_detected, version_str, libvirtualhid_minimum_version); bool requires_installed_driver = true; std::string backend_name; std::string runtime_error_message; @@ -1897,7 +1899,7 @@ namespace confighttp { const auto &capabilities = runtime->capabilities(); backend_name = capabilities.backend_name; requires_installed_driver = capabilities.requires_installed_driver; - output_tree = build_driver_status(driver_detected || capabilities.supports_gamepad, version_str, LIBVIRTUALHID_MINIMUM_VERSION); + output_tree = build_driver_status(driver_detected || capabilities.supports_gamepad, version_str, libvirtualhid_minimum_version); } } catch (const std::bad_alloc &exception) { runtime_error_message = exception.what(); @@ -1909,7 +1911,7 @@ namespace confighttp { output_tree["error"] = runtime_error_message; } #else - auto output_tree = build_driver_status(false, "", LIBVIRTUALHID_MINIMUM_VERSION); + auto output_tree = build_driver_status(false, "", libvirtualhid_minimum_version); output_tree["error"] = "libvirtualhid driver status is only available on Windows"; output_tree["backend_name"] = ""; output_tree["requires_installed_driver"] = false; diff --git a/src/confighttp.h b/src/confighttp.h index 60fe51e498b..7337daebae5 100644 --- a/src/confighttp.h +++ b/src/confighttp.h @@ -102,12 +102,23 @@ namespace confighttp { */ void savePin(const resp_https_t &response, const req_https_t &request); + /** + * @brief Check whether a detected driver version identifies a development build. + * + * Numeric versions beginning with `0.0` and containing at least three + * components are development builds. + * + * @param version Detected driver version. + * @return True when the version identifies a development build. + */ + bool is_driver_version_development(std::string_view version); + /** * @brief Check whether a detected driver version satisfies a minimum version. * * Empty minimum versions accept any detected version. Non-empty minimum versions - * require a fully numeric dotted version string. Development versions whose - * first three components are `0.0.0` are always accepted. + * require a fully numeric dotted version string. Development versions beginning + * with `0.0` are always accepted. * * @param version Detected driver version. * @param minimum_version Minimum supported driver version, or empty for any version. diff --git a/src/main.cpp b/src/main.cpp index 6530fdbd9a1..b22359f0a12 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -453,6 +453,7 @@ int main(int argc, char *argv[]) { BOOST_LOG(info) << "Starting system tray"sv; #ifdef _WIN32 system_tray::prepare_tray_virtualhid_license(); + system_tray::prepare_tray_virtualhid_driver(); // TODO: Windows has a weird bug where when running as a service and on the first Windows boot, // the tray icon would not appear even though Sunshine is running correctly otherwise. // Restarting the service would allow the icon to appear normally. diff --git a/src/system_tray.cpp b/src/system_tray.cpp index 0c667977bd6..bd1364ef678 100644 --- a/src/system_tray.cpp +++ b/src/system_tray.cpp @@ -144,6 +144,16 @@ namespace system_tray { static std::array menu_text; return menu_text; } + + /** + * @brief Access storage for the Virtual HID Driver compatibility notification. + * + * @return Persistent string storage backing the tray notification pointer. + */ + std::string &virtualhid_driver_notification_text_storage() { + static std::string notification_text; + return notification_text; + } #endif } // namespace @@ -318,6 +328,7 @@ namespace system_tray { tray.notification_cb = nullptr; #ifdef _WIN32 virtualhid_license_menu_text_storage() = {}; + virtualhid_driver_notification_text_storage().clear(); virtualhid_license_menu = initial_virtualhid_license_menu(); #endif } @@ -486,6 +497,49 @@ namespace system_tray { const auto result = lvh::get_license_status(); update_tray_virtualhid_license(result.license, !result.license.licensed()); } + + void update_tray_virtualhid_driver( + const bool installed, + const std::string_view version, + const bool version_compatible, + const std::string_view supported_versions + ) { + if (!installed || version_compatible) { + return; + } + + const std::scoped_lock lock(tray_state_mutex()); + clear_tray_notification(); + + const auto displayed_version = version.empty() ? "unknown" : std::format("v{}", version); + auto ¬ification_text = virtualhid_driver_notification_text_storage(); + notification_text = std::format( + "Installed Virtual HID Driver {} is not supported by this version of Sunshine. Supported versions: {}. Restart Sunshine after updating. Click for instructions.", + displayed_version, + supported_versions + ); + tray.notification_title = "Update Virtual HID Driver"; + tray.notification_text = notification_text.c_str(); + tray.notification_icon = tray.allIconPaths[4]; + tray.notification_cb = []() { + launch_ui("/troubleshooting#virtualhid"); + }; + + BOOST_LOG(warning) << notification_text; + if (tray_initialized_state().load()) { + tray_update(&tray); + } + } + + void prepare_tray_virtualhid_driver() { + const auto status = confighttp::get_virtualhid_driver_status(); + update_tray_virtualhid_driver( + status.value("installed", false), + status.value("version", std::string {}), + status.value("version_compatible", false), + status.value("supported_versions", std::string {}) + ); + } #endif /** diff --git a/src/system_tray.h b/src/system_tray.h index 89d832d8d72..46f3ea8797b 100644 --- a/src/system_tray.h +++ b/src/system_tray.h @@ -6,6 +6,7 @@ // standard includes #include +#include #ifdef _WIN32 namespace lvh { @@ -127,6 +128,28 @@ namespace system_tray { * @brief Query the Virtual HID Driver license and prepare the startup tray state. */ void prepare_tray_virtualhid_license(); + + /** + * @brief Show an update notification for an unsupported Virtual HID Driver. + * + * Existing notifications are preserved when the driver is absent or supported. + * + * @param installed Whether the driver is installed. + * @param version Installed driver version. + * @param version_compatible Whether Sunshine supports the installed version. + * @param supported_versions User-visible supported version range. + */ + void update_tray_virtualhid_driver( + bool installed, + std::string_view version, + bool version_compatible, + std::string_view supported_versions + ); + + /** + * @brief Query the Virtual HID Driver version and prepare its startup notification. + */ + void prepare_tray_virtualhid_driver(); #endif /** diff --git a/src_assets/common/assets/web/index.html b/src_assets/common/assets/web/index.html index bff44590824..7c14e0b74b0 100644 --- a/src_assets/common/assets/web/index.html +++ b/src_assets/common/assets/web/index.html @@ -29,7 +29,7 @@

{{ $t('index.welcome') }}

-
+
@@ -51,6 +51,17 @@

{{ $t('index.welcome') }}

+ +
+
+ +
+

{{ $t('index.virtualhid_development_title') }}

+

{{ $t('index.virtualhid_development_desc') }}

+
+
+
+
diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 4082c880074..b88afe18cf5 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -454,6 +454,8 @@ "startup_errors": "Attention! Sunshine detected these errors during startup. We STRONGLY RECOMMEND fixing them before streaming.", "version_dirty": "Thank you for helping to make Sunshine a better software!", "version_latest": "You are running the latest version of Sunshine", + "virtualhid_development_desc": "Thank you for using a development build of Virtual HID Driver. Your testing helps make Virtual HID Driver better!", + "virtualhid_development_title": "Virtual HID Driver Development Build", "virtualhid_license_required_desc": "Virtual HID Driver adds a Raw Input keyboard and mouse plus Xbox One, Xbox Series, DualSense, Nintendo Switch Pro, and Generic gamepads. It is actively maintained by the LizardByte team. Activate or manage the license to unlock driver-backed input.", "virtualhid_license_required_title": "Virtual HID Driver License Missing", "virtualhid_missing_vigembus_installed_desc": "ViGEmBus is installed, but without the libvirtualhid driver Sunshine can only offer limited fallback gamepad support.", diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e9ac882d313..f96e5afcb86 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -174,6 +174,8 @@ set(INTEGRATION_TEST_FILES "src/config.cpp" "src_assets/common/assets/web/config.html" "docs/configuration.md" + "docs/getting_started.md" + "docs/troubleshooting.md" "src_assets/common/assets/web/public/assets/locale/en.json" "src_assets/common/assets/web/configs/tabs/General.vue" "src_assets/linux/misc/60-sunshine.rules" diff --git a/tests/integration/test_virtualhid_version_consistency.cpp b/tests/integration/test_virtualhid_version_consistency.cpp new file mode 100644 index 00000000000..253312f5986 --- /dev/null +++ b/tests/integration/test_virtualhid_version_consistency.cpp @@ -0,0 +1,41 @@ +/** + * @file tests/integration/test_virtualhid_version_consistency.cpp + * @brief Tests for the shared Virtual HID Driver minimum-version contract. + */ + +// test includes +#include "../tests_common.h" + +// standard includes +#include +#include +#include +#include + +// local includes +#include "src/file_handler.h" + +namespace { + /** + * @brief Documentation pages that publish the minimum Virtual HID Driver version. + */ + constexpr std::array virtualhid_version_documents { + "docs/getting_started.md", + "docs/troubleshooting.md", + }; +} // namespace + +TEST(VirtualHidVersionConsistencyTest, DocumentationMatchesConfiguredMinimum) { + const auto expected_text = std::format( + "Sunshine requires Virtual HID Driver version `{}` or newer", + LIBVIRTUALHID_MINIMUM_VERSION + ); + + for (const auto path : virtualhid_version_documents) { + const auto path_string = std::format("{}/{}", SUNSHINE_TEST_BIN_DIR, path); + const auto content = file_handler::read_file(path_string.c_str()); + ASSERT_FALSE(content.empty()) << "Unable to read " << path; + EXPECT_NE(content.find(expected_text), std::string::npos) + << path << " must use the CMake-configured Virtual HID Driver minimum " << LIBVIRTUALHID_MINIMUM_VERSION; + } +} diff --git a/tests/unit/test_confighttp.cpp b/tests/unit/test_confighttp.cpp index 951568ee6b6..14e37ddba6a 100644 --- a/tests/unit/test_confighttp.cpp +++ b/tests/unit/test_confighttp.cpp @@ -1469,11 +1469,21 @@ TEST(ConfigHttpDriverStatusTest, IsDriverVersionSupported_InvalidVersion_Returns ASSERT_FALSE(confighttp::is_driver_version_supported("1.17.", "1.17.0.0")); } +// Test: numeric 0.0.x development versions are identified consistently +TEST(ConfigHttpDriverStatusTest, IsDriverVersionDevelopment_RecognizesZeroMajorAndMinor) { + ASSERT_TRUE(confighttp::is_driver_version_development("0.0.0")); + ASSERT_TRUE(confighttp::is_driver_version_development("0.0.0.42")); + ASSERT_TRUE(confighttp::is_driver_version_development("0.0.1.0")); + ASSERT_FALSE(confighttp::is_driver_version_development("0.0")); + ASSERT_FALSE(confighttp::is_driver_version_development("0.1.0")); + ASSERT_FALSE(confighttp::is_driver_version_development("development")); +} + // Test: numeric development versions always bypass the production minimum TEST(ConfigHttpDriverStatusTest, IsDriverVersionSupported_DevelopmentVersionBypassesMinimum) { ASSERT_TRUE(confighttp::is_driver_version_supported("0.0.0", "2026.823.352.3")); // NOSONAR(cpp:S1313): not IP addresses ASSERT_TRUE(confighttp::is_driver_version_supported("0.0.0.42", "2026.823.352.3")); // NOSONAR(cpp:S1313): not IP addresses - ASSERT_FALSE(confighttp::is_driver_version_supported("0.0.1.0", "2026.823.352.3")); // NOSONAR(cpp:S1313): not IP addresses + ASSERT_TRUE(confighttp::is_driver_version_supported("0.0.1.0", "2026.823.352.3")); // NOSONAR(cpp:S1313): not IP addresses ASSERT_FALSE(confighttp::is_driver_version_supported("0.0", "2026.823.352.3")); // NOSONAR(cpp:S1313): not IP addresses } @@ -1485,6 +1495,7 @@ TEST(ConfigHttpDriverStatusTest, BuildDriverStatus_IncludesExpectedFields) { ASSERT_EQ(status["version"].get(), "1.17.0.0"); ASSERT_EQ(status["minimum_version"].get(), "1.17.0.0"); ASSERT_EQ(status["supported_versions"].get(), ">= 1.17.0.0"); + ASSERT_FALSE(status["development_version"].get()); ASSERT_TRUE(status["version_compatible"].get()); } @@ -1494,6 +1505,7 @@ TEST(ConfigHttpDriverStatusTest, BuildDriverStatus_NotInstalledIsNotCompatible) ASSERT_FALSE(status["installed"].get()); ASSERT_EQ(status["supported_versions"].get(), "Any"); + ASSERT_FALSE(status["development_version"].get()); ASSERT_FALSE(status["version_compatible"].get()); } @@ -1502,6 +1514,7 @@ TEST(ConfigHttpDriverStatusTest, BuildDriverStatus_OlderDetectedDriverIsInstalle const auto status = confighttp::build_driver_status(true, "2026.820.1844.57", "2026.823.352.3"); // NOSONAR(cpp:S1313): not IP addresses ASSERT_TRUE(status["installed"].get()); + ASSERT_FALSE(status["development_version"].get()); ASSERT_FALSE(status["version_compatible"].get()); } @@ -1511,6 +1524,7 @@ TEST(ConfigHttpDriverStatusTest, BuildDriverStatus_DevelopmentVersionIsCompatibl ASSERT_EQ(status["minimum_version"].get(), "2026.823.352.3"); // NOSONAR(cpp:S1313): not an IP address ASSERT_EQ(status["supported_versions"].get(), ">= 2026.823.352.3"); // NOSONAR(cpp:S1313): not an IP address + ASSERT_TRUE(status["development_version"].get()); ASSERT_TRUE(status["version_compatible"].get()); } @@ -1519,10 +1533,11 @@ TEST(ConfigHttpDriverStatusTest, BuildsLiveVirtualInputDriverStatus) { EXPECT_TRUE(virtualhid.contains("installed")); EXPECT_TRUE(virtualhid.contains("version")); EXPECT_TRUE(virtualhid.contains("version_compatible")); + EXPECT_TRUE(virtualhid.contains("development_version")); EXPECT_TRUE(virtualhid.contains("backend_name")); EXPECT_TRUE(virtualhid.contains("requires_installed_driver")); - EXPECT_EQ(virtualhid["minimum_version"].get(), "2026.829.2338.54"); // NOSONAR(cpp:S1313): not an IP address - EXPECT_EQ(virtualhid["supported_versions"].get(), ">= 2026.829.2338.54"); // NOSONAR(cpp:S1313): not an IP address + EXPECT_EQ(virtualhid["minimum_version"].get(), LIBVIRTUALHID_MINIMUM_VERSION); + EXPECT_EQ(virtualhid["supported_versions"].get(), std::format(">= {}", LIBVIRTUALHID_MINIMUM_VERSION)); const auto vigembus = confighttp::get_vigembus_driver_status(); EXPECT_TRUE(vigembus.contains("installed")); diff --git a/tests/unit/test_system_tray.cpp b/tests/unit/test_system_tray.cpp index daa61ce8161..f8940e1063b 100644 --- a/tests/unit/test_system_tray.cpp +++ b/tests/unit/test_system_tray.cpp @@ -366,6 +366,47 @@ TEST_F(SystemTrayTest, PreparesLicensedVirtualHidMenuBeforeInitialization) { EXPECT_STREQ(license_menu[3].text, "Machine activations: Not reported"); } +TEST_F(SystemTrayTest, NotifiesWhenVirtualHidDriverIsUnsupported) { + const auto supported_versions = std::format(">= {}", LIBVIRTUALHID_MINIMUM_VERSION); + system_tray::update_tray_virtualhid_driver(true, "2026.829.2338.54", false, supported_versions); // NOSONAR(cpp:S1313): not an IP address + + const auto &tray_data = system_tray::tray_data_for_testing(); + const auto expected_notification = std::format( + "Installed Virtual HID Driver v2026.829.2338.54 is not supported by this version of Sunshine. Supported versions: {}. Restart Sunshine after updating. Click for instructions.", + supported_versions + ); + EXPECT_STREQ(tray_data.notification_title, "Update Virtual HID Driver"); + EXPECT_STREQ(tray_data.notification_text, expected_notification.c_str()); + EXPECT_STREQ(tray_data.notification_icon, tray_data.allIconPaths[4]); + EXPECT_NE(tray_data.notification_cb, nullptr); + + system_tray::resolve_tray_icon_paths_for_testing(); + EXPECT_STREQ(tray_data.notification_icon, tray_data.allIconPaths[4]); +} + +TEST_F(SystemTrayTest, PreservesExistingNotificationWhenVirtualHidDriverIsUsable) { + lvh::LicenseStatus license; + license.service_available = true; + license.state = lvh::LicenseState::unlicensed; + system_tray::update_tray_virtualhid_license(license, true); + + const auto &tray_data = system_tray::tray_data_for_testing(); + const auto *notification_title = tray_data.notification_title; + const auto *notification_text = tray_data.notification_text; + const auto notification_callback = tray_data.notification_cb; + + const auto supported_versions = std::format(">= {}", LIBVIRTUALHID_MINIMUM_VERSION); + system_tray::update_tray_virtualhid_driver(false, "", false, supported_versions); + EXPECT_EQ(tray_data.notification_title, notification_title); + EXPECT_EQ(tray_data.notification_text, notification_text); + EXPECT_EQ(tray_data.notification_cb, notification_callback); + + system_tray::update_tray_virtualhid_driver(true, "0.0.1", true, supported_versions); + EXPECT_EQ(tray_data.notification_title, notification_title); + EXPECT_EQ(tray_data.notification_text, notification_text); + EXPECT_EQ(tray_data.notification_cb, notification_callback); +} + /** * @brief License-state fixture for the Windows Virtual HID Driver tray menu. */ diff --git a/third-party/libvirtualhid b/third-party/libvirtualhid index 45db9957e55..6fdb8bd4de3 160000 --- a/third-party/libvirtualhid +++ b/third-party/libvirtualhid @@ -1 +1 @@ -Subproject commit 45db9957e55f030cba9b4d56feef4d2248eceea8 +Subproject commit 6fdb8bd4de3b68d96c30e5303ac2ebb333c09746