UI: Fix crash at render_display while shutdown on macOS

The display context was sometimes created again by a resize event after
destruction from `OBSBasic::closeEvent`. That resulted in the display
context alive until reaching the destructor of the `OBSQTDisplay` class
and caused a crash in `render_display` on macOS. To avoid this, destroy
the display context at the event `SurfaceAboutToBeDestroyed` and let not
create the display context again.
This commit is contained in:
Norihiro Kamae
2023-08-15 13:22:40 +09:00
parent fa17168ba2
commit fd502cbd4d
3 changed files with 44 additions and 5 deletions

View File

@@ -13,6 +13,39 @@
#include <Windows.h>
#endif
class SurfaceEventFilter : public QObject {
OBSQTDisplay *display;
public:
SurfaceEventFilter(OBSQTDisplay *src) : display(src) {}
protected:
bool eventFilter(QObject *obj, QEvent *event) override
{
bool result = QObject::eventFilter(obj, event);
QPlatformSurfaceEvent *surfaceEvent;
switch (event->type()) {
case QEvent::PlatformSurface:
surfaceEvent =
static_cast<QPlatformSurfaceEvent *>(event);
switch (surfaceEvent->surfaceEventType()) {
case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
display->DestroyDisplay();
break;
default:
break;
}
break;
default:
break;
}
return result;
}
};
static inline long long color_to_int(const QColor &color)
{
auto shift = [&](unsigned val, int shift) {
@@ -65,6 +98,8 @@ OBSQTDisplay::OBSQTDisplay(QWidget *parent, Qt::WindowFlags flags)
connect(windowHandle(), &QWindow::visibleChanged, windowVisible);
connect(windowHandle(), &QWindow::screenChanged, screenChanged);
windowHandle()->installEventFilter(new SurfaceEventFilter(this));
}
QColor OBSQTDisplay::GetDisplayBackgroundColor() const
@@ -92,6 +127,9 @@ void OBSQTDisplay::CreateDisplay()
if (display)
return;
if (destroying)
return;
if (!windowHandle()->isExposed())
return;

View File

@@ -12,6 +12,7 @@ class OBSQTDisplay : public QWidget {
SetDisplayBackgroundColor)
OBSDisplay display;
bool destroying = false;
virtual void paintEvent(QPaintEvent *event) override;
virtual void moveEvent(QMoveEvent *event) override;
@@ -38,7 +39,11 @@ public:
void SetDisplayBackgroundColor(const QColor &color);
void UpdateDisplayBackgroundColor();
void CreateDisplay();
void DestroyDisplay() { display = nullptr; };
void DestroyDisplay()
{
display = nullptr;
destroying = true;
};
void OnMove();
void OnDisplayChange();

View File

@@ -5154,10 +5154,6 @@ void OBSBasic::closeEvent(QCloseEvent *event)
delete extraBrowsers;
ui->preview->DestroyDisplay();
if (program)
program->DestroyDisplay();
config_set_string(App()->GlobalConfig(), "BasicWindow", "DockState",
saveState().toBase64().constData());