From 37cbe65a852231f2ee85e41c4ce623afe11fce6b Mon Sep 17 00:00:00 2001 From: WarmUpTill <19472752+WarmUpTill@users.noreply.github.com> Date: Mon, 23 Feb 2026 17:18:15 +0100 Subject: [PATCH] Show dialogs after OBS_FRONTEND_EVENT_FINISHED_LOADING is fired --- lib/utils/backup.cpp | 17 ++--------- lib/utils/crash-handler.cpp | 17 ++--------- lib/utils/plugin-state-helpers.cpp | 46 ++++++++++++++++++++++++++++++ lib/utils/plugin-state-helpers.hpp | 3 ++ plugins/twitch/twitch-tab.cpp | 23 +++------------ 5 files changed, 57 insertions(+), 49 deletions(-) diff --git a/lib/utils/backup.cpp b/lib/utils/backup.cpp index 7cfe14d0..17355695 100644 --- a/lib/utils/backup.cpp +++ b/lib/utils/backup.cpp @@ -54,31 +54,18 @@ void AskForBackup(obs_data_t *settings) // or crashing. // Therefore, we ask the user whether they want to back up the settings // asynchronously. - // - // On macOS, an additional QTimer::singleShot wrapper is required for - // this to work correctly. auto json = obs_data_get_json(settings); static QString jsonQString = json ? json : ""; static const auto askForBackupWrapper = [](void *) { -#ifdef __APPLE__ - QTimer::singleShot(0, - static_cast( - obs_frontend_get_main_window()), - []() { -#endif - showBackupDialogs(jsonQString); -#ifdef __APPLE__ - }); -#endif + showBackupDialogs(jsonQString); }; - std::thread t([]() { + AddFinishedLoadingStep([]() { obs_queue_task(OBS_TASK_UI, askForBackupWrapper, nullptr, false); }); - t.detach(); } void BackupSettingsOfCurrentVersion() diff --git a/lib/utils/crash-handler.cpp b/lib/utils/crash-handler.cpp index f88439c8..e2cc89e4 100644 --- a/lib/utils/crash-handler.cpp +++ b/lib/utils/crash-handler.cpp @@ -126,26 +126,13 @@ bool ShouldSkipPluginStartOnUncleanShutdown() // or crashing. // Therefore, we ask the user whether they want to start the plugin // asynchronously. - // - // On macOS, an additional QTimer::singleShot wrapper is required for - // this to work correctly. static const auto showDialogWrapper = [](void *) { -#ifdef __APPLE__ - QTimer::singleShot(0, - static_cast( - obs_frontend_get_main_window()), - []() { -#endif - askForStartupSkip(); -#ifdef __APPLE__ - }); -#endif + askForStartupSkip(); }; - std::thread t([]() { + AddFinishedLoadingStep([]() { obs_queue_task(OBS_TASK_UI, showDialogWrapper, nullptr, false); }); - t.detach(); return true; } diff --git a/lib/utils/plugin-state-helpers.cpp b/lib/utils/plugin-state-helpers.cpp index 0f908320..6973dd1d 100644 --- a/lib/utils/plugin-state-helpers.cpp +++ b/lib/utils/plugin-state-helpers.cpp @@ -3,12 +3,42 @@ #include "macro-signals.hpp" #include "switcher-data.hpp" +#include "obs-frontend-api.h" + namespace advss { static std::mutex initMutex; static std::mutex postLoadMutex; +static std::mutex finishLoadMutex; static std::mutex mutex; +static bool setup(); +static bool setupDonw = setup(); +bool loadingFinished = false; + +static std::vector> &getFinishLoadSteps(); + +static bool setup() +{ + static auto handleEvent = [](enum obs_frontend_event event, void *) { + switch (event) { + case OBS_FRONTEND_EVENT_FINISHED_LOADING: { + std::lock_guard lock(finishLoadMutex); + for (const auto &step : getFinishLoadSteps()) { + step(); + } + getFinishLoadSteps().clear(); + loadingFinished = true; + break; + } + default: + break; + }; + }; + obs_frontend_add_event_callback(handleEvent, nullptr); + return true; +} + static std::vector> &getPluginInitSteps() { static std::vector> steps; @@ -63,6 +93,12 @@ static std::vector> &getPostLoadSteps() return steps; } +static std::vector> &getFinishLoadSteps() +{ + static std::vector> steps; + return steps; +} + void SavePluginSettings(obs_data_t *obj) { GetSwitcher()->SaveSettings(obj); @@ -178,6 +214,16 @@ void RunIntervalResetSteps() } } +void AddFinishedLoadingStep(std::function step) +{ + std::lock_guard lock(finishLoadMutex); + if (loadingFinished) { + return; + } + + getFinishLoadSteps().emplace_back(step); +} + void AddStartStep(std::function step) { std::lock_guard lock(mutex); diff --git a/lib/utils/plugin-state-helpers.hpp b/lib/utils/plugin-state-helpers.hpp index 4251d7d3..1df274d3 100644 --- a/lib/utils/plugin-state-helpers.hpp +++ b/lib/utils/plugin-state-helpers.hpp @@ -34,6 +34,9 @@ void RunStartSteps(); void RunStopSteps(); void RunIntervalResetSteps(); +// Steps are executed after OBS_FRONTEND_EVENT_FINISHED_LOADING is fired +EXPORT void AddFinishedLoadingStep(std::function); + enum class NoMatchBehavior { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 }; EXPORT void SetPluginNoMatchBehavior(NoMatchBehavior); EXPORT NoMatchBehavior GetPluginNoMatchBehavior(); diff --git a/plugins/twitch/twitch-tab.cpp b/plugins/twitch/twitch-tab.cpp index a8f935a5..7636d5eb 100644 --- a/plugins/twitch/twitch-tab.cpp +++ b/plugins/twitch/twitch-tab.cpp @@ -28,7 +28,7 @@ static bool setup() AddSetupTabCallback("twitchConnectionTab", TwitchConnectionsTable::Create, setupTab); - static const auto showInvalidWarnings = []() { + static const auto showInvalidWarnings = [](void *) { const auto invalidTokens = getInvalidTokens(); for (const auto &token : invalidTokens) { QueueUITask( @@ -47,24 +47,9 @@ static bool setup() // or crashing. // Therefore, we ask the user whether they want to update their Twitch // connections asynchronously. - // - // On macOS, an additional QTimer::singleShot wrapper is required for - // this to work correctly. - AddLoadStep([](obs_data_t *) { - AddPostLoadStep([]() { -#ifdef __APPLE__ - QTimer::singleShot( - 0, - static_cast( - obs_frontend_get_main_window()), - []() { -#endif - showInvalidWarnings(); - -#ifdef __APPLE__ - }); -#endif - }); + AddFinishedLoadingStep([]() { + obs_queue_task(OBS_TASK_UI, showInvalidWarnings, nullptr, + false); }); return true;