Acknowledge QWidgetWindow::widget() may be null
We guard QWidgetWindow's widget with a QPointer to avoid sending it events during destruction (which may result in undefined behavior, since this originates from ~QObject and we expect the object to behave as a QWidget). Therefore, we need to harden all access to that widget since it can now be null, specially during destruction. As an example, QGestureManager may crash when we delete a top-level widget. The crash stack trace is: 1 QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>>::data() const 2 QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>>::pointer qGetPtrHelper<QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>>>(QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>> const&) 3 QWidget::d_func() 4 QGestureManager::filterEvent(QWidget *, QEvent *) <-- the widget ptr is null 5 QGestureManager::filterEvent(QObject *, QEvent *) 6 QApplication::notify(QObject *, QEvent *) 7 QCoreApplication::notifyInternal2(QObject *, QEvent *) 8 QCoreApplication::sendEvent(QObject *, QEvent *) 9 QWindow::destroy() 10 QWidgetPrivate::deleteTLSysExtra() 11 QWidgetPrivate::deleteExtra() 12 QWidgetPrivate::~QWidgetPrivate() 13 QWidgetPrivate::~QWidgetPrivate() 14 QWidgetPrivate::~QWidgetPrivate() 15 QScopedPointerDeleter<QObjectData>::cleanup(QObjectData *) 16 QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>>::~QScopedPointer() 17 QScopedPointer<QObjectData, QScopedPointerDeleter<QObjectData>>::~QScopedPointer() 18 QObject::~QObject() 19 QWidget::~QWidget() Task-number: QTBUG-53103 Change-Id: I1bb32648270c4f7791f668b8f0b639ddb4235703 Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com> Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
This commit is contained in:
parent
6a84a51611
commit
ce37467acf
@ -2249,10 +2249,10 @@ void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
|
||||
QApplication::setActiveWindow(tlw);
|
||||
// QTBUG-37126, Active X controls may set the focus on native child widgets.
|
||||
if (wnd && tlw && wnd != tlw->windowHandle()) {
|
||||
if (QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(wnd)) {
|
||||
if (widgetWindow->widget()->inherits("QAxHostWidget"))
|
||||
widgetWindow->widget()->setFocus(Qt::ActiveWindowFocusReason);
|
||||
}
|
||||
if (QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(wnd))
|
||||
if (QWidget *widget = widgetWindow->widget())
|
||||
if (widget->inherits("QAxHostWidget"))
|
||||
widget->setFocus(Qt::ActiveWindowFocusReason);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -545,7 +545,7 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
|
||||
// filter method.
|
||||
QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(receiver);
|
||||
|
||||
if (widgetWindow)
|
||||
if (widgetWindow && widgetWindow->widget())
|
||||
return filterEvent(widgetWindow->widget(), event);
|
||||
|
||||
QGesture *state = qobject_cast<QGesture *>(receiver);
|
||||
|
@ -87,7 +87,7 @@ QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const
|
||||
{
|
||||
Q_Q(const QWidgetWindow);
|
||||
const QWidget *widget = q->widget();
|
||||
if (!widget->isWindow() || !widget->hasHeightForWidth())
|
||||
if (!widget || !widget->isWindow() || !widget->hasHeightForWidth())
|
||||
return QRect();
|
||||
const QSize oldSize = rect.size().toSize();
|
||||
const QSize newSize = QLayout::closestAcceptableSize(widget, oldSize);
|
||||
@ -142,16 +142,18 @@ QAccessibleInterface *QWidgetWindow::accessibleRoot() const
|
||||
|
||||
QObject *QWidgetWindow::focusObject() const
|
||||
{
|
||||
QWidget *widget = m_widget->focusWidget();
|
||||
QWidget *windowWidget = m_widget;
|
||||
if (!windowWidget)
|
||||
return Q_NULLPTR;
|
||||
|
||||
QWidget *widget = windowWidget->focusWidget();
|
||||
|
||||
if (!widget)
|
||||
widget = m_widget;
|
||||
widget = windowWidget;
|
||||
|
||||
if (widget) {
|
||||
QObject *focusObj = QWidgetPrivate::get(widget)->focusObject();
|
||||
if (focusObj)
|
||||
return focusObj;
|
||||
}
|
||||
QObject *focusObj = QWidgetPrivate::get(widget)->focusObject();
|
||||
if (focusObj)
|
||||
return focusObj;
|
||||
|
||||
return widget;
|
||||
}
|
||||
@ -204,7 +206,7 @@ bool QWidgetWindow::event(QEvent *event)
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
QAccessible::State state;
|
||||
state.active = true;
|
||||
QAccessibleStateChangeEvent ev(widget(), state);
|
||||
QAccessibleStateChangeEvent ev(m_widget, state);
|
||||
QAccessible::updateAccessibility(&ev);
|
||||
#endif
|
||||
return false; }
|
||||
|
Loading…
Reference in New Issue
Block a user