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, QQuickItem *parent)
349 const char *name =
"_q_QQuickOverlay";
351 if (QQuickItemPrivate::customOverlayRequested) {
353 if (QQuickItemPrivate::get(parent)->customOverlay) {
354 QQuickOverlay *overlay = parent->property(name).value<QQuickOverlay *>();
356 overlay =
new QQuickOverlay(parent);
357 parent->setProperty(name, QVariant::fromValue(overlay));
361 parent = parent->parentItem();
364 QQuickOverlay *overlay = window->property(name).value<QQuickOverlay *>();
366 QQuickItem *content = window->contentItem();
369 if (content && content->window()) {
370 overlay =
new QQuickOverlay(window->contentItem());
371 window->setProperty(name, QVariant::fromValue(overlay));
382void QQuickOverlay::itemChange(ItemChange change,
const ItemChangeData &data)
385 QQuickItem::itemChange(change, data);
387 if (change == ItemChildAddedChange || change == ItemChildRemovedChange) {
388 setVisible(!d->allDrawers.isEmpty() || !childItems().isEmpty());
389 if (data.item->parent() == d->mouseGrabberPopup)
390 d->setMouseGrabberPopup(
nullptr);
458bool QQuickOverlay::childMouseEventFilter(QQuickItem *item, QEvent *event)
461 const auto popups = d->stackingOrderPopups();
462 for (QQuickPopup *popup : popups) {
463 QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
467 if (item == p->popupItem || p->popupItem->isAncestorOf(item))
473 if (item == p->dimmer || !p->popupItem->isAncestorOf(item)) {
474 bool handled =
false;
475 switch (event->type()) {
476#if QT_CONFIG(quicktemplates2_multitouch)
477 case QEvent::TouchBegin:
478 case QEvent::TouchUpdate:
479 case QEvent::TouchEnd:
480 handled = d->handleTouchEvent(item,
static_cast<QTouchEvent *>(event), popup);
483 case QEvent::HoverEnter:
484 case QEvent::HoverMove:
485 case QEvent::HoverLeave:
489 if (
auto *control = qobject_cast<QQuickControl *>(item)) {
490 if (control->isHovered() && event->type() == QEvent::HoverLeave)
493 handled = d->handleHoverEvent(item,
static_cast<QHoverEvent *>(event), popup);
496 case QEvent::MouseButtonPress:
497 case QEvent::MouseMove:
498 case QEvent::MouseButtonRelease:
499 handled = d->handleMouseEvent(item,
static_cast<QMouseEvent *>(event), popup);
528bool QQuickOverlay::eventFilter(QObject *object, QEvent *event)
531 if (!isVisible() || object != d->window)
534 switch (event->type()) {
535#if QT_CONFIG(quicktemplates2_multitouch)
536 case QEvent::TouchBegin:
537 case QEvent::TouchUpdate:
538 case QEvent::TouchEnd:
539 if (
static_cast<QTouchEvent *>(event)->touchPointStates() & QEventPoint::Pressed)
541 if (
static_cast<QTouchEvent *>(event)->touchPointStates() & QEventPoint::Released)
545 if (!d->mouseGrabberPopup) {
546 QTouchEvent *touchEvent =
static_cast<QTouchEvent *>(event);
547 for (
const QTouchEvent::TouchPoint &point : touchEvent->points()) {
548 if (point.state() == QEventPoint::Released) {
549 QQuickDeliveryAgentPrivate::translateTouchEvent(touchEvent);
550 if (d->handleRelease(d->window->contentItem(), event,
nullptr))
557 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
558 d->deliveryAgentPrivate()->handleTouchEvent(
static_cast<QTouchEvent *>(event));
559 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent =
nullptr;
568 d->deliveryAgentPrivate()->clearGrabbers(
static_cast<QPointerEvent *>(event));
572 case QEvent::MouseButtonPress: {
573 auto *mouseEvent =
static_cast<QMouseEvent *>(event);
578 if (mouseEvent->button() == Qt::RightButton)
581#if QT_CONFIG(quicktemplates2_multitouch)
583 if (mouseEvent->source() == Qt::MouseEventNotSynthesized)
588 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
589 d->deliveryAgentPrivate()->handleMouseEvent(mouseEvent);
590 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent =
nullptr;
599 case QEvent::MouseButtonRelease: {
600 auto *mouseEvent =
static_cast<QMouseEvent *>(event);
601 if (mouseEvent->button() == Qt::RightButton)
604#if QT_CONFIG(quicktemplates2_multitouch)
606 if (mouseEvent->source() == Qt::MouseEventNotSynthesized)
611 if (!d->mouseGrabberPopup)
612 d->handleRelease(d->window->contentItem(), event,
nullptr);
615#if QT_CONFIG(wheelevent)
616 case QEvent::Wheel: {
620 QWheelEvent *we =
static_cast<QWheelEvent *>(event);
621 const QList<QQuickItem *> targetItems = d->deliveryAgentPrivate()->pointerTargets(
622 d->window->contentItem(), we, we->point(0),
false,
false);
623 if (targetItems.isEmpty())
626 QQuickItem *
const dimmerItem = property(
"_q_dimmerItem").value<QQuickItem *>();
627 QQuickItem *
const topItem = targetItems.first();
629 QQuickItem *item = topItem;
630 while ((item = item->parentItem())) {
631 if (qobject_cast<QQuickPopupItem *>(item))
635 if (!item && dimmerItem != topItem && isAncestorOf(topItem))
638 const auto popups = d->stackingOrderPopups();
641 for (
const auto &popup : popups) {
642 const QQuickItem *popupItem = popup->popupItem();
646 if (popupItem == item)
649 if (popup->overlayEvent(topItem, we))
684 Q_Q(QQuickOverlayAttached);
685 if (window == newWindow)
688 if (QQuickOverlay *oldOverlay = QQuickOverlay::overlay(window, parent)) {
689 QObject::disconnect(oldOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
690 QObject::disconnect(oldOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
693 if (QQuickOverlay *newOverlay = QQuickOverlay::overlay(newWindow, parent)) {
694 QObject::connect(newOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
695 QObject::connect(newOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
701 emit q->overlayChanged();
728QQuickOverlayAttached::QQuickOverlayAttached(QObject *parent)
729 : QObject(*(
new QQuickOverlayAttachedPrivate), parent)
731 Q_D(QQuickOverlayAttached);
732 if (QQuickItem *item = qobject_cast<QQuickItem *>(parent)) {
733 d->setWindowAndParent(item->window(), item);
734 QObjectPrivate::connect(item, &QQuickItem::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
735 }
else if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(parent)) {
736 d->setWindowAndParent(popup->window(), popup->parentItem());
737 QObjectPrivate::connect(popup, &QQuickPopup::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
739 d->setWindow(qobject_cast<QQuickWindow *>(parent));