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