aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates/qquickoverlay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktemplates/qquickoverlay.cpp')
-rw-r--r--src/quicktemplates/qquickoverlay.cpp750
1 files changed, 750 insertions, 0 deletions
diff --git a/src/quicktemplates/qquickoverlay.cpp b/src/quicktemplates/qquickoverlay.cpp
new file mode 100644
index 0000000000..36fa669d22
--- /dev/null
+++ b/src/quicktemplates/qquickoverlay.cpp
@@ -0,0 +1,750 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qquickcontrol_p_p.h"
+#include "qquickoverlay_p.h"
+#include "qquickoverlay_p_p.h"
+#include "qquickpopupitem_p_p.h"
+#include "qquickpopup_p_p.h"
+#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>
+#include <algorithm>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Overlay
+ \inherits Item
+//! \instantiates QQuickOverlay
+ \inqmlmodule QtQuick.Controls
+ \since 5.10
+ \brief A window overlay for popups.
+
+ Overlay provides a layer for popups, ensuring that popups are displayed above
+ other content and that the background is dimmed when a \l {Popup::}{modal} or
+ \l {Popup::dim}{dimmed} popup is visible.
+
+ The overlay is an ordinary Item that covers the entire window. It can be used
+ as a visual parent to position a popup in scene coordinates.
+
+ \include qquickoverlay-popup-parent.qdocinc
+
+ \sa ApplicationWindow
+*/
+
+QList<QQuickPopup *> QQuickOverlayPrivate::stackingOrderPopups() const
+{
+ const QList<QQuickItem *> children = paintOrderChildItems();
+
+ QList<QQuickPopup *> popups;
+ popups.reserve(children.size());
+
+ for (auto it = children.crbegin(), end = children.crend(); it != end; ++it) {
+ QQuickPopup *popup = qobject_cast<QQuickPopup *>((*it)->parent());
+ if (popup)
+ popups += popup;
+ }
+
+ return popups;
+}
+
+QList<QQuickPopup *> QQuickOverlayPrivate::stackingOrderDrawers() const
+{
+ QList<QQuickPopup *> sorted(allDrawers);
+ std::sort(sorted.begin(), sorted.end(), [](const QQuickPopup *one, const QQuickPopup *another) {
+ return one->z() > another->z();
+ });
+ return sorted;
+}
+
+void QQuickOverlayPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
+{
+ updateGeometry();
+}
+
+void QQuickOverlayPrivate::itemRotationChanged(QQuickItem *)
+{
+ updateGeometry();
+}
+
+bool QQuickOverlayPrivate::startDrag(QEvent *event, const QPointF &pos)
+{
+ Q_Q(QQuickOverlay);
+ if (allDrawers.isEmpty())
+ return false;
+
+ // don't start dragging a drawer if a modal popup overlay is blocking (QTBUG-60602)
+ QQuickItem *item = q->childAt(pos.x(), pos.y());
+ if (item) {
+ const auto popups = stackingOrderPopups();
+ for (QQuickPopup *popup : popups) {
+ QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
+ if (p->dimmer == item && popup->isVisible() && popup->isModal())
+ return false;
+ }
+ }
+
+ const QList<QQuickPopup *> drawers = stackingOrderDrawers();
+ for (QQuickPopup *popup : drawers) {
+ QQuickDrawer *drawer = qobject_cast<QQuickDrawer *>(popup);
+ Q_ASSERT(drawer);
+ QQuickDrawerPrivate *p = QQuickDrawerPrivate::get(drawer);
+ if (p->startDrag(event)) {
+ setMouseGrabberPopup(drawer);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool QQuickOverlayPrivate::handlePress(QQuickItem *source, QEvent *event, QQuickPopup *target)
+{
+ if (target) {
+ if (target->overlayEvent(source, event)) {
+ setMouseGrabberPopup(target);
+ return true;
+ }
+ return false;
+ }
+
+ switch (event->type()) {
+ default: {
+ if (mouseGrabberPopup)
+ break;
+#if QT_CONFIG(quicktemplates2_multitouch)
+ Q_FALLTHROUGH();
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+#endif
+ // allow non-modal popups to close themselves,
+ // and non-dimming modal popups to block the event
+ const auto popups = stackingOrderPopups();
+ for (QQuickPopup *popup : popups) {
+ if (popup->overlayEvent(source, event)) {
+ setMouseGrabberPopup(popup);
+ return true;
+ }
+ }
+ break;
+ }
+ }
+
+ event->ignore();
+ return false;
+}
+
+bool QQuickOverlayPrivate::handleMove(QQuickItem *source, QEvent *event, QQuickPopup *target)
+{
+ if (target)
+ return target->overlayEvent(source, event);
+ return false;
+}
+
+bool QQuickOverlayPrivate::handleRelease(QQuickItem *source, QEvent *event, QQuickPopup *target)
+{
+ if (target) {
+ setMouseGrabberPopup(nullptr);
+ if (target->overlayEvent(source, event)) {
+ setMouseGrabberPopup(nullptr);
+ return true;
+ }
+ } else {
+ const auto popups = stackingOrderPopups();
+ for (QQuickPopup *popup : popups) {
+ if (popup->overlayEvent(source, event))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QQuickOverlayPrivate::handleMouseEvent(QQuickItem *source, QMouseEvent *event, QQuickPopup *target)
+{
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ if (!target && startDrag(event, event->scenePosition()))
+ return true;
+ return handlePress(source, event, target);
+ case QEvent::MouseMove:
+ return handleMove(source, event, target ? target : mouseGrabberPopup.data());
+ case QEvent::MouseButtonRelease:
+ return handleRelease(source, event, target ? target : mouseGrabberPopup.data());
+ default:
+ break;
+ }
+ return false;
+}
+
+bool QQuickOverlayPrivate::handleHoverEvent(QQuickItem *source, QHoverEvent *event, QQuickPopup *target)
+{
+ switch (event->type()) {
+ case QEvent::HoverEnter:
+ case QEvent::HoverMove:
+ case QEvent::HoverLeave:
+ if (target)
+ return target->overlayEvent(source, event);
+ return false;
+ default:
+ Q_UNREACHABLE(); // function must only be called on hover events
+ break;
+ }
+ return false;
+}
+
+#if QT_CONFIG(quicktemplates2_multitouch)
+bool QQuickOverlayPrivate::handleTouchEvent(QQuickItem *source, QTouchEvent *event, QQuickPopup *target)
+{
+ bool handled = false;
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ for (const QTouchEvent::TouchPoint &point : event->points()) {
+ switch (point.state()) {
+ case QEventPoint::Pressed:
+ if (!target && startDrag(event, point.scenePosition()))
+ handled = true;
+ else
+ handled |= handlePress(source, event, target);
+ break;
+ case QEventPoint::Updated:
+ handled |= handleMove(source, event, target ? target : mouseGrabberPopup.data());
+ break;
+ case QEventPoint::Released:
+ handled |= handleRelease(source, event, target ? target : mouseGrabberPopup.data());
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return handled;
+}
+#endif
+
+void QQuickOverlayPrivate::addPopup(QQuickPopup *popup)
+{
+ Q_Q(QQuickOverlay);
+ allPopups += popup;
+ if (QQuickDrawer *drawer = qobject_cast<QQuickDrawer *>(popup)) {
+ allDrawers += drawer;
+ q->setVisible(!allDrawers.isEmpty() || !q->childItems().isEmpty());
+ }
+}
+
+void QQuickOverlayPrivate::removePopup(QQuickPopup *popup)
+{
+ Q_Q(QQuickOverlay);
+ allPopups.removeOne(popup);
+ if (allDrawers.removeOne(popup))
+ q->setVisible(!allDrawers.isEmpty() || !q->childItems().isEmpty());
+}
+
+void QQuickOverlayPrivate::setMouseGrabberPopup(QQuickPopup *popup)
+{
+ if (popup && !popup->isVisible())
+ popup = nullptr;
+ mouseGrabberPopup = popup;
+}
+
+void QQuickOverlayPrivate::updateGeometry()
+{
+ Q_Q(QQuickOverlay);
+ if (!window || !window->contentItem())
+ return;
+
+ 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);
+}
+
+QQuickOverlay::QQuickOverlay(QQuickItem *parent)
+ : QQuickItem(*(new QQuickOverlayPrivate), parent)
+{
+ Q_D(QQuickOverlay);
+ setZ(1000001); // DefaultWindowDecoration+1
+ setAcceptedMouseButtons(Qt::AllButtons);
+#if QT_CONFIG(quicktemplates2_multitouch)
+ setAcceptTouchEvents(true);
+#endif
+ setFiltersChildMouseEvents(true);
+ setVisible(false);
+
+ if (parent) {
+ d->updateGeometry();
+ QQuickItemPrivate::get(parent)->addItemChangeListener(d, QQuickItemPrivate::Geometry);
+ if (QQuickWindow *window = parent->window()) {
+ window->installEventFilter(this);
+ if (QQuickItem *contentItem = window->contentItem())
+ QQuickItemPrivate::get(contentItem)->addItemChangeListener(d, QQuickItemPrivate::Rotation);
+ }
+ }
+}
+
+QQuickOverlay::~QQuickOverlay()
+{
+ Q_D(QQuickOverlay);
+ 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
+{
+ Q_D(const QQuickOverlay);
+ return d->modal;
+}
+
+void QQuickOverlay::setModal(QQmlComponent *modal)
+{
+ Q_D(QQuickOverlay);
+ if (d->modal == modal)
+ return;
+
+ d->modal = modal;
+ emit modalChanged();
+}
+
+QQmlComponent *QQuickOverlay::modeless() const
+{
+ Q_D(const QQuickOverlay);
+ return d->modeless;
+}
+
+void QQuickOverlay::setModeless(QQmlComponent *modeless)
+{
+ Q_D(QQuickOverlay);
+ if (d->modeless == modeless)
+ return;
+
+ d->modeless = modeless;
+ emit modelessChanged();
+}
+
+QQuickOverlay *QQuickOverlay::overlay(QQuickWindow *window)
+{
+ if (!window)
+ return nullptr;
+
+ const char *name = "_q_QQuickOverlay";
+ QQuickOverlay *overlay = window->property(name).value<QQuickOverlay *>();
+ if (!overlay) {
+ QQuickItem *content = window->contentItem();
+ // Do not re-create the overlay if the window is being destroyed
+ // and thus, its content item no longer has a window associated.
+ if (content && content->window()) {
+ overlay = new QQuickOverlay(window->contentItem());
+ window->setProperty(name, QVariant::fromValue(overlay));
+ }
+ }
+ return overlay;
+}
+
+QQuickOverlayAttached *QQuickOverlay::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickOverlayAttached(object);
+}
+
+void QQuickOverlay::itemChange(ItemChange change, const ItemChangeData &data)
+{
+ Q_D(QQuickOverlay);
+ QQuickItem::itemChange(change, data);
+
+ if (change == ItemChildAddedChange || change == ItemChildRemovedChange) {
+ setVisible(!d->allDrawers.isEmpty() || !childItems().isEmpty());
+ if (data.item->parent() == d->mouseGrabberPopup)
+ d->setMouseGrabberPopup(nullptr);
+ }
+}
+
+void QQuickOverlay::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickOverlay);
+ QQuickItem::geometryChange(newGeometry, oldGeometry);
+ for (QQuickPopup *popup : std::as_const(d->allPopups))
+ QQuickPopupPrivate::get(popup)->resizeDimmer();
+}
+
+void QQuickOverlay::mousePressEvent(QMouseEvent *event)
+{
+ Q_D(QQuickOverlay);
+ d->handleMouseEvent(this, event);
+}
+
+void QQuickOverlay::mouseMoveEvent(QMouseEvent *event)
+{
+ Q_D(QQuickOverlay);
+ d->handleMouseEvent(this, event);
+}
+
+void QQuickOverlay::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_D(QQuickOverlay);
+ d->handleMouseEvent(this, event);
+}
+
+#if QT_CONFIG(quicktemplates2_multitouch)
+void QQuickOverlay::touchEvent(QTouchEvent *event)
+{
+ Q_D(QQuickOverlay);
+ d->handleTouchEvent(this, event);
+}
+#endif
+
+#if QT_CONFIG(wheelevent)
+void QQuickOverlay::wheelEvent(QWheelEvent *event)
+{
+ Q_D(QQuickOverlay);
+ if (d->mouseGrabberPopup) {
+ d->mouseGrabberPopup->overlayEvent(this, event);
+ return;
+ } else {
+ const auto popups = d->stackingOrderPopups();
+ for (QQuickPopup *popup : popups) {
+ if (popup->overlayEvent(this, event))
+ return;
+ }
+ }
+ event->ignore();
+}
+#endif
+
+bool QQuickOverlay::childMouseEventFilter(QQuickItem *item, QEvent *event)
+{
+ Q_D(QQuickOverlay);
+ const auto popups = d->stackingOrderPopups();
+ for (QQuickPopup *popup : popups) {
+ QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
+
+ // Stop filtering overlay events when reaching a popup item or an item
+ // that is inside the popup. Let the popup content handle its events.
+ if (item == p->popupItem || p->popupItem->isAncestorOf(item))
+ break;
+
+ // Let the popup try closing itself when pressing or releasing over its
+ // background dimming OR over another popup underneath, in case the popup
+ // does not have background dimming.
+ if (item == p->dimmer || !p->popupItem->isAncestorOf(item)) {
+ bool handled = false;
+ switch (event->type()) {
+#if QT_CONFIG(quicktemplates2_multitouch)
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ handled = d->handleTouchEvent(item, static_cast<QTouchEvent *>(event), popup);
+ break;
+#endif
+ case QEvent::HoverEnter:
+ case QEvent::HoverMove:
+ case QEvent::HoverLeave:
+ handled = d->handleHoverEvent(item, static_cast<QHoverEvent *>(event), popup);
+ break;
+
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ handled = d->handleMouseEvent(item, static_cast<QMouseEvent *>(event), popup);
+ break;
+
+ default:
+ break;
+ }
+ if (handled)
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QQuickOverlay::eventFilter(QObject *object, QEvent *event)
+{
+ Q_D(QQuickOverlay);
+ if (!isVisible() || object != d->window)
+ return false;
+
+ switch (event->type()) {
+#if QT_CONFIG(quicktemplates2_multitouch)
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ if (static_cast<QTouchEvent *>(event)->touchPointStates() & QEventPoint::Pressed)
+ emit pressed();
+ if (static_cast<QTouchEvent *>(event)->touchPointStates() & QEventPoint::Released)
+ emit released();
+
+ // allow non-modal popups to close on touch release outside
+ if (!d->mouseGrabberPopup) {
+ for (const QTouchEvent::TouchPoint &point : static_cast<QTouchEvent *>(event)->points()) {
+ if (point.state() == QEventPoint::Released) {
+ if (d->handleRelease(d->window->contentItem(), event, nullptr))
+ break;
+ }
+ }
+ }
+
+ // setup currentEventDeliveryAgent like in QQuickDeliveryAgent::event
+ QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
+ d->deliveryAgentPrivate()->handleTouchEvent(static_cast<QTouchEvent *>(event));
+ QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = nullptr;
+
+ // If a touch event hasn't been accepted after being delivered, there
+ // were no items interested in touch events at any of the touch points.
+ // 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
+
+ case QEvent::MouseButtonPress:
+#if QT_CONFIG(quicktemplates2_multitouch)
+ // do not emit pressed() twice when mouse events have been synthesized from touch events
+ if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized)
+#endif
+ emit pressed();
+
+ // setup currentEventDeliveryAgent like in QQuickDeliveryAgent::event
+ QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
+ d->deliveryAgentPrivate()->handleMouseEvent(static_cast<QMouseEvent *>(event));
+ QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = nullptr;
+
+ // If a mouse event hasn't been accepted after being delivered, there
+ // was no item interested in mouse events at the mouse point. Make sure
+ // to accept the mouse event in order to receive the consequent mouse
+ // events, to be able to close non-modal popups on release outside.
+ event->accept();
+ return true;
+
+ case QEvent::MouseButtonRelease:
+#if QT_CONFIG(quicktemplates2_multitouch)
+ // do not emit released() twice when mouse events have been synthesized from touch events
+ if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized)
+#endif
+ emit released();
+
+ // allow non-modal popups to close on mouse release outside
+ if (!d->mouseGrabberPopup)
+ d->handleRelease(d->window->contentItem(), event, nullptr);
+ break;
+
+#if QT_CONFIG(wheelevent)
+ case QEvent::Wheel: {
+ // If the top item in the drawing-order is blocked by a modal popup, then
+ // eat the event. There is no scenario where the top most item is blocked
+ // by a popup, but an item further down in the drawing order is not.
+ QWheelEvent *we = static_cast<QWheelEvent *>(event);
+ const QVector<QQuickItem *> targetItems = d->deliveryAgentPrivate()->pointerTargets(
+ d->window->contentItem(), we, we->point(0), false, false);
+ 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.
+ for (const auto &popup : popups) {
+ const QQuickItem *popupItem = popup->popupItem();
+ if (!popupItem)
+ continue;
+ // 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))
+ return true;
+ }
+ break;
+ }
+#endif
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+class QQuickOverlayAttachedPrivate : public QObjectPrivate
+{
+public:
+ Q_DECLARE_PUBLIC(QQuickOverlayAttached)
+
+ void setWindow(QQuickWindow *newWindow);
+
+ QQuickWindow *window = nullptr;
+ QQmlComponent *modal = nullptr;
+ QQmlComponent *modeless = nullptr;
+};
+
+void QQuickOverlayAttachedPrivate::setWindow(QQuickWindow *newWindow)
+{
+ Q_Q(QQuickOverlayAttached);
+ if (window == newWindow)
+ return;
+
+ if (QQuickOverlay *oldOverlay = QQuickOverlay::overlay(window)) {
+ QObject::disconnect(oldOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
+ QObject::disconnect(oldOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
+ }
+
+ if (QQuickOverlay *newOverlay = QQuickOverlay::overlay(newWindow)) {
+ QObject::connect(newOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
+ QObject::connect(newOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
+ }
+
+ window = newWindow;
+ emit q->overlayChanged();
+}
+
+/*!
+ \qmlattachedsignal QtQuick.Controls::Overlay::pressed()
+
+ This attached signal is emitted when the overlay is pressed by the user while
+ a popup is visible.
+
+ The signal can be attached to any item, popup, or window. When attached to an
+ item or a popup, the signal is only emitted if the item or popup is in a window.
+*/
+
+/*!
+ \qmlattachedsignal QtQuick.Controls::Overlay::released()
+
+ This attached signal is emitted when the overlay is released by the user while
+ a popup is visible.
+
+ The signal can be attached to any item, popup, or window. When attached to an
+ item or a popup, the signal is only emitted if the item or popup is in a window.
+*/
+
+QQuickOverlayAttached::QQuickOverlayAttached(QObject *parent)
+ : QObject(*(new QQuickOverlayAttachedPrivate), parent)
+{
+ Q_D(QQuickOverlayAttached);
+ if (QQuickItem *item = qobject_cast<QQuickItem *>(parent)) {
+ d->setWindow(item->window());
+ QObjectPrivate::connect(item, &QQuickItem::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
+ } else if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(parent)) {
+ d->setWindow(popup->window());
+ QObjectPrivate::connect(popup, &QQuickPopup::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
+ } else {
+ d->setWindow(qobject_cast<QQuickWindow *>(parent));
+ }
+}
+
+/*!
+ \qmlattachedproperty Overlay QtQuick.Controls::Overlay::overlay
+ \readonly
+
+ This attached property holds the window overlay item.
+
+ The property can be attached to any item, popup, or window. When attached to an
+ item or a popup, the value is \c null if the item or popup is not in a window.
+*/
+QQuickOverlay *QQuickOverlayAttached::overlay() const
+{
+ Q_D(const QQuickOverlayAttached);
+ return QQuickOverlay::overlay(d->window);
+}
+
+/*!
+ \qmlattachedproperty Component QtQuick.Controls::Overlay::modal
+
+ This attached property holds a component to use as a visual item that implements
+ background dimming for modal popups. It is created for and stacked below visible
+ modal popups.
+
+ The property can be attached to any popup.
+
+ For example, to change the color of the background dimming for a modal
+ popup, the following code can be used:
+
+ \snippet qtquickcontrols-overlay-modal.qml 1
+
+ \sa Popup::modal
+*/
+QQmlComponent *QQuickOverlayAttached::modal() const
+{
+ Q_D(const QQuickOverlayAttached);
+ return d->modal;
+}
+
+void QQuickOverlayAttached::setModal(QQmlComponent *modal)
+{
+ Q_D(QQuickOverlayAttached);
+ if (d->modal == modal)
+ return;
+
+ d->modal = modal;
+ emit modalChanged();
+}
+
+/*!
+ \qmlattachedproperty Component QtQuick.Controls::Overlay::modeless
+
+ This attached property holds a component to use as a visual item that implements
+ background dimming for modeless popups. It is created for and stacked below visible
+ dimming popups.
+
+ The property can be attached to any popup.
+
+ For example, to change the color of the background dimming for a modeless
+ popup, the following code can be used:
+
+ \snippet qtquickcontrols-overlay-modeless.qml 1
+
+ \sa Popup::dim
+*/
+QQmlComponent *QQuickOverlayAttached::modeless() const
+{
+ Q_D(const QQuickOverlayAttached);
+ return d->modeless;
+}
+
+void QQuickOverlayAttached::setModeless(QQmlComponent *modeless)
+{
+ Q_D(QQuickOverlayAttached);
+ if (d->modeless == modeless)
+ return;
+
+ d->modeless = modeless;
+ emit modelessChanged();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickoverlay_p.cpp"