4242#include < QFile>
4343#endif
4444
45- #ifdef _WIN32
4645#include < QSessionManager>
47- #else
46+ #ifndef _WIN32
4847#include < QSocketNotifier>
4948#endif
5049
@@ -78,6 +77,7 @@ extern string opt_starting_profile;
7877
7978#ifndef _WIN32
8079int OBSApp::sigintFd[2 ];
80+ int OBSApp::sigtermFd[2 ];
8181#endif
8282
8383// GPU hint exports for AMD/NVIDIA laptops
@@ -280,6 +280,54 @@ string CurrentDateTimeString()
280280 return buf;
281281}
282282
283+ bool OBSNativeEventFilter::nativeEventFilter (const QByteArray &eventType, void *message, qintptr *result)
284+ {
285+ if (eventType == " windows_generic_MSG" ) {
286+ #ifdef _WIN32
287+ MSG *msg = static_cast <MSG *>(message);
288+
289+ OBSBasic *main = OBSBasic::Get ();
290+ if (!main) {
291+ return false ;
292+ }
293+
294+ switch (msg->message ) {
295+ case WM_QUERYENDSESSION:
296+ main->saveAll ();
297+ if (msg->lParam == ENDSESSION_CRITICAL) {
298+ break ;
299+ }
300+
301+ if (main->shouldPromptForClose ()) {
302+ *result = FALSE ;
303+ return true ;
304+ }
305+
306+ return false ;
307+ case WM_ENDSESSION:
308+ if (msg->wParam == TRUE ) {
309+ // Session is ending, start closing the main window now with no checks or prompts.
310+ main->closeWindow ();
311+ } else {
312+ /* Session is no longer ending. If OBS is still open, odds are it is what held
313+ * up the session end due to it's higher than default priority. We call the
314+ * close method to trigger the confirmation window flow. We do this after the fact
315+ * to avoid blocking the main window event loop prior to this message.
316+ * Otherwise OBS is already gone and invoking this does nothing */
317+ main->close ();
318+ }
319+
320+ return true ;
321+ }
322+ #else
323+ UNUSED_PARAMETER (message);
324+ UNUSED_PARAMETER (result);
325+ #endif
326+ }
327+
328+ return false ;
329+ }
330+
283331#define DEFAULT_LANG " en-US"
284332
285333bool OBSApp::InitGlobalConfigDefaults ()
@@ -868,6 +916,8 @@ OBSApp::OBSApp(int &argc, char **argv, profiler_name_store_t *store)
868916 profilerNameStore(store),
869917 appLaunchUUID_(QUuid::createUuid())
870918{
919+ installNativeEventFilter (new OBSNativeEventFilter);
920+
871921 /* fix float handling */
872922#if defined(Q_OS_UNIX)
873923 if (!setlocale (LC_NUMERIC, " C" ))
@@ -879,9 +929,14 @@ OBSApp::OBSApp(int &argc, char **argv, profiler_name_store_t *store)
879929 socketpair (AF_UNIX, SOCK_STREAM, 0 , sigintFd);
880930 snInt = new QSocketNotifier (sigintFd[1 ], QSocketNotifier::Read, this );
881931 connect (snInt, &QSocketNotifier::activated, this , &OBSApp::ProcessSigInt);
882- #else
883- connect (qApp, &QGuiApplication::commitDataRequest, this , &OBSApp::commitData);
932+
933+ /* Handle SIGTERM */
934+ socketpair (AF_UNIX, SOCK_STREAM, 0 , sigtermFd);
935+ snTerm = new QSocketNotifier (sigtermFd[1 ], QSocketNotifier::Read, this );
936+ connect (snTerm, &QSocketNotifier::activated, this , &OBSApp::ProcessSigTerm);
884937#endif
938+ connect (qApp, &QGuiApplication::commitDataRequest, this , &OBSApp::commitData, Qt::DirectConnection);
939+
885940 if (multi) {
886941 crashHandler_ = std::make_unique<OBS::CrashHandler>();
887942 } else {
@@ -1229,7 +1284,20 @@ bool OBSApp::OBSInit()
12291284 mainWindow = new OBSBasic ();
12301285
12311286 mainWindow->setAttribute (Qt::WA_DeleteOnClose, true );
1232- connect (mainWindow, &OBSBasic::destroyed, this , &OBSApp::quit);
1287+
1288+ connect (QApplication::instance (), &QApplication::aboutToQuit, this , [this ]() {
1289+ crashHandler_->applicationShutdownHandler ();
1290+
1291+ /* Ensure OBSMainWindow gets closed */
1292+ if (mainWindow) {
1293+ mainWindow->close ();
1294+ delete mainWindow;
1295+ }
1296+
1297+ if (libobs_initialized) {
1298+ applicationShutdown ();
1299+ }
1300+ });
12331301
12341302 mainWindow->OBSInit ();
12351303
@@ -1748,6 +1816,14 @@ void OBSApp::SigIntSignalHandler(int s)
17481816 char a = 1 ;
17491817 send (sigintFd[0 ], &a, sizeof (a), 0 );
17501818}
1819+
1820+ void OBSApp::SigTermSignalHandler (int s)
1821+ {
1822+ UNUSED_PARAMETER (s);
1823+
1824+ char a = 1 ;
1825+ send (sigtermFd[0 ], &a, sizeof (a), 0 );
1826+ }
17511827#endif
17521828
17531829void OBSApp::ProcessSigInt (void )
@@ -1759,20 +1835,39 @@ void OBSApp::ProcessSigInt(void)
17591835 recv (sigintFd[1 ], &tmp, sizeof (tmp), 0 );
17601836
17611837 OBSBasic *main = OBSBasic::Get ();
1762- if (main)
1838+ if (main) {
1839+ main->saveAll ();
17631840 main->close ();
1841+ }
1842+ #endif
1843+ }
1844+
1845+ void OBSApp::ProcessSigTerm (void )
1846+ {
1847+ #ifndef _WIN32
1848+ char tmp;
1849+ recv (sigtermFd[1 ], &tmp, sizeof (tmp), 0 );
1850+
1851+ OBSBasic *main = OBSBasic::Get ();
1852+ if (main) {
1853+ main->saveAll ();
1854+ }
1855+
1856+ quit ();
17641857#endif
17651858}
17661859
1767- #ifdef _WIN32
17681860void OBSApp::commitData (QSessionManager &manager)
17691861{
1770- if (auto main = App ()->GetMainWindow ()) {
1771- QMetaObject::invokeMethod (main, " close" , Qt::QueuedConnection);
1772- manager.cancel ();
1862+ OBSBasic *main = OBSBasic::Get ();
1863+ if (main) {
1864+ main->saveAll ();
1865+
1866+ if (manager.allowsInteraction () && main->shouldPromptForClose ()) {
1867+ manager.cancel ();
1868+ }
17731869 }
17741870}
1775- #endif
17761871
17771872void OBSApp::applicationShutdown () noexcept
17781873{
@@ -1784,6 +1879,10 @@ void OBSApp::applicationShutdown() noexcept
17841879 delete snInt;
17851880 close (sigintFd[0 ]);
17861881 close (sigintFd[1 ]);
1882+
1883+ delete snTerm;
1884+ close (sigtermFd[0 ]);
1885+ close (sigtermFd[1 ]);
17871886#endif
17881887
17891888#ifdef __APPLE__
0 commit comments