5#include <QtCore/qdebug.h>
6#include <QtGui/private/qevent_p.h>
7#include <QtGui/private/qeventpoint_p.h>
8#include <QtGui/private/qguiapplication_p.h>
9#include <QtGui/qpa/qplatformtheme.h>
10#include <QtQml/private/qabstractanimationjob_p.h>
11#include <QtQuick/private/qquickdeliveryagent_p_p.h>
12#include <QtQuick/private/qquickhoverhandler_p.h>
13#include <QtQuick/private/qquickpointerhandler_p_p.h>
14#if QT_CONFIG(quick_draganddrop)
15#include <QtQuick/private/qquickdrag_p.h>
17#include <QtQuick/private/qquickitem_p.h>
18#include <QtQuick/private/qquickprofiler_p.h>
19#include <QtQuick/private/qquickrendercontrol_p.h>
20#include <QtQuick/private/qquickwindow_p.h>
22#include <QtCore/qpointer.h>
29Q_STATIC_LOGGING_CATEGORY(lcTouchCmprs,
"qt.quick.touch.compression")
30Q_LOGGING_CATEGORY(lcTouchTarget,
"qt.quick.touch.target")
31Q_LOGGING_CATEGORY(lcMouse,
"qt.quick.mouse")
32Q_STATIC_LOGGING_CATEGORY(lcMouseTarget,
"qt.quick.mouse.target")
33Q_STATIC_LOGGING_CATEGORY(lcTablet,
"qt.quick.tablet")
34Q_LOGGING_CATEGORY(lcPtr,
"qt.quick.pointer")
35Q_STATIC_LOGGING_CATEGORY(lcPtrLoc,
"qt.quick.pointer.localization")
36Q_STATIC_LOGGING_CATEGORY(lcWheelTarget,
"qt.quick.wheel.target")
37Q_LOGGING_CATEGORY(lcHoverTrace,
"qt.quick.hover.trace")
38Q_LOGGING_CATEGORY(lcFocus,
"qt.quick.focus")
39Q_STATIC_LOGGING_CATEGORY(lcContextMenu,
"qt.quick.contextmenu")
41extern Q_GUI_EXPORT
bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp,
int k, Qt::KeyboardModifiers mods,
const QString &text = QString(),
bool autorep =
false, ushort count = 1);
43bool QQuickDeliveryAgentPrivate::subsceneAgentsExist(
false);
44QQuickDeliveryAgent *QQuickDeliveryAgentPrivate::currentEventDeliveryAgent(
nullptr);
48 static int allowRightClick = -1;
49 if (allowRightClick < 0) {
51 allowRightClick = qEnvironmentVariableIntValue(
"QT_QUICK_ALLOW_SYNTHETIC_RIGHT_CLICK", &ok);
55 return allowRightClick != 0;
58void QQuickDeliveryAgentPrivate::touchToMouseEvent(QEvent::Type type,
const QEventPoint &p,
const QTouchEvent *touchEvent, QMutableSinglePointEvent *mouseEvent)
60 Q_ASSERT(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents));
61 QMutableSinglePointEvent ret(type, touchEvent->pointingDevice(), p,
62 (type == QEvent::MouseMove ? Qt::NoButton : Qt::LeftButton),
63 (type == QEvent::MouseButtonRelease ? Qt::NoButton : Qt::LeftButton),
64 touchEvent->modifiers(), Qt::MouseEventSynthesizedByQt);
65 ret.setAccepted(
true);
66 ret.setTimestamp(touchEvent->timestamp());
70 Q_ASSERT(mouseEvent->device() == touchEvent->device());
71 if (Q_UNLIKELY(mouseEvent->device()->type() == QInputDevice::DeviceType::Mouse))
72 qWarning() <<
"Unexpected: synthesized an indistinguishable mouse event" << mouseEvent;
76
77
78bool QQuickDeliveryAgentPrivate::isWithinDoubleClickInterval(ulong timeInterval)
80 return timeInterval <
static_cast<ulong>(QGuiApplication::styleHints()->mouseDoubleClickInterval());
84
85
86bool QQuickDeliveryAgentPrivate::isWithinDoubleTapDistance(
const QPoint &distanceBetweenPresses)
88 auto square = [](qint64 v) {
return v * v; };
89 return square(distanceBetweenPresses.x()) + square(distanceBetweenPresses.y()) <
90 square(QGuiApplication::styleHints()->touchDoubleTapDistance());
93bool QQuickDeliveryAgentPrivate::checkIfDoubleTapped(ulong newPressEventTimestamp,
const QPoint &newPressPos)
95 const bool doubleClicked = isDeliveringTouchAsMouse() &&
96 isWithinDoubleTapDistance(newPressPos - touchMousePressPos) &&
97 isWithinDoubleClickInterval(newPressEventTimestamp - touchMousePressTimestamp);
99 touchMousePressTimestamp = 0;
101 touchMousePressTimestamp = newPressEventTimestamp;
102 touchMousePressPos = newPressPos;
104 return doubleClicked;
107void QQuickDeliveryAgentPrivate::resetIfDoubleTapPrevented(
const QEventPoint &pressedPoint)
109 if (touchMousePressTimestamp > 0 &&
110 (!isWithinDoubleTapDistance(pressedPoint.globalPosition().toPoint() - touchMousePressPos) ||
111 !isWithinDoubleClickInterval(pressedPoint.timestamp() - touchMousePressTimestamp))) {
112 touchMousePressTimestamp = 0;
113 touchMousePressPos = QPoint();
118
119
120
121
122
123
124
125QPointerEvent *QQuickDeliveryAgentPrivate::eventInDelivery()
const
127 if (eventsInDelivery.isEmpty())
129 return eventsInDelivery.top();
133
134
135
136
137QPointingDevicePrivate::EventPointData *QQuickDeliveryAgentPrivate::mousePointData()
139 if (eventsInDelivery.isEmpty())
141 auto devPriv = QPointingDevicePrivate::get(
const_cast<QPointingDevice*>(eventsInDelivery.top()->pointingDevice()));
142 return devPriv->pointById(isDeliveringTouchAsMouse() ? touchMouseId : 0);
145void QQuickDeliveryAgentPrivate::cancelTouchMouseSynthesis()
147 qCDebug(lcTouchTarget) <<
"id" << touchMouseId <<
"on" << touchMouseDevice;
149 touchMouseDevice =
nullptr;
152bool QQuickDeliveryAgentPrivate::deliverTouchAsMouse(QQuickItem *item, QTouchEvent *pointerEvent)
154 Q_Q(QQuickDeliveryAgent);
155 Q_ASSERT(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents));
156 auto device = pointerEvent->pointingDevice();
159 if (device->type() == QInputDevice::DeviceType::TouchPad && device->capabilities().testFlag(QInputDevice::Capability::MouseEmulation)) {
160 qCDebug(lcTouchTarget) << q <<
"skipping delivery of synth-mouse event from" << device;
165 QMutableTouchEvent event;
166 QQuickItemPrivate::get(item)->localizedTouchEvent(pointerEvent,
false, &event);
167 if (!event.points().size())
173 for (
auto &p : event.points()) {
175 if (touchMouseId == -1 && p.state() & QEventPoint::State::Pressed) {
176 QPointF pos = item->mapFromScene(p.scenePosition());
179 if (!item->contains(pos))
182 qCDebug(lcTouchTarget) << q << device <<
"TP (mouse)" << Qt::hex << p.id() <<
"->" << item;
183 QMutableSinglePointEvent mousePress;
184 touchToMouseEvent(QEvent::MouseButtonPress, p, &event, &mousePress);
187 QCoreApplication::sendEvent(item, &mousePress);
188 event.setAccepted(mousePress.isAccepted());
189 if (mousePress.isAccepted()) {
190 touchMouseDevice = device;
191 touchMouseId = p.id();
192 const auto &pt = mousePress.point(0);
193 if (!mousePress.exclusiveGrabber(pt))
194 mousePress.setExclusiveGrabber(pt, item);
196 if (checkIfDoubleTapped(event.timestamp(), p.globalPosition().toPoint())) {
199 QMutableSinglePointEvent mouseDoubleClick;
200 touchToMouseEvent(QEvent::MouseButtonDblClick, p, &event, &mouseDoubleClick);
201 QCoreApplication::sendEvent(item, &mouseDoubleClick);
202 event.setAccepted(mouseDoubleClick.isAccepted());
203 if (!mouseDoubleClick.isAccepted())
204 cancelTouchMouseSynthesis();
212 }
else if (touchMouseDevice == device && p.id() == touchMouseId) {
213 if (p.state() & QEventPoint::State::Updated) {
214 if (touchMousePressTimestamp != 0) {
215 if (!isWithinDoubleTapDistance(p.globalPosition().toPoint() - touchMousePressPos))
216 touchMousePressTimestamp = 0;
218 if (QQuickItem *mouseGrabberItem = qmlobject_cast<QQuickItem *>(pointerEvent->exclusiveGrabber(p))) {
219 QMutableSinglePointEvent me;
220 touchToMouseEvent(QEvent::MouseMove, p, &event, &me);
221 QCoreApplication::sendEvent(item, &me);
222 event.setAccepted(me.isAccepted());
224 qCDebug(lcTouchTarget) << q << device <<
"TP (mouse)" << Qt::hex << p.id() <<
"->" << mouseGrabberItem;
225 return event.isAccepted();
230 QMutableSinglePointEvent me;
231 touchToMouseEvent(QEvent::MouseMove, p, &event, &me);
232 if (lastMousePosition.isNull())
233 lastMousePosition = me.scenePosition();
234 QPointF last = lastMousePosition;
235 lastMousePosition = me.scenePosition();
237 deliverHoverEvent(me.scenePosition(), last, me.modifiers(), me.timestamp());
240 }
else if (p.state() & QEventPoint::State::Released) {
242 if (QQuickItem *mouseGrabberItem = qmlobject_cast<QQuickItem *>(pointerEvent->exclusiveGrabber(p))) {
243 QMutableSinglePointEvent me;
244 touchToMouseEvent(QEvent::MouseButtonRelease, p, &event, &me);
245 QCoreApplication::sendEvent(item, &me);
247 if (item->acceptHoverEvents() && p.globalPosition() != QGuiApplicationPrivate::lastCursorPosition) {
248 QPointF localMousePos(qInf(), qInf());
249 if (QWindow *w = item->window())
250 localMousePos = item->mapFromScene(w->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition));
251 QMouseEvent mm(QEvent::MouseMove, localMousePos, QGuiApplicationPrivate::lastCursorPosition,
252 Qt::NoButton, Qt::NoButton, event.modifiers());
253 QCoreApplication::sendEvent(item, &mm);
255 if (pointerEvent->exclusiveGrabber(p) == mouseGrabberItem)
256 pointerEvent->setExclusiveGrabber(p,
nullptr);
258 cancelTouchMouseSynthesis();
259 return me.isAccepted();
269
270
271
272
273
274
275
276
277void QQuickDeliveryAgentPrivate::removeGrabber(QQuickItem *grabber,
bool mouse,
bool touch,
bool cancel)
279 Q_Q(QQuickDeliveryAgent);
280 if (eventsInDelivery.isEmpty()) {
282 for (
auto dev : knownPointingDevices) {
283 auto devPriv = QPointingDevicePrivate::get(
const_cast<QPointingDevice *>(dev));
284 devPriv->removeGrabber(grabber, cancel);
288 auto eventInDelivery = eventsInDelivery.top();
289 if (Q_LIKELY(mouse) && eventInDelivery) {
290 auto epd = mousePointData();
291 if (epd && epd->exclusiveGrabber == grabber && epd->exclusiveGrabberContext.data() == q) {
292 QQuickItem *oldGrabber = qobject_cast<QQuickItem *>(epd->exclusiveGrabber);
293 qCDebug(lcMouseTarget) <<
"removeGrabber" << oldGrabber <<
"-> null";
294 eventInDelivery->setExclusiveGrabber(epd->eventPoint,
nullptr);
297 if (Q_LIKELY(touch)) {
299 const auto touchDevices = QPointingDevice::devices();
300 for (
auto device : touchDevices) {
301 if (device->type() != QInputDevice::DeviceType::TouchScreen)
303 if (QPointingDevicePrivate::get(
const_cast<QPointingDevice *>(
static_cast<
const QPointingDevice *>(device)))->
304 removeExclusiveGrabber(eventInDelivery, grabber))
308 grabber->touchUngrabEvent();
313
314
315
316
317
318
319
320
321
322
323
324void QQuickDeliveryAgentPrivate::clearGrabbers(QPointerEvent *pointerEvent)
326 if (pointerEvent->isEndEvent()
327 && !(isTabletEvent(pointerEvent)
328 && (qApp->testAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents)
329 || QWindowSystemInterfacePrivate::TabletEvent::platformSynthesizesMouse))) {
330 if (pointerEvent->isSinglePointEvent()) {
331 if (
static_cast<QSinglePointEvent *>(pointerEvent)->buttons() == Qt::NoButton) {
332 auto &firstPt = pointerEvent->point(0);
333 pointerEvent->setExclusiveGrabber(firstPt,
nullptr);
334 pointerEvent->clearPassiveGrabbers(firstPt);
337 for (
auto &point : pointerEvent->points()) {
338 if (point.state() == QEventPoint::State::Released) {
339 pointerEvent->setExclusiveGrabber(point,
nullptr);
340 pointerEvent->clearPassiveGrabbers(point);
348
349
350
351
352void QQuickDeliveryAgentPrivate::translateTouchEvent(QTouchEvent *touchEvent)
354 for (qsizetype i = 0; i != touchEvent->pointCount(); ++i) {
355 auto &pt = touchEvent->point(i);
356 QMutableEventPoint::setScenePosition(pt, pt.position());
363 const QWindow *focusWindow = QGuiApplication::focusWindow();
364 return win == focusWindow || QQuickRenderControlPrivate::isRenderWindowFor(win, focusWindow) || !focusWindow;
369 QQuickItem *parentItem = item->parentItem();
371 if (parentItem && parentItem->flags() & QQuickItem::ItemIsFocusScope)
372 return findFurthestFocusScopeAncestor(parentItem);
379static inline bool singleWindowOnScreen(QQuickWindow *win)
381 const QWindowList windowList = QGuiApplication::allWindows();
382 for (
int i = 0; i < windowList.count(); i++) {
383 QWindow *ii = windowList.at(i);
386 if (ii->screen() == win->screen())
395
396
397
398
399void QQuickDeliveryAgentPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item,
400 Qt::FocusReason reason, FocusOptions options)
402 Q_Q(QQuickDeliveryAgent);
404 Q_ASSERT(scope || item == rootItem);
406 qCDebug(lcFocus) << q <<
"focus" << item <<
"in scope" << scope;
408 qCDebug(lcFocus) <<
" scopeSubFocusItem:" << QQuickItemPrivate::get(scope)->subFocusItem;
410 QQuickItemPrivate *scopePrivate = scope ? QQuickItemPrivate::get(scope) :
nullptr;
411 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
413 QQuickItem *oldActiveFocusItem =
nullptr;
414 QQuickItem *currentActiveFocusItem = activeFocusItem;
415 QQuickItem *newActiveFocusItem =
nullptr;
416 bool sendFocusIn =
false;
418 lastFocusReason = reason;
420 QVarLengthArray<QQuickItem *, 20> changed;
423 if (item == rootItem || scopePrivate->activeFocus) {
424 oldActiveFocusItem = activeFocusItem;
425 if (item->isEnabled()) {
426 newActiveFocusItem = item;
427 while (newActiveFocusItem->isFocusScope()
428 && newActiveFocusItem->scopedFocusItem()
429 && newActiveFocusItem->scopedFocusItem()->isEnabled()) {
430 newActiveFocusItem = newActiveFocusItem->scopedFocusItem();
433 newActiveFocusItem = scope;
436 if (oldActiveFocusItem) {
438 QGuiApplication::inputMethod()->commit();
441 activeFocusItem =
nullptr;
443 QQuickItem *afi = oldActiveFocusItem;
444 while (afi && afi != scope) {
445 if (QQuickItemPrivate::get(afi)->activeFocus) {
446 QQuickItemPrivate::get(afi)->activeFocus =
false;
449 afi = afi->parentItem();
454 if (item != rootItem && !(options & DontChangeSubFocusItem)) {
455 QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem;
456 if (oldSubFocusItem) {
457 QQuickItemPrivate *priv = QQuickItemPrivate::get(oldSubFocusItem);
459 priv->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, oldSubFocusItem, reason);
460 changed << oldSubFocusItem;
463 QQuickItemPrivate::get(item)->updateSubFocusItem(scope,
true);
466 if (!(options & DontChangeFocusProperty)) {
467 if (item != rootItem || windowHasFocus(rootItem->window())
471 || singleWindowOnScreen(rootItem->window())
474 itemPrivate->focus =
true;
475 itemPrivate->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, item, reason);
480 if (newActiveFocusItem && (rootItem->hasFocus() || (rootItem->window()->type() == Qt::Popup))) {
481 activeFocusItem = newActiveFocusItem;
483 QQuickItemPrivate::get(newActiveFocusItem)->activeFocus =
true;
484 changed << newActiveFocusItem;
486 QQuickItem *afi = newActiveFocusItem->parentItem();
487 while (afi && afi != scope) {
488 if (afi->isFocusScope()) {
489 QQuickItemPrivate::get(afi)->activeFocus =
true;
492 afi = afi->parentItem();
494 updateFocusItemTransform();
500 if (oldActiveFocusItem) {
501 QFocusEvent event(QEvent::FocusOut, reason);
502 QCoreApplication::sendEvent(oldActiveFocusItem, &event);
506 if (sendFocusIn && activeFocusItem == newActiveFocusItem) {
507 QFocusEvent event(QEvent::FocusIn, reason);
508 QCoreApplication::sendEvent(newActiveFocusItem, &event);
511 if (activeFocusItem != currentActiveFocusItem)
512 emit rootItem->window()->focusObjectChanged(activeFocusItem);
514 if (!changed.isEmpty())
515 notifyFocusChangesRecur(changed.data(), changed.size() - 1, reason);
516 if (isSubsceneAgent) {
517 auto da = QQuickWindowPrivate::get(rootItem->window())->deliveryAgent;
518 qCDebug(lcFocus) <<
" delegating setFocusInScope to" << da;
526 QQuickItem *ancestorFS = findFurthestFocusScopeAncestor(item);
527 if (ancestorFS != item)
528 options |= QQuickDeliveryAgentPrivate::DontChangeSubFocusItem;
529 QQuickWindowPrivate::get(rootItem->window())->deliveryAgentPrivate()->setFocusInScope(da->rootItem(), item, reason, options);
531 if (oldActiveFocusItem == activeFocusItem)
532 qCDebug(lcFocus) <<
" activeFocusItem remains" << activeFocusItem <<
"in" << q;
534 qCDebug(lcFocus) <<
" activeFocusItem" << oldActiveFocusItem <<
"->" << activeFocusItem <<
"in" << q;
537void QQuickDeliveryAgentPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions options)
540 Q_ASSERT(scope || item == rootItem);
541 Q_Q(QQuickDeliveryAgent);
542 qCDebug(lcFocus) << q <<
"clear focus" << item <<
"in scope" << scope;
544 QQuickItemPrivate *scopePrivate =
nullptr;
546 scopePrivate = QQuickItemPrivate::get(scope);
547 if ( !scopePrivate->subFocusItem )
551 QQuickItem *currentActiveFocusItem = activeFocusItem;
552 QQuickItem *oldActiveFocusItem =
nullptr;
553 QQuickItem *newActiveFocusItem =
nullptr;
555 lastFocusReason = reason;
557 QVarLengthArray<QQuickItem *, 20> changed;
559 Q_ASSERT(item == rootItem || item == scopePrivate->subFocusItem);
562 if (item == rootItem || scopePrivate->activeFocus) {
563 oldActiveFocusItem = activeFocusItem;
564 newActiveFocusItem = scope;
567 QGuiApplication::inputMethod()->commit();
570 activeFocusItem =
nullptr;
572 if (oldActiveFocusItem) {
573 QQuickItem *afi = oldActiveFocusItem;
574 while (afi && afi != scope) {
575 if (QQuickItemPrivate::get(afi)->activeFocus) {
576 QQuickItemPrivate::get(afi)->activeFocus =
false;
579 afi = afi->parentItem();
584 if (item != rootItem && !(options & DontChangeSubFocusItem)) {
585 QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem;
586 if (oldSubFocusItem && !(options & DontChangeFocusProperty)) {
587 QQuickItemPrivate *priv = QQuickItemPrivate::get(oldSubFocusItem);
589 priv->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, oldSubFocusItem, reason);
590 changed << oldSubFocusItem;
593 QQuickItemPrivate::get(item)->updateSubFocusItem(scope,
false);
595 }
else if (!(options & DontChangeFocusProperty)) {
596 QQuickItemPrivate *priv = QQuickItemPrivate::get(item);
598 priv->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, item, reason);
602 if (newActiveFocusItem) {
603 Q_ASSERT(newActiveFocusItem == scope);
604 activeFocusItem = scope;
605 updateFocusItemTransform();
610 if (oldActiveFocusItem) {
611 QFocusEvent event(QEvent::FocusOut, reason);
612 QCoreApplication::sendEvent(oldActiveFocusItem, &event);
616 if (newActiveFocusItem && activeFocusItem == newActiveFocusItem) {
617 QFocusEvent event(QEvent::FocusIn, reason);
618 QCoreApplication::sendEvent(newActiveFocusItem, &event);
621 QQuickWindow *rootItemWindow = rootItem->window();
622 if (activeFocusItem != currentActiveFocusItem && rootItemWindow)
623 emit rootItemWindow->focusObjectChanged(activeFocusItem);
625 if (!changed.isEmpty())
626 notifyFocusChangesRecur(changed.data(), changed.size() - 1, reason);
627 if (isSubsceneAgent && rootItemWindow) {
628 auto da = QQuickWindowPrivate::get(rootItemWindow)->deliveryAgent;
629 qCDebug(lcFocus) <<
" delegating clearFocusInScope to" << da;
630 QQuickWindowPrivate::get(rootItemWindow)->deliveryAgentPrivate()->clearFocusInScope(da->rootItem(), item, reason, options);
632 if (oldActiveFocusItem == activeFocusItem)
633 qCDebug(lcFocus) <<
"activeFocusItem remains" << activeFocusItem <<
"in" << q;
635 qCDebug(lcFocus) <<
" activeFocusItem" << oldActiveFocusItem <<
"->" << activeFocusItem <<
"in" << q;
638void QQuickDeliveryAgentPrivate::clearFocusObject()
640 if (activeFocusItem == rootItem)
643 clearFocusInScope(rootItem, QQuickItemPrivate::get(rootItem)->subFocusItem, Qt::OtherFocusReason);
646void QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(QQuickItem **items,
int remaining, Qt::FocusReason reason)
648 QPointer<QQuickItem> item(*items);
651 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
653 if (itemPrivate->notifiedFocus != itemPrivate->focus) {
654 itemPrivate->notifiedFocus = itemPrivate->focus;
655 itemPrivate->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, item, reason);
656 emit item->focusChanged(itemPrivate->focus);
659 if (item && itemPrivate->notifiedActiveFocus != itemPrivate->activeFocus) {
660 itemPrivate->notifiedActiveFocus = itemPrivate->activeFocus;
661 itemPrivate->itemChange(QQuickItem::ItemActiveFocusHasChanged,
bool(itemPrivate->activeFocus));
662 itemPrivate->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, item, reason);
663 emit item->activeFocusChanged(itemPrivate->activeFocus);
668 notifyFocusChangesRecur(items + 1, remaining - 1, reason);
671bool QQuickDeliveryAgentPrivate::clearHover(ulong timestamp)
673 if (hoverItems.isEmpty())
676 QQuickWindow *window = rootItem->window();
680 const QPointF lastPos = window->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition);
681 const auto modifiers = QGuiApplication::keyboardModifiers();
689 for (
auto it = hoverItems.cbegin(); it != hoverItems.cend(); ++it) {
690 if (
const auto &item = it.key()) {
691 deliverHoverEventToItem(item, lastPos, lastPos, modifiers, timestamp, HoverChange::Clear);
692 Q_ASSERT(([
this, item]{
693 const auto &it2 = std::as_const(hoverItems).find(item);
694 return it2 == hoverItems.cend() || it2.value() == 0;
702void QQuickDeliveryAgentPrivate::updateFocusItemTransform()
705 if (activeFocusItem && QGuiApplication::focusObject() == activeFocusItem) {
706 QQuickItemPrivate *focusPrivate = QQuickItemPrivate::get(activeFocusItem);
707 QGuiApplication::inputMethod()->setInputItemTransform(focusPrivate->itemToWindowTransform());
708 QGuiApplication::inputMethod()->setInputItemRectangle(QRectF(0, 0, focusPrivate->width, focusPrivate->height));
709 activeFocusItem->updateInputMethod(Qt::ImInputItemClipRectangle);
715
716
717
718QQuickItem *QQuickDeliveryAgentPrivate::focusTargetItem()
const
721 return activeFocusItem;
724 QQuickItem *targetItem = rootItem;
726 while (targetItem->isFocusScope()
727 && targetItem->scopedFocusItem()
728 && targetItem->scopedFocusItem()->isEnabled()) {
729 targetItem = targetItem->scopedFocusItem();
736
737
738
739
740
741QQuickDeliveryAgent *QQuickDeliveryAgentPrivate::currentOrItemDeliveryAgent(
const QQuickItem *item)
743 if (currentEventDeliveryAgent)
744 return currentEventDeliveryAgent;
746 return QQuickItemPrivate::get(
const_cast<QQuickItem *>(item))->deliveryAgent();
751
752
753
754
755QQuickDeliveryAgent::QQuickDeliveryAgent(QQuickItem *rootItem)
756 : QObject(*
new QQuickDeliveryAgentPrivate(rootItem), rootItem)
760QQuickDeliveryAgent::~QQuickDeliveryAgent()
764QQuickDeliveryAgent::Transform::~Transform()
769
770
771
772QQuickItem *QQuickDeliveryAgent::rootItem()
const
774 Q_D(
const QQuickDeliveryAgent);
779
780
781
782
783QQuickDeliveryAgent::Transform *QQuickDeliveryAgent::sceneTransform()
const
785 Q_D(
const QQuickDeliveryAgent);
786 return d->sceneTransform;
790
791
792
793
794void QQuickDeliveryAgent::setSceneTransform(QQuickDeliveryAgent::Transform *transform)
796 Q_D(QQuickDeliveryAgent);
797 if (d->sceneTransform == transform)
799 qCDebug(lcPtr) <<
this << d->sceneTransform <<
"->" << transform;
800 if (d->sceneTransform)
801 delete d->sceneTransform;
802 d->sceneTransform = transform;
806
807
808
809
810
811
812bool QQuickDeliveryAgent::event(QEvent *ev)
814 Q_D(QQuickDeliveryAgent);
815 d->currentEventDeliveryAgent =
this;
816 auto cleanup = qScopeGuard([d] { d->currentEventDeliveryAgent =
nullptr; });
818 switch (ev->type()) {
819 case QEvent::MouseButtonPress:
820 case QEvent::MouseButtonRelease:
821 case QEvent::MouseButtonDblClick:
822 case QEvent::MouseMove: {
823 QMouseEvent *me =
static_cast<QMouseEvent*>(ev);
824 d->handleMouseEvent(me);
827 case QEvent::HoverEnter:
828 case QEvent::HoverLeave:
829 case QEvent::HoverMove: {
830 QHoverEvent *he =
static_cast<QHoverEvent*>(ev);
831 bool accepted = d->deliverHoverEvent(he->scenePosition(),
832 he->points().first().sceneLastPosition(),
833 he->modifiers(), he->timestamp());
834 d->lastMousePosition = he->scenePosition();
835 he->setAccepted(accepted);
837 QQuickWindowPrivate::get(d->rootItem->window())->updateCursor(d->sceneTransform ?
838 d->sceneTransform->map(he->scenePosition()) : he->scenePosition(), d->rootItem);
842 case QEvent::TouchBegin:
843 case QEvent::TouchUpdate:
844 case QEvent::TouchEnd: {
845 QTouchEvent *touch =
static_cast<QTouchEvent*>(ev);
846 d->handleTouchEvent(touch);
847 if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents))) {
854 case QEvent::TouchCancel:
856 return d->deliverTouchCancelEvent(
static_cast<QTouchEvent*>(ev));
858 case QEvent::Enter: {
861 QEnterEvent *enter =
static_cast<QEnterEvent*>(ev);
862 const auto scenePos = enter->scenePosition();
863 qCDebug(lcHoverTrace) <<
this <<
"sending hover event due to QEnterEvent" << enter;
864 bool accepted = d->deliverHoverEvent(scenePos,
865 enter->points().first().sceneLastPosition(),
866 enter->modifiers(), enter->timestamp());
867 d->lastMousePosition = scenePos;
869 Q_ASSERT(enter->scenePosition() == scenePos);
870 enter->setAccepted(accepted);
872 QQuickWindowPrivate::get(d->rootItem->window())->updateCursor(enter->scenePosition(), d->rootItem);
878 d->lastMousePosition = QPointF();
880#if QT_CONFIG(quick_draganddrop)
881 case QEvent::DragEnter:
882 case QEvent::DragLeave:
883 case QEvent::DragMove:
885 d->deliverDragEvent(d->dragGrabber, ev);
888 case QEvent::FocusAboutToChange:
890 if (d->activeFocusItem)
891 qGuiApp->inputMethod()->commit();
894#if QT_CONFIG(gestures)
895 case QEvent::NativeGesture:
896 d->deliverSinglePointEventUntilAccepted(
static_cast<QPointerEvent *>(ev));
899 case QEvent::ShortcutOverride:
900 d->deliverKeyEvent(
static_cast<QKeyEvent *>(ev));
902 case QEvent::InputMethod:
903 case QEvent::InputMethodQuery:
905 QQuickItem *target = d->focusTargetItem();
907 QCoreApplication::sendEvent(target, ev);
910#if QT_CONFIG(wheelevent)
911 case QEvent::Wheel: {
912 auto event =
static_cast<QWheelEvent *>(ev);
913 qCDebug(lcMouse) << event;
916 if (d->lastWheelEventAccepted && event->angleDelta().isNull() && event->phase() == Qt::ScrollUpdate)
920 Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseWheel,
921 event->angleDelta().x(), event->angleDelta().y());
922 d->deliverSinglePointEventUntilAccepted(event);
923 d->lastWheelEventAccepted = event->isAccepted();
927#if QT_CONFIG(tabletevent)
928 case QEvent::TabletPress:
929 case QEvent::TabletMove:
930 case QEvent::TabletRelease:
932 auto *tabletEvent =
static_cast<QTabletEvent *>(ev);
933 d->deliverPointerEvent(tabletEvent);
935 QQuickWindowPrivate::get(d->rootItem->window())->updateCursor(tabletEvent->scenePosition(), d->rootItem);
940#ifndef QT_NO_CONTEXTMENU
941 case QEvent::ContextMenu:
942 d->deliverContextMenuEvent(
static_cast<QContextMenuEvent *>(ev));
952void QQuickDeliveryAgentPrivate::deliverKeyEvent(QKeyEvent *e)
954 if (activeFocusItem) {
955 const bool keyPress = (e->type() == QEvent::KeyPress);
957 case QEvent::KeyPress:
958 Q_QUICK_INPUT_PROFILE(QQuickProfiler::Key, QQuickProfiler::InputKeyPress, e->key(), e->modifiers());
960 case QEvent::KeyRelease:
961 Q_QUICK_INPUT_PROFILE(QQuickProfiler::Key, QQuickProfiler::InputKeyRelease, e->key(), e->modifiers());
967 QQuickItem *item = activeFocusItem;
970 if (keyPress && e->spontaneous() ==
false)
971 qt_sendShortcutOverrideEvent(item, e->timestamp(),
972 e->key(), e->modifiers(), e->text(),
973 e->isAutoRepeat(), e->count());
976 Q_ASSERT(e->type() != QEvent::ShortcutOverride || !e->isAccepted());
977 if (e->type() != QEvent::ShortcutOverride)
979 QCoreApplication::sendEvent(item, e);
980 }
while (!e->isAccepted() && (item = item->parentItem()));
984QQuickDeliveryAgentPrivate::QQuickDeliveryAgentPrivate(QQuickItem *root) :
988 isSubsceneAgent(!qmlobject_cast<QQuickRootItem *>(rootItem))
990#if QT_CONFIG(quick_draganddrop)
991 dragGrabber =
new QQuickDragGrabber;
994 subsceneAgentsExist =
true;
997QQuickDeliveryAgentPrivate::~QQuickDeliveryAgentPrivate()
999#if QT_CONFIG(quick_draganddrop)
1001 dragGrabber =
nullptr;
1003 delete sceneTransform;
1007
1008
1009
1010
1011
1012
1013QPointerEvent *QQuickDeliveryAgentPrivate::clonePointerEvent(QPointerEvent *event, std::optional<QPointF> transformedLocalPos)
1015 QPointerEvent *ret = event->clone();
1016 QEventPoint &point = ret->point(0);
1017 QMutableEventPoint::detach(point);
1018 QMutableEventPoint::setTimestamp(point, event->timestamp());
1019 if (transformedLocalPos)
1020 QMutableEventPoint::setPosition(point, *transformedLocalPos);
1025void QQuickDeliveryAgentPrivate::deliverToPassiveGrabbers(
const QVector<QPointer <QObject> > &passiveGrabbers,
1026 QPointerEvent *pointerEvent)
1028 const QVector<QObject *> &eventDeliveryTargets =
1029 QQuickPointerHandlerPrivate::deviceDeliveryTargets(pointerEvent->device());
1030 QVarLengthArray<std::pair<QQuickItem *,
bool>, 4> sendFilteredPointerEventResult;
1031 hasFiltered.clear();
1032 for (QObject *grabberObject : passiveGrabbers) {
1034 if (Q_UNLIKELY(!grabberObject))
1037 if (QQuickPointerHandler *handler = qobject_cast<QQuickPointerHandler *>(grabberObject)) {
1038 if (handler && !eventDeliveryTargets.contains(handler)) {
1039 bool alreadyFiltered =
false;
1040 QQuickItem *par = handler->parentItem();
1043 auto it = std::find_if(sendFilteredPointerEventResult.begin(), sendFilteredPointerEventResult.end(),
1044 [par](
const std::pair<QQuickItem *,
bool> &pair) {
return pair.first == par; });
1045 if (it != sendFilteredPointerEventResult.end()) {
1048 alreadyFiltered = it->second;
1050 alreadyFiltered = sendFilteredPointerEvent(pointerEvent, par);
1051 sendFilteredPointerEventResult << std::make_pair(par, alreadyFiltered);
1053 if (!alreadyFiltered) {
1055 localizePointerEvent(pointerEvent, par);
1056 handler->handlePointerEvent(pointerEvent);
1059 }
else if (QQuickItem *grabberItem =
static_cast<QQuickItem *>(grabberObject)) {
1061 if (QQuickItem *excGrabber =
static_cast<QQuickItem *>(pointerEvent->exclusiveGrabber(pointerEvent->point(0)))) {
1062 if ((isMouseEvent(pointerEvent) && excGrabber->keepMouseGrab())
1063 || (isTouchEvent(pointerEvent) && excGrabber->keepTouchGrab())) {
1067 localizePointerEvent(pointerEvent, grabberItem);
1068 QCoreApplication::sendEvent(grabberItem, pointerEvent);
1069 pointerEvent->accept();
1074bool QQuickDeliveryAgentPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
1075 const QPointF &scenePos,
const QPointF &lastScenePos,
1076 Qt::KeyboardModifiers modifiers, ulong timestamp)
1078 auto itemPrivate = QQuickItemPrivate::get(item);
1079 const auto transform = itemPrivate->windowToItemTransform();
1081 const auto localPos = transform.map(scenePos);
1082 const auto globalPos = item->mapToGlobal(localPos);
1083 const auto lastLocalPos = transform.map(lastScenePos);
1084 const auto lastGlobalPos = item->mapToGlobal(lastLocalPos);
1085 QHoverEvent hoverEvent(type, scenePos, globalPos, lastLocalPos, modifiers);
1086 hoverEvent.setTimestamp(timestamp);
1087 hoverEvent.setAccepted(
true);
1088 QEventPoint &point = hoverEvent.point(0);
1089 QMutableEventPoint::setPosition(point, localPos);
1090 QMutableEventPoint::setGlobalLastPosition(point, lastGlobalPos);
1092 hasFiltered.clear();
1093 if (sendFilteredMouseEvent(&hoverEvent, item, item->parentItem()))
1096 QCoreApplication::sendEvent(item, &hoverEvent);
1098 return hoverEvent.isAccepted();
1102
1103
1104
1105
1107bool QQuickDeliveryAgentPrivate::deliverHoverEvent(
1108 const QPointF &scenePos,
const QPointF &lastScenePos,
1109 Qt::KeyboardModifiers modifiers, ulong timestamp)
1127 const bool subtreeHoverEnabled = QQuickItemPrivate::get(rootItem)->subtreeHoverEnabled;
1128 const bool itemsWasHovered = !hoverItems.isEmpty();
1130 if (!subtreeHoverEnabled && !itemsWasHovered)
1135 if (subtreeHoverEnabled) {
1136 hoveredLeafItemFound =
false;
1137 QQuickPointerHandlerPrivate::deviceDeliveryTargets(QPointingDevice::primaryPointingDevice()).clear();
1138 deliverHoverEventRecursive(rootItem, scenePos, lastScenePos, modifiers, timestamp);
1142 for (
auto it = hoverItems.begin(); it != hoverItems.end();) {
1143 const auto &[item, hoverId] = *it;
1144 if (hoverId == currentHoverId) {
1151 if (item && hoverId != 0)
1152 deliverHoverEventToItem(item, scenePos, lastScenePos, modifiers, timestamp, HoverChange::Clear);
1153 it = hoverItems.erase(it);
1157 const bool itemsAreHovered = !hoverItems.isEmpty();
1158 return itemsWasHovered || itemsAreHovered;
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197bool QQuickDeliveryAgentPrivate::deliverHoverEventRecursive(
1198 QQuickItem *item,
const QPointF &scenePos,
const QPointF &lastScenePos,
1199 Qt::KeyboardModifiers modifiers, ulong timestamp)
1202 const QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1203 const QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1204 const bool hadChildrenChanged = itemPrivate->dirtyAttributes & QQuickItemPrivate::ChildrenChanged;
1206 for (
int ii = children.size() - 1; ii >= 0; --ii) {
1210 if (!hadChildrenChanged && Q_UNLIKELY(itemPrivate->dirtyAttributes & QQuickItemPrivate::ChildrenChanged))
1212 QQuickItem *child = children.at(ii);
1213 const QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
1215 if (!child->isVisible() || childPrivate->culled)
1217 if (!childPrivate->subtreeHoverEnabled)
1219 if (childPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1220 const QPointF localPos = child->mapFromScene(scenePos);
1221 if (!child->contains(localPos))
1226 const bool accepted = deliverHoverEventRecursive(child, scenePos, lastScenePos, modifiers, timestamp);
1231 if (hoveredLeafItemFound) {
1239 return deliverHoverEventToItem(item, scenePos, lastScenePos, modifiers, timestamp, HoverChange::Set);
1243
1244
1245
1246
1247
1248
1249
1250bool QQuickDeliveryAgentPrivate::deliverHoverEventToItem(
1251 QQuickItem *item,
const QPointF &scenePos,
const QPointF &lastScenePos,
1252 Qt::KeyboardModifiers modifiers, ulong timestamp, HoverChange hoverChange)
1254 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1255 const QPointF localPos = item->mapFromScene(scenePos);
1256 const QPointF globalPos = item->mapToGlobal(localPos);
1257 const bool isHovering = item->contains(localPos);
1258 const auto hoverItemIterator = hoverItems.find(item);
1259 const bool wasHovering = hoverItemIterator != hoverItems.end() && hoverItemIterator.value() != 0;
1261 qCDebug(lcHoverTrace) <<
"item:" << item <<
"scene pos:" << scenePos <<
"localPos:" << localPos
1262 <<
"wasHovering:" << wasHovering <<
"isHovering:" << isHovering;
1264 bool accepted =
false;
1269 if (itemPrivate->hoverEnabled && isHovering && hoverChange == HoverChange::Set) {
1274 hoveredLeafItemFound =
true;
1275 if (hoverItemIterator != hoverItems.end())
1276 hoverItemIterator.value() = currentHoverId;
1278 hoverItems[item] = currentHoverId;
1281 accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, timestamp);
1283 accepted = sendHoverEvent(QEvent::HoverEnter, item, scenePos, lastScenePos, modifiers, timestamp);
1284 }
else if (wasHovering) {
1286 hoverItemIterator.value() = 0;
1287 sendHoverEvent(QEvent::HoverLeave, item, scenePos, lastScenePos, modifiers, timestamp);
1290 if (!itemPrivate->hasPointerHandlers())
1300 if (hoverChange == HoverChange::Clear) {
1302 QHoverEvent hoverEvent(QEvent::HoverLeave, scenePos, globalPos, lastScenePos, modifiers);
1303 hoverEvent.setTimestamp(timestamp);
1305 for (QQuickPointerHandler *h : itemPrivate->extra->pointerHandlers) {
1306 if (QQuickHoverHandler *hh = qmlobject_cast<QQuickHoverHandler *>(h)) {
1307 if (!hh->isHovered())
1309 hoverEvent.setAccepted(
true);
1310 QCoreApplication::sendEvent(hh, &hoverEvent);
1314 QMouseEvent hoverEvent(QEvent::MouseMove, localPos, scenePos, globalPos, Qt::NoButton, Qt::NoButton, modifiers);
1315 hoverEvent.setTimestamp(timestamp);
1317 for (QQuickPointerHandler *h : itemPrivate->extra->pointerHandlers) {
1318 if (QQuickHoverHandler *hh = qmlobject_cast<QQuickHoverHandler *>(h)) {
1321 hoverEvent.setAccepted(
true);
1322 hh->handlePointerEvent(&hoverEvent);
1323 if (hh->isHovered()) {
1326 hoveredLeafItemFound =
true;
1327 if (hoverItemIterator != hoverItems.end())
1328 hoverItemIterator.value() = currentHoverId;
1330 hoverItems[item] = currentHoverId;
1331 if (hh->isBlocking()) {
1332 qCDebug(lcHoverTrace) <<
"skipping rest of hover delivery due to blocking" << hh;
1346bool QQuickDeliveryAgentPrivate::deliverSinglePointEventUntilAccepted(QPointerEvent *event)
1348 Q_ASSERT(event->points().size() == 1);
1349 QQuickPointerHandlerPrivate::deviceDeliveryTargets(event->pointingDevice()).clear();
1350 QEventPoint &point = event->point(0);
1351 QVector<QQuickItem *> targetItems = pointerTargets(rootItem, event, point,
false,
false);
1352 point.setAccepted(
false);
1357 for (
const auto &passiveGrabber : event->passiveGrabbers(point)) {
1358 if (
auto *grabberItem = qobject_cast<QQuickItem *>(passiveGrabber)) {
1359 if (targetItems.contains(grabberItem))
1361 localizePointerEvent(event, grabberItem);
1362 QCoreApplication::sendEvent(grabberItem, event);
1369 for (QQuickItem *item : targetItems) {
1370 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1371 localizePointerEvent(event, item);
1373 itemPrivate->handlePointerEvent(event);
1374 if (point.isAccepted())
1377 QCoreApplication::sendEvent(item, event);
1378 if (event->isAccepted()) {
1379 qCDebug(lcWheelTarget) << event <<
"->" << item;
1387bool QQuickDeliveryAgentPrivate::deliverTouchCancelEvent(QTouchEvent *event)
1389 qCDebug(lcTouch) << event;
1394 const_cast<QPointingDevicePrivate *>(QPointingDevicePrivate::get(event->pointingDevice()))->
1395 sendTouchCancelEvent(event);
1397 cancelTouchMouseSynthesis();
1402void QQuickDeliveryAgentPrivate::deliverDelayedTouchEvent()
1407 std::unique_ptr<QTouchEvent> e(std::move(delayedTouch));
1408 qCDebug(lcTouchCmprs) <<
"delivering" << e.get();
1409 compressedTouchCount = 0;
1410 deliverPointerEvent(e.get());
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423void QQuickDeliveryAgentPrivate::handleWindowDeactivate(QQuickWindow *win)
1425 Q_Q(QQuickDeliveryAgent);
1426 qCDebug(lcFocus) <<
"deactivated" << win->title();
1427 const auto inputDevices = QInputDevice::devices();
1428 for (
auto device : inputDevices) {
1429 if (
auto pointingDevice = qobject_cast<
const QPointingDevice *>(device)) {
1430 auto devPriv = QPointingDevicePrivate::get(
const_cast<QPointingDevice *>(pointingDevice));
1431 for (
auto epd : devPriv->activePoints.values()) {
1432 if (!epd.exclusiveGrabber.isNull()) {
1433 bool relevant =
false;
1434 if (QQuickItem *item = qmlobject_cast<QQuickItem *>(epd.exclusiveGrabber.data()))
1435 relevant = (item->window() == win);
1436 else if (QQuickPointerHandler *handler = qmlobject_cast<QQuickPointerHandler *>(epd.exclusiveGrabber.data())) {
1437 if (handler->parentItem())
1438 relevant = (handler->parentItem()->window() == win && epd.exclusiveGrabberContext.data() == q);
1445 devPriv->setExclusiveGrabber(
nullptr, epd.eventPoint,
nullptr);
1454void QQuickDeliveryAgentPrivate::handleWindowHidden(QQuickWindow *win)
1456 qCDebug(lcFocus) <<
"hidden" << win->title();
1458 lastMousePosition = QPointF();
1461bool QQuickDeliveryAgentPrivate::allUpdatedPointsAccepted(
const QPointerEvent *ev)
1463 for (
auto &point : ev->points()) {
1464 if (point.state() != QEventPoint::State::Pressed && !point.isAccepted())
1471
1472
1473
1474
1475
1476void QQuickDeliveryAgentPrivate::localizePointerEvent(QPointerEvent *ev,
const QQuickItem *dest)
1478 for (
int i = 0; i < ev->pointCount(); ++i) {
1479 auto &point = ev->point(i);
1480 QMutableEventPoint::setPosition(point, dest->mapFromScene(point.scenePosition()));
1481 qCDebug(lcPtrLoc) << ev->type() <<
"@" << point.scenePosition() <<
"to"
1482 << dest <<
"@" << dest->mapToScene(QPointF()) <<
"->" << point;
1486QList<QObject *> QQuickDeliveryAgentPrivate::exclusiveGrabbers(QPointerEvent *ev)
1488 QList<QObject *> result;
1489 for (
const QEventPoint &point : ev->points()) {
1490 if (QObject *grabber = ev->exclusiveGrabber(point)) {
1491 if (!result.contains(grabber))
1498bool QQuickDeliveryAgentPrivate::anyPointGrabbed(
const QPointerEvent *ev)
1500 for (
const QEventPoint &point : ev->points()) {
1501 if (ev->exclusiveGrabber(point) || !ev->passiveGrabbers(point).isEmpty())
1507bool QQuickDeliveryAgentPrivate::allPointsGrabbed(
const QPointerEvent *ev)
1509 for (
const auto &point : ev->points()) {
1510 if (!ev->exclusiveGrabber(point) && ev->passiveGrabbers(point).isEmpty())
1516bool QQuickDeliveryAgentPrivate::isMouseEvent(
const QPointerEvent *ev)
1518 switch (ev->type()) {
1519 case QEvent::MouseButtonPress:
1520 case QEvent::MouseButtonRelease:
1521 case QEvent::MouseButtonDblClick:
1522 case QEvent::MouseMove:
1529bool QQuickDeliveryAgentPrivate::isMouseOrWheelEvent(
const QPointerEvent *ev)
1531 return isMouseEvent(ev) || ev->type() == QEvent::Wheel;
1534bool QQuickDeliveryAgentPrivate::isHoverEvent(
const QPointerEvent *ev)
1536 switch (ev->type()) {
1537 case QEvent::HoverEnter:
1538 case QEvent::HoverMove:
1539 case QEvent::HoverLeave:
1546bool QQuickDeliveryAgentPrivate::isTouchEvent(
const QPointerEvent *ev)
1548 switch (ev->type()) {
1549 case QEvent::TouchBegin:
1550 case QEvent::TouchUpdate:
1551 case QEvent::TouchEnd:
1552 case QEvent::TouchCancel:
1559bool QQuickDeliveryAgentPrivate::isTabletEvent(
const QPointerEvent *ev)
1561#if QT_CONFIG(tabletevent)
1562 switch (ev->type()) {
1563 case QEvent::TabletPress:
1564 case QEvent::TabletMove:
1565 case QEvent::TabletRelease:
1566 case QEvent::TabletEnterProximity:
1567 case QEvent::TabletLeaveProximity:
1578bool QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(
const QPointerEvent *ev)
1580 const auto devType = ev->device()->type();
1581 return devType == QInputDevice::DeviceType::Mouse ||
1582 devType == QInputDevice::DeviceType::TouchPad;
1585bool QQuickDeliveryAgentPrivate::isSynthMouse(
const QPointerEvent *ev)
1587 return (!isEventFromMouseOrTouchpad(ev) && isMouseEvent(ev));
1591
1592
1593
1594bool QQuickDeliveryAgentPrivate::isSinglePointDevice(
const QInputDevice *dev)
1596 switch (dev->type()) {
1597 case QInputDevice::DeviceType::Mouse:
1598 case QInputDevice::DeviceType::TouchPad:
1599 case QInputDevice::DeviceType::Puck:
1600 case QInputDevice::DeviceType::Stylus:
1601 case QInputDevice::DeviceType::Airbrush:
1603 case QInputDevice::DeviceType::TouchScreen:
1604 case QInputDevice::DeviceType::Keyboard:
1605 case QInputDevice::DeviceType::Unknown:
1606 case QInputDevice::DeviceType::AllDevices:
1612QQuickPointingDeviceExtra *QQuickDeliveryAgentPrivate::deviceExtra(
const QInputDevice *device)
1614 QInputDevicePrivate *devPriv = QInputDevicePrivate::get(
const_cast<QInputDevice *>(device));
1615 if (devPriv->qqExtra)
1616 return static_cast<QQuickPointingDeviceExtra *>(devPriv->qqExtra);
1617 auto extra =
new QQuickPointingDeviceExtra;
1618 devPriv->qqExtra = extra;
1619 QObject::connect(device, &QObject::destroyed, [devPriv]() {
1620 delete static_cast<QQuickPointingDeviceExtra *>(devPriv->qqExtra);
1621 devPriv->qqExtra =
nullptr;
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650bool QQuickDeliveryAgentPrivate::compressTouchEvent(QTouchEvent *event)
1654 if (isSubsceneAgent)
1657 QEventPoint::States states = event->touchPointStates();
1658 if (states.testFlag(QEventPoint::State::Pressed) || states.testFlag(QEventPoint::State::Released)) {
1659 qCDebug(lcTouchCmprs) <<
"no compression" << event;
1664 if (!delayedTouch) {
1665 delayedTouch.reset(
new QMutableTouchEvent(event->type(), event->pointingDevice(), event->modifiers(), event->points()));
1666 delayedTouch->setTimestamp(event->timestamp());
1667 for (qsizetype i = 0; i < delayedTouch->pointCount(); ++i) {
1668 auto &tp = delayedTouch->point(i);
1669 QMutableEventPoint::detach(tp);
1671 ++compressedTouchCount;
1672 qCDebug(lcTouchCmprs) <<
"delayed" << compressedTouchCount << delayedTouch.get();
1673 if (QQuickWindow *window = rootItem->window())
1674 window->maybeUpdate();
1679 if (delayedTouch->type() == event->type() &&
1680 delayedTouch->device() == event->device() &&
1681 delayedTouch->modifiers() == event->modifiers() &&
1682 delayedTouch->pointCount() == event->pointCount())
1685 bool mismatch =
false;
1687 auto tpts = event->points();
1688 for (qsizetype i = 0; i < event->pointCount(); ++i) {
1689 const auto &tp = tpts.at(i);
1690 const auto &tpDelayed = delayedTouch->point(i);
1691 if (tp.id() != tpDelayed.id()) {
1696 if (tpDelayed.state() == QEventPoint::State::Updated && tp.state() == QEventPoint::State::Stationary)
1697 QMutableEventPoint::setState(tpts[i], QEventPoint::State::Updated);
1704 delayedTouch.reset(
new QMutableTouchEvent(event->type(), event->pointingDevice(), event->modifiers(), tpts));
1705 delayedTouch->setTimestamp(event->timestamp());
1706 for (qsizetype i = 0; i < delayedTouch->pointCount(); ++i) {
1707 auto &tp = delayedTouch->point(i);
1708 QMutableEventPoint::detach(tp);
1710 ++compressedTouchCount;
1711 qCDebug(lcTouchCmprs) <<
"coalesced" << compressedTouchCount << delayedTouch.get();
1712 if (QQuickWindow *window = rootItem->window())
1713 window->maybeUpdate();
1719 deliverDelayedTouchEvent();
1720 delayedTouch.reset(
new QMutableTouchEvent(event->type(), event->pointingDevice(),
1721 event->modifiers(), event->points()));
1722 delayedTouch->setTimestamp(event->timestamp());
1730void QQuickDeliveryAgentPrivate::handleTouchEvent(QTouchEvent *event)
1732 Q_Q(QQuickDeliveryAgent);
1733 translateTouchEvent(event);
1735 if (event->pointCount()) {
1736 auto &point = event->point(0);
1737 if (point.state() == QEventPoint::State::Released) {
1738 lastMousePosition = QPointF();
1740 lastMousePosition = point.position();
1744 qCDebug(lcTouch) << q << event;
1746 static bool qquickwindow_no_touch_compression = qEnvironmentVariableIsSet(
"QML_NO_TOUCH_COMPRESSION");
1748 if (qquickwindow_no_touch_compression || pointerEventRecursionGuard) {
1749 deliverPointerEvent(event);
1753 if (!compressTouchEvent(event)) {
1755 deliverDelayedTouchEvent();
1756 qCDebug(lcTouchCmprs) <<
"resuming delivery" << event;
1758 deliverPointerEvent(event);
1763
1764
1765void QQuickDeliveryAgentPrivate::handleMouseEvent(QMouseEvent *event)
1767 Q_Q(QQuickDeliveryAgent);
1771 if (event->source() == Qt::MouseEventSynthesizedBySystem &&
1772 !(event->button() == Qt::RightButton && allowSyntheticRightClick())) {
1776 qCDebug(lcMouse) << q << event;
1778 switch (event->type()) {
1779 case QEvent::MouseButtonPress:
1780 Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMousePress, event->button(),
1782 deliverPointerEvent(event);
1784 case QEvent::MouseButtonRelease:
1785 Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseRelease, event->button(),
1787 deliverPointerEvent(event);
1788#if QT_CONFIG(cursor)
1789 QQuickWindowPrivate::get(rootItem->window())->updateCursor(event->scenePosition());
1792 case QEvent::MouseButtonDblClick:
1793 Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseDoubleClick,
1794 event->button(), event->buttons());
1795 deliverPointerEvent(event);
1797 case QEvent::MouseMove: {
1798 Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseMove,
1799 event->position().x(), event->position().y());
1801 const QPointF last = lastMousePosition.isNull() ? event->scenePosition() : lastMousePosition;
1802 lastMousePosition = event->scenePosition();
1803 qCDebug(lcHoverTrace) << q << event <<
"mouse pos" << last <<
"->" << lastMousePosition;
1804 if (!event->points().size() || !event->exclusiveGrabber(event->point(0))) {
1805 bool accepted = deliverHoverEvent(event->scenePosition(), last, event->modifiers(), event->timestamp());
1806 event->setAccepted(accepted);
1808 deliverPointerEvent(event);
1809#if QT_CONFIG(cursor)
1811 QQuickWindowPrivate::get(rootItem->window())->updateCursor(event->scenePosition());
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836void QQuickDeliveryAgentPrivate::flushFrameSynchronousEvents(QQuickWindow *win)
1838 Q_Q(QQuickDeliveryAgent);
1839 QQuickDeliveryAgent *deliveringAgent = QQuickDeliveryAgentPrivate::currentEventDeliveryAgent;
1840 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = q;
1843 deliverDelayedTouchEvent();
1847 QQmlAnimationTimer *ut = QQmlAnimationTimer::instance();
1848 if (ut && ut->hasStartAnimationPending())
1849 ut->startAnimations();
1854#if !defined(Q_OS_WEBOS)
1861 if (frameSynchronousHoverEnabled && !win->mouseGrabberItem() &&
1862 !lastMousePosition.isNull() && QQuickWindowPrivate::get(win)->dirtyItemList) {
1863 qCDebug(lcHoverTrace) << q <<
"delivering frame-sync hover to root @" << lastMousePosition;
1864 if (deliverHoverEvent(lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), 0)) {
1865#if QT_CONFIG(cursor)
1866 QQuickWindowPrivate::get(rootItem->window())->updateCursor(
1867 sceneTransform ? sceneTransform->map(lastMousePosition) : lastMousePosition, rootItem);
1871 qCDebug(lcHoverTrace) << q <<
"frame-sync hover delivery done";
1876 if (Q_UNLIKELY(QQuickDeliveryAgentPrivate::currentEventDeliveryAgent &&
1877 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent != q))
1878 qCWarning(lcPtr,
"detected interleaved frame-sync and actual events");
1879 QQuickDeliveryAgentPrivate::currentEventDeliveryAgent = deliveringAgent;
1883
1884
1885
1886
1887
1888
1889
1890void QQuickDeliveryAgentPrivate::onGrabChanged(QObject *grabber, QPointingDevice::GrabTransition transition,
1891 const QPointerEvent *event,
const QEventPoint &point)
1893 Q_Q(QQuickDeliveryAgent);
1894 const bool grabGained = (transition == QPointingDevice::GrabTransition::GrabExclusive ||
1895 transition == QPointingDevice::GrabTransition::GrabPassive);
1898 if (
auto *handler = qmlobject_cast<QQuickPointerHandler *>(grabber)) {
1899 if (handler->parentItem()) {
1900 auto itemPriv = QQuickItemPrivate::get(handler->parentItem());
1901 if (itemPriv->deliveryAgent() == q) {
1902 handler->onGrabChanged(handler, transition,
const_cast<QPointerEvent *>(event),
1903 const_cast<QEventPoint &>(point));
1908 if (isSubsceneAgent && (!itemPriv->extra.isAllocated() || !itemPriv->extra->subsceneDeliveryAgent))
1909 itemPriv->maybeHasSubsceneDeliveryAgent =
true;
1911 }
else if (!isSubsceneAgent) {
1912 handler->onGrabChanged(handler, transition,
const_cast<QPointerEvent *>(event),
1913 const_cast<QEventPoint &>(point));
1915 }
else if (
auto *grabberItem = qmlobject_cast<QQuickItem *>(grabber)) {
1916 switch (transition) {
1917 case QPointingDevice::CancelGrabExclusive:
1918 case QPointingDevice::UngrabExclusive:
1919 if (isDeliveringTouchAsMouse() || isSinglePointDevice(point.device())) {
1922 QMutableSinglePointEvent e(QEvent::UngrabMouse, point.device(), point);
1923 hasFiltered.clear();
1924 if (!sendFilteredMouseEvent(&e, grabberItem, grabberItem->parentItem())) {
1925 lastUngrabbed = grabberItem;
1926 grabberItem->mouseUngrabEvent();
1931 bool allReleasedOrCancelled =
true;
1932 if (transition == QPointingDevice::UngrabExclusive && event) {
1933 for (
const auto &pt : event->points()) {
1934 if (pt.state() != QEventPoint::State::Released) {
1935 allReleasedOrCancelled =
false;
1940 if (allReleasedOrCancelled)
1941 grabberItem->touchUngrabEvent();
1947 auto *itemPriv = QQuickItemPrivate::get(grabberItem);
1950 if (isSubsceneAgent && grabGained && (!itemPriv->extra.isAllocated() || !itemPriv->extra->subsceneDeliveryAgent))
1951 itemPriv->maybeHasSubsceneDeliveryAgent =
true;
1954 if (currentEventDeliveryAgent == q && event && event->device()) {
1955 switch (transition) {
1956 case QPointingDevice::GrabPassive: {
1957 auto epd = QPointingDevicePrivate::get(
const_cast<QPointingDevice*>(event->pointingDevice()))->queryPointById(point.id());
1959 QPointingDevicePrivate::setPassiveGrabberContext(epd, grabber, q);
1960 qCDebug(lcPtr) <<
"remembering that" << q <<
"handles point" << point.id() <<
"after" << transition;
1962 case QPointingDevice::GrabExclusive: {
1963 auto epd = QPointingDevicePrivate::get(
const_cast<QPointingDevice*>(event->pointingDevice()))->queryPointById(point.id());
1965 epd->exclusiveGrabberContext = q;
1966 qCDebug(lcPtr) <<
"remembering that" << q <<
"handles point" << point.id() <<
"after" << transition;
1968 case QPointingDevice::CancelGrabExclusive:
1969 case QPointingDevice::UngrabExclusive:
1972 case QPointingDevice::UngrabPassive:
1973 case QPointingDevice::CancelGrabPassive:
1976 case QPointingDevice::OverrideGrabPassive:
1984
1985
1986
1987
1988
1989
1990
1991
1992void QQuickDeliveryAgentPrivate::ensureDeviceConnected(
const QPointingDevice *dev)
1994 Q_Q(QQuickDeliveryAgent);
1995 if (knownPointingDevices.contains(dev))
1997 knownPointingDevices.append(dev);
1998 connect(dev, &QPointingDevice::grabChanged,
this, &QQuickDeliveryAgentPrivate::onGrabChanged);
1999 QObject::connect(dev, &QObject::destroyed, q, [
this, dev] {
this->knownPointingDevices.removeAll(dev);});
2003
2004
2005
2006
2007
2008
2009void QQuickDeliveryAgentPrivate::deliverPointerEvent(QPointerEvent *event)
2011 Q_Q(QQuickDeliveryAgent);
2012 if (isTabletEvent(event))
2013 qCDebug(lcTablet) << q << event;
2018 ++pointerEventRecursionGuard;
2019 eventsInDelivery.push(event);
2025 QVarLengthArray<QPointF, 16> originalScenePositions;
2026 if (sceneTransform) {
2027 originalScenePositions.resize(event->pointCount());
2028 for (
int i = 0; i < event->pointCount(); ++i) {
2029 auto &pt = event->point(i);
2030 originalScenePositions[i] = pt.scenePosition();
2031 QMutableEventPoint::setScenePosition(pt, sceneTransform->map(pt.scenePosition()));
2032 qCDebug(lcPtrLoc) << q << event->type() << pt.id() <<
"transformed scene pos" << pt.scenePosition();
2034 }
else if (isSubsceneAgent) {
2035 qCDebug(lcPtrLoc) << q << event->type() <<
"no scene transform set";
2038 skipDelivery.clear();
2039 QQuickPointerHandlerPrivate::deviceDeliveryTargets(event->pointingDevice()).clear();
2041 qCDebug(lcPtr) << q <<
"delivering with" << sceneTransform << event;
2043 qCDebug(lcPtr) << q <<
"delivering" << event;
2044 for (
int i = 0; i < event->pointCount(); ++i)
2045 event->point(i).setAccepted(
false);
2047 if (event->isBeginEvent()) {
2048 ensureDeviceConnected(event->pointingDevice());
2049 if (event->type() == QEvent::MouseButtonPress && rootItem->window()
2050 &&
static_cast<QSinglePointEvent *>(event)->button() == Qt::RightButton) {
2051 QQuickWindowPrivate::get(rootItem->window())->rmbContextMenuEventEnabled =
true;
2053 if (!deliverPressOrReleaseEvent(event))
2054 event->setAccepted(
false);
2057 auto isHoveringMoveEvent = [](QPointerEvent *event) ->
bool {
2058 if (event->type() == QEvent::MouseMove) {
2059 const auto *spe =
static_cast<
const QSinglePointEvent *>(event);
2060 if (spe->button() == Qt::NoButton && spe->buttons() == Qt::NoButton)
2067
2068
2069
2070
2071
2072
2073
2074
2075 if (!allUpdatedPointsAccepted(event) && !isHoveringMoveEvent(event))
2076 deliverUpdatedPoints(event);
2077 if (event->isEndEvent())
2078 deliverPressOrReleaseEvent(event,
true);
2082 if (isTouchEvent(event) && touchMouseId >= 0) {
2083 if (
static_cast<QTouchEvent *>(event)->touchPointStates() == QEventPoint::State::Released) {
2084 cancelTouchMouseSynthesis();
2086 auto touchMousePoint = event->pointById(touchMouseId);
2087 if (touchMousePoint && touchMousePoint->state() == QEventPoint::State::Released)
2088 cancelTouchMouseSynthesis();
2092 eventsInDelivery.pop();
2093 if (sceneTransform) {
2094 for (
int i = 0; i < event->pointCount(); ++i)
2095 QMutableEventPoint::setScenePosition(event->point(i), originalScenePositions.at(i));
2097 --pointerEventRecursionGuard;
2098 lastUngrabbed =
nullptr;
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2118QVector<QQuickItem *> QQuickDeliveryAgentPrivate::eventTargets(QQuickItem *item,
const QEvent *event, QPointF scenePos,
2119 qxp::function_ref<std::optional<
bool> (QQuickItem *,
const QEvent *)> predicate)
const
2121 QVector<QQuickItem *> targets;
2122 auto itemPrivate = QQuickItemPrivate::get(item);
2123 const auto itemPos = item->mapFromScene(scenePos);
2124 bool relevant = item->contains(itemPos);
2126 if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
2127 if (!item->clipRect().contains(itemPos))
2130 QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
2131 const std::optional<
bool> override = predicate(item, event);
2132 if (override.has_value())
2133 relevant = override.value();
2135 auto it = std::lower_bound(children.begin(), children.end(), 0,
2136 [](
auto lhs,
auto rhs) ->
bool {
return lhs->z() < rhs; });
2137 children.insert(it, item);
2140 for (
int ii = children.size() - 1; ii >= 0; --ii) {
2141 QQuickItem *child = children.at(ii);
2142 auto childPrivate = QQuickItemPrivate::get(child);
2143 if (!child->isVisible() || !child->isEnabled() || childPrivate->culled ||
2144 (child != item && childPrivate->extra.isAllocated() && childPrivate->extra->subsceneDeliveryAgent))
2150 targets << eventTargets(child, event, scenePos, predicate);
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185QVector<QQuickItem *> QQuickDeliveryAgentPrivate::pointerTargets(QQuickItem *item,
const QPointerEvent *event,
const QEventPoint &point,
2186 bool checkMouseButtons,
bool checkAcceptsTouch)
const
2188 auto predicate = [point, checkMouseButtons, checkAcceptsTouch](QQuickItem *item,
const QEvent *ev) -> std::optional<
bool> {
2189 const QPointerEvent *event =
static_cast<
const QPointerEvent *>(ev);
2190 auto itemPrivate = QQuickItemPrivate::get(item);
2191 if (itemPrivate->hasPointerHandlers()) {
2192 if (itemPrivate->anyPointerHandlerWants(event, point))
2195 if (checkMouseButtons && item->acceptedMouseButtons() == Qt::NoButton)
2197 if (checkAcceptsTouch && !(item->acceptTouchEvents() || item->acceptedMouseButtons()))
2201 return std::nullopt;
2204 return eventTargets(item, event, point.scenePosition(), predicate);
2208
2209
2210
2211QVector<QQuickItem *> QQuickDeliveryAgentPrivate::mergePointerTargets(
const QVector<QQuickItem *> &list1,
const QVector<QQuickItem *> &list2)
const
2213 QVector<QQuickItem *> targets = list1;
2217 int insertPosition = targets.size();
2218 for (
int i = list2.size() - 1; i >= 0; --i) {
2219 int newInsertPosition = targets.lastIndexOf(list2.at(i), insertPosition);
2220 if (newInsertPosition >= 0) {
2221 Q_ASSERT(newInsertPosition <= insertPosition);
2222 insertPosition = newInsertPosition;
2225 if (insertPosition == targets.size() || list2.at(i) != targets.at(insertPosition))
2226 targets.insert(insertPosition, list2.at(i));
2232
2233
2234void QQuickDeliveryAgentPrivate::deliverUpdatedPoints(QPointerEvent *event)
2236 Q_Q(
const QQuickDeliveryAgent);
2238 const auto grabbers = exclusiveGrabbers(event);
2239 hasFiltered.clear();
2240 for (
auto grabber : grabbers) {
2242 QQuickItem *receiver = qmlobject_cast<QQuickItem *>(grabber);
2245 QQuickPointerHandler *handler =
static_cast<QQuickPointerHandler *>(grabber);
2246 receiver =
static_cast<QQuickPointerHandler *>(grabber)->parentItem();
2250 hasFiltered.clear();
2251 if (sendFilteredPointerEvent(event, receiver))
2253 localizePointerEvent(event, receiver);
2255 handler->handlePointerEvent(event);
2261 hasFiltered.clear();
2263 deliverMatchingPointsToItem(receiver,
true, event);
2267 for (
auto &point : event->points()) {
2268 auto epd = QPointingDevicePrivate::get(event->pointingDevice())->queryPointById(point.id());
2269 if (Q_UNLIKELY(!epd)) {
2270 qWarning() <<
"point is not in activePoints" << point;
2273 QList<QPointer<QObject>> relevantPassiveGrabbers;
2274 for (
int i = 0; i < epd->passiveGrabbersContext.size(); ++i) {
2275 if (epd->passiveGrabbersContext.at(i).data() == q)
2276 relevantPassiveGrabbers << epd->passiveGrabbers.at(i);
2278 if (!relevantPassiveGrabbers.isEmpty())
2279 deliverToPassiveGrabbers(relevantPassiveGrabbers, event);
2282 if (event->type() == QEvent::TouchUpdate) {
2283 for (
const auto &[item, id] : hoverItems) {
2285 bool res = deliverHoverEventToItem(item, point.scenePosition(), point.sceneLastPosition(),
2286 event->modifiers(), event->timestamp(), HoverChange::Set);
2288 Q_ASSERT(!res || hoverItems.value(item));
2298 if (!allPointsGrabbed(event)) {
2299 QVector<QQuickItem *> targetItems;
2300 for (
auto &point : event->points()) {
2303 if (point.state() == QEventPoint::Pressed || qmlobject_cast<QQuickItem *>(event->exclusiveGrabber(point)))
2305 QVector<QQuickItem *> targetItemsForPoint = pointerTargets(rootItem, event, point,
false,
false);
2306 if (targetItems.size()) {
2307 targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
2309 targetItems = targetItemsForPoint;
2312 for (QQuickItem *item : targetItems) {
2313 if (grabbers.contains(item))
2315 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
2316 localizePointerEvent(event, item);
2317 itemPrivate->handlePointerEvent(event,
true);
2318 if (allPointsGrabbed(event))
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363bool QQuickDeliveryAgentPrivate::deliverPressOrReleaseEvent(QPointerEvent *event,
bool handlersOnly)
2365 QVector<QQuickItem *> targetItems;
2366 const bool isTouch = isTouchEvent(event);
2367 if (isTouch && event->isBeginEvent() && isDeliveringTouchAsMouse()) {
2368 if (
auto point =
const_cast<QPointingDevicePrivate *>(QPointingDevicePrivate::get(touchMouseDevice))->queryPointById(touchMouseId)) {
2378 if (qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point->eventPoint)))
2379 cancelTouchMouseSynthesis();
2381 qCWarning(lcTouchTarget) <<
"during delivery of touch press, synth-mouse ID" << Qt::hex << touchMouseId <<
"is missing from" << event;
2384 for (
int i = 0; i < event->pointCount(); ++i) {
2385 auto &point = event->point(i);
2389 if (isTouch && point.state() == QEventPoint::Pressed)
2390 resetIfDoubleTapPrevented(point);
2391 QVector<QQuickItem *> targetItemsForPoint = pointerTargets(rootItem, event, point, !isTouch, isTouch);
2392 if (targetItems.size()) {
2393 targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
2395 targetItems = targetItemsForPoint;
2399 QVector<QPointer<QQuickItem>> safeTargetItems(targetItems.begin(), targetItems.end());
2401 for (
auto &item : safeTargetItems) {
2405 if (isSubsceneAgent)
2406 QQuickItemPrivate::get(item)->maybeHasSubsceneDeliveryAgent =
true;
2408 hasFiltered.clear();
2409 if (!handlersOnly && sendFilteredPointerEvent(event, item)) {
2410 if (event->isAccepted())
2412 skipDelivery.append(item);
2417 if (skipDelivery.contains(item))
2422 for (
int i = 0; i < event->pointCount(); ++i)
2423 event->point(i).setAccepted(
false);
2425 deliverMatchingPointsToItem(item,
false, event, handlersOnly);
2426 if (event->allPointsAccepted())
2427 handlersOnly =
true;
2433 return handlersOnly;
2437
2438
2439
2440
2441
2442
2443
2444void QQuickDeliveryAgentPrivate::deliverMatchingPointsToItem(QQuickItem *item,
bool isGrabber, QPointerEvent *pointerEvent,
bool handlersOnly)
2446 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
2447#if defined(Q_OS_ANDROID) && QT_VERSION < QT_VERSION_CHECK(6
, 0
, 0
)
2452 if (itemPrivate->wasDeleted)
2455 localizePointerEvent(pointerEvent, item);
2456 bool isMouse = isMouseEvent(pointerEvent);
2460 if (pointerEvent->type() != QEvent::MouseButtonDblClick)
2461 itemPrivate->handlePointerEvent(pointerEvent);
2468 if (pointerEvent->isEndEvent() && !pointerEvent->isUpdateEvent()
2469 && !exclusiveGrabbers(pointerEvent).contains(item))
2473 if (sendFilteredPointerEvent(pointerEvent, item))
2479 auto button =
static_cast<QSinglePointEvent *>(pointerEvent)->button();
2480 if ((isGrabber && button == Qt::NoButton) || item->acceptedMouseButtons().testFlag(button)) {
2483 auto oldMouseGrabber = pointerEvent->exclusiveGrabber(pointerEvent->point(0));
2484 pointerEvent->accept();
2485 if (isGrabber && sendFilteredPointerEvent(pointerEvent, item))
2487 localizePointerEvent(pointerEvent, item);
2488 QCoreApplication::sendEvent(item, pointerEvent);
2489 if (pointerEvent->isAccepted()) {
2490 auto &point = pointerEvent->point(0);
2491 auto mouseGrabber = pointerEvent->exclusiveGrabber(point);
2492 if (mouseGrabber && mouseGrabber != item && mouseGrabber != oldMouseGrabber) {
2498 if (item != lastUngrabbed) {
2499 item->mouseUngrabEvent();
2500 lastUngrabbed = item;
2502 }
else if (item->isEnabled() && item->isVisible() && point.state() == QEventPoint::State::Pressed) {
2503 pointerEvent->setExclusiveGrabber(point, item);
2505 point.setAccepted(
true);
2511 if (!isTouchEvent(pointerEvent))
2514 bool eventAccepted =
false;
2515 QMutableTouchEvent touchEvent;
2516 itemPrivate->localizedTouchEvent(
static_cast<QTouchEvent *>(pointerEvent),
false, &touchEvent);
2517 if (touchEvent.type() == QEvent::None)
2520 if (item->acceptTouchEvents()) {
2521 qCDebug(lcTouch) <<
"considering delivering" << &touchEvent <<
" to " << item;
2524 qCDebug(lcTouch) <<
"actually delivering" << &touchEvent <<
" to " << item;
2525 QCoreApplication::sendEvent(item, &touchEvent);
2526 eventAccepted = touchEvent.isAccepted();
2529 if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)) &&
2530 !eventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton))
2531 deliverTouchAsMouse(item, &touchEvent);
2535 Q_ASSERT(item->acceptTouchEvents());
2536 if (eventAccepted) {
2537 bool isPressOrRelease = pointerEvent->isBeginEvent() || pointerEvent->isEndEvent();
2538 for (
int i = 0; i < touchEvent.pointCount(); ++i) {
2539 auto &point = touchEvent.point(i);
2541 point.setAccepted();
2543 if (isPressOrRelease && !(itemPrivate->deliveryAgent() && pointerEvent->exclusiveGrabber(point)))
2544 pointerEvent->setExclusiveGrabber(point, item);
2549 for (
const auto &point: touchEvent.points()) {
2550 if (point.state() == QEventPoint::State::Pressed) {
2551 if (pointerEvent->exclusiveGrabber(point) == item) {
2552 qCDebug(lcTouchTarget) <<
"TP" << Qt::hex << point.id() <<
"disassociated";
2553 pointerEvent->setExclusiveGrabber(point,
nullptr);
2560#if QT_CONFIG(quick_draganddrop)
2561void QQuickDeliveryAgentPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *event)
2563 QObject *formerTarget = grabber->target();
2564 grabber->resetTarget();
2565 QQuickDragGrabber::iterator grabItem = grabber->begin();
2566 if (grabItem != grabber->end()) {
2567 Q_ASSERT(event->type() != QEvent::DragEnter);
2568 if (event->type() == QEvent::Drop) {
2569 QDropEvent *e =
static_cast<QDropEvent *>(event);
2570 for (e->setAccepted(
false); !e->isAccepted() && grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
2571 QPointF p = (**grabItem)->mapFromScene(e->position().toPoint());
2572 QDropEvent translatedEvent(
2574 e->possibleActions(),
2578 QQuickDropEventEx::copyActions(&translatedEvent, *e);
2579 QCoreApplication::sendEvent(**grabItem, &translatedEvent);
2580 e->setAccepted(translatedEvent.isAccepted());
2581 e->setDropAction(translatedEvent.dropAction());
2582 grabber->setTarget(**grabItem);
2585 if (event->type() != QEvent::DragMove) {
2586 QDragLeaveEvent leaveEvent;
2587 for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem))
2588 QCoreApplication::sendEvent(**grabItem, &leaveEvent);
2589 grabber->ignoreList().clear();
2592 QDragMoveEvent *moveEvent =
static_cast<QDragMoveEvent *>(event);
2596 QVarLengthArray<QQuickItem*, 64> currentGrabItems;
2597 for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem))
2598 currentGrabItems.append(**grabItem);
2601 QDragEnterEvent enterEvent(
2602 moveEvent->position().toPoint(),
2603 moveEvent->possibleActions(),
2604 moveEvent->mimeData(),
2605 moveEvent->buttons(),
2606 moveEvent->modifiers());
2607 QQuickDropEventEx::copyActions(&enterEvent, *moveEvent);
2608 event->setAccepted(deliverDragEvent(grabber, rootItem, &enterEvent, ¤tGrabItems,
2611 for (grabItem = grabber->begin(); grabItem != grabber->end(); ++grabItem) {
2612 int i = currentGrabItems.indexOf(**grabItem);
2614 currentGrabItems.remove(i);
2616 QDragMoveEvent translatedEvent(
2617 (**grabItem)->mapFromScene(moveEvent->position().toPoint()).toPoint(),
2618 moveEvent->possibleActions(),
2619 moveEvent->mimeData(),
2620 moveEvent->buttons(),
2621 moveEvent->modifiers());
2622 QQuickDropEventEx::copyActions(&translatedEvent, *moveEvent);
2623 QCoreApplication::sendEvent(**grabItem, &translatedEvent);
2624 event->setAccepted(translatedEvent.isAccepted());
2625 QQuickDropEventEx::copyActions(moveEvent, translatedEvent);
2630 QDragLeaveEvent leaveEvent;
2631 for (QQuickItem *i : currentGrabItems)
2632 QCoreApplication::sendEvent(i, &leaveEvent);
2637 if (event->type() == QEvent::DragEnter || event->type() == QEvent::DragMove) {
2638 QDragMoveEvent *e =
static_cast<QDragMoveEvent *>(event);
2639 QDragEnterEvent enterEvent(
2640 e->position().toPoint(),
2641 e->possibleActions(),
2645 QQuickDropEventEx::copyActions(&enterEvent, *e);
2646 event->setAccepted(deliverDragEvent(grabber, rootItem, &enterEvent));
2648 grabber->ignoreList().clear();
2652bool QQuickDeliveryAgentPrivate::deliverDragEvent(
2653 QQuickDragGrabber *grabber, QQuickItem *item, QDragMoveEvent *event,
2654 QVarLengthArray<QQuickItem *, 64> *currentGrabItems, QObject *formerTarget)
2656 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
2657 if (!item->isVisible() || !item->isEnabled() || QQuickItemPrivate::get(item)->culled)
2659 QPointF p = item->mapFromScene(event->position().toPoint());
2660 bool itemContained = item->contains(p);
2662 const int itemIndex = grabber->ignoreList().indexOf(item);
2663 if (!itemContained) {
2665 grabber->ignoreList().remove(itemIndex);
2667 if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape)
2671 QDragEnterEvent enterEvent(
2672 event->position().toPoint(),
2673 event->possibleActions(),
2676 event->modifiers());
2677 QQuickDropEventEx::copyActions(&enterEvent, *event);
2678 QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
2681 for (
int ii = children.size() - 1; ii >= 0; --ii) {
2682 if (children.at(ii)->z() < 0)
2684 if (deliverDragEvent(grabber, children.at(ii), &enterEvent, currentGrabItems, formerTarget))
2688 if (itemContained) {
2691 if (currentGrabItems && currentGrabItems->contains(item)) {
2692 grabber->grab(item);
2693 grabber->setTarget(item);
2697 if (event->type() == QEvent::DragMove || itemPrivate->flags & QQuickItem::ItemAcceptsDrops) {
2698 if (event->type() == QEvent::DragEnter) {
2700 QQuickItem *formerTargetItem = qobject_cast<QQuickItem *>(formerTarget);
2701 if (formerTargetItem && currentGrabItems) {
2702 QDragLeaveEvent leaveEvent;
2703 QCoreApplication::sendEvent(formerTarget, &leaveEvent);
2707 currentGrabItems->removeAll(formerTarget);
2709 }
else if (itemIndex >= 0) {
2714 QDragMoveEvent translatedEvent(p.toPoint(), event->possibleActions(), event->mimeData(),
2715 event->buttons(), event->modifiers(), event->type());
2716 QQuickDropEventEx::copyActions(&translatedEvent, *event);
2717 translatedEvent.setAccepted(event->isAccepted());
2718 QCoreApplication::sendEvent(item, &translatedEvent);
2719 event->setAccepted(translatedEvent.isAccepted());
2720 event->setDropAction(translatedEvent.dropAction());
2721 if (event->type() == QEvent::DragEnter) {
2722 if (translatedEvent.isAccepted()) {
2723 grabber->grab(item);
2724 grabber->setTarget(item);
2726 }
else if (itemIndex < 0) {
2727 grabber->ignoreList().append(item);
2736 for (
int ii = children.size() - 1; ii >= 0; --ii) {
2737 if (children.at(ii)->z() >= 0)
2739 if (deliverDragEvent(grabber, children.at(ii), &enterEvent, currentGrabItems, formerTarget))
2748
2749
2750
2751
2752
2753
2754
2755bool QQuickDeliveryAgentPrivate::sendFilteredPointerEvent(QPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent)
2757 return sendFilteredPointerEventImpl(event, receiver, filteringParent ? filteringParent : receiver->parentItem());
2761
2762
2763bool QQuickDeliveryAgentPrivate::sendFilteredPointerEventImpl(QPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent)
2765 if (!allowChildEventFiltering)
2767 if (!filteringParent)
2769 bool filtered =
false;
2770 const bool hasHandlers = QQuickItemPrivate::get(receiver)->hasPointerHandlers();
2771 if (filteringParent->filtersChildMouseEvents() && !hasFiltered.contains(filteringParent)) {
2772 hasFiltered.append(filteringParent);
2773 if (isMouseEvent(event)) {
2774 if (receiver->acceptedMouseButtons()) {
2775 const bool wasAccepted = event->allPointsAccepted();
2776 Q_ASSERT(event->pointCount());
2777 localizePointerEvent(event, receiver);
2778 event->setAccepted(
true);
2779 auto oldMouseGrabber = event->exclusiveGrabber(event->point(0));
2780 if (filteringParent->childMouseEventFilter(receiver, event)) {
2781 qCDebug(lcMouse) <<
"mouse event intercepted by childMouseEventFilter of " << filteringParent;
2782 skipDelivery.append(filteringParent);
2784 if (event->isAccepted() && event->isBeginEvent()) {
2785 auto &point = event->point(0);
2786 auto mouseGrabber = event->exclusiveGrabber(point);
2787 if (mouseGrabber && mouseGrabber != receiver && mouseGrabber != oldMouseGrabber) {
2788 receiver->mouseUngrabEvent();
2790 event->setExclusiveGrabber(point, receiver);
2795 event->setAccepted(wasAccepted);
2798 }
else if (isTouchEvent(event)) {
2799 const bool acceptsTouchEvents = receiver->acceptTouchEvents() || hasHandlers;
2800 auto device = event->device();
2801 if (device->type() == QInputDevice::DeviceType::TouchPad &&
2802 device->capabilities().testFlag(QInputDevice::Capability::MouseEmulation)) {
2803 qCDebug(lcTouchTarget) <<
"skipping filtering of synth-mouse event from" << device;
2804 }
else if (acceptsTouchEvents || receiver->acceptedMouseButtons()) {
2807 QMutableTouchEvent filteringParentTouchEvent;
2808 QQuickItemPrivate::get(receiver)->localizedTouchEvent(
static_cast<QTouchEvent *>(event),
true, &filteringParentTouchEvent);
2809 if (filteringParentTouchEvent.type() != QEvent::None) {
2810 qCDebug(lcTouch) <<
"letting parent" << filteringParent <<
"filter for" << receiver << &filteringParentTouchEvent;
2811 filtered = filteringParent->childMouseEventFilter(receiver, &filteringParentTouchEvent);
2813 qCDebug(lcTouch) <<
"touch event intercepted by childMouseEventFilter of " << filteringParent;
2814 event->setAccepted(filteringParentTouchEvent.isAccepted());
2815 skipDelivery.append(filteringParent);
2816 if (event->isAccepted()) {
2817 for (
auto point : filteringParentTouchEvent.points()) {
2818 const QQuickItem *exclusiveGrabber = qobject_cast<
const QQuickItem *>(event->exclusiveGrabber(point));
2819 if (!exclusiveGrabber || !exclusiveGrabber->keepTouchGrab())
2820 event->setExclusiveGrabber(point, filteringParent);
2823 }
else if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)) &&
2824 !filteringParent->acceptTouchEvents()) {
2825 qCDebug(lcTouch) <<
"touch event NOT intercepted by childMouseEventFilter of " << filteringParent
2826 <<
"; accepts touch?" << filteringParent->acceptTouchEvents()
2827 <<
"receiver accepts touch?" << acceptsTouchEvents
2828 <<
"so, letting parent filter a synth-mouse event";
2830 for (
auto &tp : filteringParentTouchEvent.points()) {
2832 switch (tp.state()) {
2833 case QEventPoint::State::Pressed:
2834 t = QEvent::MouseButtonPress;
2836 case QEventPoint::State::Released:
2837 t = QEvent::MouseButtonRelease;
2839 case QEventPoint::State::Stationary:
2842 t = QEvent::MouseMove;
2846 bool touchMouseUnset = (touchMouseId == -1);
2848 if (touchMouseUnset || touchMouseId == tp.id()) {
2851 QMutableSinglePointEvent mouseEvent;
2852 touchToMouseEvent(t, tp, &filteringParentTouchEvent, &mouseEvent);
2856 touchMouseId = tp.id();
2857 touchMouseDevice = event->pointingDevice();
2858 filtered = filteringParent->childMouseEventFilter(receiver, &mouseEvent);
2860 qCDebug(lcTouch) <<
"touch event intercepted as synth mouse event by childMouseEventFilter of " << filteringParent;
2861 event->setAccepted(mouseEvent.isAccepted());
2862 skipDelivery.append(filteringParent);
2863 if (event->isAccepted() && event->isBeginEvent()) {
2864 qCDebug(lcTouchTarget) <<
"TP (mouse)" << Qt::hex << tp.id() <<
"->" << filteringParent;
2865 filteringParentTouchEvent.setExclusiveGrabber(tp, filteringParent);
2866 touchMouseUnset =
false;
2867 filteringParent->grabMouse();
2870 if (touchMouseUnset)
2873 cancelTouchMouseSynthesis();
2874 mouseEvent.point(0).setAccepted(
false);
2885 return sendFilteredPointerEventImpl(event, receiver, filteringParent->parentItem()) || filtered;
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899bool QQuickDeliveryAgentPrivate::sendFilteredMouseEvent(QEvent *event, QQuickItem *receiver, QQuickItem *filteringParent)
2901 if (!filteringParent)
2904 QQuickItemPrivate *filteringParentPrivate = QQuickItemPrivate::get(filteringParent);
2905 if (filteringParentPrivate->replayingPressEvent)
2908 bool filtered =
false;
2909 if (filteringParentPrivate->filtersChildMouseEvents && !hasFiltered.contains(filteringParent)) {
2910 hasFiltered.append(filteringParent);
2911 if (filteringParent->childMouseEventFilter(receiver, event)) {
2913 skipDelivery.append(filteringParent);
2915 qCDebug(lcMouseTarget) <<
"for" << receiver << filteringParent <<
"childMouseEventFilter ->" << filtered;
2918 return sendFilteredMouseEvent(event, receiver, filteringParent->parentItem()) || filtered;
2922
2923
2924
2925
2926
2927
2928bool QQuickDeliveryAgentPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event,
int startDragThreshold)
2930 QStyleHints *styleHints = QGuiApplication::styleHints();
2931 bool dragVelocityLimitAvailable = event->device()->capabilities().testFlag(QInputDevice::Capability::Velocity)
2932 && styleHints->startDragVelocity();
2933 bool overThreshold = qAbs(d) > (startDragThreshold >= 0 ? startDragThreshold : styleHints->startDragDistance());
2934 if (dragVelocityLimitAvailable) {
2935 QVector2D velocityVec = event->point(0).velocity();
2936 qreal velocity = axis == Qt::XAxis ? velocityVec.x() : velocityVec.y();
2937 overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
2939 return overThreshold;
2943
2944
2945
2946
2947
2948
2949bool QQuickDeliveryAgentPrivate::dragOverThreshold(qreal d, Qt::Axis axis,
const QEventPoint &tp,
int startDragThreshold)
2951 QStyleHints *styleHints = qApp->styleHints();
2952 bool overThreshold = qAbs(d) > (startDragThreshold >= 0 ? startDragThreshold : styleHints->startDragDistance());
2953 const bool dragVelocityLimitAvailable = (styleHints->startDragVelocity() > 0);
2954 if (!overThreshold && dragVelocityLimitAvailable) {
2955 qreal velocity = axis == Qt::XAxis ? tp.velocity().x() : tp.velocity().y();
2956 overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
2958 return overThreshold;
2962
2963
2964
2965
2966bool QQuickDeliveryAgentPrivate::dragOverThreshold(QVector2D delta)
2968 int threshold = qApp->styleHints()->startDragDistance();
2969 return qAbs(delta.x()) > threshold || qAbs(delta.y()) > threshold;
2973
2974
2975
2976
2977
2978
2979QVector<QQuickItem *> QQuickDeliveryAgentPrivate::contextMenuTargets(QQuickItem *item,
const QContextMenuEvent *event)
const
2981 auto predicate = [](QQuickItem *,
const QEvent *) -> std::optional<
bool> {
2982 return std::nullopt;
2985 const auto pos = event->pos().isNull() ? activeFocusItem->mapToScene({}).toPoint() : event->pos();
2986 if (event->pos().isNull())
2987 qCDebug(lcContextMenu) <<
"for QContextMenuEvent, active focus item is" << activeFocusItem <<
"@" << pos;
2988 return eventTargets(item, event, pos, predicate);
2992
2993
2994
2995
2996void QQuickDeliveryAgentPrivate::deliverContextMenuEvent(QContextMenuEvent *event)
2998 skipDelivery.clear();
2999 QVector<QQuickItem *> targetItems = contextMenuTargets(rootItem, event);
3000 qCDebug(lcContextMenu) <<
"delivering context menu event" << event <<
"to" << targetItems.size() <<
"target item(s)";
3001 QVector<QPointer<QQuickItem>> safeTargetItems(targetItems.begin(), targetItems.end());
3002 for (
auto &item : safeTargetItems) {
3003 qCDebug(lcContextMenu) <<
"- attempting to deliver to" << item;
3007 if (isSubsceneAgent)
3008 QQuickItemPrivate::get(item)->maybeHasSubsceneDeliveryAgent =
true;
3010 QCoreApplication::sendEvent(item, event);
3011 if (event->isAccepted())
3016#ifndef QT_NO_DEBUG_STREAM
3019 QDebugStateSaver saver(debug);
3022 debug <<
"QQuickDeliveryAgent(0)";
3026 debug <<
"QQuickDeliveryAgent(";
3027 if (!da->objectName().isEmpty())
3028 debug << da->objectName() <<
' ';
3029 auto root = da->rootItem();
3030 if (Q_LIKELY(root)) {
3031 debug <<
"root=" << root->metaObject()->className();
3032 if (!root->objectName().isEmpty())
3033 debug <<
' ' << root->objectName();
3044#include "moc_qquickdeliveryagent_p.cpp"
QDebug operator<<(QDebug dbg, const NSObject *nsObject)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
static bool allowSyntheticRightClick()
static bool windowHasFocus(QQuickWindow *win)
static QQuickItem * findFurthestFocusScopeAncestor(QQuickItem *item)