@@ -88,6 +88,45 @@ WINAPI BOOL ConsoleCtrlHandler(DWORD type) {
8888}
8989#endif
9090
91+ #if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
92+ constexpr bool tray_is_enabled = true ;
93+ #else
94+ constexpr bool tray_is_enabled = false ;
95+ #endif
96+
97+ void mainThreadLoop (const std::shared_ptr<safe::event_t <bool >> &shutdown_event) {
98+ bool run_loop = false ;
99+
100+ // Conditions that would require the main thread event loop
101+ #ifndef _WIN32
102+ run_loop = tray_is_enabled; // On Windows, tray runs in separate thread, so no main loop needed for tray
103+ #endif
104+
105+ if (!run_loop) {
106+ BOOST_LOG (info) << " No main thread features enabled, skipping event loop" sv;
107+ return ;
108+ }
109+
110+ // Main thread event loop
111+ BOOST_LOG (info) << " Starting main loop" sv;
112+ while (true ) {
113+ if (shutdown_event->peek ()) {
114+ BOOST_LOG (info) << " Shutdown event detected, breaking main loop" sv;
115+ if (tray_is_enabled) {
116+ system_tray::end_tray ();
117+ }
118+ break ;
119+ }
120+
121+ if (tray_is_enabled) {
122+ system_tray::process_tray_events ();
123+ }
124+
125+ // Sleep to avoid busy waiting
126+ std::this_thread::sleep_for (std::chrono::milliseconds (50 ));
127+ }
128+ }
129+
91130int main (int argc, char *argv[]) {
92131 lifetime::argv = argv;
93132
@@ -157,7 +196,7 @@ int main(int argc, char *argv[]) {
157196 BOOST_LOG (error) << " Display device session failed to initialize" sv;
158197 }
159198
160- #ifdef WIN32
199+ #ifdef _WIN32
161200 // Modify relevant NVIDIA control panel settings if the system has corresponding gpu
162201 if (nvprefs_instance.load ()) {
163202 // Restore global settings to the undo file left by improper termination of sunshine.exe
@@ -246,11 +285,6 @@ int main(int argc, char *argv[]) {
246285
247286 task_pool.start (1 );
248287
249- #if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
250- // create tray thread and detach it
251- system_tray::run_tray ();
252- #endif
253-
254288 // Create signal handler after logging has been initialized
255289 auto shutdown_event = mail::man->event <bool >(mail::shutdown);
256290 on_signal (SIGINT, [&force_shutdown, &display_device_deinit_guard, shutdown_event]() {
@@ -350,7 +384,23 @@ int main(int argc, char *argv[]) {
350384 }
351385#endif
352386
353- // Wait for shutdown
387+ if (tray_is_enabled) {
388+ BOOST_LOG (info) << " Starting system tray" sv;
389+ #ifdef _WIN32
390+ // TODO: Windows has a weird bug where when running as a service and on the first Windows boot,
391+ // he tray icon would not appear even though Sunshine is running correctly otherwise.
392+ // Restarting the service would allow the icon to appear normally.
393+ // For now we will keep the Windows tray icon on a separate thread.
394+ // Ideally, we would run the system tray on the main thread for all platforms.
395+ system_tray::init_tray_threaded ();
396+ #else
397+ system_tray::init_tray ();
398+ #endif
399+ }
400+
401+ mainThreadLoop (shutdown_event);
402+
403+ // Wait for shutdown, this is not necessary when we're using the main event loop
354404 shutdown_event->view ();
355405
356406 httpThread.join ();
@@ -360,17 +410,17 @@ int main(int argc, char *argv[]) {
360410 task_pool.stop ();
361411 task_pool.join ();
362412
363- // stop system tray
364- #if defined SUNSHINE_TRAY && SUNSHINE_TRAY >= 1
365- system_tray::end_tray ();
366- #endif
367-
368- #ifdef WIN32
413+ #ifdef _WIN32
369414 // Restore global NVIDIA control panel settings
370415 if (nvprefs_instance.owning_undo_file () && nvprefs_instance.load ()) {
371416 nvprefs_instance.restore_global_profile ();
372417 nvprefs_instance.unload ();
373418 }
419+
420+ // Stop the threaded tray if it was started
421+ if (tray_is_enabled) {
422+ system_tray::end_tray_threaded ();
423+ }
374424#endif
375425
376426 return lifetime::desired_exit_code;
0 commit comments