From 7fc567eda8a187e365f4c29c6e8f08440bf31218 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sat, 30 Jan 2016 17:21:55 +0100 Subject: Make popups work without ApplicationWindow, to some degree Using ApplicationWindow is highly recommended. First of all, with a plain Window, QQuickPopup attempts to set a high z-value, but cannot guarantee correct stacking order. Secondly, we cannot provide style- specific background dimming for modal popups, because it is styled as part of ApplicationWindow. Last but not least, QQuickPopup has to install a window-level event filter, which is far less efficient than how event handling done in QQuickOverlay. Change-Id: I08915abce7a1764177b92f7539eef77c054a405a Task-number: QTBUG-49921 Reviewed-by: J-P Nurmi --- src/templates/qquickoverlay.cpp | 59 +++++++++++------------------------------ 1 file changed, 15 insertions(+), 44 deletions(-) (limited to 'src/templates/qquickoverlay.cpp') diff --git a/src/templates/qquickoverlay.cpp b/src/templates/qquickoverlay.cpp index 589cafdf..dd9d2c5d 100644 --- a/src/templates/qquickoverlay.cpp +++ b/src/templates/qquickoverlay.cpp @@ -35,7 +35,7 @@ ****************************************************************************/ #include "qquickoverlay_p.h" -#include "qquickpopup_p.h" +#include "qquickpopup_p_p.h" #include "qquickdrawer_p.h" #include #include @@ -52,13 +52,12 @@ public: void popupAboutToShow(); void popupAboutToHide(); - void closePopup(QQuickPopup *popup, QMouseEvent *event); void drawerPositionChange(); void resizeBackground(); QQuickItem *background; QVector drawers; - QHash popups; + QVector popups; int modalPopups; }; @@ -90,30 +89,6 @@ void QQuickOverlayPrivate::popupAboutToHide() QQmlProperty::write(background, QStringLiteral("opacity"), 0.0); } -void QQuickOverlayPrivate::closePopup(QQuickPopup *popup, QMouseEvent *event) -{ - Q_Q(QQuickOverlay); - const bool isPress = event->type() == QEvent::MouseButtonPress; - const bool onOutside = popup->closePolicy().testFlag(isPress ? QQuickPopup::OnPressOutside : QQuickPopup::OnReleaseOutside); - const bool onOutsideParent = popup->closePolicy().testFlag(isPress ? QQuickPopup::OnPressOutsideParent : QQuickPopup::OnReleaseOutsideParent); - if (onOutside || onOutsideParent) { - QQuickItem *popupItem = popup->popupItem(); - QQuickItem *parentItem = popup->parentItem(); - - if (onOutside && onOutsideParent) { - if (!popupItem->contains(q->mapToItem(popupItem, event->pos())) && - (!parentItem || !parentItem->contains(q->mapToItem(parentItem, event->pos())))) - popup->close(); - } else if (onOutside) { - if (!popupItem->contains(q->mapToItem(popupItem, event->pos()))) - popup->close(); - } else if (onOutsideParent) { - if (!parentItem || !parentItem->contains(q->mapToItem(parentItem, event->pos()))) - popup->close(); - } - } -} - void QQuickOverlayPrivate::drawerPositionChange() { Q_Q(QQuickOverlay); @@ -197,27 +172,19 @@ void QQuickOverlay::itemChange(ItemChange change, const ItemChangeData &data) return; if (change == ItemChildAddedChange) { - if (QQuickPopup *prevPopup = d->popups.value(data.item)) { - qmlInfo(popup).nospace() << "Popup is sharing item " << data.item << " with " << prevPopup - << ". This is not supported and strange things are about to happen."; - return; - } - - d->popups.insert(data.item, popup); + d->popups.append(popup); if (popup->isModal()) ++d->modalPopups; QObjectPrivate::connect(popup, &QQuickPopup::aboutToShow, d, &QQuickOverlayPrivate::popupAboutToShow); QObjectPrivate::connect(popup, &QQuickPopup::aboutToHide, d, &QQuickOverlayPrivate::popupAboutToHide); } else if (change == ItemChildRemovedChange) { - Q_ASSERT(popup == d->popups.value(data.item)); + d->popups.removeOne(popup); + if (popup->isModal()) + --d->modalPopups; QObjectPrivate::disconnect(popup, &QQuickPopup::aboutToShow, d, &QQuickOverlayPrivate::popupAboutToShow); QObjectPrivate::disconnect(popup, &QQuickPopup::aboutToHide, d, &QQuickOverlayPrivate::popupAboutToHide); - - if (popup->isModal()) - --d->modalPopups; - d->popups.remove(data.item); } } @@ -247,8 +214,10 @@ void QQuickOverlay::mousePressEvent(QMouseEvent *event) event->setAccepted(d->modalPopups > 0); emit pressed(); - foreach (QQuickPopup *popup, d->popups) - d->closePopup(popup, event); + for (int i = d->popups.count() - 1; i >= 0; --i) { + if (QQuickPopupPrivate::get(d->popups.at(i))->tryClose(this, event)) + break; + } } void QQuickOverlay::mouseMoveEvent(QMouseEvent *event) @@ -263,8 +232,10 @@ void QQuickOverlay::mouseReleaseEvent(QMouseEvent *event) event->setAccepted(d->modalPopups > 0); emit released(); - foreach (QQuickPopup *popup, d->popups) - d->closePopup(popup, event); + for (int i = d->popups.count() - 1; i >= 0; --i) { + if (QQuickPopupPrivate::get(d->popups.at(i))->tryClose(this, event)) + break; + } } void QQuickOverlay::wheelEvent(QWheelEvent *event) @@ -292,7 +263,7 @@ bool QQuickOverlay::childMouseEventFilter(QQuickItem *item, QEvent *event) if (popupItem == item) break; - QQuickPopup *popup = d->popups.value(popupItem); + QQuickPopup *popup = qobject_cast(popupItem->parent()); if (popup) { QQuickPopup::ClosePolicy policy = popup->closePolicy(); if (policy.testFlag(QQuickPopup::OnPressOutside) || policy.testFlag(QQuickPopup::OnPressOutsideParent)) -- cgit v1.2.3