From 0eef4e25eed9927dd3259c9e138f53d8d0e25323 Mon Sep 17 00:00:00 2001 From: Matt Gajownik Date: Sat, 19 Oct 2024 14:51:34 +1100 Subject: [PATCH] UI: Split out Whats New dialog, fix crash on shutdown CEF crashes on shutdown if any browser window remains open during the shutdown flow. Reproducible 100% of the time on Linux with What's New. The previous implementation of the What's New dialog correctly deleted all the Qt widgets, but the CEF internal event flow would only call the "preparing to close" function, and never the "window safely closed" function. Moving the code (practically unchanged) to a custom QDialog solves the problem entirely, and is more consistent with other uses. --- UI/cmake/ui-windows.cmake | 2 ++ UI/window-basic-main.cpp | 35 ++++-------------- UI/window-whats-new.cpp | 74 +++++++++++++++++++++++++++++++++++++++ UI/window-whats-new.hpp | 20 +++++++++++ 4 files changed, 102 insertions(+), 29 deletions(-) create mode 100644 UI/window-whats-new.cpp create mode 100644 UI/window-whats-new.hpp diff --git a/UI/cmake/ui-windows.cmake b/UI/cmake/ui-windows.cmake index 5cdca10fd..84f561edb 100644 --- a/UI/cmake/ui-windows.cmake +++ b/UI/cmake/ui-windows.cmake @@ -58,4 +58,6 @@ target_sources( window-projector.hpp window-remux.cpp window-remux.hpp + window-whats-new.cpp + window-whats-new.hpp ) diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 6d7fa7bc5..34a7bb231 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -68,6 +68,7 @@ #include "window-youtube-actions.hpp" #include "youtube-api-wrappers.hpp" #endif +#include "window-whats-new.hpp" #include "context-bar-controls.hpp" #include "obs-proxy-style.hpp" #include "display-helpers.hpp" @@ -128,6 +129,8 @@ void DestroyPanelCookieManager(); namespace { +QPointer obsWhatsNew; + template struct SignalContainer { OBSRef ref; vector> handlers; @@ -2544,37 +2547,11 @@ void OBSBasic::ShowWhatsNew(const QString &url) if (closing) return; - std::string info_url = QT_TO_UTF8(url); - - QDialog *dlg = new QDialog(this); - dlg->setAttribute(Qt::WA_DeleteOnClose, true); - dlg->setWindowTitle("What's New"); - dlg->resize(700, 600); - - Qt::WindowFlags flags = dlg->windowFlags(); - Qt::WindowFlags helpFlag = Qt::WindowContextHelpButtonHint; - dlg->setWindowFlags(flags & (~helpFlag)); - - QCefWidget *cefWidget = cef->create_widget(nullptr, info_url); - if (!cefWidget) { - return; + if (obsWhatsNew) { + obsWhatsNew->close(); } - connect(cefWidget, &QCefWidget::titleChanged, dlg, &QDialog::setWindowTitle); - - QPushButton *close = new QPushButton(QTStr("Close")); - connect(close, &QAbstractButton::clicked, dlg, &QDialog::accept); - - QHBoxLayout *bottomLayout = new QHBoxLayout(); - bottomLayout->addStretch(); - bottomLayout->addWidget(close); - bottomLayout->addStretch(); - - QVBoxLayout *topLayout = new QVBoxLayout(dlg); - topLayout->addWidget(cefWidget); - topLayout->addLayout(bottomLayout); - - dlg->show(); + obsWhatsNew = new OBSWhatsNew(this, QT_TO_UTF8(url)); #else UNUSED_PARAMETER(url); #endif diff --git a/UI/window-whats-new.cpp b/UI/window-whats-new.cpp new file mode 100644 index 000000000..a39fc0b51 --- /dev/null +++ b/UI/window-whats-new.cpp @@ -0,0 +1,74 @@ +#include "moc_window-whats-new.cpp" + +#include +#include +#include + +#include "window-basic-main.hpp" + +#ifdef BROWSER_AVAILABLE +#include +extern QCef *cef; +#endif + +/* ------------------------------------------------------------------------- */ + +OBSWhatsNew::OBSWhatsNew(QWidget *parent, const std::string &url) : QDialog(parent) +{ +#ifdef BROWSER_AVAILABLE + if (!cef) { + return; + } + + setWindowTitle("What's New"); + setAttribute(Qt::WA_DeleteOnClose, true); + resize(700, 600); + + Qt::WindowFlags flags = windowFlags(); + Qt::WindowFlags helpFlag = Qt::WindowContextHelpButtonHint; + setWindowFlags(flags & (~helpFlag)); + + OBSBasic::InitBrowserPanelSafeBlock(); + + cefWidget = cef->create_widget(nullptr, url); + if (!cefWidget) { + return; + } + + connect(cefWidget, &QCefWidget::titleChanged, this, &OBSWhatsNew::setWindowTitle); + + QPushButton *close = new QPushButton(QTStr("Close")); + connect(close, &QAbstractButton::clicked, this, &QDialog::accept); + + QHBoxLayout *bottomLayout = new QHBoxLayout(); + bottomLayout->addStretch(); + bottomLayout->addWidget(close); + bottomLayout->addStretch(); + + QVBoxLayout *topLayout = new QVBoxLayout(this); + topLayout->addWidget(cefWidget); + topLayout->addLayout(bottomLayout); + + show(); +#else + UNUSED_PARAMETER(url); +#endif +} + +OBSWhatsNew::~OBSWhatsNew() {} + +void OBSWhatsNew::reject() +{ +#ifdef BROWSER_AVAILABLE + delete cefWidget; +#endif + QDialog::reject(); +} + +void OBSWhatsNew::accept() +{ +#ifdef BROWSER_AVAILABLE + delete cefWidget; +#endif + QDialog::accept(); +} diff --git a/UI/window-whats-new.hpp b/UI/window-whats-new.hpp new file mode 100644 index 000000000..1c39a850c --- /dev/null +++ b/UI/window-whats-new.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + +class QCefWidget; + +class OBSWhatsNew : public QDialog { + Q_OBJECT + + QCefWidget *cefWidget = nullptr; + +public: + OBSWhatsNew(QWidget *parent, const std::string &url); + ~OBSWhatsNew(); + + virtual void reject() override; + virtual void accept() override; +};