1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQuick module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QQUICKWINDOW_P_H
41#define QQUICKWINDOW_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include "qquickitem.h"
55#include "qquickwindow.h"
56#include "qquickevents_p_p.h"
57
58#include <QtQuick/private/qsgcontext_p.h>
59
60#include <QtCore/qthread.h>
61#include <QtCore/qmutex.h>
62#include <QtCore/qwaitcondition.h>
63#include <QtCore/qrunnable.h>
64#include <private/qwindow_p.h>
65#include <private/qopengl_p.h>
66#include <qopenglcontext.h>
67#include <QtGui/qopenglframebufferobject.h>
68#include <QtGui/qevent.h>
69#include <QtGui/qstylehints.h>
70#include <QtGui/qguiapplication.h>
71
72QT_BEGIN_NAMESPACE
73
74class QOpenGLVertexArrayObjectHelper;
75class QQuickAnimatorController;
76class QQuickDragGrabber;
77class QQuickItemPrivate;
78class QQuickPointerDevice;
79class QQuickRenderControl;
80class QQuickWindowIncubationController;
81class QQuickWindowPrivate;
82class QQuickWindowRenderLoop;
83class QSGRenderLoop;
84class QTouchEvent;
85class QRhi;
86class QRhiSwapChain;
87class QRhiRenderBuffer;
88class QRhiRenderPassDescriptor;
89
90//Make it easy to identify and customize the root item if needed
91class QQuickRootItem : public QQuickItem
92{
93 Q_OBJECT
94public:
95 QQuickRootItem();
96public Q_SLOTS:
97 void setWidth(int w) {QQuickItem::setWidth(qreal(w));}
98 void setHeight(int h) {QQuickItem::setHeight(qreal(h));}
99};
100
101class Q_QUICK_PRIVATE_EXPORT QQuickCustomRenderStage
102{
103public:
104 virtual ~QQuickCustomRenderStage() {}
105 virtual bool render() = 0;
106 virtual bool swap() = 0;
107};
108
109class Q_QUICK_PRIVATE_EXPORT QQuickWindowPrivate : public QWindowPrivate
110{
111public:
112 Q_DECLARE_PUBLIC(QQuickWindow)
113
114 enum CustomEvents {
115 FullUpdateRequest = QEvent::User + 1
116 };
117
118 static inline QQuickWindowPrivate *get(QQuickWindow *c) { return c->d_func(); }
119
120 QQuickWindowPrivate();
121 ~QQuickWindowPrivate() override;
122
123 void init(QQuickWindow *, QQuickRenderControl *control = nullptr);
124
125 QQuickRootItem *contentItem;
126 QSet<QQuickItem *> parentlessItems;
127 QQmlListProperty<QObject> data();
128
129 QQuickItem *activeFocusItem;
130
131 void deliverKeyEvent(QKeyEvent *e);
132
133 // Keeps track of the item currently receiving mouse events
134#if QT_CONFIG(cursor)
135 QQuickItem *cursorItem;
136#endif
137#if QT_CONFIG(quick_draganddrop)
138 QQuickDragGrabber *dragGrabber;
139#endif
140 int touchMouseId;
141 QQuickPointerDevice *touchMouseDevice;
142 bool checkIfDoubleTapped(ulong newPressEventTimestamp, QPoint newPressPos);
143 ulong touchMousePressTimestamp;
144 QPoint touchMousePressPos; // in screen coordiantes
145 void cancelTouchMouseSynthesis();
146
147 // Mouse positions are saved in widget coordinates
148 QPointF lastMousePosition;
149 bool deliverTouchAsMouse(QQuickItem *item, QQuickPointerEvent *pointerEvent);
150 bool isDeliveringTouchAsMouse() const { return touchMouseId != -1 && touchMouseDevice; }
151 void translateTouchEvent(QTouchEvent *touchEvent);
152 void grabTouchPoints(QObject *grabber, const QVector<int> &ids);
153 void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true);
154 void sendUngrabEvent(QQuickItem *grabber, bool touch);
155 static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = nullptr);
156 void deliverToPassiveGrabbers(const QVector<QPointer <QQuickPointerHandler> > &passiveGrabbers, QQuickPointerEvent *pointerEvent);
157 void deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent);
158 bool sendFilteredMouseEvent(QEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
159 bool sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent = nullptr);
160 bool sendFilteredPointerEventImpl(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
161 bool deliverSinglePointEventUntilAccepted(QQuickPointerEvent *);
162
163 // entry point of events to the window
164 void handleTouchEvent(QTouchEvent *);
165 void handleMouseEvent(QMouseEvent *);
166 bool compressTouchEvent(QTouchEvent *);
167 void flushFrameSynchronousEvents();
168 void deliverDelayedTouchEvent();
169
170 // the device-specific event instances which are reused during event delivery
171 mutable QVector<QQuickPointerEvent *> pointerEventInstances;
172 QQuickPointerEvent *queryPointerEventInstance(QQuickPointerDevice *device, QEvent::Type eventType = QEvent::None) const;
173 QQuickPointerEvent *pointerEventInstance(QQuickPointerDevice *device, QEvent::Type eventType = QEvent::None) const;
174
175 // delivery of pointer events:
176 QQuickPointerEvent *pointerEventInstance(QEvent *ev) const;
177 void deliverPointerEvent(QQuickPointerEvent *);
178 void deliverTouchEvent(QQuickPointerTouchEvent *);
179 bool deliverTouchCancelEvent(QTouchEvent *);
180 bool deliverPressOrReleaseEvent(QQuickPointerEvent *, bool handlersOnly = false);
181 void deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event);
182 void deliverMatchingPointsToItem(QQuickItem *item, QQuickPointerEvent *pointerEvent, bool handlersOnly = false);
183
184 QVector<QQuickItem *> pointerTargets(QQuickItem *, QQuickEventPoint *point, bool checkMouseButtons, bool checkAcceptsTouch) const;
185 QVector<QQuickItem *> mergePointerTargets(const QVector<QQuickItem *> &list1, const QVector<QQuickItem *> &list2) const;
186
187 // hover delivery
188 bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted);
189 bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos,
190 Qt::KeyboardModifiers modifiers, ulong timestamp, bool accepted);
191 bool clearHover(ulong timestamp = 0);
192
193#if QT_CONFIG(quick_draganddrop)
194 void deliverDragEvent(QQuickDragGrabber *, QEvent *);
195 bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *);
196#endif
197#if QT_CONFIG(cursor)
198 void updateCursor(const QPointF &scenePos);
199 QQuickItem *findCursorItem(QQuickItem *item, const QPointF &scenePos);
200#endif
201
202 QList<QQuickItem*> hoverItems;
203 enum FocusOption {
204 DontChangeFocusProperty = 0x01,
205 DontChangeSubFocusItem = 0x02
206 };
207 Q_DECLARE_FLAGS(FocusOptions, FocusOption)
208
209 void setFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = nullptr);
210 void clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = nullptr);
211 static void notifyFocusChangesRecur(QQuickItem **item, int remaining);
212 void clearFocusObject() override;
213
214 void updateFocusItemTransform();
215
216 void dirtyItem(QQuickItem *);
217 void cleanup(QSGNode *);
218
219 void polishItems();
220 void forcePolish();
221 void syncSceneGraph();
222 void renderSceneGraph(const QSize &size, const QSize &surfaceSize = QSize());
223
224 bool isRenderable() const;
225
226 bool emitError(QQuickWindow::SceneGraphError error, const QString &msg);
227
228 QQuickItem::UpdatePaintNodeData updatePaintNodeData;
229
230 QQuickItem *dirtyItemList;
231 QList<QSGNode *> cleanupNodeList;
232
233 QVector<QQuickItem *> itemsToPolish;
234 QVector<QQuickItem *> hasFiltered; // during event delivery to a single receiver, the filtering parents for which childMouseEventFilter was already called
235 QVector<QQuickItem *> skipDelivery; // during delivery of one event to all receivers, Items to which we know delivery is no longer necessary
236
237 qreal devicePixelRatio;
238 QMetaObject::Connection physicalDpiChangedConnection;
239
240 void updateDirtyNodes();
241 void cleanupNodes();
242 void cleanupNodesOnShutdown();
243 bool updateEffectiveOpacity(QQuickItem *);
244 void updateEffectiveOpacityRoot(QQuickItem *, qreal);
245 void updateDirtyNode(QQuickItem *);
246
247 void fireFrameSwapped() { Q_EMIT q_func()->frameSwapped(); }
248 void fireOpenGLContextCreated(QOpenGLContext *context) { Q_EMIT q_func()->openglContextCreated(context); }
249 void fireAboutToStop() { Q_EMIT q_func()->sceneGraphAboutToStop(); }
250
251 QSGRenderContext *context;
252 QSGRenderer *renderer;
253 QByteArray customRenderMode; // Default renderer supports "clip", "overdraw", "changes", "batches" and blank.
254
255 QSGRenderLoop *windowManager;
256 QQuickRenderControl *renderControl;
257 QQuickAnimatorController *animationController;
258 QScopedPointer<QTouchEvent> delayedTouch;
259
260 int pointerEventRecursionGuard;
261 QQuickCustomRenderStage *customRenderStage;
262
263 QColor clearColor;
264
265 uint clearBeforeRendering : 1;
266
267 uint persistentGLContext : 1;
268 uint persistentSceneGraph : 1;
269
270 uint lastWheelEventAccepted : 1;
271 bool componentCompleted : 1;
272
273 bool allowChildEventFiltering : 1;
274 bool allowDoubleClick : 1;
275
276 Qt::FocusReason lastFocusReason;
277
278 QOpenGLFramebufferObject *renderTarget;
279 uint renderTargetId;
280 QSize renderTargetSize;
281
282 QOpenGLVertexArrayObjectHelper *vaoHelper;
283
284 mutable QQuickWindowIncubationController *incubationController;
285
286 static bool defaultAlphaBuffer;
287 static QQuickWindow::TextRenderType textRenderType;
288
289 static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold = -1);
290
291 template <typename TEventPoint>
292 static bool dragOverThreshold(qreal d, Qt::Axis axis, const TEventPoint *p, int startDragThreshold = -1)
293 {
294 QStyleHints *styleHints = qApp->styleHints();
295 bool overThreshold = qAbs(d) > (startDragThreshold >= 0 ? startDragThreshold : styleHints->startDragDistance());
296 const bool dragVelocityLimitAvailable = (styleHints->startDragVelocity() > 0);
297 if (!overThreshold && dragVelocityLimitAvailable) {
298 qreal velocity = axis == Qt::XAxis ? p->velocity().x() : p->velocity().y();
299 overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
300 }
301 return overThreshold;
302 }
303
304 static bool dragOverThreshold(const QQuickEventPoint *point)
305 {
306 QPointF delta = point->scenePosition() - point->scenePressPosition();
307 return (QQuickWindowPrivate::dragOverThreshold(delta.x(), Qt::XAxis, point) ||
308 QQuickWindowPrivate::dragOverThreshold(delta.y(), Qt::YAxis, point));
309 }
310
311 static bool dragOverThreshold(QVector2D delta);
312
313 // data property
314 static void data_append(QQmlListProperty<QObject> *, QObject *);
315 static int data_count(QQmlListProperty<QObject> *);
316 static QObject *data_at(QQmlListProperty<QObject> *, int);
317 static void data_clear(QQmlListProperty<QObject> *);
318
319 static void contextCreationFailureMessage(const QSurfaceFormat &format,
320 QString *translatedMessage,
321 QString *untranslatedMessage,
322 bool isEs);
323
324 static void emitBeforeRenderPassRecording(void *ud);
325 static void emitAfterRenderPassRecording(void *ud);
326
327 QMutex renderJobMutex;
328 QList<QRunnable *> beforeSynchronizingJobs;
329 QList<QRunnable *> afterSynchronizingJobs;
330 QList<QRunnable *> beforeRenderingJobs;
331 QList<QRunnable *> afterRenderingJobs;
332 QList<QRunnable *> afterSwapJobs;
333
334 void runAndClearJobs(QList<QRunnable *> *jobs);
335
336 QQuickWindow::GraphicsStateInfo rhiStateInfo;
337 QRhi *rhi = nullptr;
338 QRhiSwapChain *swapchain = nullptr;
339 QRhiRenderBuffer *depthStencilForSwapchain = nullptr;
340 QRhiRenderPassDescriptor *rpDescForSwapchain = nullptr;
341 uint hasActiveSwapchain : 1;
342 uint hasRenderableSwapchain : 1;
343 uint swapchainJustBecameRenderable : 1;
344
345private:
346 static void cleanupNodesOnShutdown(QQuickItem *);
347};
348
349class QQuickWindowQObjectCleanupJob : public QRunnable
350{
351public:
352 QQuickWindowQObjectCleanupJob(QObject *o) : object(o) { }
353 void run() override { delete object; }
354 QObject *object;
355 static void schedule(QQuickWindow *window, QObject *object) {
356 Q_ASSERT(window);
357 Q_ASSERT(object);
358 window->scheduleRenderJob(new QQuickWindowQObjectCleanupJob(object), QQuickWindow::AfterSynchronizingStage);
359 }
360};
361
362Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickWindowPrivate::FocusOptions)
363
364QT_END_NAMESPACE
365
366#endif // QQUICKWINDOW_P_H
367