summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel/qwidgetwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/kernel/qwidgetwindow.cpp')
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp125
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) {