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);
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 QTouchEvent *touchEvent =
static_cast<QTouchEvent *>(event);
533 for (
const QTouchEvent::TouchPoint &point : touchEvent->points()) {
534 if (point.state() == QEventPoint::Released) {
535 QQuickDeliveryAgentPrivate::translateTouchEvent(touchEvent);
536 if (d->handleRelease(d->window->contentItem(), event,
nullptr))
543 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
544 d->deliveryAgentPrivate()->handleTouchEvent(
static_cast<QTouchEvent *>(event));
545 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent =
nullptr;
554 d->deliveryAgentPrivate()->clearGrabbers(
static_cast<QPointerEvent *>(event));
558 case QEvent::MouseButtonPress: {
559 auto *mouseEvent =
static_cast<QMouseEvent *>(event);
564 if (mouseEvent->button() == Qt::RightButton)
567#if QT_CONFIG(quicktemplates2_multitouch)
569 if (mouseEvent->source() == Qt::MouseEventNotSynthesized)
574 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
575 d->deliveryAgentPrivate()->handleMouseEvent(mouseEvent);
576 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent =
nullptr;
585 case QEvent::MouseButtonRelease: {
586 auto *mouseEvent =
static_cast<QMouseEvent *>(event);
587 if (mouseEvent->button() == Qt::RightButton)
590#if QT_CONFIG(quicktemplates2_multitouch)
592 if (mouseEvent->source() == Qt::MouseEventNotSynthesized)
597 if (!d->mouseGrabberPopup)
598 d->handleRelease(d->window->contentItem(), event,
nullptr);
601#if QT_CONFIG(wheelevent)
602 case QEvent::Wheel: {
606 QWheelEvent *we =
static_cast<QWheelEvent *>(event);
607 const QVector<QQuickItem *> targetItems = d->deliveryAgentPrivate()->pointerTargets(
608 d->window->contentItem(), we, we->point(0),
false,
false);
609 if (targetItems.isEmpty())
612 QQuickItem *
const dimmerItem = property(
"_q_dimmerItem").value<QQuickItem *>();
613 QQuickItem *
const topItem = targetItems.first();
615 QQuickItem *item = topItem;
616 while ((item = item->parentItem())) {
617 if (qobject_cast<QQuickPopupItem *>(item))
621 if (!item && dimmerItem != topItem && isAncestorOf(topItem))
624 const auto popups = d->stackingOrderPopups();
627 for (
const auto &popup : popups) {
628 const QQuickItem *popupItem = popup->popupItem();
632 if (popupItem == item)
635 if (popup->overlayEvent(topItem, we))
663 Q_Q(QQuickOverlayAttached);
664 if (window == newWindow)
667 if (QQuickOverlay *oldOverlay = QQuickOverlay::overlay(window)) {
668 QObject::disconnect(oldOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
669 QObject::disconnect(oldOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
672 if (QQuickOverlay *newOverlay = QQuickOverlay::overlay(newWindow)) {
673 QObject::connect(newOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
674 QObject::connect(newOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
678 emit q->overlayChanged();
705QQuickOverlayAttached::QQuickOverlayAttached(QObject *parent)
706 : QObject(*(
new QQuickOverlayAttachedPrivate), parent)
708 Q_D(QQuickOverlayAttached);
709 if (QQuickItem *item = qobject_cast<QQuickItem *>(parent)) {
710 d->setWindow(item->window());
711 QObjectPrivate::connect(item, &QQuickItem::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
712 }
else if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(parent)) {
713 d->setWindow(popup->window());
714 QObjectPrivate::connect(popup, &QQuickPopup::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
716 d->setWindow(qobject_cast<QQuickWindow *>(parent));