41QList<QQuickPopup *> QQuickOverlayPrivate::stackingOrderPopups()
const
43 const QList<QQuickItem *> children = paintOrderChildItems();
45 QList<QQuickPopup *> popups;
46 popups.reserve(children.size());
48 for (
auto it = children.crbegin(), end = children.crend(); it != end; ++it) {
49 QQuickPopup *popup = qobject_cast<QQuickPopup *>((*it)->parent());
76bool QQuickOverlayPrivate::startDrag(QEvent *event,
const QPointF &pos)
79 if (allDrawers.isEmpty())
83 QQuickItem *item = q->childAt(pos.x(), pos.y());
85 const auto popups = stackingOrderPopups();
86 for (QQuickPopup *popup : popups) {
87 QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
88 if (p->dimmer == item && popup->isVisible() && popup->isModal())
93 const QList<QQuickPopup *> drawers = stackingOrderDrawers();
94 for (QQuickPopup *popup : drawers) {
95 QQuickDrawer *drawer = qobject_cast<QQuickDrawer *>(popup);
97 QQuickDrawerPrivate *p = QQuickDrawerPrivate::get(drawer);
98 if (p->startDrag(event)) {
99 setMouseGrabberPopup(drawer);
107bool QQuickOverlayPrivate::handlePress(QQuickItem *source, QEvent *event, QQuickPopup *target)
110 if (target->overlayEvent(source, event)) {
111 setMouseGrabberPopup(target);
117 switch (event->type()) {
119 if (mouseGrabberPopup)
121#if QT_CONFIG(quicktemplates2_multitouch)
123 case QEvent::TouchBegin:
124 case QEvent::TouchUpdate:
125 case QEvent::TouchEnd:
129 const auto popups = stackingOrderPopups();
130 for (QQuickPopup *popup : popups) {
131 if (popup->overlayEvent(source, event)) {
132 setMouseGrabberPopup(popup);
151bool QQuickOverlayPrivate::handleRelease(QQuickItem *source, QEvent *event, QQuickPopup *target)
154 setMouseGrabberPopup(
nullptr);
155 if (target->overlayEvent(source, event)) {
156 setMouseGrabberPopup(
nullptr);
160 const auto popups = stackingOrderPopups();
161 for (QQuickPopup *popup : popups) {
162 if (popup->overlayEvent(source, event))
169bool QQuickOverlayPrivate::handleMouseEvent(QQuickItem *source, QMouseEvent *event, QQuickPopup *target)
171 switch (event->type()) {
172 case QEvent::MouseButtonPress:
173 if (!target && startDrag(event, event->scenePosition()))
175 return handlePress(source, event, target);
176 case QEvent::MouseMove:
177 return handleMove(source, event, target ? target : mouseGrabberPopup.data());
178 case QEvent::MouseButtonRelease:
179 return handleRelease(source, event, target ? target : mouseGrabberPopup.data());
263void QQuickOverlayPrivate::updateGeometry()
266 if (!window || !window->contentItem())
269 const QSizeF size = window->contentItem()->size();
270 const QPointF pos(-(size.width() - window->size().width()) / 2,
271 -(size.height() - window->size().height()) / 2);
277QQuickOverlay::QQuickOverlay(QQuickItem *parent)
278 : QQuickItem(*(
new QQuickOverlayPrivate), parent)
282 setAcceptedMouseButtons(Qt::AllButtons);
283#if QT_CONFIG(quicktemplates2_multitouch)
284 setAcceptTouchEvents(
true);
286 setFiltersChildMouseEvents(
true);
291 QQuickItemPrivate::get(parent)->addItemChangeListener(d, QQuickItemPrivate::Geometry);
292 if (QQuickWindow *window = parent->window()) {
293 window->installEventFilter(
this);
294 if (QQuickItem *contentItem = window->contentItem())
295 QQuickItemPrivate::get(contentItem)->addItemChangeListener(d, QQuickItemPrivate::Rotation);
300QQuickOverlay::~QQuickOverlay()
303 if (QQuickItem *parent = parentItem()) {
304 QQuickItemPrivate::get(parent)->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
305 if (QQuickWindow *window = parent->window()) {
306 if (QQuickItem *contentItem = window->contentItem())
307 QQuickItemPrivate::get(contentItem)->removeItemChangeListener(d, QQuickItemPrivate::Rotation);
344QQuickOverlay *QQuickOverlay::overlay(QQuickWindow *window)
349 const char *name =
"_q_QQuickOverlay";
350 QQuickOverlay *overlay = window->property(name).value<QQuickOverlay *>();
352 QQuickItem *content = window->contentItem();
355 if (content && content->window()) {
356 overlay =
new QQuickOverlay(window->contentItem());
357 window->setProperty(name, QVariant::fromValue(overlay));
368void QQuickOverlay::itemChange(ItemChange change,
const ItemChangeData &data)
371 QQuickItem::itemChange(change, data);
373 if (change == ItemChildAddedChange || change == ItemChildRemovedChange) {
374 setVisible(!d->allDrawers.isEmpty() || !childItems().isEmpty());
375 if (data.item->parent() == d->mouseGrabberPopup)
376 d->setMouseGrabberPopup(
nullptr);
380void QQuickOverlay::geometryChange(
const QRectF &newGeometry,
const QRectF &oldGeometry)
383 QQuickItem::geometryChange(newGeometry, oldGeometry);
384 for (QQuickPopup *popup : std::as_const(d->allPopups))
385 QQuickPopupPrivate::get(popup)->resizeDimmer();
444bool QQuickOverlay::childMouseEventFilter(QQuickItem *item, QEvent *event)
447 const auto popups = d->stackingOrderPopups();
448 for (QQuickPopup *popup : popups) {
449 QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
453 if (item == p->popupItem || p->popupItem->isAncestorOf(item))
459 if (item == p->dimmer || !p->popupItem->isAncestorOf(item)) {
460 bool handled =
false;
461 switch (event->type()) {
462#if QT_CONFIG(quicktemplates2_multitouch)
463 case QEvent::TouchBegin:
464 case QEvent::TouchUpdate:
465 case QEvent::TouchEnd:
466 handled = d->handleTouchEvent(item,
static_cast<QTouchEvent *>(event), popup);
469 case QEvent::HoverEnter:
470 case QEvent::HoverMove:
471 case QEvent::HoverLeave:
475 if (
auto *control = qobject_cast<QQuickControl *>(item)) {
476 if (control->isHovered() && event->type() == QEvent::HoverLeave)
479 handled = d->handleHoverEvent(item,
static_cast<QHoverEvent *>(event), popup);
482 case QEvent::MouseButtonPress:
483 case QEvent::MouseMove:
484 case QEvent::MouseButtonRelease:
485 handled = d->handleMouseEvent(item,
static_cast<QMouseEvent *>(event), popup);
514bool QQuickOverlay::eventFilter(QObject *object, QEvent *event)
517 if (!isVisible() || object != d->window)
520 switch (event->type()) {
521#if QT_CONFIG(quicktemplates2_multitouch)
522 case QEvent::TouchBegin:
523 case QEvent::TouchUpdate:
524 case QEvent::TouchEnd:
525 if (
static_cast<QTouchEvent *>(event)->touchPointStates() & QEventPoint::Pressed)
527 if (
static_cast<QTouchEvent *>(event)->touchPointStates() & QEventPoint::Released)
531 if (!d->mouseGrabberPopup) {
532 for (
const QTouchEvent::TouchPoint &point :
static_cast<QTouchEvent *>(event)->points()) {
533 if (point.state() == QEventPoint::Released) {
534 if (d->handleRelease(d->window->contentItem(), event,
nullptr))
541 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
542 d->deliveryAgentPrivate()->handleTouchEvent(
static_cast<QTouchEvent *>(event));
543 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent =
nullptr;
552 d->deliveryAgentPrivate()->clearGrabbers(
static_cast<QPointerEvent *>(event));
556 case QEvent::MouseButtonPress: {
557 auto *mouseEvent =
static_cast<QMouseEvent *>(event);
562 if (mouseEvent->button() == Qt::RightButton)
565#if QT_CONFIG(quicktemplates2_multitouch)
567 if (mouseEvent->source() == Qt::MouseEventNotSynthesized)
572 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
573 d->deliveryAgentPrivate()->handleMouseEvent(mouseEvent);
574 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent =
nullptr;
583 case QEvent::MouseButtonRelease: {
584 auto *mouseEvent =
static_cast<QMouseEvent *>(event);
585 if (mouseEvent->button() == Qt::RightButton)
588#if QT_CONFIG(quicktemplates2_multitouch)
590 if (mouseEvent->source() == Qt::MouseEventNotSynthesized)
595 if (!d->mouseGrabberPopup)
596 d->handleRelease(d->window->contentItem(), event,
nullptr);
599#if QT_CONFIG(wheelevent)
600 case QEvent::Wheel: {
604 QWheelEvent *we =
static_cast<QWheelEvent *>(event);
605 const QVector<QQuickItem *> targetItems = d->deliveryAgentPrivate()->pointerTargets(
606 d->window->contentItem(), we, we->point(0),
false,
false);
607 if (targetItems.isEmpty())
610 QQuickItem *
const dimmerItem = property(
"_q_dimmerItem").value<QQuickItem *>();
611 QQuickItem *
const topItem = targetItems.first();
613 QQuickItem *item = topItem;
614 while ((item = item->parentItem())) {
615 if (qobject_cast<QQuickPopupItem *>(item))
619 if (!item && dimmerItem != topItem && isAncestorOf(topItem))
622 const auto popups = d->stackingOrderPopups();
625 for (
const auto &popup : popups) {
626 const QQuickItem *popupItem = popup->popupItem();
630 if (popupItem == item)
633 if (popup->overlayEvent(topItem, we))
661 Q_Q(QQuickOverlayAttached);
662 if (window == newWindow)
665 if (QQuickOverlay *oldOverlay = QQuickOverlay::overlay(window)) {
666 QObject::disconnect(oldOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
667 QObject::disconnect(oldOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
670 if (QQuickOverlay *newOverlay = QQuickOverlay::overlay(newWindow)) {
671 QObject::connect(newOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
672 QObject::connect(newOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
676 emit q->overlayChanged();
703QQuickOverlayAttached::QQuickOverlayAttached(QObject *parent)
704 : QObject(*(
new QQuickOverlayAttachedPrivate), parent)
706 Q_D(QQuickOverlayAttached);
707 if (QQuickItem *item = qobject_cast<QQuickItem *>(parent)) {
708 d->setWindow(item->window());
709 QObjectPrivate::connect(item, &QQuickItem::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
710 }
else if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(parent)) {
711 d->setWindow(popup->window());
712 QObjectPrivate::connect(popup, &QQuickPopup::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
714 d->setWindow(qobject_cast<QQuickWindow *>(parent));