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 Q_QUICK_PRIVATE_EXPORT 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 TriggerContextCreationFailure = QEvent::User + 2
117 };
118
119 static inline QQuickWindowPrivate *get(QQuickWindow *c) { return c->d_func(); }
120
121 QQuickWindowPrivate();
122 ~QQuickWindowPrivate() override;
123
124 void init(QQuickWindow *, QQuickRenderControl *control = nullptr);
125
126 QQuickRootItem *contentItem;
127 QSet<QQuickItem *> parentlessItems;
128 QQmlListProperty<QObject> data();
129
130 QQuickItem *activeFocusItem;
131
132 void deliverKeyEvent(QKeyEvent *e);
133
134 // Keeps track of the item currently receiving mouse events
135#if QT_CONFIG(cursor)
136 QQuickItem *cursorItem;
137 QQuickPointerHandler *cursorHandler;
138#endif
139#if QT_CONFIG(quick_draganddrop)
140 QQuickDragGrabber *dragGrabber;
141#endif
142 int touchMouseId;
143 QQuickPointerDevice *touchMouseDevice;
144 bool checkIfDoubleTapped(ulong newPressEventTimestamp, QPoint newPressPos);
145 ulong touchMousePressTimestamp;
146 QPoint touchMousePressPos; // in screen coordiantes
147 void cancelTouchMouseSynthesis();
148
149 // Mouse positions are saved in widget coordinates
150 QPointF lastMousePosition;
151 bool deliverTouchAsMouse(QQuickItem *item, QQuickPointerEvent *pointerEvent);
152 bool isDeliveringTouchAsMouse() const { return touchMouseId != -1 && touchMouseDevice; }
153 void translateTouchEvent(QTouchEvent *touchEvent);
154 void grabTouchPoints(QObject *grabber, const QVector<int> &ids);
155 void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true);
156 void sendUngrabEvent(QQuickItem *grabber, bool touch);
157 static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = nullptr);
158 void deliverToPassiveGrabbers(const QVector<QPointer <QQuickPointerHandler> > &passiveGrabbers, QQuickPointerEvent *pointerEvent);
159 void deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent);
160 bool sendFilteredMouseEvent(QEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
161 bool sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent = nullptr);
162 bool sendFilteredPointerEventImpl(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
163 bool deliverSinglePointEventUntilAccepted(QQuickPointerEvent *);
164
165 // entry point of events to the window
166 void handleTouchEvent(QTouchEvent *);
167 void handleMouseEvent(QMouseEvent *);
168 bool compressTouchEvent(QTouchEvent *);
169 void flushFrameSynchronousEvents();
170 void deliverDelayedTouchEvent();
171
172 // the device-specific event instances which are reused during event delivery
173 mutable QVector<QQuickPointerEvent *> pointerEventInstances;
174 QQuickPointerEvent *queryPointerEventInstance(QQuickPointerDevice *device, QEvent::Type eventType = QEvent::None) const;
175 QQuickPointerEvent *pointerEventInstance(QQuickPointerDevice *device, QEvent::Type eventType = QEvent::None) const;
176
177 // delivery of pointer events:
178 QQuickPointerEvent *pointerEventInstance(QEvent *ev) const;
179 void deliverPointerEvent(QQuickPointerEvent *);
180 void deliverTouchEvent(QQuickPointerTouchEvent *);
181 bool deliverTouchCancelEvent(QTouchEvent *);
182 bool deliverPressOrReleaseEvent(QQuickPointerEvent *, bool handlersOnly = false);
183 void deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event);
184 void deliverMatchingPointsToItem(QQuickItem *item, QQuickPointerEvent *pointerEvent, bool handlersOnly = false);
185
186 QVector<QQuickItem *> pointerTargets(QQuickItem *, QQuickEventPoint *point, bool checkMouseButtons, bool checkAcceptsTouch) const;
187 QVector<QQuickItem *> mergePointerTargets(const QVector<QQuickItem *> &list1, const QVector<QQuickItem *> &list2) const;
188
189 // hover delivery
190 bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted);
191 bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos,
192 Qt::KeyboardModifiers modifiers, ulong timestamp, bool accepted);
193 bool clearHover(ulong timestamp = 0);
194
195#if QT_CONFIG(quick_draganddrop)
196 void deliverDragEvent(QQuickDragGrabber *, QEvent *);
197 bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *, QVarLengthArray<QQuickItem*, 64> *currentGrabItems = nullptr);
198#endif
199#if QT_CONFIG(cursor)
200 void updateCursor(const QPointF &scenePos);
201 QPair<QQuickItem*, QQuickPointerHandler*> findCursorItemAndHandler(QQuickItem *item, const QPointF &scenePos) const;
202#endif
203
204 QList<QQuickItem*> hoverItems;
205 enum FocusOption {
206 DontChangeFocusProperty = 0x01,
207 DontChangeSubFocusItem = 0x02
208 };
209 Q_DECLARE_FLAGS(FocusOptions, FocusOption)
210
211 void setFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = { });
212 void clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = { });
213 static void notifyFocusChangesRecur(QQuickItem **item, int remaining);
214 void clearFocusObject() override;
215
216 void updateFocusItemTransform();
217
218 void dirtyItem(QQuickItem *);
219 void cleanup(QSGNode *);
220
221 void polishItems();
222 void forcePolish();
223 void syncSceneGraph();
224 void renderSceneGraph(const QSize &size, const QSize &surfaceSize = QSize());
225
226 bool isRenderable() const;
227
228 bool emitError(QQuickWindow::SceneGraphError error, const QString &msg);
229
230 QQuickItem::UpdatePaintNodeData updatePaintNodeData;
231
232 QQuickItem *dirtyItemList;
233 QList<QSGNode *> cleanupNodeList;
234
235 QVector<QQuickItem *> itemsToPolish;
236 QVector<QQuickItem *> hasFiltered; // during event delivery to a single receiver, the filtering parents for which childMouseEventFilter was already called
237 QVector<QQuickItem *> skipDelivery; // during delivery of one event to all receivers, Items to which we know delivery is no longer necessary
238
239 qreal devicePixelRatio;
240 QMetaObject::Connection physicalDpiChangedConnection;
241
242 void updateDirtyNodes();
243 void cleanupNodes();
244 void cleanupNodesOnShutdown();
245 bool updateEffectiveOpacity(QQuickItem *);
246 void updateEffectiveOpacityRoot(QQuickItem *, qreal);
247 void updateDirtyNode(QQuickItem *);
248
249 void fireFrameSwapped() { Q_EMIT q_func()->frameSwapped(); }
250 void fireOpenGLContextCreated(QOpenGLContext *context) { Q_EMIT q_func()->openglContextCreated(context); }
251 void fireAboutToStop() { Q_EMIT q_func()->sceneGraphAboutToStop(); }
252
253 QSGRenderContext *context;
254 QSGRenderer *renderer;
255 QByteArray customRenderMode; // Default renderer supports "clip", "overdraw", "changes", "batches" and blank.
256
257 QSGRenderLoop *windowManager;
258 QQuickRenderControl *renderControl;
259 QScopedPointer<QQuickAnimatorController> animationController;
260 QScopedPointer<QTouchEvent> delayedTouch;
261
262 int pointerEventRecursionGuard;
263 QQuickCustomRenderStage *customRenderStage;
264
265 QColor clearColor;
266
267 uint clearBeforeRendering : 1;
268
269 uint persistentGLContext : 1;
270 uint persistentSceneGraph : 1;
271
272 uint lastWheelEventAccepted : 1;
273 bool componentCompleted : 1;
274
275 bool allowChildEventFiltering : 1;
276 bool allowDoubleClick : 1;
277
278 Qt::FocusReason lastFocusReason;
279
280 QOpenGLFramebufferObject *renderTarget;
281 uint renderTargetId;
282 QSize renderTargetSize;
283
284 QOpenGLVertexArrayObjectHelper *vaoHelper;
285
286 mutable QQuickWindowIncubationController *incubationController;
287
288 static bool defaultAlphaBuffer;
289 static QQuickWindow::TextRenderType textRenderType;
290
291 static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold = -1);
292
293 static bool dragOverThreshold(qreal d, Qt::Axis axis, const QTouchEvent::TouchPoint *tp, int startDragThreshold = -1);
294
295 static bool dragOverThreshold(QVector2D delta);
296
297 // data property
298 static void data_append(QQmlListProperty<QObject> *, QObject *);
299 static int data_count(QQmlListProperty<QObject> *);
300 static QObject *data_at(QQmlListProperty<QObject> *, int);
301 static void data_clear(QQmlListProperty<QObject> *);
302 static void data_replace(QQmlListProperty<QObject> *, int, QObject *);
303 static void data_removeLast(QQmlListProperty<QObject> *);
304
305 static void contextCreationFailureMessage(const QSurfaceFormat &format,
306 QString *translatedMessage,
307 QString *untranslatedMessage);
308 static void rhiCreationFailureMessage(const QString &backendName,
309 QString *translatedMessage,
310 QString *untranslatedMessage);
311
312 static void emitBeforeRenderPassRecording(void *ud);
313 static void emitAfterRenderPassRecording(void *ud);
314
315 QMutex renderJobMutex;
316 QList<QRunnable *> beforeSynchronizingJobs;
317 QList<QRunnable *> afterSynchronizingJobs;
318 QList<QRunnable *> beforeRenderingJobs;
319 QList<QRunnable *> afterRenderingJobs;
320 QList<QRunnable *> afterSwapJobs;
321
322 void runAndClearJobs(QList<QRunnable *> *jobs);
323
324 QQuickWindow::GraphicsStateInfo rhiStateInfo;
325 QRhi *rhi = nullptr;
326 QRhiSwapChain *swapchain = nullptr;
327 QRhiRenderBuffer *depthStencilForSwapchain = nullptr;
328 QRhiRenderPassDescriptor *rpDescForSwapchain = nullptr;
329 uint hasActiveSwapchain : 1;
330 uint hasRenderableSwapchain : 1;
331 uint swapchainJustBecameRenderable : 1;
332
333private:
334 static void cleanupNodesOnShutdown(QQuickItem *);
335};
336
337class QQuickWindowQObjectCleanupJob : public QRunnable
338{
339public:
340 QQuickWindowQObjectCleanupJob(QObject *o) : object(o) { }
341 void run() override { delete object; }
342 QObject *object;
343 static void schedule(QQuickWindow *window, QObject *object) {
344 Q_ASSERT(window);
345 Q_ASSERT(object);
346 window->scheduleRenderJob(job: new QQuickWindowQObjectCleanupJob(object), schedule: QQuickWindow::AfterSynchronizingStage);
347 }
348};
349
350Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickWindowPrivate::FocusOptions)
351
352QT_END_NAMESPACE
353
354#endif // QQUICKWINDOW_P_H
355

source code of qtdeclarative/src/quick/items/qquickwindow_p.h