From 910617b4997b0f53f2b3f95c7d2fa0f4a0753a92 Mon Sep 17 00:00:00 2001 From: Matt Gajownik Date: Fri, 18 Oct 2024 17:32:59 +1100 Subject: [PATCH] Wait for CEF close event for docks The original solution works fine when not using the Qt event loop, however any method of waiting with the Qt event loop causes all CEF events to go on hold too, resulting in a hang or crash. Instead, wait for CEF to announce it's ready, then delete the widget. --- panel/browser-panel-client.cpp | 7 +++++++ panel/browser-panel-client.hpp | 2 ++ panel/browser-panel-internal.hpp | 4 ++++ panel/browser-panel.cpp | 24 ++++++++++++++++-------- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/panel/browser-panel-client.cpp b/panel/browser-panel-client.cpp index d3744b400..7e8297412 100644 --- a/panel/browser-panel-client.cpp +++ b/panel/browser-panel-client.cpp @@ -213,6 +213,13 @@ bool QCefBrowserClient::OnBeforePopup(CefRefPtr, CefRefPtr return true; } +void QCefBrowserClient::OnBeforeClose(CefRefPtr) +{ + if (widget) { + emit widget->CloseSafely(); + } +} + bool QCefBrowserClient::OnSetFocus(CefRefPtr, CefFocusHandler::FocusSource source) { /* Don't steal focus when the webpage navigates. This is especially diff --git a/panel/browser-panel-client.hpp b/panel/browser-panel-client.hpp index 2ec7320bf..43404c60b 100644 --- a/panel/browser-panel-client.hpp +++ b/panel/browser-panel-client.hpp @@ -57,6 +57,8 @@ class QCefBrowserClient : public CefClient, CefRefPtr &client, CefBrowserSettings &settings, CefRefPtr &extra_info, bool *no_javascript_access) override; + virtual void OnBeforeClose(CefRefPtr browser) override; + /* CefFocusHandler */ virtual bool OnSetFocus(CefRefPtr browser, CefFocusHandler::FocusSource source) override; diff --git a/panel/browser-panel-internal.hpp b/panel/browser-panel-internal.hpp index 1516f4f17..cd36ca151 100644 --- a/panel/browser-panel-internal.hpp +++ b/panel/browser-panel-internal.hpp @@ -51,6 +51,7 @@ class QCefWidgetInternal : public QCefWidget { virtual bool zoomPage(int direction) override; virtual void executeJavaScript(const std::string &script) override; + void CloseSafely(); void Resize(); #ifdef __linux__ @@ -61,4 +62,7 @@ class QCefWidgetInternal : public QCefWidget { public slots: void Init(); + +signals: + void readyToClose(); }; diff --git a/panel/browser-panel.cpp b/panel/browser-panel.cpp index 0d999cefa..9584a93c7 100644 --- a/panel/browser-panel.cpp +++ b/panel/browser-panel.cpp @@ -160,21 +160,24 @@ void QCefWidgetInternal::closeBrowser() { CefRefPtr browser = cefBrowser; if (!!browser) { - auto destroyBrowser = [](CefRefPtr cefBrowser) { + auto destroyBrowser = [=](CefRefPtr cefBrowser) { CefRefPtr client = cefBrowser->GetHost()->GetClient(); QCefBrowserClient *bc = reinterpret_cast(client.get()); - if (bc) { - bc->widget = nullptr; - } - cefBrowser->GetHost()->CloseBrowser(true); #if !defined(_WIN32) && !defined(__APPLE__) && CHROME_VERSION_BUILD >= 6533 - while (cefBrowser && cefBrowser->IsValid()) { - os_sleep_ms(10); - } + QEventLoop loop; + + connect(this, &QCefWidgetInternal::readyToClose, &loop, &QEventLoop::quit); + + QTimer::singleShot(1000, &loop, &QEventLoop::quit); + + loop.exec(); #endif + if (bc) { + bc->widget = nullptr; + } }; /* So you're probably wondering what's going on here. If you @@ -398,6 +401,11 @@ void QCefWidgetInternal::Resize() #endif } +void QCefWidgetInternal::CloseSafely() +{ + emit readyToClose(); +} + void QCefWidgetInternal::showEvent(QShowEvent *event) { QWidget::showEvent(event);