1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquickcontrol_p_p.h"
5#include "qquickoverlay_p.h"
6#include "qquickoverlay_p_p.h"
7#include "qquickpopupitem_p_p.h"
8#include "qquickpopup_p_p.h"
9#include "qquickdrawer_p.h"
10#include "qquickdrawer_p_p.h"
11#include "qquickapplicationwindow_p.h"
12#include <QtQml/qqmlinfo.h>
13#include <QtQml/qqmlproperty.h>
14#include <QtQml/qqmlcomponent.h>
15#include <algorithm>
16
17QT_BEGIN_NAMESPACE
18
19/*!
20 \qmltype Overlay
21 \inherits Item
22//! \instantiates QQuickOverlay
23 \inqmlmodule QtQuick.Controls
24 \since 5.10
25 \brief A window overlay for popups.
26
27 Overlay provides a layer for popups, ensuring that popups are displayed above
28 other content and that the background is dimmed when a \l {Popup::}{modal} or
29 \l {Popup::dim}{dimmed} popup is visible.
30
31 The overlay is an ordinary Item that covers the entire window. It can be used
32 as a visual parent to position a popup in scene coordinates.
33
34 \include qquickoverlay-popup-parent.qdocinc
35
36 \sa ApplicationWindow
37*/
38
39QList<QQuickPopup *> QQuickOverlayPrivate::stackingOrderPopups() const
40{
41 const QList<QQuickItem *> children = paintOrderChildItems();
42
43 QList<QQuickPopup *> popups;
44 popups.reserve(size: children.size());
45
46 for (auto it = children.crbegin(), end = children.crend(); it != end; ++it) {
47 QQuickPopup *popup = qobject_cast<QQuickPopup *>(object: (*it)->parent());
48 if (popup)
49 popups += popup;
50 }
51
52 return popups;
53}
54
55QList<QQuickPopup *> QQuickOverlayPrivate::stackingOrderDrawers() const
56{
57 QList<QQuickPopup *> sorted(allDrawers);
58 std::sort(first: sorted.begin(), last: sorted.end(), comp: [](const QQuickPopup *one, const QQuickPopup *another) {
59 return one->z() > another->z();
60 });
61 return sorted;
62}
63
64void QQuickOverlayPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
65{
66 updateGeometry();
67}
68
69bool QQuickOverlayPrivate::startDrag(QEvent *event, const QPointF &pos)
70{
71 Q_Q(QQuickOverlay);
72 if (allDrawers.isEmpty())
73 return false;
74
75 // don't start dragging a drawer if a modal popup overlay is blocking (QTBUG-60602)
76 QQuickItem *item = q->childAt(x: pos.x(), y: pos.y());
77 if (item) {
78 const auto popups = stackingOrderPopups();
79 for (QQuickPopup *popup : popups) {
80 QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
81 if (p->dimmer == item && popup->isVisible() && popup->isModal())
82 return false;
83 }
84 }
85
86 const QList<QQuickPopup *> drawers = stackingOrderDrawers();
87 for (QQuickPopup *popup : drawers) {
88 QQuickDrawer *drawer = qobject_cast<QQuickDrawer *>(object: popup);
89 Q_ASSERT(drawer);
90 QQuickDrawerPrivate *p = QQuickDrawerPrivate::get(drawer);
91 if (p->startDrag(event)) {
92 setMouseGrabberPopup(drawer);
93 return true;
94 }
95 }
96
97 return false;
98}
99
100bool QQuickOverlayPrivate::handlePress(QQuickItem *source, QEvent *event, QQuickPopup *target)
101{
102 if (target) {
103 if (target->overlayEvent(item: source, event)) {
104 setMouseGrabberPopup(target);
105 return true;
106 }
107 return false;
108 }
109
110 switch (event->type()) {
111 default: {
112 if (mouseGrabberPopup)
113 break;
114#if QT_CONFIG(quicktemplates2_multitouch)
115 Q_FALLTHROUGH();
116 case QEvent::TouchBegin:
117 case QEvent::TouchUpdate:
118 case QEvent::TouchEnd:
119#endif
120 // allow non-modal popups to close themselves,
121 // and non-dimming modal popups to block the event
122 const auto popups = stackingOrderPopups();
123 for (QQuickPopup *popup : popups) {
124 if (popup->overlayEvent(item: source, event)) {
125 setMouseGrabberPopup(popup);
126 return true;
127 }
128 }
129 break;
130 }
131 }
132
133 event->ignore();
134 return false;
135}
136
137bool QQuickOverlayPrivate::handleMove(QQuickItem *source, QEvent *event, QQuickPopup *target)
138{
139 if (target)
140 return target->overlayEvent(item: source, event);
141 return false;
142}
143
144bool QQuickOverlayPrivate::handleRelease(QQuickItem *source, QEvent *event, QQuickPopup *target)
145{
146 if (target) {
147 setMouseGrabberPopup(nullptr);
148 if (target->overlayEvent(item: source, event)) {
149 setMouseGrabberPopup(nullptr);
150 return true;
151 }
152 } else {
153 const auto popups = stackingOrderPopups();
154 for (QQuickPopup *popup : popups) {
155 if (popup->overlayEvent(item: source, event))
156 return true;
157 }
158 }
159 return false;
160}
161
162bool QQuickOverlayPrivate::handleMouseEvent(QQuickItem *source, QMouseEvent *event, QQuickPopup *target)
163{
164 switch (event->type()) {
165 case QEvent::MouseButtonPress:
166 if (!target && startDrag(event, pos: event->scenePosition()))
167 return true;
168 return handlePress(source, event, target);
169 case QEvent::MouseMove:
170 return handleMove(source, event, target: target ? target : mouseGrabberPopup.data());
171 case QEvent::MouseButtonRelease:
172 return handleRelease(source, event, target: target ? target : mouseGrabberPopup.data());
173 default:
174 break;
175 }
176 return false;
177}
178
179bool QQuickOverlayPrivate::handleHoverEvent(QQuickItem *source, QHoverEvent *event, QQuickPopup *target)
180{
181 switch (event->type()) {
182 case QEvent::HoverEnter:
183 case QEvent::HoverMove:
184 case QEvent::HoverLeave:
185 if (target)
186 return target->overlayEvent(item: source, event);
187 return false;
188 default:
189 Q_UNREACHABLE(); // function must only be called on hover events
190 break;
191 }
192 return false;
193}
194
195#if QT_CONFIG(quicktemplates2_multitouch)
196bool QQuickOverlayPrivate::handleTouchEvent(QQuickItem *source, QTouchEvent *event, QQuickPopup *target)
197{
198 bool handled = false;
199 switch (event->type()) {
200 case QEvent::TouchBegin:
201 case QEvent::TouchUpdate:
202 case QEvent::TouchEnd:
203 for (const QTouchEvent::TouchPoint &point : event->points()) {
204 switch (point.state()) {
205 case QEventPoint::Pressed:
206 if (!target && startDrag(event, pos: point.scenePosition()))
207 handled = true;
208 else
209 handled |= handlePress(source, event, target);
210 break;
211 case QEventPoint::Updated:
212 handled |= handleMove(source, event, target: target ? target : mouseGrabberPopup.data());
213 break;
214 case QEventPoint::Released:
215 handled |= handleRelease(source, event, target: target ? target : mouseGrabberPopup.data());
216 break;
217 default:
218 break;
219 }
220 }
221 break;
222
223 default:
224 break;
225 }
226
227 return handled;
228}
229#endif
230
231void QQuickOverlayPrivate::addPopup(QQuickPopup *popup)
232{
233 Q_Q(QQuickOverlay);
234 allPopups += popup;
235 if (QQuickDrawer *drawer = qobject_cast<QQuickDrawer *>(object: popup)) {
236 allDrawers += drawer;
237 q->setVisible(!allDrawers.isEmpty() || !q->childItems().isEmpty());
238 }
239}
240
241void QQuickOverlayPrivate::removePopup(QQuickPopup *popup)
242{
243 Q_Q(QQuickOverlay);
244 allPopups.removeOne(t: popup);
245 if (allDrawers.removeOne(t: popup))
246 q->setVisible(!allDrawers.isEmpty() || !q->childItems().isEmpty());
247}
248
249void QQuickOverlayPrivate::setMouseGrabberPopup(QQuickPopup *popup)
250{
251 if (popup && !popup->isVisible())
252 popup = nullptr;
253 mouseGrabberPopup = popup;
254}
255
256void QQuickOverlayPrivate::updateGeometry()
257{
258 Q_Q(QQuickOverlay);
259 if (!window)
260 return;
261
262 QPointF pos;
263 QSizeF size = window->size();
264 qreal rotation = 0;
265
266 switch (window->contentOrientation()) {
267 case Qt::PrimaryOrientation:
268 case Qt::PortraitOrientation:
269 size = window->size();
270 break;
271 case Qt::LandscapeOrientation:
272 rotation = 90;
273 pos = QPointF((size.width() - size.height()) / 2, -(size.width() - size.height()) / 2);
274 size.transpose();
275 break;
276 case Qt::InvertedPortraitOrientation:
277 rotation = 180;
278 break;
279 case Qt::InvertedLandscapeOrientation:
280 rotation = 270;
281 pos = QPointF((size.width() - size.height()) / 2, -(size.width() - size.height()) / 2);
282 size.transpose();
283 break;
284 default:
285 break;
286 }
287
288 q->setSize(size);
289 q->setPosition(pos);
290 q->setRotation(rotation);
291}
292
293QQuickOverlay::QQuickOverlay(QQuickItem *parent)
294 : QQuickItem(*(new QQuickOverlayPrivate), parent)
295{
296 Q_D(QQuickOverlay);
297 setZ(1000001); // DefaultWindowDecoration+1
298 setAcceptedMouseButtons(Qt::AllButtons);
299#if QT_CONFIG(quicktemplates2_multitouch)
300 setAcceptTouchEvents(true);
301#endif
302 setFiltersChildMouseEvents(true);
303 setVisible(false);
304
305 if (parent) {
306 d->updateGeometry();
307 QQuickItemPrivate::get(item: parent)->addItemChangeListener(listener: d, types: QQuickItemPrivate::Geometry);
308 if (QQuickWindow *window = parent->window()) {
309 window->installEventFilter(filterObj: this);
310 QObjectPrivate::connect(sender: window, signal: &QWindow::contentOrientationChanged, receiverPrivate: d, slot: &QQuickOverlayPrivate::updateGeometry);
311 }
312 }
313}
314
315QQuickOverlay::~QQuickOverlay()
316{
317 Q_D(QQuickOverlay);
318 if (QQuickItem *parent = parentItem())
319 QQuickItemPrivate::get(item: parent)->removeItemChangeListener(d, types: QQuickItemPrivate::Geometry);
320}
321
322QQmlComponent *QQuickOverlay::modal() const
323{
324 Q_D(const QQuickOverlay);
325 return d->modal;
326}
327
328void QQuickOverlay::setModal(QQmlComponent *modal)
329{
330 Q_D(QQuickOverlay);
331 if (d->modal == modal)
332 return;
333
334 d->modal = modal;
335 emit modalChanged();
336}
337
338QQmlComponent *QQuickOverlay::modeless() const
339{
340 Q_D(const QQuickOverlay);
341 return d->modeless;
342}
343
344void QQuickOverlay::setModeless(QQmlComponent *modeless)
345{
346 Q_D(QQuickOverlay);
347 if (d->modeless == modeless)
348 return;
349
350 d->modeless = modeless;
351 emit modelessChanged();
352}
353
354QQuickOverlay *QQuickOverlay::overlay(QQuickWindow *window)
355{
356 if (!window)
357 return nullptr;
358
359 const char *name = "_q_QQuickOverlay";
360 QQuickOverlay *overlay = window->property(name).value<QQuickOverlay *>();
361 if (!overlay) {
362 QQuickItem *content = window->contentItem();
363 // Do not re-create the overlay if the window is being destroyed
364 // and thus, its content item no longer has a window associated.
365 if (content && content->window()) {
366 overlay = new QQuickOverlay(window->contentItem());
367 window->setProperty(name, value: QVariant::fromValue(value: overlay));
368 }
369 }
370 return overlay;
371}
372
373QQuickOverlayAttached *QQuickOverlay::qmlAttachedProperties(QObject *object)
374{
375 return new QQuickOverlayAttached(object);
376}
377
378void QQuickOverlay::itemChange(ItemChange change, const ItemChangeData &data)
379{
380 Q_D(QQuickOverlay);
381 QQuickItem::itemChange(change, data);
382
383 if (change == ItemChildAddedChange || change == ItemChildRemovedChange) {
384 setVisible(!d->allDrawers.isEmpty() || !childItems().isEmpty());
385 if (data.item->parent() == d->mouseGrabberPopup)
386 d->setMouseGrabberPopup(nullptr);
387 }
388}
389
390void QQuickOverlay::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
391{
392 Q_D(QQuickOverlay);
393 QQuickItem::geometryChange(newGeometry, oldGeometry);
394 for (QQuickPopup *popup : std::as_const(t&: d->allPopups))
395 QQuickPopupPrivate::get(popup)->resizeOverlay();
396}
397
398void QQuickOverlay::mousePressEvent(QMouseEvent *event)
399{
400 Q_D(QQuickOverlay);
401 d->handleMouseEvent(source: this, event);
402}
403
404void QQuickOverlay::mouseMoveEvent(QMouseEvent *event)
405{
406 Q_D(QQuickOverlay);
407 d->handleMouseEvent(source: this, event);
408}
409
410void QQuickOverlay::mouseReleaseEvent(QMouseEvent *event)
411{
412 Q_D(QQuickOverlay);
413 d->handleMouseEvent(source: this, event);
414}
415
416#if QT_CONFIG(quicktemplates2_multitouch)
417void QQuickOverlay::touchEvent(QTouchEvent *event)
418{
419 Q_D(QQuickOverlay);
420 d->handleTouchEvent(source: this, event);
421}
422#endif
423
424#if QT_CONFIG(wheelevent)
425void QQuickOverlay::wheelEvent(QWheelEvent *event)
426{
427 Q_D(QQuickOverlay);
428 if (d->mouseGrabberPopup) {
429 d->mouseGrabberPopup->overlayEvent(item: this, event);
430 return;
431 } else {
432 const auto popups = d->stackingOrderPopups();
433 for (QQuickPopup *popup : popups) {
434 if (popup->overlayEvent(item: this, event))
435 return;
436 }
437 }
438 event->ignore();
439}
440#endif
441
442bool QQuickOverlay::childMouseEventFilter(QQuickItem *item, QEvent *event)
443{
444 Q_D(QQuickOverlay);
445 const auto popups = d->stackingOrderPopups();
446 for (QQuickPopup *popup : popups) {
447 QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
448
449 // Stop filtering overlay events when reaching a popup item or an item
450 // that is inside the popup. Let the popup content handle its events.
451 if (item == p->popupItem || p->popupItem->isAncestorOf(child: item))
452 break;
453
454 // Let the popup try closing itself when pressing or releasing over its
455 // background dimming OR over another popup underneath, in case the popup
456 // does not have background dimming.
457 if (item == p->dimmer || !p->popupItem->isAncestorOf(child: item)) {
458 bool handled = false;
459 switch (event->type()) {
460#if QT_CONFIG(quicktemplates2_multitouch)
461 case QEvent::TouchBegin:
462 case QEvent::TouchUpdate:
463 case QEvent::TouchEnd:
464 handled = d->handleTouchEvent(source: item, event: static_cast<QTouchEvent *>(event), target: popup);
465 break;
466#endif
467 case QEvent::HoverEnter:
468 case QEvent::HoverMove:
469 case QEvent::HoverLeave:
470 handled = d->handleHoverEvent(source: item, event: static_cast<QHoverEvent *>(event), target: popup);
471 break;
472
473 case QEvent::MouseButtonPress:
474 case QEvent::MouseMove:
475 case QEvent::MouseButtonRelease:
476 handled = d->handleMouseEvent(source: item, event: static_cast<QMouseEvent *>(event), target: popup);
477 break;
478
479 default:
480 break;
481 }
482 if (handled)
483 return true;
484 }
485 }
486 return false;
487}
488
489bool QQuickOverlay::eventFilter(QObject *object, QEvent *event)
490{
491 Q_D(QQuickOverlay);
492 if (!isVisible() || object != d->window)
493 return false;
494
495 switch (event->type()) {
496#if QT_CONFIG(quicktemplates2_multitouch)
497 case QEvent::TouchBegin:
498 case QEvent::TouchUpdate:
499 case QEvent::TouchEnd:
500 if (static_cast<QTouchEvent *>(event)->touchPointStates() & QEventPoint::Pressed)
501 emit pressed();
502 if (static_cast<QTouchEvent *>(event)->touchPointStates() & QEventPoint::Released)
503 emit released();
504
505 // allow non-modal popups to close on touch release outside
506 if (!d->mouseGrabberPopup) {
507 for (const QTouchEvent::TouchPoint &point : static_cast<QTouchEvent *>(event)->points()) {
508 if (point.state() == QEventPoint::Released) {
509 if (d->handleRelease(source: d->window->contentItem(), event, target: nullptr))
510 break;
511 }
512 }
513 }
514
515 // setup currentEventDeliveryAgent like in QQuickDeliveryAgent::event
516 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
517 d->deliveryAgentPrivate()->handleTouchEvent(static_cast<QTouchEvent *>(event));
518 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = nullptr;
519
520 // If a touch event hasn't been accepted after being delivered, there
521 // were no items interested in touch events at any of the touch points.
522 // Make sure to accept the touch event in order to receive the consequent
523 // touch events, to be able to close non-modal popups on release outside.
524 event->accept();
525 // Since we eat the event, QQuickWindow::event never sees it to clean up the
526 // grabber states. So we have to do so explicitly.
527 if (QQuickWindow *window = parentItem() ? parentItem()->window() : nullptr) {
528 QQuickWindowPrivate *d = QQuickWindowPrivate::get(c: window);
529 d->clearGrabbers(event: static_cast<QPointerEvent *>(event));
530 }
531 return true;
532#endif
533
534 case QEvent::MouseButtonPress:
535#if QT_CONFIG(quicktemplates2_multitouch)
536 // do not emit pressed() twice when mouse events have been synthesized from touch events
537 if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized)
538#endif
539 emit pressed();
540
541 // setup currentEventDeliveryAgent like in QQuickDeliveryAgent::event
542 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
543 d->deliveryAgentPrivate()->handleMouseEvent(static_cast<QMouseEvent *>(event));
544 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = nullptr;
545
546 // If a mouse event hasn't been accepted after being delivered, there
547 // was no item interested in mouse events at the mouse point. Make sure
548 // to accept the mouse event in order to receive the consequent mouse
549 // events, to be able to close non-modal popups on release outside.
550 event->accept();
551 return true;
552
553 case QEvent::MouseButtonRelease:
554#if QT_CONFIG(quicktemplates2_multitouch)
555 // do not emit released() twice when mouse events have been synthesized from touch events
556 if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized)
557#endif
558 emit released();
559
560 // allow non-modal popups to close on mouse release outside
561 if (!d->mouseGrabberPopup)
562 d->handleRelease(source: d->window->contentItem(), event, target: nullptr);
563 break;
564
565#if QT_CONFIG(wheelevent)
566 case QEvent::Wheel: {
567 // If the top item in the drawing-order is blocked by a modal popup, then
568 // eat the event. There is no scenario where the top most item is blocked
569 // by a popup, but an item further down in the drawing order is not.
570 QWheelEvent *we = static_cast<QWheelEvent *>(event);
571 const QVector<QQuickItem *> targetItems = d->deliveryAgentPrivate()->pointerTargets(
572 d->window->contentItem(), event: we, point: we->point(i: 0), checkMouseButtons: false, checkAcceptsTouch: false);
573 if (targetItems.isEmpty())
574 break;
575
576 QQuickItem * const dimmerItem = property(name: "_q_dimmerItem").value<QQuickItem *>();
577 QQuickItem * const topItem = targetItems.first();
578
579 QQuickItem *item = topItem;
580 while ((item = item->parentItem())) {
581 if (qobject_cast<QQuickPopupItem *>(object: item))
582 break;
583 }
584
585 if (!item && dimmerItem != topItem && isAncestorOf(child: topItem))
586 break;
587
588 const auto popups = d->stackingOrderPopups();
589 // Eat the event if receiver topItem is not a child of a popup before
590 // the first modal popup.
591 for (const auto &popup : popups) {
592 const QQuickItem *popupItem = popup->popupItem();
593 if (!popupItem)
594 continue;
595 // if current popup item matches with any popup in stack, deliver the event
596 if (popupItem == item)
597 break;
598 // if the popup doesn't contain the item but is modal, eat the event
599 if (popup->overlayEvent(item: topItem, event: we))
600 return true;
601 }
602 break;
603 }
604#endif
605
606 default:
607 break;
608 }
609
610 return false;
611}
612
613class QQuickOverlayAttachedPrivate : public QObjectPrivate
614{
615public:
616 Q_DECLARE_PUBLIC(QQuickOverlayAttached)
617
618 void setWindow(QQuickWindow *newWindow);
619
620 QQuickWindow *window = nullptr;
621 QQmlComponent *modal = nullptr;
622 QQmlComponent *modeless = nullptr;
623};
624
625void QQuickOverlayAttachedPrivate::setWindow(QQuickWindow *newWindow)
626{
627 Q_Q(QQuickOverlayAttached);
628 if (window == newWindow)
629 return;
630
631 if (QQuickOverlay *oldOverlay = QQuickOverlay::overlay(window)) {
632 QObject::disconnect(sender: oldOverlay, signal: &QQuickOverlay::pressed, receiver: q, slot: &QQuickOverlayAttached::pressed);
633 QObject::disconnect(sender: oldOverlay, signal: &QQuickOverlay::released, receiver: q, slot: &QQuickOverlayAttached::released);
634 }
635
636 if (QQuickOverlay *newOverlay = QQuickOverlay::overlay(window: newWindow)) {
637 QObject::connect(sender: newOverlay, signal: &QQuickOverlay::pressed, context: q, slot: &QQuickOverlayAttached::pressed);
638 QObject::connect(sender: newOverlay, signal: &QQuickOverlay::released, context: q, slot: &QQuickOverlayAttached::released);
639 }
640
641 window = newWindow;
642 emit q->overlayChanged();
643}
644
645/*!
646 \qmlattachedsignal QtQuick.Controls::Overlay::pressed()
647
648 This attached signal is emitted when the overlay is pressed by the user while
649 a popup is visible.
650
651 The signal can be attached to any item, popup, or window. When attached to an
652 item or a popup, the signal is only emitted if the item or popup is in a window.
653*/
654
655/*!
656 \qmlattachedsignal QtQuick.Controls::Overlay::released()
657
658 This attached signal is emitted when the overlay is released by the user while
659 a popup is visible.
660
661 The signal can be attached to any item, popup, or window. When attached to an
662 item or a popup, the signal is only emitted if the item or popup is in a window.
663*/
664
665QQuickOverlayAttached::QQuickOverlayAttached(QObject *parent)
666 : QObject(*(new QQuickOverlayAttachedPrivate), parent)
667{
668 Q_D(QQuickOverlayAttached);
669 if (QQuickItem *item = qobject_cast<QQuickItem *>(o: parent)) {
670 d->setWindow(item->window());
671 QObjectPrivate::connect(sender: item, signal: &QQuickItem::windowChanged, receiverPrivate: d, slot: &QQuickOverlayAttachedPrivate::setWindow);
672 } else if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(object: parent)) {
673 d->setWindow(popup->window());
674 QObjectPrivate::connect(sender: popup, signal: &QQuickPopup::windowChanged, receiverPrivate: d, slot: &QQuickOverlayAttachedPrivate::setWindow);
675 } else {
676 d->setWindow(qobject_cast<QQuickWindow *>(object: parent));
677 }
678}
679
680/*!
681 \qmlattachedproperty Overlay QtQuick.Controls::Overlay::overlay
682 \readonly
683
684 This attached property holds the window overlay item.
685
686 The property can be attached to any item, popup, or window. When attached to an
687 item or a popup, the value is \c null if the item or popup is not in a window.
688*/
689QQuickOverlay *QQuickOverlayAttached::overlay() const
690{
691 Q_D(const QQuickOverlayAttached);
692 return QQuickOverlay::overlay(window: d->window);
693}
694
695/*!
696 \qmlattachedproperty Component QtQuick.Controls::Overlay::modal
697
698 This attached property holds a component to use as a visual item that implements
699 background dimming for modal popups. It is created for and stacked below visible
700 modal popups.
701
702 The property can be attached to any popup.
703
704 For example, to change the color of the background dimming for a modal
705 popup, the following code can be used:
706
707 \snippet qtquickcontrols-overlay-modal.qml 1
708
709 \sa Popup::modal
710*/
711QQmlComponent *QQuickOverlayAttached::modal() const
712{
713 Q_D(const QQuickOverlayAttached);
714 return d->modal;
715}
716
717void QQuickOverlayAttached::setModal(QQmlComponent *modal)
718{
719 Q_D(QQuickOverlayAttached);
720 if (d->modal == modal)
721 return;
722
723 d->modal = modal;
724 emit modalChanged();
725}
726
727/*!
728 \qmlattachedproperty Component QtQuick.Controls::Overlay::modeless
729
730 This attached property holds a component to use as a visual item that implements
731 background dimming for modeless popups. It is created for and stacked below visible
732 dimming popups.
733
734 The property can be attached to any popup.
735
736 For example, to change the color of the background dimming for a modeless
737 popup, the following code can be used:
738
739 \snippet qtquickcontrols-overlay-modeless.qml 1
740
741 \sa Popup::dim
742*/
743QQmlComponent *QQuickOverlayAttached::modeless() const
744{
745 Q_D(const QQuickOverlayAttached);
746 return d->modeless;
747}
748
749void QQuickOverlayAttached::setModeless(QQmlComponent *modeless)
750{
751 Q_D(QQuickOverlayAttached);
752 if (d->modeless == modeless)
753 return;
754
755 d->modeless = modeless;
756 emit modelessChanged();
757}
758
759QT_END_NAMESPACE
760
761#include "moc_qquickoverlay_p.cpp"
762

source code of qtdeclarative/src/quicktemplates/qquickoverlay.cpp