mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-19 17:49:14 +00:00
UI: Don't open settings or close in event subloop
Fixes a crash that can happen if you try to use the settings window while in an even subloop, or if you try to close OBS while in an event subloop. Continually retries (defers) the actions every one second until the subloop has finished.
This commit is contained in:
parent
11c0d6e976
commit
29a1a97392
|
@ -19,6 +19,7 @@
|
|||
#include "obs-app.hpp"
|
||||
|
||||
#include <graphics/graphics.h>
|
||||
#include <util/threading.h>
|
||||
#include <QWidget>
|
||||
#include <QLayout>
|
||||
#include <QMessageBox>
|
||||
|
@ -224,6 +225,8 @@ QThread *CreateQThread(std::function<void()> func)
|
|||
return new QuickThread(func);
|
||||
}
|
||||
|
||||
volatile long insideEventLoop = 0;
|
||||
|
||||
void ExecuteFuncSafeBlock(std::function<void()> func)
|
||||
{
|
||||
QEventLoop eventLoop;
|
||||
|
@ -235,10 +238,12 @@ void ExecuteFuncSafeBlock(std::function<void()> func)
|
|||
Qt::QueuedConnection);
|
||||
};
|
||||
|
||||
os_atomic_inc_long(&insideEventLoop);
|
||||
QScopedPointer<QThread> thread(CreateQThread(wait));
|
||||
thread->start();
|
||||
eventLoop.exec();
|
||||
thread->wait();
|
||||
os_atomic_dec_long(&insideEventLoop);
|
||||
}
|
||||
|
||||
void ExecuteFuncSafeBlockMsgBox(
|
||||
|
@ -258,10 +263,12 @@ void ExecuteFuncSafeBlockMsgBox(
|
|||
QMetaObject::invokeMethod(&dlg, "accept", Qt::QueuedConnection);
|
||||
};
|
||||
|
||||
os_atomic_inc_long(&insideEventLoop);
|
||||
QScopedPointer<QThread> thread(CreateQThread(wait));
|
||||
thread->start();
|
||||
dlg.exec();
|
||||
thread->wait();
|
||||
os_atomic_dec_long(&insideEventLoop);
|
||||
}
|
||||
|
||||
static bool enable_message_boxes = false;
|
||||
|
|
|
@ -98,6 +98,8 @@ struct SignalContainer {
|
|||
|
||||
}
|
||||
|
||||
extern volatile long insideEventLoop;
|
||||
|
||||
Q_DECLARE_METATYPE(OBSScene);
|
||||
Q_DECLARE_METATYPE(OBSSceneItem);
|
||||
Q_DECLARE_METATYPE(OBSSource);
|
||||
|
@ -3761,6 +3763,15 @@ void OBSBasic::ClearSceneData()
|
|||
|
||||
void OBSBasic::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
/* Do not close window if inside of a temporary event loop because we
|
||||
* could be inside of an Auth::LoadUI call. Keep trying once per
|
||||
* second until we've exit any known sub-loops. */
|
||||
if (os_atomic_load_long(&insideEventLoop) != 0) {
|
||||
QTimer::singleShot(1000, this, SLOT(close()));
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if (isVisible())
|
||||
config_set_string(App()->GlobalConfig(),
|
||||
"BasicWindow", "geometry",
|
||||
|
@ -3860,9 +3871,28 @@ void OBSBasic::on_actionRemux_triggered()
|
|||
|
||||
void OBSBasic::on_action_Settings_triggered()
|
||||
{
|
||||
static bool settings_already_executing = false;
|
||||
|
||||
/* Do not load settings window if inside of a temporary event loop
|
||||
* because we could be inside of an Auth::LoadUI call. Keep trying
|
||||
* once per second until we've exit any known sub-loops. */
|
||||
if (os_atomic_load_long(&insideEventLoop) != 0) {
|
||||
QTimer::singleShot(1000, this,
|
||||
SLOT(on_action_Settings_triggered()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings_already_executing) {
|
||||
return;
|
||||
}
|
||||
|
||||
settings_already_executing = true;
|
||||
|
||||
OBSBasicSettings settings(this);
|
||||
settings.exec();
|
||||
SystemTray(false);
|
||||
|
||||
settings_already_executing = false;
|
||||
}
|
||||
|
||||
void OBSBasic::on_actionAdvAudioProperties_triggered()
|
||||
|
|
Loading…
Reference in a new issue