1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QQUICKDELIVERYAGENT_P_P_H
5#define QQUICKDELIVERYAGENT_P_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtQuick/private/qquickdeliveryagent_p.h>
19#include <QtGui/qevent.h>
20#include <QtCore/qstack.h>
21#include <QtCore/qxpfunctional.h>
22
23#include <private/qevent_p.h>
24#include <private/qpointingdevice_p.h>
25
26#include <QtCore/qpointer.h>
27#include <private/qobject_p.h>
28
29#include <memory>
30
31QT_BEGIN_NAMESPACE
32
33class QQuickDragGrabber;
34class QQuickItem;
35class QQuickPointerHandler;
36class QQuickWindow;
37
38/*! \internal
39 Extra device-specific data to be stored in QInputDevicePrivate::qqExtra
40*/
41struct QQuickPointingDeviceExtra {
42 // used in QQuickPointerHandlerPrivate::deviceDeliveryTargets
43 QVector<QObject *> deliveryTargets;
44};
45
46class Q_QUICK_EXPORT QQuickDeliveryAgentPrivate : public QObjectPrivate
47{
48public:
49 Q_DECLARE_PUBLIC(QQuickDeliveryAgent)
50 QQuickDeliveryAgentPrivate(QQuickItem *root);
51 ~QQuickDeliveryAgentPrivate();
52
53 QQuickItem *rootItem = nullptr;
54
55 QQuickItem *activeFocusItem = nullptr;
56
57 void deliverKeyEvent(QKeyEvent *e);
58
59 enum FocusOption {
60 DontChangeFocusProperty = 0x01,
61 DontChangeSubFocusItem = 0x02
62 };
63 Q_DECLARE_FLAGS(FocusOptions, FocusOption)
64
65 void setFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = { });
66 void clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = { });
67 static void notifyFocusChangesRecur(QQuickItem **item, int remaining, Qt::FocusReason reason);
68 void clearFocusObject();
69 void updateFocusItemTransform();
70
71 QQuickItem *focusTargetItem() const;
72
73 // Keeps track of the item currently receiving mouse events
74#if QT_CONFIG(quick_draganddrop)
75 QQuickDragGrabber *dragGrabber = nullptr;
76#endif
77 QQuickItem *lastUngrabbed = nullptr;
78 QStack<QPointerEvent *> eventsInDelivery;
79 QFlatMap<QPointer<QQuickItem>, uint> hoverItems;
80 QVector<QQuickItem *> hasFiltered; // during event delivery to a single receiver, the filtering parents for which childMouseEventFilter was already called
81 QVector<QQuickItem *> skipDelivery; // during delivery of one event to all receivers, Items to which we know delivery is no longer necessary
82
83 std::unique_ptr<QMutableTouchEvent> delayedTouch;
84 QList<const QPointingDevice *> knownPointingDevices;
85
86 uint currentHoverId = 0;
87#if QT_CONFIG(wheelevent)
88 uint lastWheelEventAccepted = 0;
89#endif
90 uchar compressedTouchCount = 0;
91 bool allowChildEventFiltering = true;
92 bool frameSynchronousHoverEnabled = true;
93 bool hoveredLeafItemFound = false;
94
95 bool isSubsceneAgent = false;
96 static bool subsceneAgentsExist;
97 // QQuickDeliveryAgent::event() sets this to the one that's currently (trying to) handle the event
98 static QQuickDeliveryAgent *currentEventDeliveryAgent;
99 static QQuickDeliveryAgent *currentOrItemDeliveryAgent(const QQuickItem *item);
100
101 Qt::FocusReason lastFocusReason = Qt::OtherFocusReason;
102 int pointerEventRecursionGuard = 0;
103
104 int touchMouseId = -1; // only for obsolete stuff like QQuickItem::grabMouse()
105 // TODO get rid of these
106 const QPointingDevice *touchMouseDevice = nullptr;
107 ulong touchMousePressTimestamp = 0;
108 QPoint touchMousePressPos; // in screen coordinates
109
110 QQuickDeliveryAgent::Transform *sceneTransform = nullptr;
111
112 bool isDeliveringTouchAsMouse() const { return touchMouseId != -1 && touchMouseDevice; }
113 void cancelTouchMouseSynthesis();
114
115 bool checkIfDoubleTapped(ulong newPressEventTimestamp, const QPoint &newPressPos);
116 void resetIfDoubleTapPrevented(const QEventPoint &pressedPoint);
117 QPointingDevicePrivate::EventPointData *mousePointData();
118 QPointerEvent *eventInDelivery() const;
119
120 // Mouse positions are saved in widget coordinates
121 QPointF lastMousePosition;
122 bool deliverTouchAsMouse(QQuickItem *item, QTouchEvent *pointerEvent);
123 void translateTouchEvent(QTouchEvent *touchEvent);
124 void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true, bool cancel = false);
125 void clearGrabbers(QPointerEvent *pointerEvent);
126 void onGrabChanged(QObject *grabber, QPointingDevice::GrabTransition transition, const QPointerEvent *event, const QEventPoint &point);
127 static QPointerEvent *clonePointerEvent(QPointerEvent *event, std::optional<QPointF> transformedLocalPos = std::nullopt);
128 void deliverToPassiveGrabbers(const QVector<QPointer<QObject> > &passiveGrabbers, QPointerEvent *pointerEvent);
129 bool sendFilteredMouseEvent(QEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
130 bool sendFilteredPointerEvent(QPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent = nullptr);
131 bool sendFilteredPointerEventImpl(QPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
132 bool deliverSinglePointEventUntilAccepted(QPointerEvent *);
133
134 // entry point of events to the window
135 void handleTouchEvent(QTouchEvent *);
136 void handleMouseEvent(QMouseEvent *);
137 bool compressTouchEvent(QTouchEvent *);
138 void flushFrameSynchronousEvents(QQuickWindow *win);
139 void deliverDelayedTouchEvent();
140 void handleWindowDeactivate(QQuickWindow *win);
141 void handleWindowHidden(QQuickWindow *win);
142
143 // utility functions that used to be in QQuickPointerEvent et al.
144 bool allUpdatedPointsAccepted(const QPointerEvent *ev);
145 static void localizePointerEvent(QPointerEvent *ev, const QQuickItem *dest);
146 QList<QObject *> exclusiveGrabbers(QPointerEvent *ev);
147 static bool anyPointGrabbed(const QPointerEvent *ev);
148 static bool allPointsGrabbed(const QPointerEvent *ev);
149 static bool isMouseEvent(const QPointerEvent *ev);
150 static bool isMouseOrWheelEvent(const QPointerEvent *ev);
151 static bool isHoverEvent(const QPointerEvent *ev);
152 static bool isHoveringMoveEvent(const QPointerEvent *ev);
153 static bool isTouchEvent(const QPointerEvent *ev);
154 static bool isTabletEvent(const QPointerEvent *ev);
155 static bool isEventFromMouseOrTouchpad(const QPointerEvent *ev);
156 static bool isSynthMouse(const QPointerEvent *ev);
157 static bool isWithinDoubleClickInterval(ulong timeInterval);
158 static bool isWithinDoubleTapDistance(const QPoint &distanceBetweenPresses);
159 static bool isSinglePointDevice(const QInputDevice *dev);
160 static QQuickPointingDeviceExtra *deviceExtra(const QInputDevice *device);
161
162 // delivery of pointer events:
163 void touchToMouseEvent(QEvent::Type type, const QEventPoint &p, const QTouchEvent *touchEvent, QMutableSinglePointEvent *mouseEvent);
164 void ensureDeviceConnected(const QPointingDevice *dev);
165 void deliverPointerEvent(QPointerEvent *);
166 bool deliverTouchCancelEvent(QTouchEvent *);
167 bool deliverPressOrReleaseEvent(QPointerEvent *, bool handlersOnly = false);
168 void deliverUpdatedPoints(QPointerEvent *event);
169 void deliverMatchingPointsToItem(QQuickItem *item, bool isGrabber, QPointerEvent *pointerEvent, bool handlersOnly = false);
170
171 QVector<QQuickItem *> eventTargets(QQuickItem *, const QEvent *event, QPointF scenePos, qxp::function_ref<std::optional<bool> (QQuickItem *, const QEvent *)> predicate) const;
172 QVector<QQuickItem *> pointerTargets(QQuickItem *, const QPointerEvent *event, const QEventPoint &point,
173 bool checkMouseButtons, bool checkAcceptsTouch) const;
174 QVector<QQuickItem *> mergePointerTargets(const QVector<QQuickItem *> &list1, const QVector<QQuickItem *> &list2) const;
175
176 // hover delivery
177 enum class HoverChange : uint8_t {
178 Clear,
179 Set,
180 };
181 bool deliverHoverEvent(const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp);
182 bool deliverHoverEventRecursive(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp);
183 bool deliverHoverEventToItem(QQuickItem *item, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp,
184 HoverChange hoverChange);
185 bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos,
186 Qt::KeyboardModifiers modifiers, ulong timestamp);
187 bool clearHover(ulong timestamp = 0);
188
189#if QT_CONFIG(quick_draganddrop)
190 void deliverDragEvent(QQuickDragGrabber *, QEvent *);
191 bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *,
192 QVarLengthArray<QQuickItem *, 64> *currentGrabItems = nullptr,
193 QObject *formerTarget = nullptr);
194#endif
195
196 static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold = -1);
197
198 static bool dragOverThreshold(qreal d, Qt::Axis axis, const QEventPoint &tp, int startDragThreshold = -1);
199
200 static bool dragOverThreshold(QVector2D delta);
201
202 // context menu events
203 QVector<QQuickItem *> contextMenuTargets(QQuickItem *item, const QContextMenuEvent *event) const;
204 void deliverContextMenuEvent(QContextMenuEvent *event);
205};
206
207Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickDeliveryAgentPrivate::FocusOptions)
208
209QT_END_NAMESPACE
210
211#endif // QQUICKDELIVERYAGENT_P_P_H
212

source code of qtdeclarative/src/quick/util/qquickdeliveryagent_p_p.h