diff options
Diffstat (limited to 'src/quicktemplates/qquickoverlay.cpp')
-rw-r--r-- | src/quicktemplates/qquickoverlay.cpp | 70 |
1 files changed, 38 insertions, 32 deletions
diff --git a/src/quicktemplates/qquickoverlay.cpp b/src/quicktemplates/qquickoverlay.cpp index bbbde24602..36fa669d22 100644 --- a/src/quicktemplates/qquickoverlay.cpp +++ b/src/quicktemplates/qquickoverlay.cpp @@ -9,6 +9,7 @@ #include "qquickdrawer_p.h" #include "qquickdrawer_p_p.h" #include "qquickapplicationwindow_p.h" +#include <QtGui/qpainterpath.h> #include <QtQml/qqmlinfo.h> #include <QtQml/qqmlproperty.h> #include <QtQml/qqmlcomponent.h> @@ -66,6 +67,11 @@ void QQuickOverlayPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChang updateGeometry(); } +void QQuickOverlayPrivate::itemRotationChanged(QQuickItem *) +{ + updateGeometry(); +} + bool QQuickOverlayPrivate::startDrag(QEvent *event, const QPointF &pos) { Q_Q(QQuickOverlay); @@ -256,38 +262,15 @@ void QQuickOverlayPrivate::setMouseGrabberPopup(QQuickPopup *popup) void QQuickOverlayPrivate::updateGeometry() { Q_Q(QQuickOverlay); - if (!window) + if (!window || !window->contentItem()) return; - QPointF pos; - QSizeF size = window->size(); - qreal rotation = 0; - - switch (window->contentOrientation()) { - case Qt::PrimaryOrientation: - case Qt::PortraitOrientation: - size = window->size(); - break; - case Qt::LandscapeOrientation: - rotation = 90; - pos = QPointF((size.width() - size.height()) / 2, -(size.width() - size.height()) / 2); - size.transpose(); - break; - case Qt::InvertedPortraitOrientation: - rotation = 180; - break; - case Qt::InvertedLandscapeOrientation: - rotation = 270; - pos = QPointF((size.width() - size.height()) / 2, -(size.width() - size.height()) / 2); - size.transpose(); - break; - default: - break; - } + const QSizeF size = window->contentItem()->size(); + const QPointF pos(-(size.width() - window->size().width()) / 2, + -(size.height() - window->size().height()) / 2); q->setSize(size); q->setPosition(pos); - q->setRotation(rotation); } QQuickOverlay::QQuickOverlay(QQuickItem *parent) @@ -307,7 +290,8 @@ QQuickOverlay::QQuickOverlay(QQuickItem *parent) QQuickItemPrivate::get(parent)->addItemChangeListener(d, QQuickItemPrivate::Geometry); if (QQuickWindow *window = parent->window()) { window->installEventFilter(this); - QObjectPrivate::connect(window, &QWindow::contentOrientationChanged, d, &QQuickOverlayPrivate::updateGeometry); + if (QQuickItem *contentItem = window->contentItem()) + QQuickItemPrivate::get(contentItem)->addItemChangeListener(d, QQuickItemPrivate::Rotation); } } } @@ -315,8 +299,13 @@ QQuickOverlay::QQuickOverlay(QQuickItem *parent) QQuickOverlay::~QQuickOverlay() { Q_D(QQuickOverlay); - if (QQuickItem *parent = parentItem()) + if (QQuickItem *parent = parentItem()) { QQuickItemPrivate::get(parent)->removeItemChangeListener(d, QQuickItemPrivate::Geometry); + if (QQuickWindow *window = parent->window()) { + if (QQuickItem *contentItem = window->contentItem()) + QQuickItemPrivate::get(contentItem)->removeItemChangeListener(d, QQuickItemPrivate::Rotation); + } + } } QQmlComponent *QQuickOverlay::modal() const @@ -392,7 +381,7 @@ void QQuickOverlay::geometryChange(const QRectF &newGeometry, const QRectF &oldG Q_D(QQuickOverlay); QQuickItem::geometryChange(newGeometry, oldGeometry); for (QQuickPopup *popup : std::as_const(d->allPopups)) - QQuickPopupPrivate::get(popup)->resizeOverlay(); + QQuickPopupPrivate::get(popup)->resizeDimmer(); } void QQuickOverlay::mousePressEvent(QMouseEvent *event) @@ -522,6 +511,12 @@ bool QQuickOverlay::eventFilter(QObject *object, QEvent *event) // Make sure to accept the touch event in order to receive the consequent // touch events, to be able to close non-modal popups on release outside. event->accept(); + // Since we eat the event, QQuickWindow::event never sees it to clean up the + // grabber states. So we have to do so explicitly. + if (QQuickWindow *window = parentItem() ? parentItem()->window() : nullptr) { + QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); + d->clearGrabbers(static_cast<QPointerEvent *>(event)); + } return true; #endif @@ -567,7 +562,18 @@ bool QQuickOverlay::eventFilter(QObject *object, QEvent *event) if (targetItems.isEmpty()) break; + QQuickItem * const dimmerItem = property("_q_dimmerItem").value<QQuickItem *>(); QQuickItem * const topItem = targetItems.first(); + + QQuickItem *item = topItem; + while ((item = item->parentItem())) { + if (qobject_cast<QQuickPopupItem *>(item)) + break; + } + + if (!item && dimmerItem != topItem && isAncestorOf(topItem)) + break; + const auto popups = d->stackingOrderPopups(); // Eat the event if receiver topItem is not a child of a popup before // the first modal popup. @@ -575,8 +581,8 @@ bool QQuickOverlay::eventFilter(QObject *object, QEvent *event) const QQuickItem *popupItem = popup->popupItem(); if (!popupItem) continue; - // if we reach a popup that contains the item, deliver the event - if (popupItem->isAncestorOf(topItem)) + // if current popup item matches with any popup in stack, deliver the event + if (popupItem == item) break; // if the popup doesn't contain the item but is modal, eat the event if (popup->overlayEvent(topItem, we)) |