diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 7cb23bb588c8c574fe381f4247523f1d297286f0..3641398f6aa66c562a649f2eecfc26a4981d53c9 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -1072,7 +1072,11 @@ bool RenderWidgetHostViewQt::forwardEvent(QEvent *event) case QEvent::MouseMove: // Skip second MouseMove event when a window is being adopted, so that Chromium // can properly handle further move events. - if (m_adapterClient->isBeingAdopted()) + // Also make sure the adapter client exists to prevent a null pointer dereference, + // because it's possible for a QWebEnginePagePrivate (adapter) instance to be destroyed, + // and then the OS (observed on Windows) might still send mouse move events to a still + // existing popup RWHVQDW instance. + if (m_adapterClient && m_adapterClient->isBeingAdopted()) return false; handleMouseEvent(static_cast<QMouseEvent*>(event)); break; @@ -1171,6 +1175,15 @@ QVariant RenderWidgetHostViewQt::inputMethodQuery(Qt::InputMethodQuery query) } } +void RenderWidgetHostViewQt::closePopup() +{ + // We notify the popup to be closed by telling it that it lost focus. WebKit does the rest + // (hiding the widget and automatic memory cleanup via + // RenderWidget::CloseWidgetSoon() -> RenderWidgetHostImpl::ShutdownAndDestroyWidget(true). + m_host->SetActive(false); + m_host->Blur(); +} + void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) { Q_UNUSED(touch); const bool eventConsumed = ack_result == content::INPUT_EVENT_ACK_STATE_CONSUMED; diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 0c62b727980507c071abd4a726566834ea2b0d98..cc62fa110fb722db432f923d6af4b014388dd571 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -174,6 +174,7 @@ public: void windowChanged() override; bool forwardEvent(QEvent *) override; QVariant inputMethodQuery(Qt::InputMethodQuery query) override; + void closePopup() override; // Overridden from content::TextInputManager::Observer void OnUpdateTextInputStateCalled(content::TextInputManager *text_input_manager, RenderWidgetHostViewBase *updated_view, bool did_update_state) override; diff --git a/src/core/render_widget_host_view_qt_delegate.h b/src/core/render_widget_host_view_qt_delegate.h index bcd0f49f7b6ee55818eff9b74095a665dca61002..3ac3ccc1e4c1afc813e6dfa3f92fd44f8c6adcc9 100644 --- a/src/core/render_widget_host_view_qt_delegate.h +++ b/src/core/render_widget_host_view_qt_delegate.h @@ -78,6 +78,7 @@ public: virtual void windowChanged() = 0; virtual bool forwardEvent(QEvent *) = 0; virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) = 0; + virtual void closePopup() = 0; }; class QWEBENGINE_EXPORT RenderWidgetHostViewQtDelegate { diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp index 98482ae785e836e064df26c6cfe1e4e288fac7bb..c32e89f0cff5aa40074cc74692dd0d103048d89d 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -218,20 +218,24 @@ void RenderWidgetHostViewQtDelegateWidget::initAsPopup(const QRect& screenRect) // to be destroyed. setAttribute(Qt::WA_ShowWithoutActivating); setFocusPolicy(Qt::NoFocus); - -#ifdef Q_OS_MACOS - // macOS doesn't like Qt::ToolTip when QWebEngineView is inside a modal dialog, specifically by - // not forwarding click events to the popup. So we use Qt::Tool which behaves the same way, but - // works on macOS too. - setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); -#else - setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); -#endif + setWindowFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); setGeometry(screenRect); show(); } +void RenderWidgetHostViewQtDelegateWidget::closeEvent(QCloseEvent *event) +{ + Q_UNUSED(event); + + // If a close event was received from the window manager (e.g. when moving the parent window, + // clicking outside the popup area) + // make sure to notify the Chromium WebUI popup and its underlying + // RenderWidgetHostViewQtDelegate instance to be closed. + if (m_isPopup) + m_client->closePopup(); +} + QRectF RenderWidgetHostViewQtDelegateWidget::screenRect() const { return QRectF(x(), y(), width(), height()); diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h index 79958132c8bb546d4eed9b6275346fef816e9949..ab24b1e4123044355351a9fa6e17476e68100153 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h @@ -83,6 +83,7 @@ protected: void resizeEvent(QResizeEvent *resizeEvent) override; void showEvent(QShowEvent *) override; void hideEvent(QHideEvent *) override; + void closeEvent(QCloseEvent *event) override; QVariant inputMethodQuery(Qt::InputMethodQuery query) const override;