diff options
Diffstat (limited to 'src/widgets/kernel/qwidgetwindow.cpp')
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 125 |
1 files changed, 82 insertions, 43 deletions
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 3c7dddc42f..f51baba88b 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -7,7 +7,7 @@ #include "private/qwidget_p.h" #include "private/qapplication_p.h" -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) #include <QtGui/qaccessible.h> #endif #include <private/qwidgetrepaintmanager_p.h> @@ -39,21 +39,25 @@ public: void setVisible(bool visible) override { Q_Q(QWidgetWindow); + qCDebug(lcWidgetShowHide) << "Setting visibility of" << q->widget() + << "to" << visible << "via QWidgetWindowPrivate"; + if (QWidget *widget = q->widget()) { - // Check if the widget was already hidden, as this indicates it was done - // explicitly and not because the parent window in this case made it hidden. - // In which case do not automatically show the widget when the parent - // window is shown. - const bool wasExplicitShowHide = widget->testAttribute(Qt::WA_WState_ExplicitShowHide); - const bool wasHidden = widget->testAttribute(Qt::WA_WState_Hidden); - QWidgetPrivate::get(widget)->setVisible(visible); - if (wasExplicitShowHide) { - widget->setAttribute(Qt::WA_WState_ExplicitShowHide, wasExplicitShowHide); - widget->setAttribute(Qt::WA_WState_Hidden, wasHidden); - } - } else { - QWindowPrivate::setVisible(visible); + // If the widget's visible state is already matching the new QWindow + // visible state we assume the widget has already synced up. + if (visible != widget->isVisible()) + QWidgetPrivate::get(widget)->setVisible(visible); } + + // If we end up calling QWidgetPrivate::setVisible() above, we will + // in most cases recurse back into setNativeWindowVisibility() to + // update the QWindow state. But during QWidget::destroy() this is + // not the case, as Qt::WA_WState_Created has been unset by the time + // we check if we should call hide_helper(). We handle this case, as + // well as the cases where we don't call QWidgetPrivate::setVisible(), + // by syncing up the QWindow state here if needed. + if (q->isVisible() != visible) + QWindowPrivate::setVisible(visible); } QWindow *eventReceiver() override { @@ -129,14 +133,29 @@ QWidgetWindow::QWidgetWindow(QWidget *widget) } connect(widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName); - connect(this, SIGNAL(screenChanged(QScreen*)), this, SLOT(handleScreenChange())); + connect(this, &QWidgetWindow::screenChanged, this, &QWidgetWindow::handleScreenChange); } QWidgetWindow::~QWidgetWindow() { + if (!m_widget) + return; + + QTLWExtra *topData = QWidgetPrivate::get(m_widget)->topData(); + Q_ASSERT(topData); + + // The QPlaformBackingStore may hold a reference to the window, + // so the backingstore needs to be deleted first. + topData->repaintManager.reset(nullptr); + delete topData->backingStore; + topData->backingStore = nullptr; + topData->widgetTextures.clear(); + + // Too late to do anything beyond this point + topData->window = nullptr; } -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) QAccessibleInterface *QWidgetWindow::accessibleRoot() const { if (m_widget) @@ -170,6 +189,9 @@ QObject *QWidgetWindow::focusObject() const void QWidgetWindow::setNativeWindowVisibility(bool visible) { Q_D(QWidgetWindow); + qCDebug(lcWidgetShowHide) << "Setting visibility of" << this + << "to" << visible << "via QWidgetWindow::setNativeWindowVisibility"; + // Call base class setVisible() implementation to run the QWindow // visibility logic. Don't call QWidgetWindowPrivate::setVisible() // since that will recurse back into QWidget code. @@ -211,7 +233,7 @@ bool QWidgetWindow::event(QEvent *event) handleFocusInEvent(static_cast<QFocusEvent *>(event)); Q_FALLTHROUGH(); case QEvent::FocusOut: { -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) QAccessible::State state; state.active = true; QAccessibleStateChangeEvent ev(m_widget, state); @@ -329,6 +351,10 @@ bool QWidgetWindow::event(QEvent *event) m_widget->repaint(); return true; + case QEvent::DevicePixelRatioChange: + handleDevicePixelRatioChange(); + break; + default: break; } @@ -451,11 +477,11 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) QEvent::MouseButtonRelease : QEvent::MouseButtonPress; if (QApplicationPrivate::inPopupMode()) { QPointer<QWidget> activePopupWidget = QApplication::activePopupWidget(); - QPoint mapped = event->position().toPoint(); + QPointF mapped = event->position(); if (activePopupWidget != m_widget) - mapped = activePopupWidget->mapFromGlobal(event->globalPosition().toPoint()); + mapped = activePopupWidget->mapFromGlobal(event->globalPosition()); bool releaseAfter = false; - QWidget *popupChild = activePopupWidget->childAt(mapped); + QWidget *popupChild = activePopupWidget->childAt(mapped.toPoint()); if (activePopupWidget != qt_popup_down) { qt_button_down = nullptr; @@ -482,15 +508,15 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) // deliver event qt_replay_popup_mouse_event = false; QPointer<QWidget> receiver = activePopupWidget; - QPoint widgetPos = mapped; + QPointF widgetPos = mapped; if (qt_button_down) receiver = qt_button_down; else if (popupChild) receiver = popupChild; if (receiver != activePopupWidget) - widgetPos = receiver->mapFromGlobal(event->globalPosition().toPoint()); + widgetPos = receiver->mapFromGlobal(event->globalPosition()); - const bool reallyUnderMouse = activePopupWidget->rect().contains(mapped); + const bool reallyUnderMouse = activePopupWidget->rect().contains(mapped.toPoint()); const bool underMouse = activePopupWidget->underMouse(); if (underMouse != reallyUnderMouse) { if (reallyUnderMouse) { @@ -629,6 +655,8 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) && m_widget->rect().contains(event->position().toPoint())) { QContextMenuEvent e(QContextMenuEvent::Mouse, mapped, event->globalPosition().toPoint(), event->modifiers()); QGuiApplication::forwardEvent(receiver, &e, event); + if (e.isAccepted()) + event->accept(); } #endif } @@ -693,22 +721,32 @@ void QWidgetWindow::updateMargins() m_widget->data->fstrut_dirty = false; } -static void sendScreenChangeRecursively(QWidget *widget) +static void sendChangeRecursively(QWidget *widget, QEvent::Type type) { - QEvent e(QEvent::ScreenChangeInternal); + QEvent e(type); QCoreApplication::sendEvent(widget, &e); QWidgetPrivate *d = QWidgetPrivate::get(widget); for (int i = 0; i < d->children.size(); ++i) { QWidget *w = qobject_cast<QWidget *>(d->children.at(i)); if (w) - sendScreenChangeRecursively(w); + sendChangeRecursively(w, type); } } void QWidgetWindow::handleScreenChange() { // Send an event recursively to the widget and its children. - sendScreenChangeRecursively(m_widget); + sendChangeRecursively(m_widget, QEvent::ScreenChangeInternal); + + // Invalidate the backing store buffer and repaint immediately. + if (screen()) + repaintWindow(); +} + +void QWidgetWindow::handleDevicePixelRatioChange() +{ + // Send an event recursively to the widget and its children. + sendChangeRecursively(m_widget, QEvent::DevicePixelRatioChange); // Invalidate the backing store buffer and repaint immediately. if (screen()) @@ -897,8 +935,9 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event) event->ignore(); if (m_dragTarget) { // Send DragLeave to previous QDragLeaveEvent leaveEvent; - QGuiApplication::forwardEvent(m_dragTarget, &leaveEvent, event); + QWidget *dragTarget = m_dragTarget; m_dragTarget = nullptr; + QGuiApplication::forwardEvent(dragTarget, &leaveEvent, event); } } else { const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->position().toPoint())); @@ -912,8 +951,9 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event) } else { if (m_dragTarget) { // Send DragLeave to previous QDragLeaveEvent leaveEvent; - QGuiApplication::forwardEvent(m_dragTarget, &leaveEvent, event); + QWidget *dragTarget = m_dragTarget; m_dragTarget = nullptr; + QGuiApplication::forwardEvent(dragTarget, &leaveEvent, event); } // widget might have been deleted when handling the leaveEvent if (widget) { @@ -935,9 +975,11 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event) void QWidgetWindow::handleDragLeaveEvent(QDragLeaveEvent *event) { - if (m_dragTarget) - QGuiApplication::forwardEvent(m_dragTarget, event); - m_dragTarget = nullptr; + if (m_dragTarget) { + QWidget *dragTarget = m_dragTarget; + m_dragTarget = nullptr; + QGuiApplication::forwardEvent(dragTarget, event); + } } void QWidgetWindow::handleDropEvent(QDropEvent *event) @@ -949,10 +991,11 @@ void QWidgetWindow::handleDropEvent(QDropEvent *event) } const QPoint mapped = m_dragTarget->mapFromGlobal(m_widget->mapToGlobal(event->position().toPoint())); QDropEvent translated(mapped, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers()); - QGuiApplication::forwardEvent(m_dragTarget, &translated, event); + QWidget *dragTarget = m_dragTarget; + m_dragTarget = nullptr; + QGuiApplication::forwardEvent(dragTarget, &translated, event); event->setAccepted(translated.isAccepted()); event->setDropAction(translated.dropAction()); - m_dragTarget = nullptr; } #endif // QT_CONFIG(draganddrop) @@ -997,11 +1040,8 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event) m_widget->setAttribute(Qt::WA_Mapped); for (QWidget *p = m_widget->parentWidget(); p && !p->testAttribute(Qt::WA_Mapped); p = p->parentWidget()) p->setAttribute(Qt::WA_Mapped); -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - if (!event->region().isNull()) - wPriv->syncBackingStore(event->region()); -QT_WARNING_POP + if (!event->m_region.isNull()) + wPriv->syncBackingStore(event->m_region); } else { m_widget->setAttribute(Qt::WA_Mapped, false); } @@ -1049,11 +1089,10 @@ void QWidgetWindow::handleTabletEvent(QTabletEvent *event) if (!widget) { widget = m_widget->childAt(event->position().toPoint()); - if (event->type() == QEvent::TabletPress) { - if (!widget) - widget = m_widget; + if (!widget) + widget = m_widget; + if (event->type() == QEvent::TabletPress) qt_tablet_target = widget; - } } if (widget) { |