153bool QQuickOverlayPrivate::startDrag(QEvent *event,
const QPointF &pos)
156 if (allDrawers.isEmpty())
160 QQuickItem *item = q->childAt(pos.x(), pos.y());
162 const auto popups = stackingOrderPopups();
163 for (QQuickPopup *popup : popups) {
164 QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
165 if (p->dimmer == item && popup->isVisible() && popup->isModal())
170 const QList<QQuickPopup *> drawers = stackingOrderDrawers();
171 for (QQuickPopup *popup : drawers) {
172 QQuickDrawer *drawer = qobject_cast<QQuickDrawer *>(popup);
174 QQuickDrawerPrivate *p = QQuickDrawerPrivate::get(drawer);
175 if (p->startDrag(event)) {
176 setMouseGrabberPopup(drawer);
184bool QQuickOverlayPrivate::handlePress(QQuickItem *source, QEvent *event, QQuickPopup *target)
187 if (target->overlayEvent(source, event)) {
188 setMouseGrabberPopup(target);
194 switch (event->type()) {
196 if (mouseGrabberPopup)
198#if QT_CONFIG(quicktemplates2_multitouch)
200 case QEvent::TouchBegin:
201 case QEvent::TouchUpdate:
202 case QEvent::TouchEnd:
206 const auto popups = stackingOrderPopups();
207 for (QQuickPopup *popup : popups) {
208 if (popup->overlayEvent(source, event)) {
209 setMouseGrabberPopup(popup);
246bool QQuickOverlayPrivate::handleMouseEvent(QQuickItem *source, QMouseEvent *event, QQuickPopup *target)
248 switch (event->type()) {
249 case QEvent::MouseButtonPress:
250 if (!target && startDrag(event, event->scenePosition()))
252 return handlePress(source, event, target);
253 case QEvent::MouseMove:
254 return handleMove(source, event, target ? target : mouseGrabberPopup.data());
255 case QEvent::MouseButtonRelease:
256 return handleRelease(source, event, target ? target : mouseGrabberPopup.data());
354QQuickOverlay::QQuickOverlay(QQuickItem *parent)
355 : QQuickItem(*(
new QQuickOverlayPrivate), parent)
359 setAcceptedMouseButtons(Qt::AllButtons);
360#if QT_CONFIG(quicktemplates2_multitouch)
361 setAcceptTouchEvents(
true);
363 setFiltersChildMouseEvents(
true);
368 QQuickItemPrivate::get(parent)->addItemChangeListener(d, QQuickItemPrivate::Geometry);
369 if (QQuickWindow *window = parent->window()) {
370 window->installEventFilter(
this);
371 if (QQuickItem *contentItem = window->contentItem())
372 QQuickItemPrivate::get(contentItem)->addItemChangeListener(d, QQuickItemPrivate::Rotation);
421QQuickOverlay *QQuickOverlay::overlay(QQuickWindow *window, QQuickItem *parent)
426 const char *name =
"_q_QQuickOverlay";
428 if (QQuickItemPrivate::customOverlayRequested) {
430 if (QQuickItemPrivate::get(parent)->customOverlay) {
431 QQuickOverlay *overlay = parent->property(name).value<QQuickOverlay *>();
433 overlay =
new QQuickOverlay(parent);
434 parent->setProperty(name, QVariant::fromValue(overlay));
438 parent = parent->parentItem();
441 QQuickOverlay *overlay = window->property(name).value<QQuickOverlay *>();
443 QQuickItem *content = window->contentItem();
446 if (content && content->window()) {
447 overlay =
new QQuickOverlay(window->contentItem());
448 window->setProperty(name, QVariant::fromValue(overlay));
562bool QQuickOverlay::childMouseEventFilter(QQuickItem *item, QEvent *event)
565 const auto popups = d->stackingOrderPopups();
566 for (QQuickPopup *popup : popups) {
567 QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
571 if (item == p->popupItem || p->popupItem->isAncestorOf(item))
577 if (item == p->dimmer || !p->popupItem->isAncestorOf(item)) {
578 bool handled =
false;
579 switch (event->type()) {
580#if QT_CONFIG(quicktemplates2_multitouch)
581 case QEvent::TouchBegin:
582 case QEvent::TouchUpdate:
583 case QEvent::TouchEnd:
584 handled = d->handleTouchEvent(item,
static_cast<QTouchEvent *>(event), popup);
587 case QEvent::HoverEnter:
588 case QEvent::HoverMove:
589 case QEvent::HoverLeave:
593 if (
auto *control = qobject_cast<QQuickControl *>(item)) {
594 if (control->isHovered() && event->type() == QEvent::HoverLeave)
597 handled = d->handleHoverEvent(item,
static_cast<QHoverEvent *>(event), popup);
600 case QEvent::MouseButtonPress:
601 case QEvent::MouseMove:
602 case QEvent::MouseButtonRelease:
603 handled = d->handleMouseEvent(item,
static_cast<QMouseEvent *>(event), popup);
632bool QQuickOverlay::eventFilter(QObject *object, QEvent *event)
635 if (!isVisible() || object != d->window)
638#if QT_CONFIG(wheelevent) || QT_CONFIG(quick_draganddrop)
639 auto targetItemsForEvent = [&](QEvent *){
640#if QT_CONFIG(wheelevent)
641 if (event->type() == QEvent::Wheel) {
642 QWheelEvent *we =
static_cast<QWheelEvent *>(event);
643 return d->deliveryAgentPrivate()->pointerTargets(
644 d->window->contentItem(), we, we->point(0),
false,
false);
647#if QT_CONFIG(quick_draganddrop)
648 bool isDnDEvent =
false;
649 switch (event->type()) {
650 case QEvent::DragEnter:
651 case QEvent::DragMove:
659 QDropEvent *de =
static_cast<QDropEvent *>(event);
660 auto position = mapFromScene(de->position());
661 return d->deliveryAgentPrivate()->eventTargets(
662 d->window->contentItem(), de, -1, position, de->position(),
663 [](QQuickItem *item,
const QEvent *) -> std::optional<
bool> {
666 if (!item->flags().testFlag(QQuickItem::ItemAcceptsDrops))
673 Q_UNREACHABLE_RETURN(QList<QQuickItem *> {});
677 switch (event->type()) {
678#if QT_CONFIG(quicktemplates2_multitouch)
679 case QEvent::TouchBegin:
680 case QEvent::TouchUpdate:
681 case QEvent::TouchEnd:
682 if (
static_cast<QTouchEvent *>(event)->touchPointStates() & QEventPoint::Pressed)
684 if (
static_cast<QTouchEvent *>(event)->touchPointStates() & QEventPoint::Released)
688 if (!d->mouseGrabberPopup) {
689 QTouchEvent *touchEvent =
static_cast<QTouchEvent *>(event);
690 for (
const QTouchEvent::TouchPoint &point : touchEvent->points()) {
691 if (point.state() == QEventPoint::Released) {
692 QQuickDeliveryAgentPrivate::translateTouchEvent(touchEvent);
693 if (d->handleRelease(d->window->contentItem(), event,
nullptr))
700 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
701 d->deliveryAgentPrivate()->handleTouchEvent(
static_cast<QTouchEvent *>(event));
702 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent =
nullptr;
711 d->deliveryAgentPrivate()->clearGrabbers(
static_cast<QPointerEvent *>(event));
715 case QEvent::MouseButtonPress: {
716 auto *mouseEvent =
static_cast<QMouseEvent *>(event);
721 if (mouseEvent->button() == Qt::RightButton)
724#if QT_CONFIG(quicktemplates2_multitouch)
726 if (mouseEvent->source() == Qt::MouseEventNotSynthesized)
731 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
732 d->deliveryAgentPrivate()->handleMouseEvent(mouseEvent);
733 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent =
nullptr;
742 case QEvent::MouseButtonRelease: {
743 auto *mouseEvent =
static_cast<QMouseEvent *>(event);
744 if (mouseEvent->button() == Qt::RightButton)
747#if QT_CONFIG(quicktemplates2_multitouch)
749 if (mouseEvent->source() == Qt::MouseEventNotSynthesized)
754 if (!d->mouseGrabberPopup)
755 d->handleRelease(d->window->contentItem(), event,
nullptr);
758#if QT_CONFIG(quick_draganddrop)
759 case QEvent::DragEnter:
760 case QEvent::DragMove:
763 const QList<QQuickItem *> targetItems = targetItemsForEvent(event);
764 if (targetItems.isEmpty())
766 QQuickItem *
const dimmerItem = property(
"_q_dimmerItem").value<QQuickItem *>();
767 QQuickItem *
const topItem = targetItems.first();
768 QQuickItem *item = qobject_cast<QQuickPopupItem *>(topItem) ? topItem :
nullptr;
771 while ((item = item->parentItem())) {
772 if (qobject_cast<QQuickPopupItem *>(item))
776 if (!item && dimmerItem != topItem && isAncestorOf(topItem))
778 for (
const auto &popup : d->stackingOrderPopups()) {
779 const QQuickItem *popupItem = popup->popupItem();
782 if (popupItem == item)
784 if (popup->overlayEvent(topItem, event))
790#if QT_CONFIG(wheelevent)
792 return d->eatEventIfBlockedByModal(
static_cast<QWheelEvent *>(event));
794#if QT_CONFIG(tabletevent)
795 case QEvent::TabletMove:
796 case QEvent::TabletPress:
797 case QEvent::TabletRelease:
798 return d->eatEventIfBlockedByModal(
static_cast<QTabletEvent *>(event));
828 Q_Q(QQuickOverlayAttached);
829 if (window == newWindow)
832 if (QQuickOverlay *oldOverlay = QQuickOverlay::overlay(window, parent)) {
833 QObject::disconnect(oldOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
834 QObject::disconnect(oldOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
837 if (QQuickOverlay *newOverlay = QQuickOverlay::overlay(newWindow, parent)) {
838 QObject::connect(newOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
839 QObject::connect(newOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
845 emit q->overlayChanged();
872QQuickOverlayAttached::QQuickOverlayAttached(QObject *parent)
873 : QObject(*(
new QQuickOverlayAttachedPrivate), parent)
875 Q_D(QQuickOverlayAttached);
876 if (QQuickItem *item = qobject_cast<QQuickItem *>(parent)) {
877 d->setWindowAndParent(item->window(), item);
878 QObjectPrivate::connect(item, &QQuickItem::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
879 }
else if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(parent)) {
880 d->setWindowAndParent(popup->window(), popup->parentItem());
881 QObjectPrivate::connect(popup, &QQuickPopup::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
883 d->setWindow(qobject_cast<QQuickWindow *>(parent));