mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-10-23 06:24:44 -04:00
Merge pull request #9435 from norihiro/qtdisplay-destroy-at-surface-event-3
Fix crash at render_display while shutdown on macOS
This commit is contained in:
3 files changed
+24
-45
No files matched your search
+7
-39
@@ -13,15 +13,11 @@
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_WAYLAND
|
||||
#include <obs-nix-platform.h>
|
||||
|
||||
class SurfaceEventFilter : public QObject {
|
||||
OBSQTDisplay *display;
|
||||
int mTimerId;
|
||||
|
||||
public:
|
||||
SurfaceEventFilter(OBSQTDisplay *src) : display(src), mTimerId(0) {}
|
||||
SurfaceEventFilter(OBSQTDisplay *src) : display(src) {}
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override
|
||||
@@ -35,22 +31,12 @@ protected:
|
||||
static_cast<QPlatformSurfaceEvent *>(event);
|
||||
|
||||
switch (surfaceEvent->surfaceEventType()) {
|
||||
case QPlatformSurfaceEvent::SurfaceCreated:
|
||||
if (display->windowHandle()->isExposed())
|
||||
createOBSDisplay();
|
||||
else
|
||||
mTimerId = startTimer(67); // Arbitrary
|
||||
break;
|
||||
case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
|
||||
display->DestroyDisplay();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case QEvent::Expose:
|
||||
createOBSDisplay();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -58,25 +44,8 @@ protected:
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void timerEvent(QTimerEvent *) override
|
||||
{
|
||||
createOBSDisplay(display->isVisible());
|
||||
}
|
||||
|
||||
private:
|
||||
void createOBSDisplay(bool force = false)
|
||||
{
|
||||
display->CreateDisplay(force);
|
||||
if (mTimerId > 0) {
|
||||
killTimer(mTimerId);
|
||||
mTimerId = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static inline long long color_to_int(const QColor &color)
|
||||
{
|
||||
auto shift = [&](unsigned val, int shift) {
|
||||
@@ -130,11 +99,7 @@ OBSQTDisplay::OBSQTDisplay(QWidget *parent, Qt::WindowFlags flags)
|
||||
connect(windowHandle(), &QWindow::visibleChanged, windowVisible);
|
||||
connect(windowHandle(), &QWindow::screenChanged, screenChanged);
|
||||
|
||||
#ifdef ENABLE_WAYLAND
|
||||
if (obs_get_nix_platform() == OBS_NIX_PLATFORM_WAYLAND)
|
||||
windowHandle()->installEventFilter(
|
||||
new SurfaceEventFilter(this));
|
||||
#endif
|
||||
windowHandle()->installEventFilter(new SurfaceEventFilter(this));
|
||||
}
|
||||
|
||||
QColor OBSQTDisplay::GetDisplayBackgroundColor() const
|
||||
@@ -157,12 +122,15 @@ void OBSQTDisplay::UpdateDisplayBackgroundColor()
|
||||
obs_display_set_background_color(display, backgroundColor);
|
||||
}
|
||||
|
||||
void OBSQTDisplay::CreateDisplay(bool force)
|
||||
void OBSQTDisplay::CreateDisplay()
|
||||
{
|
||||
if (display)
|
||||
return;
|
||||
|
||||
if (!windowHandle()->isExposed() && !force)
|
||||
if (destroying)
|
||||
return;
|
||||
|
||||
if (!windowHandle()->isExposed())
|
||||
return;
|
||||
|
||||
QSize size = GetPixelSize(this);
|
||||
|
||||
+7
-2
@@ -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;
|
||||
@@ -37,8 +38,12 @@ public:
|
||||
QColor GetDisplayBackgroundColor() const;
|
||||
void SetDisplayBackgroundColor(const QColor &color);
|
||||
void UpdateDisplayBackgroundColor();
|
||||
void CreateDisplay(bool force = false);
|
||||
void DestroyDisplay() { display = nullptr; };
|
||||
void CreateDisplay();
|
||||
void DestroyDisplay()
|
||||
{
|
||||
display = nullptr;
|
||||
destroying = true;
|
||||
};
|
||||
|
||||
void OnMove();
|
||||
void OnDisplayChange();
|
||||
|
||||
@@ -5128,6 +5128,16 @@ void OBSBasic::closeEvent(QCloseEvent *event)
|
||||
|
||||
closing = true;
|
||||
|
||||
/* While closing, a resize event to OBSQTDisplay could be triggered.
|
||||
* The graphics thread on macOS dispatches a lambda function to be
|
||||
* executed asynchronously in the main thread. However, the display is
|
||||
* sometimes deleted before the lambda function is actually executed.
|
||||
* To avoid such a case, destroy displays earlier than others such as
|
||||
* deleting browser docks. */
|
||||
ui->preview->DestroyDisplay();
|
||||
if (program)
|
||||
program->DestroyDisplay();
|
||||
|
||||
if (outputHandler->VirtualCamActive())
|
||||
outputHandler->StopVirtualCam();
|
||||
|
||||
@@ -5154,10 +5164,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());
|
||||
|
||||
|
||||
Reference in new issue
Block a user