fix(tray): optionally run tray in main event loop enabling support for macOS (#3818)

Co-authored-by: Lukas Senionis <22381748+FrogTheFrog@users.noreply.github.com>
This commit is contained in:
ReenigneArcher
2025-09-01 11:30:18 -04:00
committed by GitHub
parent 705d763729
commit 73f84fb6dd
6 changed files with 224 additions and 76 deletions

View File

@@ -88,6 +88,45 @@ WINAPI BOOL ConsoleCtrlHandler(DWORD type) {
}
#endif
#if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
constexpr bool tray_is_enabled = true;
#else
constexpr bool tray_is_enabled = false;
#endif
void mainThreadLoop(const std::shared_ptr<safe::event_t<bool>> &shutdown_event) {
bool run_loop = false;
// Conditions that would require the main thread event loop
#ifndef _WIN32
run_loop = tray_is_enabled; // On Windows, tray runs in separate thread, so no main loop needed for tray
#endif
if (!run_loop) {
BOOST_LOG(info) << "No main thread features enabled, skipping event loop"sv;
return;
}
// Main thread event loop
BOOST_LOG(info) << "Starting main loop"sv;
while (true) {
if (shutdown_event->peek()) {
BOOST_LOG(info) << "Shutdown event detected, breaking main loop"sv;
if (tray_is_enabled) {
system_tray::end_tray();
}
break;
}
if (tray_is_enabled) {
system_tray::process_tray_events();
}
// Sleep to avoid busy waiting
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}
int main(int argc, char *argv[]) {
lifetime::argv = argv;
@@ -157,7 +196,7 @@ int main(int argc, char *argv[]) {
BOOST_LOG(error) << "Display device session failed to initialize"sv;
}
#ifdef WIN32
#ifdef _WIN32
// Modify relevant NVIDIA control panel settings if the system has corresponding gpu
if (nvprefs_instance.load()) {
// Restore global settings to the undo file left by improper termination of sunshine.exe
@@ -246,11 +285,6 @@ int main(int argc, char *argv[]) {
task_pool.start(1);
#if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
// create tray thread and detach it
system_tray::run_tray();
#endif
// Create signal handler after logging has been initialized
auto shutdown_event = mail::man->event<bool>(mail::shutdown);
on_signal(SIGINT, [&force_shutdown, &display_device_deinit_guard, shutdown_event]() {
@@ -350,7 +384,23 @@ int main(int argc, char *argv[]) {
}
#endif
// Wait for shutdown
if (tray_is_enabled) {
BOOST_LOG(info) << "Starting system tray"sv;
#ifdef _WIN32
// TODO: Windows has a weird bug where when running as a service and on the first Windows boot,
// he tray icon would not appear even though Sunshine is running correctly otherwise.
// Restarting the service would allow the icon to appear normally.
// For now we will keep the Windows tray icon on a separate thread.
// Ideally, we would run the system tray on the main thread for all platforms.
system_tray::init_tray_threaded();
#else
system_tray::init_tray();
#endif
}
mainThreadLoop(shutdown_event);
// Wait for shutdown, this is not necessary when we're using the main event loop
shutdown_event->view();
httpThread.join();
@@ -360,17 +410,17 @@ int main(int argc, char *argv[]) {
task_pool.stop();
task_pool.join();
// stop system tray
#if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
system_tray::end_tray();
#endif
#ifdef WIN32
#ifdef _WIN32
// Restore global NVIDIA control panel settings
if (nvprefs_instance.owning_undo_file() && nvprefs_instance.load()) {
nvprefs_instance.restore_global_profile();
nvprefs_instance.unload();
}
// Stop the threaded tray if it was started
if (tray_is_enabled) {
system_tray::end_tray_threaded();
}
#endif
return lifetime::desired_exit_code;