149bool QQuickOverlayPrivate::startDrag(QEvent *event,
const QPointF &pos)
152 if (allDrawers.isEmpty())
156 QQuickItem *item = q->childAt(pos.x(), pos.y());
158 const auto popups = stackingOrderPopups();
159 for (QQuickPopup *popup : popups) {
160 QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
161 if (p->dimmer == item && popup->isVisible() && popup->isModal())
166 const QList<QQuickPopup *> drawers = stackingOrderDrawers();
167 for (QQuickPopup *popup : drawers) {
168 QQuickDrawer *drawer = qobject_cast<QQuickDrawer *>(popup);
170 QQuickDrawerPrivate *p = QQuickDrawerPrivate::get(drawer);
171 if (p->startDrag(event)) {
172 setMouseGrabberPopup(drawer);
180bool QQuickOverlayPrivate::handlePress(QQuickItem *source, QEvent *event, QQuickPopup *target)
183 if (target->overlayEvent(source, event)) {
184 setMouseGrabberPopup(target);
190 switch (event->type()) {
192 if (mouseGrabberPopup)
194#if QT_CONFIG(quicktemplates2_multitouch)
196 case QEvent::TouchBegin:
197 case QEvent::TouchUpdate:
198 case QEvent::TouchEnd:
202 const auto popups = stackingOrderPopups();
203 for (QQuickPopup *popup : popups) {
204 if (popup->overlayEvent(source, event)) {
205 setMouseGrabberPopup(popup);
242bool QQuickOverlayPrivate::handleMouseEvent(QQuickItem *source, QMouseEvent *event, QQuickPopup *target)
244 switch (event->type()) {
245 case QEvent::MouseButtonPress:
246 if (!target && startDrag(event, event->scenePosition()))
248 return handlePress(source, event, target);
249 case QEvent::MouseMove:
250 return handleMove(source, event, target ? target : mouseGrabberPopup.data());
251 case QEvent::MouseButtonRelease:
252 return handleRelease(source, event, target ? target : mouseGrabberPopup.data());
350QQuickOverlay::QQuickOverlay(QQuickItem *parent)
351 : QQuickItem(*(
new QQuickOverlayPrivate), parent)
355 setAcceptedMouseButtons(Qt::AllButtons);
356#if QT_CONFIG(quicktemplates2_multitouch)
357 setAcceptTouchEvents(
true);
359 setFiltersChildMouseEvents(
true);
364 QQuickItemPrivate::get(parent)->addItemChangeListener(d, QQuickItemPrivate::Geometry);
365 if (QQuickWindow *window = parent->window()) {
366 window->installEventFilter(
this);
367 if (QQuickItem *contentItem = window->contentItem())
368 QQuickItemPrivate::get(contentItem)->addItemChangeListener(d, QQuickItemPrivate::Rotation);
417QQuickOverlay *QQuickOverlay::overlay(QQuickWindow *window, QQuickItem *parent)
422 const char *name =
"_q_QQuickOverlay";
424 if (QQuickItemPrivate::customOverlayRequested) {
426 if (QQuickItemPrivate::get(parent)->customOverlay) {
427 QQuickOverlay *overlay = parent->property(name).value<QQuickOverlay *>();
429 overlay =
new QQuickOverlay(parent);
430 parent->setProperty(name, QVariant::fromValue(overlay));
434 parent = parent->parentItem();
437 QQuickOverlay *overlay = window->property(name).value<QQuickOverlay *>();
439 QQuickItem *content = window->contentItem();
442 if (content && content->window()) {
443 overlay =
new QQuickOverlay(window->contentItem());
444 window->setProperty(name, QVariant::fromValue(overlay));
558bool QQuickOverlay::childMouseEventFilter(QQuickItem *item, QEvent *event)
561 const auto popups = d->stackingOrderPopups();
562 for (QQuickPopup *popup : popups) {
563 QQuickPopupPrivate *p = QQuickPopupPrivate::get(popup);
567 if (item == p->popupItem || p->popupItem->isAncestorOf(item))
573 if (item == p->dimmer || !p->popupItem->isAncestorOf(item)) {
574 bool handled =
false;
575 switch (event->type()) {
576#if QT_CONFIG(quicktemplates2_multitouch)
577 case QEvent::TouchBegin:
578 case QEvent::TouchUpdate:
579 case QEvent::TouchEnd:
580 handled = d->handleTouchEvent(item,
static_cast<QTouchEvent *>(event), popup);
583 case QEvent::HoverEnter:
584 case QEvent::HoverMove:
585 case QEvent::HoverLeave:
589 if (
auto *control = qobject_cast<QQuickControl *>(item)) {
590 if (control->isHovered() && event->type() == QEvent::HoverLeave)
593 handled = d->handleHoverEvent(item,
static_cast<QHoverEvent *>(event), popup);
596 case QEvent::MouseButtonPress:
597 case QEvent::MouseMove:
598 case QEvent::MouseButtonRelease:
599 handled = d->handleMouseEvent(item,
static_cast<QMouseEvent *>(event), popup);
628bool QQuickOverlay::eventFilter(QObject *object, QEvent *event)
631 if (!isVisible() || object != d->window)
634#if QT_CONFIG(wheelevent) || QT_CONFIG(quick_draganddrop)
635 auto targetItemsForEvent = [&](QEvent *){
636#if QT_CONFIG(wheelevent)
637 if (event->type() == QEvent::Wheel) {
638 QWheelEvent *we =
static_cast<QWheelEvent *>(event);
639 return d->deliveryAgentPrivate()->pointerTargets(
640 d->window->contentItem(), we, we->point(0),
false,
false);
643#if QT_CONFIG(quick_draganddrop)
644 bool isDnDEvent =
false;
645 switch (event->type()) {
646 case QEvent::DragEnter:
647 case QEvent::DragMove:
655 QDropEvent *de =
static_cast<QDropEvent *>(event);
656 auto position = mapFromScene(de->position());
657 return d->deliveryAgentPrivate()->eventTargets(
658 d->window->contentItem(), de, -1, position, de->position(),
659 [](QQuickItem *item,
const QEvent *) -> std::optional<
bool> {
662 if (!item->flags().testFlag(QQuickItem::ItemAcceptsDrops))
669 Q_UNREACHABLE_RETURN(QList<QQuickItem *> {});
673 switch (event->type()) {
674#if QT_CONFIG(quicktemplates2_multitouch)
675 case QEvent::TouchBegin:
676 case QEvent::TouchUpdate:
677 case QEvent::TouchEnd:
678 if (
static_cast<QTouchEvent *>(event)->touchPointStates() & QEventPoint::Pressed)
680 if (
static_cast<QTouchEvent *>(event)->touchPointStates() & QEventPoint::Released)
684 if (!d->mouseGrabberPopup) {
685 QTouchEvent *touchEvent =
static_cast<QTouchEvent *>(event);
686 for (
const QTouchEvent::TouchPoint &point : touchEvent->points()) {
687 if (point.state() == QEventPoint::Released) {
688 QQuickDeliveryAgentPrivate::translateTouchEvent(touchEvent);
689 if (d->handleRelease(d->window->contentItem(), event,
nullptr))
696 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
697 d->deliveryAgentPrivate()->handleTouchEvent(
static_cast<QTouchEvent *>(event));
698 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent =
nullptr;
707 d->deliveryAgentPrivate()->clearGrabbers(
static_cast<QPointerEvent *>(event));
711 case QEvent::MouseButtonPress: {
712 auto *mouseEvent =
static_cast<QMouseEvent *>(event);
717 if (mouseEvent->button() == Qt::RightButton)
720#if QT_CONFIG(quicktemplates2_multitouch)
722 if (mouseEvent->source() == Qt::MouseEventNotSynthesized)
727 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = d->deliveryAgent();
728 d->deliveryAgentPrivate()->handleMouseEvent(mouseEvent);
729 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent =
nullptr;
738 case QEvent::MouseButtonRelease: {
739 auto *mouseEvent =
static_cast<QMouseEvent *>(event);
740 if (mouseEvent->button() == Qt::RightButton)
743#if QT_CONFIG(quicktemplates2_multitouch)
745 if (mouseEvent->source() == Qt::MouseEventNotSynthesized)
750 if (!d->mouseGrabberPopup)
751 d->handleRelease(d->window->contentItem(), event,
nullptr);
754#if QT_CONFIG(quick_draganddrop)
755 case QEvent::DragEnter:
756 case QEvent::DragMove:
759 const QList<QQuickItem *> targetItems = targetItemsForEvent(event);
760 if (targetItems.isEmpty())
762 QQuickItem *
const dimmerItem = property(
"_q_dimmerItem").value<QQuickItem *>();
763 QQuickItem *
const topItem = targetItems.first();
764 QQuickItem *item = qobject_cast<QQuickPopupItem *>(topItem) ? topItem :
nullptr;
767 while ((item = item->parentItem())) {
768 if (qobject_cast<QQuickPopupItem *>(item))
772 if (!item && dimmerItem != topItem && isAncestorOf(topItem))
774 for (
const auto &popup : d->stackingOrderPopups()) {
775 const QQuickItem *popupItem = popup->popupItem();
778 if (popupItem == item)
780 if (popup->overlayEvent(topItem, event))
786#if QT_CONFIG(wheelevent)
788 return d->eatEventIfBlockedByModal(
static_cast<QWheelEvent *>(event));
790#if QT_CONFIG(tabletevent)
791 case QEvent::TabletMove:
792 case QEvent::TabletPress:
793 case QEvent::TabletRelease:
794 return d->eatEventIfBlockedByModal(
static_cast<QTabletEvent *>(event));
824 Q_Q(QQuickOverlayAttached);
825 if (window == newWindow)
828 if (QQuickOverlay *oldOverlay = QQuickOverlay::overlay(window, parent)) {
829 QObject::disconnect(oldOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
830 QObject::disconnect(oldOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
833 if (QQuickOverlay *newOverlay = QQuickOverlay::overlay(newWindow, parent)) {
834 QObject::connect(newOverlay, &QQuickOverlay::pressed, q, &QQuickOverlayAttached::pressed);
835 QObject::connect(newOverlay, &QQuickOverlay::released, q, &QQuickOverlayAttached::released);
841 emit q->overlayChanged();
868QQuickOverlayAttached::QQuickOverlayAttached(QObject *parent)
869 : QObject(*(
new QQuickOverlayAttachedPrivate), parent)
871 Q_D(QQuickOverlayAttached);
872 if (QQuickItem *item = qobject_cast<QQuickItem *>(parent)) {
873 d->setWindowAndParent(item->window(), item);
874 QObjectPrivate::connect(item, &QQuickItem::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
875 }
else if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(parent)) {
876 d->setWindowAndParent(popup->window(), popup->parentItem());
877 QObjectPrivate::connect(popup, &QQuickPopup::windowChanged, d, &QQuickOverlayAttachedPrivate::setWindow);
879 d->setWindow(qobject_cast<QQuickWindow *>(parent));