1// Copyright (C) 2020 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#include "qquickwindow.h"
5#include "qquickwindow_p.h"
6
7#include "qquickitem.h"
8#include "qquickitem_p.h"
9#include "qquickevents_p_p.h"
10#include "qquickgraphicsdevice_p.h"
11#include "qquickwindowcontainer_p.h"
12
13#include <QtQuick/private/qsgrenderer_p.h>
14#include <QtQuick/private/qsgplaintexture_p.h>
15#include <QtQuick/private/qquickpointerhandler_p.h>
16#include <QtQuick/private/qquickpointerhandler_p_p.h>
17#include <private/qsgrenderloop_p.h>
18#include <private/qsgrhisupport_p.h>
19#include <private/qquickrendercontrol_p.h>
20#include <private/qquickanimatorcontroller_p.h>
21#include <private/qquickprofiler_p.h>
22#include <private/qquicktextinterface_p.h>
23
24#include <private/qguiapplication_p.h>
25
26#include <private/qabstractanimation_p.h>
27
28#include <QtGui/qpainter.h>
29#include <QtGui/qevent.h>
30#include <QtGui/qmatrix4x4.h>
31#include <QtGui/private/qevent_p.h>
32#include <QtGui/private/qpointingdevice_p.h>
33#include <QtCore/qvarlengtharray.h>
34#include <QtCore/qabstractanimation.h>
35#include <QtCore/QLibraryInfo>
36#include <QtCore/QRunnable>
37#include <QtQml/qqmlincubator.h>
38#include <QtQml/qqmlinfo.h>
39#include <QtQml/private/qqmlmetatype_p.h>
40
41#include <QtQuick/private/qquickpixmap_p.h>
42
43#include <private/qqmldebugserviceinterfaces_p.h>
44#include <private/qqmldebugconnector_p.h>
45#include <private/qsgdefaultrendercontext_p.h>
46#include <private/qsgsoftwarerenderer_p.h>
47#if QT_CONFIG(opengl)
48#include <private/qopengl_p.h>
49#include <QOpenGLContext>
50#endif
51#ifndef QT_NO_DEBUG_STREAM
52#include <private/qdebug_p.h>
53#endif
54#include <QtCore/qpointer.h>
55
56#include <rhi/qrhi.h>
57
58#include <utility>
59#include <mutex>
60
61QT_BEGIN_NAMESPACE
62
63Q_DECLARE_LOGGING_CATEGORY(lcHoverTrace)
64Q_DECLARE_LOGGING_CATEGORY(lcMouse)
65Q_DECLARE_LOGGING_CATEGORY(lcTouch)
66Q_DECLARE_LOGGING_CATEGORY(lcPtr)
67Q_LOGGING_CATEGORY(lcDirty, "qt.quick.dirty")
68Q_LOGGING_CATEGORY(lcQuickWindow, "qt.quick.window")
69Q_LOGGING_CATEGORY(lcTransient, "qt.quick.window.transient")
70
71bool QQuickWindowPrivate::defaultAlphaBuffer = false;
72
73#if defined(QT_QUICK_DEFAULT_TEXT_RENDER_TYPE)
74QQuickWindow::TextRenderType QQuickWindowPrivate::textRenderType = QQuickWindow::QT_QUICK_DEFAULT_TEXT_RENDER_TYPE;
75#else
76QQuickWindow::TextRenderType QQuickWindowPrivate::textRenderType = QQuickWindow::QtTextRendering;
77#endif
78
79class QQuickWindowIncubationController : public QObject, public QQmlIncubationController
80{
81 Q_OBJECT
82
83public:
84 QQuickWindowIncubationController(QSGRenderLoop *loop)
85 : m_renderLoop(loop), m_timer(0)
86 {
87 // Allow incubation for 1/3 of a frame.
88 m_incubation_time = qMax(a: 1, b: int(1000 / QGuiApplication::primaryScreen()->refreshRate()) / 3);
89
90 QAnimationDriver *animationDriver = m_renderLoop->animationDriver();
91 if (animationDriver) {
92 connect(sender: animationDriver, signal: &QAnimationDriver::stopped, context: this, slot: &QQuickWindowIncubationController::animationStopped);
93 connect(sender: m_renderLoop, signal: &QSGRenderLoop::timeToIncubate, context: this, slot: &QQuickWindowIncubationController::incubate);
94 }
95 }
96
97protected:
98 void timerEvent(QTimerEvent *) override
99 {
100 killTimer(id: m_timer);
101 m_timer = 0;
102 incubate();
103 }
104
105 void incubateAgain() {
106 if (m_timer == 0) {
107 // Wait for a while before processing the next batch. Using a
108 // timer to avoid starvation of system events.
109 m_timer = startTimer(interval: m_incubation_time);
110 }
111 }
112
113public slots:
114 void incubate() {
115 if (m_renderLoop && incubatingObjectCount()) {
116 if (m_renderLoop->interleaveIncubation()) {
117 incubateFor(msecs: m_incubation_time);
118 } else {
119 incubateFor(msecs: m_incubation_time * 2);
120 if (incubatingObjectCount())
121 incubateAgain();
122 }
123 }
124 }
125
126 void animationStopped() { incubate(); }
127
128protected:
129 void incubatingObjectCountChanged(int count) override
130 {
131 if (count && m_renderLoop && !m_renderLoop->interleaveIncubation())
132 incubateAgain();
133 }
134
135private:
136 QPointer<QSGRenderLoop> m_renderLoop;
137 int m_incubation_time;
138 int m_timer;
139};
140
141#if QT_CONFIG(accessibility)
142/*!
143 Returns an accessibility interface for this window, or 0 if such an
144 interface cannot be created.
145*/
146QAccessibleInterface *QQuickWindow::accessibleRoot() const
147{
148 return QAccessible::queryAccessibleInterface(const_cast<QQuickWindow*>(this));
149}
150#endif
151
152
153/*
154Focus behavior
155==============
156
157Prior to being added to a valid window items can set and clear focus with no
158effect. Only once items are added to a window (by way of having a parent set that
159already belongs to a window) do the focus rules apply. Focus goes back to
160having no effect if an item is removed from a window.
161
162When an item is moved into a new focus scope (either being added to a window
163for the first time, or having its parent changed), if the focus scope already has
164a scope focused item that takes precedence over the item being added. Otherwise,
165the focus of the added tree is used. In the case of a tree of items being
166added to a window for the first time, which may have a conflicted focus state (two
167or more items in one scope having focus set), the same rule is applied item by item -
168thus the first item that has focus will get it (assuming the scope doesn't already
169have a scope focused item), and the other items will have their focus cleared.
170*/
171
172QQuickRootItem::QQuickRootItem()
173{
174 // child items with ItemObservesViewport can treat the window's content item
175 // as the ultimate viewport: avoid populating SG nodes that fall outside
176 setFlag(flag: ItemIsViewport);
177}
178
179/*! \reimp */
180void QQuickWindow::exposeEvent(QExposeEvent *)
181{
182 Q_D(QQuickWindow);
183 if (d->windowManager)
184 d->windowManager->exposureChanged(window: this);
185}
186
187/*! \reimp */
188void QQuickWindow::resizeEvent(QResizeEvent *ev)
189{
190 Q_D(QQuickWindow);
191 if (d->contentItem)
192 d->contentItem->setSize(ev->size());
193 if (d->windowManager)
194 d->windowManager->resize(this);
195}
196
197/*! \reimp */
198void QQuickWindow::showEvent(QShowEvent *)
199{
200 Q_D(QQuickWindow);
201 if (d->windowManager)
202 d->windowManager->show(window: this);
203}
204
205/*! \reimp */
206void QQuickWindow::hideEvent(QHideEvent *)
207{
208 Q_D(QQuickWindow);
209 if (auto da = d->deliveryAgentPrivate())
210 da->handleWindowHidden(win: this);
211 if (d->windowManager)
212 d->windowManager->hide(window: this);
213}
214
215/*! \reimp */
216void QQuickWindow::closeEvent(QCloseEvent *e)
217{
218 QQuickCloseEvent qev;
219 qev.setAccepted(e->isAccepted());
220 emit closing(close: &qev);
221 e->setAccepted(qev.isAccepted());
222}
223
224/*! \reimp */
225void QQuickWindow::focusOutEvent(QFocusEvent *ev)
226{
227 Q_D(QQuickWindow);
228 if (d->contentItem)
229 d->contentItem->setFocus(focus: false, reason: ev->reason());
230}
231
232/*! \reimp */
233void QQuickWindow::focusInEvent(QFocusEvent *ev)
234{
235 Q_D(QQuickWindow);
236 if (d->inDestructor)
237 return;
238 if (d->contentItem)
239 d->contentItem->setFocus(focus: true, reason: ev->reason());
240 if (auto da = d->deliveryAgentPrivate())
241 da->updateFocusItemTransform();
242}
243
244#if QT_CONFIG(im)
245static bool transformDirtyOnItemOrAncestor(const QQuickItem *item)
246{
247 while (item) {
248 if (QQuickItemPrivate::get(item)->dirtyAttributes & (
249 QQuickItemPrivate::TransformOrigin |
250 QQuickItemPrivate::Transform |
251 QQuickItemPrivate::BasicTransform |
252 QQuickItemPrivate::Position |
253 QQuickItemPrivate::Size |
254 QQuickItemPrivate::ParentChanged |
255 QQuickItemPrivate::Clip)) {
256 return true;
257 }
258 item = item->parentItem();
259 }
260 return false;
261}
262#endif
263
264/*!
265 * \internal
266
267 A "polish loop" can occur inside QQuickWindowPrivate::polishItems(). It is when an item calls
268 polish() on an(other?) item from updatePolish(). If this anomaly happens repeatedly and without
269 interruption (of a well-behaved updatePolish() that doesn't call polish()), it is a strong
270 indication that we are heading towards an infinite polish loop. A polish loop is not a bug in
271 Qt Quick - it is a bug caused by ill-behaved items put in the scene.
272
273 We can detect this sequence of polish loops easily, since the
274 QQuickWindowPrivate::itemsToPolish is basically a stack: polish() will push to it, and
275 polishItems() will pop from it.
276 Therefore if updatePolish() calls polish(), the immediate next item polishItems() processes is
277 the item that was polished by the previous call to updatePolish().
278 We therefore just need to count the number of polish loops we detected in _sequence_.
279*/
280struct PolishLoopDetector
281{
282 PolishLoopDetector(const QVector<QQuickItem*> &itemsToPolish)
283 : itemsToPolish(itemsToPolish)
284 {
285 }
286
287 /*
288 * returns true when it detected a likely infinite loop
289 * (suggests it should abort the polish loop)
290 **/
291 bool check(QQuickItem *item, int itemsRemainingBeforeUpdatePolish)
292 {
293 if (itemsToPolish.size() > itemsRemainingBeforeUpdatePolish) {
294 // Detected potential polish loop.
295 ++numPolishLoopsInSequence;
296 if (numPolishLoopsInSequence == 10000) {
297 // We have looped 10,000 times without actually reducing the list of items to
298 // polish, give up for now.
299 // This is not a fix, just a remedy so that the application can be somewhat
300 // responsive.
301 numPolishLoopsInSequence = 0;
302 return true;
303 }
304 if (numPolishLoopsInSequence >= 1000 && numPolishLoopsInSequence < 1005) {
305 // Start to warn about polish loop after 1000 consecutive polish loops
306 // Show the 5 next items involved in the polish loop.
307 // (most likely they will be the same 5 items...)
308 QQuickItem *guiltyItem = itemsToPolish.last();
309 qmlWarning(me: item) << "possible QQuickItem::polish() loop";
310
311 auto typeAndObjectName = [](QQuickItem *item) {
312 QString typeName = QQmlMetaType::prettyTypeName(object: item);
313 QString objName = item->objectName();
314 if (!objName.isNull())
315 return QLatin1String("%1(%2)").arg(args&: typeName, args&: objName);
316 return typeName;
317 };
318
319 qmlWarning(me: guiltyItem) << typeAndObjectName(guiltyItem)
320 << " called polish() inside updatePolish() of " << typeAndObjectName(item);
321 }
322 } else {
323 numPolishLoopsInSequence = 0;
324 }
325 return false;
326 }
327 const QVector<QQuickItem*> &itemsToPolish; // Just a ref to the one in polishItems()
328 int numPolishLoopsInSequence = 0;
329};
330
331void QQuickWindowPrivate::polishItems()
332{
333 // An item can trigger polish on another item, or itself for that matter,
334 // during its updatePolish() call. Because of this, we cannot simply
335 // iterate through the set, we must continue pulling items out until it
336 // is empty.
337 // In the case where polish is called from updatePolish() either directly
338 // or indirectly, we use a PolishLoopDetector to determine if a warning should
339 // be printed to the user.
340
341 PolishLoopDetector polishLoopDetector(itemsToPolish);
342 while (!itemsToPolish.isEmpty()) {
343 QQuickItem *item = itemsToPolish.takeLast();
344 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
345 itemPrivate->polishScheduled = false;
346 const int itemsRemaining = itemsToPolish.size();
347 itemPrivate->updatePolish();
348 item->updatePolish();
349 if (polishLoopDetector.check(item, itemsRemainingBeforeUpdatePolish: itemsRemaining) == true)
350 break;
351 }
352
353#if QT_CONFIG(im)
354 if (QQuickItem *focusItem = q_func()->activeFocusItem()) {
355 // If the current focus item, or any of its anchestors, has changed location
356 // inside the window, we need inform IM about it. This to ensure that overlays
357 // such as selection handles will be updated.
358 const bool isActiveFocusItem = (focusItem == QGuiApplication::focusObject());
359 const bool hasImEnabled = focusItem->inputMethodQuery(query: Qt::ImEnabled).toBool();
360 if (isActiveFocusItem && hasImEnabled && transformDirtyOnItemOrAncestor(item: focusItem))
361 deliveryAgentPrivate()->updateFocusItemTransform();
362 }
363#endif
364
365 if (needsChildWindowStackingOrderUpdate) {
366 updateChildWindowStackingOrder();
367 needsChildWindowStackingOrderUpdate = false;
368 }
369}
370
371/*!
372 * Schedules the window to render another frame.
373 *
374 * Calling QQuickWindow::update() differs from QQuickItem::update() in that
375 * it always triggers a repaint, regardless of changes in the underlying
376 * scene graph or not.
377 */
378void QQuickWindow::update()
379{
380 Q_D(QQuickWindow);
381 if (d->windowManager)
382 d->windowManager->update(window: this);
383 else if (d->renderControl)
384 QQuickRenderControlPrivate::get(renderControl: d->renderControl)->update();
385}
386
387static void updatePixelRatioHelper(QQuickItem *item, float pixelRatio)
388{
389 if (item->flags() & QQuickItem::ItemHasContents) {
390 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
391 itemPrivate->itemChange(QQuickItem::ItemDevicePixelRatioHasChanged, pixelRatio);
392 }
393
394 QList <QQuickItem *> items = item->childItems();
395 for (int i = 0; i < items.size(); ++i)
396 updatePixelRatioHelper(item: items.at(i), pixelRatio);
397}
398
399void QQuickWindow::physicalDpiChanged()
400{
401 Q_D(QQuickWindow);
402 const qreal newPixelRatio = effectiveDevicePixelRatio();
403 if (qFuzzyCompare(p1: newPixelRatio, p2: d->lastReportedItemDevicePixelRatio))
404 return;
405 d->lastReportedItemDevicePixelRatio = newPixelRatio;
406 if (d->contentItem)
407 updatePixelRatioHelper(item: d->contentItem, pixelRatio: newPixelRatio);
408 d->forcePolish();
409}
410
411void QQuickWindow::handleFontDatabaseChanged()
412{
413 Q_D(QQuickWindow);
414 d->pendingFontUpdate = true;
415}
416
417void forcePolishHelper(QQuickItem *item)
418{
419 if (item->flags() & QQuickItem::ItemHasContents) {
420 item->polish();
421 }
422
423 QList <QQuickItem *> items = item->childItems();
424 for (int i=0; i<items.size(); ++i)
425 forcePolishHelper(item: items.at(i));
426}
427
428void QQuickWindow::handleScreenChanged(QScreen *screen)
429{
430 Q_D(QQuickWindow);
431 Q_UNUSED(screen);
432 d->forcePolish();
433}
434
435/*!
436 Schedules polish events on all items in the scene.
437*/
438void QQuickWindowPrivate::forcePolish()
439{
440 Q_Q(QQuickWindow);
441 if (!q->screen())
442 return;
443 forcePolishHelper(item: contentItem);
444}
445
446void forceUpdate(QQuickItem *item)
447{
448 if (item->flags() & QQuickItem::ItemHasContents)
449 item->update();
450 QQuickItemPrivate::get(item)->dirty(QQuickItemPrivate::ChildrenUpdateMask);
451
452 QList <QQuickItem *> items = item->childItems();
453 for (int i=0; i<items.size(); ++i)
454 forceUpdate(item: items.at(i));
455}
456
457void QQuickWindowRenderTarget::reset(QRhi *rhi, ResetFlags flags)
458{
459 if (rhi) {
460 if (rt.owns)
461 delete rt.renderTarget;
462
463 delete res.texture;
464 delete res.renderBuffer;
465 delete res.rpDesc;
466 }
467
468 rt = {};
469 res = {};
470
471 if (!flags.testFlag(flag: ResetFlag::KeepImplicitBuffers))
472 implicitBuffers.reset(rhi);
473
474 if (sw.owns)
475 delete sw.paintDevice;
476
477 sw = {};
478}
479
480void QQuickWindowRenderTarget::ImplicitBuffers::reset(QRhi *rhi)
481{
482 if (rhi) {
483 delete depthStencil;
484 delete depthStencilTexture;
485 delete multisampleTexture;
486 }
487 *this = {};
488}
489
490void QQuickWindowPrivate::invalidateFontData(QQuickItem *item)
491{
492 QQuickTextInterface *textItem = qobject_cast<QQuickTextInterface *>(object: item);
493 if (textItem != nullptr)
494 textItem->invalidate();
495
496 QList<QQuickItem *> children = item->childItems();
497 for (QQuickItem *child : children)
498 invalidateFontData(item: child);
499}
500
501void QQuickWindowPrivate::ensureCustomRenderTarget()
502{
503 // resolve() can be expensive when importing an existing native texture, so
504 // it is important to only do it when the QQuickRenderTarget was really changed.
505 if (!redirect.renderTargetDirty)
506 return;
507
508 redirect.renderTargetDirty = false;
509
510 redirect.rt.reset(rhi, flags: QQuickWindowRenderTarget::ResetFlag::KeepImplicitBuffers);
511
512 if (!QQuickRenderTargetPrivate::get(rt: &customRenderTarget)->resolve(rhi, dst: &redirect.rt)) {
513 qWarning(msg: "Failed to set up render target redirection for QQuickWindow");
514 redirect.rt.reset(rhi);
515 }
516}
517
518void QQuickWindowPrivate::setCustomCommandBuffer(QRhiCommandBuffer *cb)
519{
520 // ownership not transferred
521 redirect.commandBuffer = cb;
522}
523
524void QQuickWindowPrivate::syncSceneGraph()
525{
526 Q_Q(QQuickWindow);
527
528 const bool wasRtDirty = redirect.renderTargetDirty;
529 ensureCustomRenderTarget();
530
531 QRhiCommandBuffer *cb = nullptr;
532 if (rhi) {
533 if (redirect.commandBuffer)
534 cb = redirect.commandBuffer;
535 else
536 cb = swapchain->currentFrameCommandBuffer();
537 }
538 context->prepareSync(devicePixelRatio: q->effectiveDevicePixelRatio(), cb, config: graphicsConfig);
539
540 animationController->beforeNodeSync();
541
542 emit q->beforeSynchronizing();
543 runAndClearJobs(jobs: &beforeSynchronizingJobs);
544
545 if (pendingFontUpdate) {
546 QFont::cleanup();
547 invalidateFontData(item: contentItem);
548 }
549
550 if (Q_UNLIKELY(!renderer)) {
551 forceUpdate(item: contentItem);
552
553 QSGRootNode *rootNode = new QSGRootNode;
554 rootNode->appendChildNode(node: QQuickItemPrivate::get(item: contentItem)->itemNode());
555 const bool useDepth = graphicsConfig.isDepthBufferEnabledFor2D();
556 const QSGRendererInterface::RenderMode renderMode = useDepth ? QSGRendererInterface::RenderMode2D
557 : QSGRendererInterface::RenderMode2DNoDepthBuffer;
558 renderer = context->createRenderer(renderMode);
559 renderer->setRootNode(rootNode);
560 } else if (Q_UNLIKELY(wasRtDirty)
561 && q->rendererInterface()->graphicsApi() == QSGRendererInterface::Software) {
562 auto softwareRenderer = static_cast<QSGSoftwareRenderer *>(renderer);
563 softwareRenderer->markDirty();
564 }
565
566 updateDirtyNodes();
567
568 animationController->afterNodeSync();
569
570 renderer->setClearColor(clearColor);
571
572 renderer->setVisualizationMode(visualizationMode);
573
574 if (pendingFontUpdate) {
575 context->invalidateGlyphCaches();
576 pendingFontUpdate = false;
577 }
578
579 emit q->afterSynchronizing();
580 runAndClearJobs(jobs: &afterSynchronizingJobs);
581}
582
583void QQuickWindowPrivate::emitBeforeRenderPassRecording(void *ud)
584{
585 QQuickWindow *w = reinterpret_cast<QQuickWindow *>(ud);
586 emit w->beforeRenderPassRecording();
587}
588
589void QQuickWindowPrivate::emitAfterRenderPassRecording(void *ud)
590{
591 QQuickWindow *w = reinterpret_cast<QQuickWindow *>(ud);
592 emit w->afterRenderPassRecording();
593}
594
595int QQuickWindowPrivate::multiViewCount()
596{
597 if (rhi) {
598 ensureCustomRenderTarget();
599 if (redirect.rt.rt.renderTarget)
600 return redirect.rt.rt.multiViewCount;
601 }
602
603 // Note that on QRhi level 0 and 1 are often used interchangeably, as both mean
604 // no-multiview. Here in Qt Quick let's always use 1 as the default
605 // (no-multiview), so that higher layers (effects, materials) do not need to
606 // handle both 0 and 1, only 1.
607 return 1;
608}
609
610QRhiRenderTarget *QQuickWindowPrivate::activeCustomRhiRenderTarget()
611{
612 if (rhi) {
613 ensureCustomRenderTarget();
614 return redirect.rt.rt.renderTarget;
615 }
616 return nullptr;
617}
618
619void QQuickWindowPrivate::renderSceneGraph()
620{
621 Q_Q(QQuickWindow);
622 if (!renderer)
623 return;
624
625 ensureCustomRenderTarget();
626
627 QSGRenderTarget sgRenderTarget;
628 if (rhi) {
629 QRhiRenderTarget *rt;
630 QRhiRenderPassDescriptor *rp;
631 QRhiCommandBuffer *cb;
632 if (redirect.rt.rt.renderTarget) {
633 rt = redirect.rt.rt.renderTarget;
634 rp = rt->renderPassDescriptor();
635 if (!rp) {
636 qWarning(msg: "Custom render target is set but no renderpass descriptor has been provided.");
637 return;
638 }
639 cb = redirect.commandBuffer;
640 if (!cb) {
641 qWarning(msg: "Custom render target is set but no command buffer has been provided.");
642 return;
643 }
644 } else {
645 if (!swapchain) {
646 qWarning(msg: "QQuickWindow: No render target (neither swapchain nor custom target was provided)");
647 return;
648 }
649 rt = swapchain->currentFrameRenderTarget();
650 rp = rpDescForSwapchain;
651 cb = swapchain->currentFrameCommandBuffer();
652 }
653 sgRenderTarget = QSGRenderTarget(rt, rp, cb);
654 sgRenderTarget.multiViewCount = multiViewCount();
655 } else {
656 sgRenderTarget = QSGRenderTarget(redirect.rt.sw.paintDevice);
657 }
658
659 context->beginNextFrame(renderer,
660 renderTarget: sgRenderTarget,
661 mainPassRecordingStart: emitBeforeRenderPassRecording,
662 mainPassRecordingEnd: emitAfterRenderPassRecording,
663 callbackUserData: q);
664
665 animationController->advance();
666 emit q->beforeRendering();
667 runAndClearJobs(jobs: &beforeRenderingJobs);
668
669 const qreal devicePixelRatio = q->effectiveDevicePixelRatio();
670 QSize pixelSize;
671 if (redirect.rt.rt.renderTarget)
672 pixelSize = redirect.rt.rt.renderTarget->pixelSize();
673 else if (redirect.rt.sw.paintDevice)
674 pixelSize = QSize(redirect.rt.sw.paintDevice->width(), redirect.rt.sw.paintDevice->height());
675 else if (rhi)
676 pixelSize = swapchain->currentPixelSize();
677 else // software or other backend
678 pixelSize = q->size() * devicePixelRatio;
679
680 renderer->setDevicePixelRatio(devicePixelRatio);
681 renderer->setDeviceRect(QRect(QPoint(0, 0), pixelSize));
682 renderer->setViewportRect(QRect(QPoint(0, 0), pixelSize));
683
684 QSGAbstractRenderer::MatrixTransformFlags matrixFlags;
685 bool flipY = rhi ? !rhi->isYUpInNDC() : false;
686 if (!customRenderTarget.isNull() && customRenderTarget.mirrorVertically())
687 flipY = !flipY;
688 if (flipY)
689 matrixFlags |= QSGAbstractRenderer::MatrixTransformFlipY;
690
691 const QRectF rect(QPointF(0, 0), pixelSize / devicePixelRatio);
692 renderer->setProjectionMatrixToRect(rect, flags: matrixFlags, nativeNDCFlipY: rhi && !rhi->isYUpInNDC());
693
694 context->renderNextFrame(renderer);
695
696 emit q->afterRendering();
697 runAndClearJobs(jobs: &afterRenderingJobs);
698
699 context->endNextFrame(renderer);
700
701 if (renderer && renderer->hasVisualizationModeWithContinuousUpdate()) {
702 // For the overdraw visualizer. This update is not urgent so avoid a
703 // direct update() call, this is only here to keep the overdraw
704 // visualization box rotating even when the scene is static.
705 QCoreApplication::postEvent(receiver: q, event: new QEvent(QEvent::Type(FullUpdateRequest)));
706 }
707}
708
709QQuickWindowPrivate::QQuickWindowPrivate()
710 : contentItem(nullptr)
711 , dirtyItemList(nullptr)
712 , lastReportedItemDevicePixelRatio(0)
713 , context(nullptr)
714 , renderer(nullptr)
715 , windowManager(nullptr)
716 , renderControl(nullptr)
717 , clearColor(Qt::white)
718 , persistentGraphics(true)
719 , persistentSceneGraph(true)
720 , inDestructor(false)
721 , incubationController(nullptr)
722 , hasActiveSwapchain(false)
723 , hasRenderableSwapchain(false)
724 , swapchainJustBecameRenderable(false)
725 , updatesEnabled(true)
726{
727}
728
729QQuickWindowPrivate::~QQuickWindowPrivate()
730{
731 inDestructor = true;
732 redirect.rt.reset(rhi);
733 if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
734 service->removeWindow(q_func());
735 deliveryAgent = nullptr;
736}
737
738void QQuickWindowPrivate::setPalette(QQuickPalette* palette)
739{
740 if (windowPaletteRef == palette)
741 return;
742
743 if (windowPaletteRef)
744 disconnect(sender: windowPaletteRef, signal: &QQuickPalette::changed, receiverPrivate: this, slot: &QQuickWindowPrivate::updateWindowPalette);
745 windowPaletteRef = palette;
746 updateWindowPalette();
747 if (windowPaletteRef)
748 connect(sender: windowPaletteRef, signal: &QQuickPalette::changed, receiverPrivate: this, slot: &QQuickWindowPrivate::updateWindowPalette);
749}
750
751void QQuickWindowPrivate::updateWindowPalette()
752{
753 QQuickPaletteProviderPrivateBase::setPalette(windowPaletteRef);
754}
755
756void QQuickWindowPrivate::updateChildrenPalettes(const QPalette &parentPalette)
757{
758 Q_Q(QQuickWindow);
759 if (auto root = q->contentItem()) {
760 for (auto &&child: root->childItems()) {
761 QQuickItemPrivate::get(item: child)->inheritPalette(parentPalette);
762 }
763 }
764}
765
766void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
767{
768 q_ptr = c;
769
770
771 Q_Q(QQuickWindow);
772
773 contentItem = new QQuickRootItem;
774 contentItem->setObjectName(q->objectName());
775 QQml_setParent_noEvent(object: contentItem, parent: c);
776 QQmlEngine::setObjectOwnership(contentItem, QQmlEngine::CppOwnership);
777 QQuickItemPrivate *contentItemPrivate = QQuickItemPrivate::get(item: contentItem);
778 contentItemPrivate->window = q;
779 contentItemPrivate->windowRefCount = 1;
780 contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
781 contentItem->setSize(q->size());
782 deliveryAgent = new QQuickDeliveryAgent(contentItem);
783
784 visualizationMode = qgetenv(varName: "QSG_VISUALIZE");
785 renderControl = control;
786 if (renderControl)
787 QQuickRenderControlPrivate::get(renderControl)->window = q;
788
789 if (!renderControl)
790 windowManager = QSGRenderLoop::instance();
791
792 Q_ASSERT(windowManager || renderControl);
793
794 QObject::connect(sender: static_cast<QGuiApplication *>(QGuiApplication::instance()),
795 signal: &QGuiApplication::fontDatabaseChanged,
796 context: q,
797 slot: &QQuickWindow::handleFontDatabaseChanged);
798
799 if (q->screen()) {
800 lastReportedItemDevicePixelRatio = q->effectiveDevicePixelRatio();
801 }
802
803 QSGContext *sg;
804 if (renderControl) {
805 QQuickRenderControlPrivate *renderControlPriv = QQuickRenderControlPrivate::get(renderControl);
806 sg = renderControlPriv->sg;
807 context = renderControlPriv->rc;
808 } else {
809 windowManager->addWindow(win: q);
810 sg = windowManager->sceneGraphContext();
811 context = windowManager->createRenderContext(sg);
812 }
813
814 q->setSurfaceType(windowManager ? windowManager->windowSurfaceType() : QSurface::OpenGLSurface);
815 q->setFormat(sg->defaultSurfaceFormat());
816 // When using Vulkan, associating a scenegraph-managed QVulkanInstance with
817 // the window (but only when not using renderControl) is deferred to
818 // QSGRhiSupport::createRhi(). This allows applications to set up their own
819 // QVulkanInstance and set that on the window, if they wish to.
820
821 animationController.reset(other: new QQuickAnimatorController(q));
822
823 QObject::connect(sender: context, signal: &QSGRenderContext::initialized, context: q, slot: &QQuickWindow::sceneGraphInitialized, type: Qt::DirectConnection);
824 QObject::connect(sender: context, signal: &QSGRenderContext::invalidated, context: q, slot: &QQuickWindow::sceneGraphInvalidated, type: Qt::DirectConnection);
825 QObject::connect(sender: context, signal: &QSGRenderContext::invalidated, context: q, slot: &QQuickWindow::cleanupSceneGraph, type: Qt::DirectConnection);
826
827 QObject::connect(sender: q, signal: &QQuickWindow::focusObjectChanged, context: q, slot: &QQuickWindow::activeFocusItemChanged);
828 QObject::connect(sender: q, signal: &QQuickWindow::screenChanged, context: q, slot: &QQuickWindow::handleScreenChanged);
829 QObject::connect(qApp, signal: &QGuiApplication::applicationStateChanged, context: q, slot: &QQuickWindow::handleApplicationStateChanged);
830 QObject::connect(sender: q, signal: &QQuickWindow::frameSwapped, context: q, slot: &QQuickWindow::runJobsAfterSwap, type: Qt::DirectConnection);
831
832 if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
833 service->addWindow(q);
834}
835
836void QQuickWindow::handleApplicationStateChanged(Qt::ApplicationState state)
837{
838 Q_D(QQuickWindow);
839 if (state != Qt::ApplicationActive && d->contentItem) {
840 auto da = d->deliveryAgentPrivate();
841 Q_ASSERT(da);
842 da->handleWindowDeactivate(win: this);
843 }
844}
845
846/*!
847 \property QQuickWindow::data
848 \internal
849*/
850
851QQmlListProperty<QObject> QQuickWindowPrivate::data()
852{
853 QQmlListProperty<QObject> ret;
854
855 ret.object = q_func();
856 ret.append = QQuickWindowPrivate::data_append;
857 ret.count = QQuickWindowPrivate::data_count;
858 ret.at = QQuickWindowPrivate::data_at;
859 ret.clear = QQuickWindowPrivate::data_clear;
860 // replace is not supported by QQuickItem. Don't synthesize it.
861 ret.removeLast = QQuickWindowPrivate::data_removeLast;
862
863 return ret;
864}
865
866void QQuickWindowPrivate::dirtyItem(QQuickItem *item)
867{
868 Q_Q(QQuickWindow);
869
870 QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
871 if (itemPriv->dirtyAttributes & QQuickItemPrivate::ChildrenStackingChanged)
872 needsChildWindowStackingOrderUpdate = true;
873
874 q->maybeUpdate();
875}
876
877/*!
878 \deprecated Use QPointerEvent::exclusiveGrabber().
879 Returns the item which currently has the mouse grab.
880*/
881QQuickItem *QQuickWindow::mouseGrabberItem() const
882{
883 Q_D(const QQuickWindow);
884 auto da = const_cast<QQuickWindowPrivate *>(d)->deliveryAgentPrivate();
885 Q_ASSERT(da);
886 // The normal use case is to call this function while an event is being delivered;
887 // but if the caller knows about the event, it should call QPointerEvent::exclusiveGrabber() instead.
888 if (auto epd = da->mousePointData())
889 return qmlobject_cast<QQuickItem *>(object: epd->exclusiveGrabber);
890
891 if (Q_LIKELY(d->deliveryAgentPrivate()->eventsInDelivery.isEmpty()))
892 // mousePointData() checked that already: it's one reason epd can be null
893 qCDebug(lcMouse, "mouse grabber ambiguous: no event is currently being delivered");
894 // If no event is being delivered, we can return "the mouse" grabber,
895 // but in general there could be more than one mouse, could be only a touchscreen etc.
896 // That's why this function is obsolete.
897 return qmlobject_cast<QQuickItem *>(object: QPointingDevicePrivate::get(q: QPointingDevice::primaryPointingDevice())->
898 firstPointExclusiveGrabber());
899}
900
901void QQuickWindowPrivate::cleanup(QSGNode *n)
902{
903 Q_Q(QQuickWindow);
904
905 Q_ASSERT(!cleanupNodeList.contains(n));
906 cleanupNodeList.append(t: n);
907 q->maybeUpdate();
908}
909
910/*!
911 \qmltype Window
912 \nativetype QQuickWindow
913 \inqmlmodule QtQuick
914 \ingroup qtquick-visual
915 \brief Creates a new top-level window.
916
917 The Window object creates a new top-level window for a Qt Quick scene. It automatically sets up the
918 window for use with \c {QtQuick} graphical types.
919
920 A Window can be declared inside an Item or inside another Window, in which
921 case the inner Window will automatically become "transient for" the outer
922 Window, with the outer Window as its \l transientParent. Most platforms will
923 show the Window centered upon the outer window in this case, and there may be
924 other platform-dependent behaviors, depending also on the \l flags. If the nested
925 window is intended to be a dialog in your application, you should also set \l flags
926 to \c Qt.Dialog, because some window managers will not provide the centering behavior
927 without that flag.
928
929 You can also declare multiple windows inside a top-level \l QtObject, in which
930 case the windows will have no transient relationship.
931
932 Alternatively you can set or bind \l x and \l y to position the Window
933 explicitly on the screen.
934
935 When the user attempts to close a window, the \l closing signal will be
936 emitted. You can force the window to stay open (for example to prompt the
937 user to save changes) by writing an \c onClosing handler that sets
938 \c {close.accepted = false} unless it's safe to close the window (for example,
939 because there are no more unsaved changes).
940
941 \code
942 onClosing: (close) => {
943 if (document.changed) {
944 close.accepted = false
945 confirmExitPopup.open()
946 }
947 }
948
949 // The confirmExitPopup allows user to save or discard the document,
950 // or to cancel the closing.
951 \endcode
952
953 \section1 Styling
954
955 As with all visual types in Qt Quick, Window supports
956 \l {palette}{palettes}. However, as with types like \l Text, Window does
957 not use palettes by default. For example, to change the background color
958 of the window when the operating system's theme changes, the \l color must
959 be set:
960
961 \snippet qml/windowPalette.qml declaration-and-color
962 \codeline
963 \snippet qml/windowPalette.qml text-item
964 \snippet qml/windowPalette.qml closing-brace
965
966 Use \l {ApplicationWindow} (and \l {Label}) from \l {Qt Quick Controls}
967 instead of Window to get automatic styling.
968*/
969
970/*!
971 \class QQuickWindow
972 \since 5.0
973
974 \inmodule QtQuick
975
976 \brief The QQuickWindow class provides the window for displaying a graphical QML scene.
977
978 QQuickWindow provides the graphical scene management needed to interact with and display
979 a scene of QQuickItems.
980
981 A QQuickWindow always has a single invisible root item. To add items to this window,
982 reparent the items to the root item or to an existing item in the scene.
983
984 For easily displaying a scene from a QML file, see \l{QQuickView}.
985
986 \section1 Rendering
987
988 QQuickWindow uses a scene graph to represent what needs to be rendered.
989 This scene graph is disconnected from the QML scene and potentially lives in
990 another thread, depending on the platform implementation. Since the
991 rendering scene graph lives independently from the QML scene, it can also be
992 completely released without affecting the state of the QML scene.
993
994 The sceneGraphInitialized() signal is emitted on the rendering thread before
995 the QML scene is rendered to the screen for the first time. If the rendering
996 scene graph has been released, the signal will be emitted again before the
997 next frame is rendered. A visible, on-screen QQuickWindow is driven
998 internally by a \c{render loop}, of which there are multiple implementations
999 provided in the scene graph. For details on the scene graph rendering
1000 process, see \l{Qt Quick Scene Graph}.
1001
1002 By default, a QQuickWindow renders using an accelerated 3D graphics API,
1003 such as OpenGL or Vulkan. See \l{Scene Graph Adaptations} for a detailed
1004 overview of scene graph backends and the supported graphics APIs.
1005
1006 \warning It is crucial that graphics operations and interaction with the
1007 scene graph happens exclusively on the rendering thread, primarily during
1008 the updatePaintNode() phase.
1009
1010 \warning As many of the signals related to rendering are emitted from the
1011 rendering thread, connections should be made using Qt::DirectConnection.
1012
1013 \section2 Integration with Accelerated 3D Graphics APIs
1014
1015 It is possible to integrate OpenGL, Vulkan, Metal, or Direct3D 11 calls
1016 directly into the QQuickWindow, as long as the QQuickWindow and the
1017 underlying scene graph is rendering using the same API. To access native
1018 graphics objects, such as device or context object handles, use
1019 QSGRendererInterface. An instance of QSGRendererInterface is queriable from
1020 QQuickWindow by calling rendererInterface(). The enablers for this
1021 integration are the beforeRendering(), beforeRenderPassRecording(),
1022 afterRenderPassRecording(), and related signals. These allow rendering
1023 underlays or overlays. Alternatively, QNativeInterface::QSGOpenGLTexture,
1024 QNativeInterface::QSGVulkanTexture, and other similar classes allow
1025 wrapping an existing native texture or image object in a QSGTexture that
1026 can then be used with the scene graph.
1027
1028 \section2 Rendering without Acceleration
1029
1030 A limited, pure software based rendering path is available as well. With the
1031 \c software backend, a number of Qt Quick features are not available, QML
1032 items relying on these will not be rendered at all. At the same time, this
1033 allows QQuickWindow to be functional even on systems where there is no 3D
1034 graphics API available at all. See \l{Qt Quick Software Adaptation} for more
1035 details.
1036
1037 \section2 Redirected Rendering
1038
1039 A QQuickWindow is not necessarily backed by a native window on screen. The
1040 rendering can be redirected to target a custom render target, such as a
1041 given native texture. This is achieved in combination with the
1042 QQuickRenderControl class, and functions such as setRenderTarget(),
1043 setGraphicsDevice(), and setGraphicsConfiguration().
1044
1045 In this case, the QQuickWindow represents the scene, and provides the
1046 intrastructure for rendering a frame. It will not be backed by a render
1047 loop and a native window. Instead, in this case the application drives
1048 rendering, effectively substituting for the render loops. This allows
1049 generating image sequences, rendering into textures for use in external 3D
1050 engines, or rendering Qt Quick content within a VR environment.
1051
1052 \section2 Resource Management
1053
1054 QML will try to cache images and scene graph nodes to improve performance,
1055 but in some low-memory scenarios it might be required to aggressively
1056 release these resources. The releaseResources() function can be used to
1057 force the clean up of certain resources, especially resource that are cached
1058 and can be recreated later when needed again.
1059
1060 Additionally, calling releaseResources() may result in releasing the entire
1061 scene graph and the associated graphics resources. The
1062 sceneGraphInvalidated() signal will be emitted when this happens. This
1063 behavior is controlled by the setPersistentGraphics() and
1064 setPersistentSceneGraph() functions.
1065
1066 \note All classes with QSG prefix should be used solely on the scene graph's
1067 rendering thread. See \l {Scene Graph and Rendering} for more information.
1068
1069 \section2 Exposure and Visibility
1070
1071 When a QQuickWindow instance is deliberately hidden with hide() or
1072 setVisible(false), it will stop rendering and its scene graph and graphics
1073 context might be released as well. This depends on the settings configured
1074 by setPersistentGraphics() and setPersistentSceneGraph(). The behavior in
1075 this respect is identical to explicitly calling the releaseResources()
1076 function. A window can become not exposed, in other words non-renderable, by
1077 other means as well. This depends on the platform and windowing system. For
1078 example, on Windows minimizing a window makes it stop rendering. On \macos
1079 fully obscuring a window by other windows on top triggers the same. On
1080 Linux/X11, the behavior is dependent on the window manager.
1081
1082 \section2 OpenGL Context and Surface Formats
1083
1084 While it is possible to specify a QSurfaceFormat for every QQuickWindow by
1085 calling the member function setFormat(), windows may also be created from
1086 QML by using the Window and ApplicationWindow elements. In this case there
1087 is no C++ code involved in the creation of the window instance, yet
1088 applications may still wish to set certain surface format values, for
1089 example to request a given OpenGL version or profile. Such applications can
1090 call the static function QSurfaceFormat::setDefaultFormat() at startup. The
1091 specified format will be used for all Quick windows created afterwards.
1092
1093 \section2 Vulkan Instance
1094
1095 When using Vulkan, a QQuickWindow is automatically associated with a
1096 QVulkanInstance that is created and managed internally by the scene graph.
1097 This way most applications do not need to worry about having a \c
1098 VkInstance available since it all happens automatically. In advanced cases
1099 an application may wish to create its own QVulkanInstance, in order to
1100 configure it in a specific way. That is possible as well. Calling
1101 \l{QWindow::setVulkanInstance()}{setVulkanInstance()} on the QQuickWindow
1102 right after construction, before making it visible, leads to using the
1103 application-supplied QVulkanInstance (and the underlying \c VkInstance).
1104 When redirecting via QQuickRenderControl, there is no QVulkanInstance
1105 provided automatically, but rather the application is expected to provide
1106 its own and associate it with the QQuickWindow.
1107
1108 \section2 Graphics Contexts and Devices
1109
1110 When the scene graph is initialized, which typically happens when the
1111 window becomes exposed or, in case of redirected rendering, initialization
1112 is performed \l{QQuickRenderControl::initialize()}{via
1113 QQuickRenderControl}, the context or device objects necessary for rendering
1114 are created automatically. This includes OpenGL contexts, Direct3D devices
1115 and device contexts, Vulkan and Metal devices. These are also queriable by
1116 application code afterwards via
1117 \l{QSGRendererInterface::getResource()}{QSGRendererInterface}. When using
1118 the \c basic render loop, which performs all rendering on the GUI thread,
1119 the same context or device is used with all visible QQuickWindows. The \c
1120 threaded render loop uses a dedicated context or device object for each
1121 rendering thread, and so for each QQuickWindow. With some graphics APIs,
1122 there is a degree of customizability provided via
1123 setGraphicsConfiguration(). This makes it possible, for example, to specify
1124 the list of Vulkan extensions to enable on the \c VkDevice. Alternatively,
1125 it is also possible to provide a set of existing context or device objects
1126 for use by the QQuickWindow, instead of letting it construct its own. This
1127 is achieved through setGraphicsDevice().
1128
1129 \sa QQuickView, QQuickRenderControl, QQuickRenderTarget,
1130 QQuickGraphicsDevice, QQuickGraphicsConfiguration, QSGRendererInterface
1131*/
1132
1133/*!
1134 Constructs a window for displaying a QML scene with parent window \a parent.
1135*/
1136QQuickWindow::QQuickWindow(QWindow *parent)
1137 : QQuickWindow(*new QQuickWindowPrivate, parent)
1138{
1139}
1140
1141
1142
1143/*!
1144 \internal
1145*/
1146QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent)
1147 : QWindow(dd, parent)
1148{
1149 Q_D(QQuickWindow);
1150 d->init(c: this);
1151}
1152
1153/*!
1154 Constructs a window for displaying a QML scene, whose rendering will
1155 be controlled by the \a control object.
1156 Please refer to QQuickRenderControl's documentation for more information.
1157
1158 \since 5.4
1159*/
1160QQuickWindow::QQuickWindow(QQuickRenderControl *control)
1161 : QWindow(*(new QQuickWindowPrivate), nullptr)
1162{
1163 Q_D(QQuickWindow);
1164 d->init(c: this, control);
1165}
1166
1167/*!
1168 \internal
1169*/
1170QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control)
1171 : QWindow(dd, nullptr)
1172{
1173 Q_D(QQuickWindow);
1174 d->init(c: this, control);
1175}
1176
1177/*!
1178 Destroys the window.
1179*/
1180QQuickWindow::~QQuickWindow()
1181{
1182 Q_D(QQuickWindow);
1183 d->inDestructor = true;
1184 if (d->renderControl) {
1185 QQuickRenderControlPrivate::get(renderControl: d->renderControl)->windowDestroyed();
1186 } else if (d->windowManager) {
1187 d->windowManager->removeWindow(win: this);
1188 d->windowManager->windowDestroyed(window: this);
1189 }
1190
1191 delete d->incubationController; d->incubationController = nullptr;
1192 QQuickRootItem *root = d->contentItem;
1193 d->contentItem = nullptr;
1194 root->setParent(nullptr); // avoid QChildEvent delivery during deletion
1195 delete root;
1196 d->deliveryAgent = nullptr; // avoid forwarding events there during destruction
1197
1198
1199 {
1200 const std::lock_guard locker(d->renderJobMutex);
1201 qDeleteAll(c: std::exchange(obj&: d->beforeSynchronizingJobs, new_val: {}));
1202 qDeleteAll(c: std::exchange(obj&: d->afterSynchronizingJobs, new_val: {}));
1203 qDeleteAll(c: std::exchange(obj&: d->beforeRenderingJobs, new_val: {}));
1204 qDeleteAll(c: std::exchange(obj&: d->afterRenderingJobs, new_val: {}));;
1205 qDeleteAll(c: std::exchange(obj&: d->afterSwapJobs, new_val: {}));
1206 }
1207
1208 // It is important that the pixmap cache is cleaned up during shutdown.
1209 // Besides playing nice, this also solves a practical problem that
1210 // QQuickTextureFactory implementations in other libraries need
1211 // have their destructors loaded while they the library is still
1212 // loaded into memory.
1213 QQuickPixmap::purgeCache();
1214}
1215
1216#if QT_CONFIG(quick_shadereffect)
1217void qtquick_shadereffect_purge_gui_thread_shader_cache();
1218#endif
1219
1220/*!
1221 This function tries to release redundant resources currently held by the QML scene.
1222
1223 Calling this function requests the scene graph to release cached graphics
1224 resources, such as graphics pipeline objects, shader programs, or image
1225 data.
1226
1227 Additionally, depending on the render loop in use, this function may also
1228 result in the scene graph and all window-related rendering resources to be
1229 released. If this happens, the sceneGraphInvalidated() signal will be
1230 emitted, allowing users to clean up their own graphics resources. The
1231 setPersistentGraphics() and setPersistentSceneGraph() functions can be used
1232 to prevent this from happening, if handling the cleanup is not feasible in
1233 the application, at the cost of higher memory usage.
1234
1235 \note The releasing of cached graphics resources, such as graphics
1236 pipelines or shader programs is not dependent on the persistency hints. The
1237 releasing of those will happen regardless of the values of the persistent
1238 graphics and scenegraph hints.
1239
1240 \note This function is not related to the QQuickItem::releaseResources()
1241 virtual function.
1242
1243 \sa sceneGraphInvalidated(), setPersistentGraphics(), setPersistentSceneGraph()
1244 */
1245
1246void QQuickWindow::releaseResources()
1247{
1248 Q_D(QQuickWindow);
1249 if (d->windowManager)
1250 d->windowManager->releaseResources(window: this);
1251 QQuickPixmap::purgeCache();
1252#if QT_CONFIG(quick_shadereffect)
1253 qtquick_shadereffect_purge_gui_thread_shader_cache();
1254#endif
1255}
1256
1257
1258
1259/*!
1260 Sets whether the graphics resources (graphics device or context,
1261 swapchain, buffers, textures) should be preserved, and cannot be
1262 released until the last window is deleted, to \a persistent. The
1263 default value is true.
1264
1265 When calling releaseResources(), or when the window gets hidden (more
1266 specifically, not renderable), some render loops have the possibility
1267 to release all, not just the cached, graphics resources. This can free
1268 up memory temporarily, but it also means the rendering engine will have
1269 to do a full, potentially costly reinitialization of the resources when
1270 the window needs to render again.
1271
1272 \note The rules for when a window is not renderable are platform and
1273 window manager specific.
1274
1275 \note All graphics resources are released when the last QQuickWindow is
1276 deleted, regardless of this setting.
1277
1278 \note This is a hint, and is not guaranteed that it is taken into account.
1279
1280 \note This hint does not apply to cached resources, that are relatively
1281 cheap to drop and then recreate later. Therefore, calling releaseResources()
1282 will typically lead to releasing those regardless of the value of this hint.
1283
1284 \sa setPersistentSceneGraph(), sceneGraphInitialized(), sceneGraphInvalidated(), releaseResources()
1285 */
1286
1287void QQuickWindow::setPersistentGraphics(bool persistent)
1288{
1289 Q_D(QQuickWindow);
1290 d->persistentGraphics = persistent;
1291}
1292
1293
1294
1295/*!
1296 Returns whether essential graphics resources can be released during the
1297 lifetime of the QQuickWindow.
1298
1299 \note This is a hint, and is not guaranteed that it is taken into account.
1300
1301 \sa setPersistentGraphics()
1302 */
1303
1304bool QQuickWindow::isPersistentGraphics() const
1305{
1306 Q_D(const QQuickWindow);
1307 return d->persistentGraphics;
1308}
1309
1310
1311
1312/*!
1313 Sets whether the scene graph nodes and resources are \a persistent.
1314 Persistent means the nodes and resources cannot be released.
1315 The default value is \c true.
1316
1317 When calling releaseResources(), when the window gets hidden (more
1318 specifically, not renderable), some render loops have the possibility
1319 to release the scene graph nodes and related graphics resources. This
1320 frees up memory temporarily, but will also mean the scene graph has to
1321 be rebuilt when the window renders next time.
1322
1323 \note The rules for when a window is not renderable are platform and
1324 window manager specific.
1325
1326 \note The scene graph nodes and resources are always released when the
1327 last QQuickWindow is deleted, regardless of this setting.
1328
1329 \note This is a hint, and is not guaranteed that it is taken into account.
1330
1331 \sa setPersistentGraphics(), sceneGraphInvalidated(), sceneGraphInitialized(), releaseResources()
1332 */
1333
1334void QQuickWindow::setPersistentSceneGraph(bool persistent)
1335{
1336 Q_D(QQuickWindow);
1337 d->persistentSceneGraph = persistent;
1338}
1339
1340
1341
1342/*!
1343 Returns whether the scene graph nodes and resources can be
1344 released during the lifetime of this QQuickWindow.
1345
1346 \note This is a hint. When and how this happens is implementation
1347 specific.
1348 */
1349
1350bool QQuickWindow::isPersistentSceneGraph() const
1351{
1352 Q_D(const QQuickWindow);
1353 return d->persistentSceneGraph;
1354}
1355
1356/*!
1357 \qmlattachedproperty Item Window::contentItem
1358 \since 5.4
1359
1360 This attached property holds the invisible root item of the scene or
1361 \c null if the item is not in a window. The Window attached property
1362 can be attached to any Item.
1363*/
1364
1365/*!
1366 \property QQuickWindow::contentItem
1367 \brief The invisible root item of the scene.
1368
1369 A QQuickWindow always has a single invisible root item containing all of its content.
1370 To add items to this window, reparent the items to the contentItem or to an existing
1371 item in the scene.
1372*/
1373QQuickItem *QQuickWindow::contentItem() const
1374{
1375 Q_D(const QQuickWindow);
1376
1377 return d->contentItem;
1378}
1379
1380/*!
1381 \property QQuickWindow::activeFocusItem
1382
1383 \brief The item which currently has active focus or \c null if there is
1384 no item with active focus.
1385
1386 \sa QQuickItem::forceActiveFocus(), {Keyboard Focus in Qt Quick}
1387*/
1388QQuickItem *QQuickWindow::activeFocusItem() const
1389{
1390 Q_D(const QQuickWindow);
1391 auto da = d->deliveryAgentPrivate();
1392 Q_ASSERT(da);
1393 return da->activeFocusItem;
1394}
1395
1396/*!
1397 \internal
1398 \reimp
1399*/
1400QObject *QQuickWindow::focusObject() const
1401{
1402 Q_D(const QQuickWindow);
1403 auto da = d->deliveryAgentPrivate();
1404 Q_ASSERT(da);
1405 if (!d->inDestructor && da->activeFocusItem)
1406 return da->activeFocusItem;
1407 return const_cast<QQuickWindow*>(this);
1408}
1409
1410/*! \reimp */
1411bool QQuickWindow::event(QEvent *event)
1412{
1413 Q_D(QQuickWindow);
1414
1415 // bypass QWindow::event dispatching of input events: deliveryAgent takes care of it
1416 QQuickDeliveryAgent *da = d->deliveryAgent;
1417 if (event->isPointerEvent()) {
1418 /*
1419 We can't bypass the virtual functions like mousePressEvent() tabletEvent() etc.,
1420 for the sake of code that subclasses QQuickWindow and overrides them, even though
1421 we no longer need them as entry points for Qt Quick event delivery.
1422 So dispatch to them now, ahead of normal delivery, and stop them from calling
1423 back into this function if they were called from here (avoid recursion).
1424 It could also be that user code expects them to work as entry points, too;
1425 in that case, windowEventDispatch _won't_ be set, so the event comes here and
1426 we'll dispatch it further below.
1427 */
1428 if (d->windowEventDispatch)
1429 return false;
1430 {
1431 const bool wasAccepted = event->isAccepted();
1432 QBoolBlocker windowEventDispatchGuard(d->windowEventDispatch, true);
1433 qCDebug(lcPtr) << "dispatching to window functions in case of override" << event;
1434 QWindow::event(event);
1435 if (event->isAccepted() && !wasAccepted)
1436 return true;
1437 }
1438 /*
1439 QQuickWindow does not override touchEvent(). If the application has a subclass
1440 of QQuickWindow which allows the event to remain accepted, it means they want
1441 to stop propagation here, so return early (below). But otherwise we will call
1442 QWindow::touchEvent(), which will ignore(); in that case, we need to continue
1443 with the usual delivery below, so we need to undo the ignore().
1444 */
1445 auto pe = static_cast<QPointerEvent *>(event);
1446 if (QQuickDeliveryAgentPrivate::isTouchEvent(ev: pe))
1447 event->accept();
1448 // end of dispatch to user-overridden virtual window functions
1449
1450 /*
1451 When delivering update and release events to existing grabbers,
1452 use the subscene delivery agent, if any. A possible scenario:
1453 1) Two touchpoints pressed on the main window: QQuickWindowPrivate::deliveryAgent delivers to QQuick3DViewport,
1454 which does picking and finds two subscenes ("root" Items mapped onto two different 3D objects) to deliver it to.
1455 2) The QTouchEvent is split up so that each subscene sees points relevant to it.
1456 3) During delivery to either subscene, an item in the subscene grabs.
1457 4) The user moves finger(s) generating a move event: the correct grabber item needs to get the update
1458 via the same subscene delivery agent from which it got the press, so that the coord transform will be done properly.
1459 5) Likewise with the touchpoint releases.
1460 With single-point events (mouse, or only one finger) it's simplified: there can only be one subscene of interest;
1461 for (pt : pe->points()) would only iterate once, so we might as well skip that logic.
1462 */
1463 if (pe->pointCount()) {
1464 const bool synthMouse = QQuickDeliveryAgentPrivate::isSynthMouse(ev: pe);
1465 if (QQuickDeliveryAgentPrivate::subsceneAgentsExist) {
1466 bool ret = false;
1467 // Split up the multi-point event according to the relevant QQuickDeliveryAgent that should deliver to each existing grabber
1468 // but send ungrabbed points to d->deliveryAgent()
1469 QFlatMap<QQuickDeliveryAgent*, QList<QEventPoint>> deliveryAgentsNeedingPoints;
1470 QEventPoint::States eventStates;
1471
1472 auto insert = [&](QQuickDeliveryAgent *ptda, const QEventPoint &pt) {
1473 if (pt.state() == QEventPoint::Pressed && !synthMouse)
1474 pe->clearPassiveGrabbers(point: pt);
1475 auto &ptList = deliveryAgentsNeedingPoints[ptda];
1476 auto idEquals = [](auto id) { return [id] (const auto &e) { return e.id() == id; }; };
1477 if (std::none_of(first: ptList.cbegin(), last: ptList.cend(), pred: idEquals(pt.id())))
1478 ptList.append(t: pt);
1479 };
1480
1481 for (const auto &pt : pe->points()) {
1482 eventStates |= pt.state();
1483 auto epd = QPointingDevicePrivate::get(q: const_cast<QPointingDevice*>(pe->pointingDevice()))->queryPointById(id: pt.id());
1484 Q_ASSERT(epd);
1485 bool foundAgent = false;
1486 if (!epd->exclusiveGrabber.isNull() && !epd->exclusiveGrabberContext.isNull()) {
1487 if (auto ptda = qobject_cast<QQuickDeliveryAgent *>(object: epd->exclusiveGrabberContext.data())) {
1488 insert(ptda, pt);
1489 qCDebug(lcPtr) << pe->type() << "point" << pt.id() << pt.state()
1490 << "@" << pt.scenePosition() << "will be re-delivered via known grabbing agent" << ptda << "to" << epd->exclusiveGrabber.data();
1491 foundAgent = true;
1492 }
1493 }
1494 for (auto pgda : epd->passiveGrabbersContext) {
1495 if (auto ptda = qobject_cast<QQuickDeliveryAgent *>(object: pgda.data())) {
1496 insert(ptda, pt);
1497 qCDebug(lcPtr) << pe->type() << "point" << pt.id() << pt.state()
1498 << "@" << pt.scenePosition() << "will be re-delivered via known passive-grabbing agent" << ptda;
1499 foundAgent = true;
1500 }
1501 }
1502 // fallback: if we didn't find remembered/known grabber agent(s), expect the root DA to handle it
1503 if (!foundAgent)
1504 insert(da, pt);
1505 }
1506 for (auto daAndPoints : deliveryAgentsNeedingPoints) {
1507 if (pe->pointCount() > 1) {
1508 Q_ASSERT(QQuickDeliveryAgentPrivate::isTouchEvent(pe));
1509 // if all points have the same state, set the event type accordingly
1510 QEvent::Type eventType = pe->type();
1511 switch (eventStates) {
1512 case QEventPoint::State::Pressed:
1513 eventType = QEvent::TouchBegin;
1514 break;
1515 case QEventPoint::State::Released:
1516 eventType = QEvent::TouchEnd;
1517 break;
1518 default:
1519 eventType = QEvent::TouchUpdate;
1520 break;
1521 }
1522 // Make a new touch event for the subscene, the same way QQuickItemPrivate::localizedTouchEvent() does it
1523 QMutableTouchEvent te(eventType, pe->pointingDevice(), pe->modifiers(), daAndPoints.second);
1524 te.setTimestamp(pe->timestamp());
1525 te.accept();
1526 qCDebug(lcTouch) << daAndPoints.first << "shall now receive" << &te;
1527 ret = daAndPoints.first->event(ev: &te) || ret;
1528 } else {
1529 qCDebug(lcPtr) << daAndPoints.first << "shall now receive" << pe;
1530 ret = daAndPoints.first->event(ev: pe) || ret;
1531 }
1532 }
1533
1534 if (ret) {
1535 d->deliveryAgentPrivate()->clearGrabbers(pointerEvent: pe);
1536 return true;
1537 }
1538 } else if (!synthMouse) {
1539 // clear passive grabbers unless it's a system synth-mouse event
1540 // QTBUG-104890: Windows sends synth mouse events (which should be ignored) after touch events
1541 for (const auto &pt : pe->points()) {
1542 if (pt.state() == QEventPoint::Pressed)
1543 pe->clearPassiveGrabbers(point: pt);
1544 }
1545 }
1546 }
1547
1548 // If it has no points, it's probably a TouchCancel, and DeliveryAgent needs to handle it.
1549 // If we didn't handle it in the block above, handle it now.
1550 // TODO should we deliver to all DAs at once then, since we don't know which one should get it?
1551 // or fix QTBUG-90851 so that the event always has points?
1552 bool ret = (da && da->event(ev: event));
1553
1554 d->deliveryAgentPrivate()->clearGrabbers(pointerEvent: pe);
1555
1556 if (ret)
1557 return true;
1558 } else if (event->isInputEvent()) {
1559 if (da && da->event(ev: event))
1560 return true;
1561 }
1562
1563 switch (event->type()) {
1564 // a few more types that are not QInputEvents, but QQuickDeliveryAgent needs to handle them anyway
1565 case QEvent::FocusAboutToChange:
1566 case QEvent::Enter:
1567 case QEvent::Leave:
1568 case QEvent::InputMethod:
1569 case QEvent::InputMethodQuery:
1570#if QT_CONFIG(quick_draganddrop)
1571 case QEvent::DragEnter:
1572 case QEvent::DragLeave:
1573 case QEvent::DragMove:
1574 case QEvent::Drop:
1575#endif
1576 if (d->inDestructor)
1577 return false;
1578 if (da && da->event(ev: event))
1579 return true;
1580 break;
1581 case QEvent::LanguageChange:
1582 case QEvent::LocaleChange:
1583 if (d->contentItem)
1584 QCoreApplication::sendEvent(receiver: d->contentItem, event);
1585 break;
1586 case QEvent::UpdateRequest:
1587 if (d->windowManager)
1588 d->windowManager->handleUpdateRequest(this);
1589 break;
1590 case QEvent::PlatformSurface:
1591 if ((static_cast<QPlatformSurfaceEvent *>(event))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) {
1592 // Ensure that the rendering thread is notified before
1593 // the QPlatformWindow is destroyed.
1594 if (d->windowManager)
1595 d->windowManager->hide(window: this);
1596 }
1597 break;
1598 case QEvent::WindowDeactivate:
1599 if (auto da = d->deliveryAgentPrivate())
1600 da->handleWindowDeactivate(win: this);
1601 Q_FALLTHROUGH();
1602 case QEvent::WindowActivate:
1603 if (d->contentItem)
1604 QCoreApplication::sendEvent(receiver: d->contentItem, event);
1605 break;
1606 case QEvent::ApplicationPaletteChange:
1607 d->inheritPalette(parentPalette: QGuiApplication::palette());
1608 if (d->contentItem)
1609 QCoreApplication::sendEvent(receiver: d->contentItem, event);
1610 break;
1611 case QEvent::DevicePixelRatioChange:
1612 physicalDpiChanged();
1613 break;
1614 case QEvent::ChildWindowAdded: {
1615 auto *childEvent = static_cast<QChildWindowEvent*>(event);
1616 auto *childWindow = childEvent->child();
1617 qCDebug(lcQuickWindow) << "Child window" << childWindow << "added to" << this;
1618 if (childWindow->handle()) {
1619 // The reparenting has already resulted in the native window
1620 // being added to its parent, on top of all other windows. We need
1621 // to do a synchronous re-stacking of the windows here, to avoid
1622 // leaving the window in the wrong position while waiting for the
1623 // asynchronous callback to QQuickWindow::polishItems().
1624 d->updateChildWindowStackingOrder();
1625 } else {
1626 qCDebug(lcQuickWindow) << "No platform window yet."
1627 << "Deferring child window stacking until surface creation";
1628 }
1629 break;
1630 }
1631 default:
1632 break;
1633 }
1634
1635 if (event->type() == QEvent::Type(QQuickWindowPrivate::FullUpdateRequest))
1636 update();
1637 else if (event->type() == QEvent::Type(QQuickWindowPrivate::TriggerContextCreationFailure))
1638 d->windowManager->handleContextCreationFailure(window: this);
1639
1640 if (event->isPointerEvent())
1641 return true;
1642 else
1643 return QWindow::event(event);
1644}
1645
1646void QQuickWindowPrivate::updateChildWindowStackingOrder(QQuickItem *item)
1647{
1648 Q_Q(QQuickWindow);
1649
1650 if (!item) {
1651 qCDebug(lcQuickWindow) << "Updating child window stacking order for" << q;
1652 item = contentItem;
1653 }
1654 auto *itemPrivate = QQuickItemPrivate::get(item);
1655 const auto paintOrderChildItems = itemPrivate->paintOrderChildItems();
1656 for (auto *child : paintOrderChildItems) {
1657 if (auto *windowContainer = qobject_cast<QQuickWindowContainer*>(object: child)) {
1658 auto *window = windowContainer->containedWindow();
1659 if (!window) {
1660 qCDebug(lcQuickWindow) << windowContainer << "has no contained window yet";
1661 continue;
1662 }
1663 if (window->parent() != q) {
1664 qCDebug(lcQuickWindow) << window << "is not yet child of this window";
1665 continue;
1666 }
1667 qCDebug(lcQuickWindow) << "Raising" << window << "owned by" << windowContainer;
1668 window->raise();
1669 }
1670
1671 updateChildWindowStackingOrder(item: child);
1672 }
1673}
1674
1675/*! \reimp */
1676void QQuickWindow::keyPressEvent(QKeyEvent *e)
1677{
1678 Q_D(QQuickWindow);
1679 if (d->windowEventDispatch)
1680 return;
1681 auto da = d->deliveryAgentPrivate();
1682 Q_ASSERT(da);
1683 da->deliverKeyEvent(e);
1684}
1685
1686/*! \reimp */
1687void QQuickWindow::keyReleaseEvent(QKeyEvent *e)
1688{
1689 Q_D(QQuickWindow);
1690 if (d->windowEventDispatch)
1691 return;
1692 auto da = d->deliveryAgentPrivate();
1693 Q_ASSERT(da);
1694 da->deliverKeyEvent(e);
1695}
1696
1697#if QT_CONFIG(wheelevent)
1698/*! \reimp */
1699void QQuickWindow::wheelEvent(QWheelEvent *event)
1700{
1701 Q_D(QQuickWindow);
1702 if (d->windowEventDispatch)
1703 return;
1704 auto da = d->deliveryAgentPrivate();
1705 Q_ASSERT(da);
1706 da->deliverSinglePointEventUntilAccepted(event);
1707}
1708#endif // wheelevent
1709
1710#if QT_CONFIG(tabletevent)
1711/*! \reimp */
1712void QQuickWindow::tabletEvent(QTabletEvent *event)
1713{
1714 Q_D(QQuickWindow);
1715 if (d->windowEventDispatch)
1716 return;
1717 auto da = d->deliveryAgentPrivate();
1718 Q_ASSERT(da);
1719 da->deliverPointerEvent(event);
1720}
1721#endif // tabletevent
1722
1723/*! \reimp */
1724void QQuickWindow::mousePressEvent(QMouseEvent *event)
1725{
1726 Q_D(QQuickWindow);
1727 if (d->windowEventDispatch)
1728 return;
1729 auto da = d->deliveryAgentPrivate();
1730 Q_ASSERT(da);
1731 da->handleMouseEvent(event);
1732}
1733/*! \reimp */
1734void QQuickWindow::mouseMoveEvent(QMouseEvent *event)
1735{
1736 Q_D(QQuickWindow);
1737 if (d->windowEventDispatch)
1738 return;
1739 auto da = d->deliveryAgentPrivate();
1740 Q_ASSERT(da);
1741 da->handleMouseEvent(event);
1742}
1743/*! \reimp */
1744void QQuickWindow::mouseDoubleClickEvent(QMouseEvent *event)
1745{
1746 Q_D(QQuickWindow);
1747 if (d->windowEventDispatch)
1748 return;
1749 auto da = d->deliveryAgentPrivate();
1750 Q_ASSERT(da);
1751 da->handleMouseEvent(event);
1752}
1753/*! \reimp */
1754void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
1755{
1756 Q_D(QQuickWindow);
1757 if (d->windowEventDispatch)
1758 return;
1759 auto da = d->deliveryAgentPrivate();
1760 Q_ASSERT(da);
1761 da->handleMouseEvent(event);
1762}
1763
1764#if QT_CONFIG(cursor)
1765void QQuickWindowPrivate::updateCursor(const QPointF &scenePos, QQuickItem *rootItem)
1766{
1767 Q_Q(QQuickWindow);
1768 if (!rootItem)
1769 rootItem = contentItem;
1770 auto cursorItemAndHandler = findCursorItemAndHandler(item: rootItem, scenePos);
1771 if (cursorItem != cursorItemAndHandler.first || cursorHandler != cursorItemAndHandler.second ||
1772 (cursorItemAndHandler.second && QQuickPointerHandlerPrivate::get(q: cursorItemAndHandler.second)->cursorDirty)) {
1773 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(win: q);
1774 QWindow *window = renderWindow ? renderWindow : q;
1775 cursorItem = cursorItemAndHandler.first;
1776 cursorHandler = cursorItemAndHandler.second;
1777 if (cursorHandler)
1778 QQuickPointerHandlerPrivate::get(q: cursorItemAndHandler.second)->cursorDirty = false;
1779 if (cursorItem) {
1780 const auto cursor = QQuickItemPrivate::get(item: cursorItem)->effectiveCursor(handler: cursorHandler);
1781 qCDebug(lcHoverTrace) << "setting cursor" << cursor << "from" << cursorHandler << "or" << cursorItem;
1782 window->setCursor(cursor);
1783 } else {
1784 qCDebug(lcHoverTrace) << "unsetting cursor";
1785 window->unsetCursor();
1786 }
1787 }
1788}
1789
1790QPair<QQuickItem*, QQuickPointerHandler*> QQuickWindowPrivate::findCursorItemAndHandler(QQuickItem *item, const QPointF &scenePos) const
1791{
1792 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1793 if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1794 QPointF p = item->mapFromScene(point: scenePos);
1795 if (!item->contains(point: p))
1796 return {nullptr, nullptr};
1797 }
1798
1799 if (itemPrivate->subtreeCursorEnabled) {
1800 QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1801 for (int ii = children.size() - 1; ii >= 0; --ii) {
1802 QQuickItem *child = children.at(i: ii);
1803 if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(item: child)->culled)
1804 continue;
1805 auto ret = findCursorItemAndHandler(item: child, scenePos);
1806 if (ret.first)
1807 return ret;
1808 }
1809 if (itemPrivate->hasCursorHandler) {
1810 if (auto handler = itemPrivate->effectiveCursorHandler()) {
1811 if (handler->parentContains(scenePosition: scenePos))
1812 return {item, handler};
1813 }
1814 }
1815 if (itemPrivate->hasCursor) {
1816 QPointF p = item->mapFromScene(point: scenePos);
1817 if (item->contains(point: p))
1818 return {item, nullptr};
1819 }
1820 }
1821
1822 return {nullptr, nullptr};
1823}
1824#endif
1825
1826void QQuickWindowPrivate::clearFocusObject()
1827{
1828 if (auto da = deliveryAgentPrivate())
1829 da->clearFocusObject();
1830}
1831
1832void QQuickWindowPrivate::setFocusToTarget(FocusTarget target, Qt::FocusReason reason)
1833{
1834 if (!contentItem)
1835 return;
1836
1837 QQuickItem *newFocusItem = nullptr;
1838 switch (target) {
1839 case FocusTarget::First:
1840 case FocusTarget::Last: {
1841 const bool forward = (target == FocusTarget::First);
1842 newFocusItem = QQuickItemPrivate::nextPrevItemInTabFocusChain(item: contentItem, forward);
1843 if (newFocusItem) {
1844 const auto *itemPriv = QQuickItemPrivate::get(item: newFocusItem);
1845 if (itemPriv->subFocusItem && itemPriv->flags & QQuickItem::ItemIsFocusScope)
1846 clearFocusInScope(scope: newFocusItem, item: itemPriv->subFocusItem, reason);
1847 }
1848 break;
1849 }
1850 case FocusTarget::Next:
1851 case FocusTarget::Prev: {
1852 const auto da = deliveryAgentPrivate();
1853 Q_ASSERT(da);
1854 QQuickItem *focusItem = da->focusTargetItem() ? da->focusTargetItem() : contentItem;
1855 bool forward = (target == FocusTarget::Next);
1856 newFocusItem = QQuickItemPrivate::nextPrevItemInTabFocusChain(item: focusItem, forward);
1857 break;
1858 }
1859 default:
1860 break;
1861 }
1862
1863 if (newFocusItem)
1864 newFocusItem->forceActiveFocus(reason);
1865}
1866
1867/*!
1868 \qmlproperty list<QtObject> Window::data
1869 \qmldefault
1870
1871 The data property allows you to freely mix visual children, resources
1872 and other Windows in a Window.
1873
1874 If you assign another Window to the data list, the nested window will
1875 become "transient for" the outer Window.
1876
1877 If you assign an \l Item to the data list, it becomes a child of the
1878 Window's \l contentItem, so that it appears inside the window. The item's
1879 parent will be the window's contentItem, which is the root of the Item
1880 ownership tree within that Window.
1881
1882 If you assign any other object type, it is added as a resource.
1883
1884 It should not generally be necessary to refer to the \c data property,
1885 as it is the default property for Window and thus all child items are
1886 automatically assigned to this property.
1887
1888 \sa QWindow::transientParent()
1889 */
1890
1891void QQuickWindowPrivate::data_append(QQmlListProperty<QObject> *property, QObject *o)
1892{
1893 if (!o)
1894 return;
1895 QQuickWindow *that = static_cast<QQuickWindow *>(property->object);
1896 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(item: that->contentItem())->data();
1897 itemProperty.append(&itemProperty, o);
1898}
1899
1900qsizetype QQuickWindowPrivate::data_count(QQmlListProperty<QObject> *property)
1901{
1902 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1903 if (!win || !win->contentItem() || !QQuickItemPrivate::get(item: win->contentItem())->data().count)
1904 return 0;
1905 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(item: win->contentItem())->data();
1906 return itemProperty.count(&itemProperty);
1907}
1908
1909QObject *QQuickWindowPrivate::data_at(QQmlListProperty<QObject> *property, qsizetype i)
1910{
1911 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1912 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(item: win->contentItem())->data();
1913 return itemProperty.at(&itemProperty, i);
1914}
1915
1916void QQuickWindowPrivate::data_clear(QQmlListProperty<QObject> *property)
1917{
1918 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1919 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(item: win->contentItem())->data();
1920 itemProperty.clear(&itemProperty);
1921}
1922
1923void QQuickWindowPrivate::data_removeLast(QQmlListProperty<QObject> *property)
1924{
1925 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1926 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(item: win->contentItem())->data();
1927 itemProperty.removeLast(&itemProperty);
1928}
1929
1930bool QQuickWindowPrivate::isRenderable() const
1931{
1932 Q_Q(const QQuickWindow);
1933 return ((q->isExposed() && q->isVisible())) && q->geometry().isValid();
1934}
1935
1936void QQuickWindowPrivate::rhiCreationFailureMessage(const QString &backendName,
1937 QString *translatedMessage,
1938 QString *untranslatedMessage)
1939{
1940 const char msg[] = QT_TRANSLATE_NOOP("QQuickWindow",
1941 "Failed to initialize graphics backend for %1.");
1942 *translatedMessage = QQuickWindow::tr(s: msg).arg(a: backendName);
1943 *untranslatedMessage = QString::fromLatin1(ba: msg).arg(a: backendName);
1944}
1945
1946void QQuickWindowPrivate::cleanupNodes()
1947{
1948 qDeleteAll(c: std::exchange(obj&: cleanupNodeList, new_val: {}));
1949}
1950
1951void QQuickWindowPrivate::cleanupNodesOnShutdown(QQuickItem *item)
1952{
1953 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
1954 if (p->itemNodeInstance) {
1955 delete p->itemNodeInstance;
1956 p->itemNodeInstance = nullptr;
1957
1958 if (p->extra.isAllocated()) {
1959 p->extra->opacityNode = nullptr;
1960 p->extra->clipNode = nullptr;
1961 p->extra->rootNode = nullptr;
1962 }
1963
1964 p->paintNode = nullptr;
1965
1966 p->dirty(QQuickItemPrivate::Window);
1967 }
1968
1969 // Qt 7: Make invalidateSceneGraph a virtual member of QQuickItem
1970 if (p->flags & QQuickItem::ItemHasContents) {
1971 const QMetaObject *mo = item->metaObject();
1972 int index = mo->indexOfSlot(slot: "invalidateSceneGraph()");
1973 if (index >= 0) {
1974 const QMetaMethod &method = mo->method(index);
1975 // Skip functions named invalidateSceneGraph() in QML items.
1976 if (strstr(haystack: method.enclosingMetaObject()->className(), needle: "_QML_") == nullptr)
1977 method.invoke(obj: item, c: Qt::DirectConnection);
1978 }
1979 }
1980
1981 for (int ii = 0; ii < p->childItems.size(); ++ii)
1982 cleanupNodesOnShutdown(item: p->childItems.at(i: ii));
1983}
1984
1985// This must be called from the render thread, with the main thread frozen
1986void QQuickWindowPrivate::cleanupNodesOnShutdown()
1987{
1988 Q_Q(QQuickWindow);
1989 cleanupNodes();
1990 cleanupNodesOnShutdown(item: contentItem);
1991 for (QSet<QQuickItem *>::const_iterator it = parentlessItems.begin(), cend = parentlessItems.end(); it != cend; ++it)
1992 cleanupNodesOnShutdown(item: *it);
1993 animationController->windowNodesDestroyed();
1994 q->cleanupSceneGraph();
1995}
1996
1997void QQuickWindowPrivate::updateDirtyNodes()
1998{
1999 qCDebug(lcDirty) << "QQuickWindowPrivate::updateDirtyNodes():";
2000
2001 cleanupNodes();
2002
2003 QQuickItem *updateList = dirtyItemList;
2004 dirtyItemList = nullptr;
2005 if (updateList) QQuickItemPrivate::get(item: updateList)->prevDirtyItem = &updateList;
2006
2007 while (updateList) {
2008 QQuickItem *item = updateList;
2009 QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
2010 itemPriv->removeFromDirtyList();
2011
2012 qCDebug(lcDirty) << " QSGNode:" << item << qPrintable(itemPriv->dirtyToString());
2013 updateDirtyNode(item);
2014 }
2015}
2016
2017static inline QSGNode *qquickitem_before_paintNode(QQuickItemPrivate *d)
2018{
2019 const QList<QQuickItem *> childItems = d->paintOrderChildItems();
2020 QQuickItem *before = nullptr;
2021 for (int i=0; i<childItems.size(); ++i) {
2022 QQuickItemPrivate *dd = QQuickItemPrivate::get(item: childItems.at(i));
2023 // Perform the same check as the in fetchNextNode below.
2024 if (dd->z() < 0 && (dd->explicitVisible || (dd->extra.isAllocated() && dd->extra->effectRefCount)))
2025 before = childItems.at(i);
2026 else
2027 break;
2028 }
2029 return Q_UNLIKELY(before) ? QQuickItemPrivate::get(item: before)->itemNode() : nullptr;
2030}
2031
2032static QSGNode *fetchNextNode(QQuickItemPrivate *itemPriv, int &ii, bool &returnedPaintNode)
2033{
2034 QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
2035
2036 for (; ii < orderedChildren.size() && orderedChildren.at(i: ii)->z() < 0; ++ii) {
2037 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(item: orderedChildren.at(i: ii));
2038 if (!childPrivate->explicitVisible &&
2039 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2040 continue;
2041
2042 ii++;
2043 return childPrivate->itemNode();
2044 }
2045
2046 if (itemPriv->paintNode && !returnedPaintNode) {
2047 returnedPaintNode = true;
2048 return itemPriv->paintNode;
2049 }
2050
2051 for (; ii < orderedChildren.size(); ++ii) {
2052 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(item: orderedChildren.at(i: ii));
2053 if (!childPrivate->explicitVisible &&
2054 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2055 continue;
2056
2057 ii++;
2058 return childPrivate->itemNode();
2059 }
2060
2061 return nullptr;
2062}
2063
2064void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
2065{
2066 QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
2067 quint32 dirty = itemPriv->dirtyAttributes;
2068 itemPriv->dirtyAttributes = 0;
2069
2070 if ((dirty & QQuickItemPrivate::TransformUpdateMask) ||
2071 (dirty & QQuickItemPrivate::Size && itemPriv->origin() != QQuickItem::TopLeft &&
2072 (itemPriv->scale() != 1. || itemPriv->rotation() != 0.))) {
2073
2074 QMatrix4x4 matrix;
2075
2076 if (itemPriv->x != 0. || itemPriv->y != 0.)
2077 matrix.translate(x: itemPriv->x, y: itemPriv->y);
2078
2079 for (int ii = itemPriv->transforms.size() - 1; ii >= 0; --ii)
2080 itemPriv->transforms.at(i: ii)->applyTo(matrix: &matrix);
2081
2082 if (itemPriv->scale() != 1. || itemPriv->rotation() != 0.) {
2083 QPointF origin = item->transformOriginPoint();
2084 matrix.translate(x: origin.x(), y: origin.y());
2085 if (itemPriv->scale() != 1.)
2086 matrix.scale(x: itemPriv->scale(), y: itemPriv->scale());
2087 if (itemPriv->rotation() != 0.)
2088 matrix.rotate(angle: itemPriv->rotation(), x: 0, y: 0, z: 1);
2089 matrix.translate(x: -origin.x(), y: -origin.y());
2090 }
2091
2092 itemPriv->itemNode()->setMatrix(matrix);
2093 }
2094
2095 const bool clipEffectivelyChanged = dirty & (QQuickItemPrivate::Clip | QQuickItemPrivate::Window);
2096 if (clipEffectivelyChanged) {
2097 QSGNode *parent = itemPriv->opacityNode() ? (QSGNode *)itemPriv->opacityNode()
2098 : (QSGNode *)itemPriv->itemNode();
2099 QSGNode *child = itemPriv->rootNode();
2100
2101 if (bool initializeClipNode = item->clip() && itemPriv->clipNode() == nullptr;
2102 initializeClipNode) {
2103 QQuickDefaultClipNode *clip = new QQuickDefaultClipNode(item->clipRect());
2104 itemPriv->extra.value().clipNode = clip;
2105 clip->update();
2106
2107 if (!child) {
2108 parent->reparentChildNodesTo(newParent: clip);
2109 parent->appendChildNode(node: clip);
2110 } else {
2111 parent->removeChildNode(node: child);
2112 clip->appendChildNode(node: child);
2113 parent->appendChildNode(node: clip);
2114 }
2115
2116 } else if (bool updateClipNode = item->clip() && itemPriv->clipNode() != nullptr;
2117 updateClipNode) {
2118 QQuickDefaultClipNode *clip = itemPriv->clipNode();
2119 clip->setClipRect(item->clipRect());
2120 clip->update();
2121 } else if (bool removeClipNode = !item->clip() && itemPriv->clipNode() != nullptr;
2122 removeClipNode) {
2123 QQuickDefaultClipNode *clip = itemPriv->clipNode();
2124 parent->removeChildNode(node: clip);
2125 if (child) {
2126 clip->removeChildNode(node: child);
2127 parent->appendChildNode(node: child);
2128 } else {
2129 clip->reparentChildNodesTo(newParent: parent);
2130 }
2131
2132 delete itemPriv->clipNode();
2133 itemPriv->extra->clipNode = nullptr;
2134 }
2135 }
2136
2137 const int effectRefCount = itemPriv->extra.isAllocated() ? itemPriv->extra->effectRefCount : 0;
2138 const bool effectRefEffectivelyChanged =
2139 (dirty & (QQuickItemPrivate::EffectReference | QQuickItemPrivate::Window))
2140 && ((effectRefCount == 0) != (itemPriv->rootNode() == nullptr));
2141 if (effectRefEffectivelyChanged) {
2142 if (dirty & QQuickItemPrivate::ChildrenUpdateMask)
2143 itemPriv->childContainerNode()->removeAllChildNodes();
2144
2145 QSGNode *parent = itemPriv->clipNode();
2146 if (!parent)
2147 parent = itemPriv->opacityNode();
2148 if (!parent)
2149 parent = itemPriv->itemNode();
2150
2151 if (itemPriv->extra.isAllocated() && itemPriv->extra->effectRefCount) {
2152 Q_ASSERT(itemPriv->rootNode() == nullptr);
2153 QSGRootNode *root = new QSGRootNode();
2154 itemPriv->extra->rootNode = root;
2155 parent->reparentChildNodesTo(newParent: root);
2156 parent->appendChildNode(node: root);
2157 } else {
2158 Q_ASSERT(itemPriv->rootNode() != nullptr);
2159 QSGRootNode *root = itemPriv->rootNode();
2160 parent->removeChildNode(node: root);
2161 root->reparentChildNodesTo(newParent: parent);
2162 delete itemPriv->rootNode();
2163 itemPriv->extra->rootNode = nullptr;
2164 }
2165 }
2166
2167 if (dirty & QQuickItemPrivate::ChildrenUpdateMask) {
2168 int ii = 0;
2169 bool fetchedPaintNode = false;
2170 QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
2171 int desiredNodesSize = orderedChildren.size() + (itemPriv->paintNode ? 1 : 0);
2172
2173 // now start making current state match the promised land of
2174 // desiredNodes. in the case of our current state matching desiredNodes
2175 // (though why would we get ChildrenUpdateMask with no changes?) then we
2176 // should make no changes at all.
2177
2178 // how many nodes did we process, when examining changes
2179 int desiredNodesProcessed = 0;
2180
2181 // currentNode is how far, in our present tree, we have processed. we
2182 // make use of this later on to trim the current child list if the
2183 // desired list is shorter.
2184 QSGNode *groupNode = itemPriv->childContainerNode();
2185 QSGNode *currentNode = groupNode->firstChild();
2186 QSGNode *desiredNode = nullptr;
2187
2188 while (currentNode && (desiredNode = fetchNextNode(itemPriv, ii, returnedPaintNode&: fetchedPaintNode))) {
2189 if (currentNode != desiredNode) {
2190 // uh oh... reality and our utopic paradise are diverging!
2191 // we need to reconcile this...
2192 if (currentNode->nextSibling() == desiredNode) {
2193 // nice and simple: a node was removed, and the next in line is correct.
2194 groupNode->removeChildNode(node: currentNode);
2195 } else {
2196 // a node needs to be added..
2197 // remove it from any pre-existing parent, and push it before currentNode,
2198 // so it's in the correct place...
2199 if (desiredNode->parent()) {
2200 desiredNode->parent()->removeChildNode(node: desiredNode);
2201 }
2202 groupNode->insertChildNodeBefore(node: desiredNode, before: currentNode);
2203 }
2204
2205 // continue iteration at the correct point, now desiredNode is in place...
2206 currentNode = desiredNode;
2207 }
2208
2209 currentNode = currentNode->nextSibling();
2210 desiredNodesProcessed++;
2211 }
2212
2213 // if we didn't process as many nodes as in the new list, then we have
2214 // more nodes at the end of desiredNodes to append to our list.
2215 // this will be the case when adding new nodes, for instance.
2216 if (desiredNodesProcessed < desiredNodesSize) {
2217 while ((desiredNode = fetchNextNode(itemPriv, ii, returnedPaintNode&: fetchedPaintNode))) {
2218 if (desiredNode->parent())
2219 desiredNode->parent()->removeChildNode(node: desiredNode);
2220 groupNode->appendChildNode(node: desiredNode);
2221 }
2222 } else if (currentNode) {
2223 // on the other hand, if we processed less than our current node
2224 // tree, then nodes have been _removed_ from the scene, and we need
2225 // to take care of that here.
2226 while (currentNode) {
2227 QSGNode *node = currentNode->nextSibling();
2228 groupNode->removeChildNode(node: currentNode);
2229 currentNode = node;
2230 }
2231 }
2232 }
2233
2234 if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode()) {
2235 itemPriv->clipNode()->setRect(item->clipRect());
2236 itemPriv->clipNode()->update();
2237 }
2238
2239 if (dirty & (QQuickItemPrivate::OpacityValue | QQuickItemPrivate::Visible
2240 | QQuickItemPrivate::HideReference | QQuickItemPrivate::Window))
2241 {
2242 qreal opacity = itemPriv->explicitVisible && (!itemPriv->extra.isAllocated() || itemPriv->extra->hideRefCount == 0)
2243 ? itemPriv->opacity() : qreal(0);
2244
2245 if (opacity != 1 && !itemPriv->opacityNode()) {
2246 QSGOpacityNode *node = new QSGOpacityNode;
2247 itemPriv->extra.value().opacityNode = node;
2248
2249 QSGNode *parent = itemPriv->itemNode();
2250 QSGNode *child = itemPriv->clipNode();
2251 if (!child)
2252 child = itemPriv->rootNode();
2253
2254 if (child) {
2255 parent->removeChildNode(node: child);
2256 node->appendChildNode(node: child);
2257 parent->appendChildNode(node);
2258 } else {
2259 parent->reparentChildNodesTo(newParent: node);
2260 parent->appendChildNode(node);
2261 }
2262 }
2263 if (itemPriv->opacityNode())
2264 itemPriv->opacityNode()->setOpacity(opacity);
2265 }
2266
2267 if (dirty & QQuickItemPrivate::ContentUpdateMask) {
2268
2269 if (itemPriv->flags & QQuickItem::ItemHasContents) {
2270 updatePaintNodeData.transformNode = itemPriv->itemNode();
2271 itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
2272
2273 Q_ASSERT(itemPriv->paintNode == nullptr ||
2274 itemPriv->paintNode->parent() == nullptr ||
2275 itemPriv->paintNode->parent() == itemPriv->childContainerNode());
2276
2277 if (itemPriv->paintNode && itemPriv->paintNode->parent() == nullptr) {
2278 QSGNode *before = qquickitem_before_paintNode(d: itemPriv);
2279 if (before && before->parent()) {
2280 Q_ASSERT(before->parent() == itemPriv->childContainerNode());
2281 itemPriv->childContainerNode()->insertChildNodeAfter(node: itemPriv->paintNode, after: before);
2282 } else {
2283 itemPriv->childContainerNode()->prependChildNode(node: itemPriv->paintNode);
2284 }
2285 }
2286 } else if (itemPriv->paintNode) {
2287 delete itemPriv->paintNode;
2288 itemPriv->paintNode = nullptr;
2289 }
2290 }
2291
2292#ifndef QT_NO_DEBUG
2293 // Check consistency.
2294
2295 QList<QSGNode *> nodes;
2296 nodes << itemPriv->itemNodeInstance
2297 << itemPriv->opacityNode()
2298 << itemPriv->clipNode()
2299 << itemPriv->rootNode()
2300 << itemPriv->paintNode;
2301 nodes.removeAll(t: nullptr);
2302
2303 Q_ASSERT(nodes.constFirst() == itemPriv->itemNodeInstance);
2304 for (int i=1; i<nodes.size(); ++i) {
2305 QSGNode *n = nodes.at(i);
2306 // Failing this means we messed up reparenting
2307 Q_ASSERT(n->parent() == nodes.at(i-1));
2308 // Only the paintNode and the one who is childContainer may have more than one child.
2309 Q_ASSERT(n == itemPriv->paintNode || n == itemPriv->childContainerNode() || n->childCount() == 1);
2310 }
2311#endif
2312
2313}
2314
2315bool QQuickWindowPrivate::emitError(QQuickWindow::SceneGraphError error, const QString &msg)
2316{
2317 Q_Q(QQuickWindow);
2318 static const QMetaMethod errorSignal = QMetaMethod::fromSignal(signal: &QQuickWindow::sceneGraphError);
2319 if (q->isSignalConnected(signal: errorSignal)) {
2320 emit q->sceneGraphError(error, message: msg);
2321 return true;
2322 }
2323 return false;
2324}
2325
2326void QQuickWindow::maybeUpdate()
2327{
2328 Q_D(QQuickWindow);
2329 if (d->renderControl)
2330 QQuickRenderControlPrivate::get(renderControl: d->renderControl)->maybeUpdate();
2331 else if (d->windowManager)
2332 d->windowManager->maybeUpdate(window: this);
2333}
2334
2335void QQuickWindow::cleanupSceneGraph()
2336{
2337 Q_D(QQuickWindow);
2338 if (!d->renderer)
2339 return;
2340
2341 delete d->renderer->rootNode();
2342 delete d->renderer;
2343 d->renderer = nullptr;
2344
2345 d->runAndClearJobs(jobs: &d->beforeSynchronizingJobs);
2346 d->runAndClearJobs(jobs: &d->afterSynchronizingJobs);
2347 d->runAndClearJobs(jobs: &d->beforeRenderingJobs);
2348 d->runAndClearJobs(jobs: &d->afterRenderingJobs);
2349 d->runAndClearJobs(jobs: &d->afterSwapJobs);
2350}
2351
2352QOpenGLContext *QQuickWindowPrivate::openglContext()
2353{
2354#if QT_CONFIG(opengl)
2355 if (context && context->isValid()) {
2356 QSGRendererInterface *rif = context->sceneGraphContext()->rendererInterface(renderContext: context);
2357 if (rif) {
2358 Q_Q(QQuickWindow);
2359 return reinterpret_cast<QOpenGLContext *>(rif->getResource(window: q, resource: QSGRendererInterface::OpenGLContextResource));
2360 }
2361 }
2362#endif
2363 return nullptr;
2364}
2365
2366/*!
2367 Returns true if the scene graph has been initialized; otherwise returns false.
2368 */
2369bool QQuickWindow::isSceneGraphInitialized() const
2370{
2371 Q_D(const QQuickWindow);
2372 return d->context != nullptr && d->context->isValid();
2373}
2374
2375/*!
2376 \fn void QQuickWindow::frameSwapped()
2377
2378 This signal is emitted when a frame has been queued for presenting. With
2379 vertical synchronization enabled the signal is emitted at most once per
2380 vsync interval in a continuously animating scene.
2381
2382 This signal will be emitted from the scene graph rendering thread.
2383*/
2384
2385/*!
2386 \qmlsignal QtQuick::Window::frameSwapped()
2387
2388 This signal is emitted when a frame has been queued for presenting. With
2389 vertical synchronization enabled the signal is emitted at most once per
2390 vsync interval in a continuously animating scene.
2391 */
2392
2393/*!
2394 \fn void QQuickWindow::sceneGraphInitialized()
2395
2396 This signal is emitted when the scene graph has been initialized.
2397
2398 This signal will be emitted from the scene graph rendering thread.
2399 */
2400
2401/*!
2402 \qmlsignal QtQuick::Window::sceneGraphInitialized()
2403 \internal
2404 */
2405
2406/*!
2407 \fn void QQuickWindow::sceneGraphInvalidated()
2408
2409 This signal is emitted when the scene graph has been invalidated.
2410
2411 This signal implies that the graphics rendering context used
2412 has been invalidated and all user resources tied to that context
2413 should be released.
2414
2415 When rendering with OpenGL, the QOpenGLContext of this window will
2416 be bound when this function is called. The only exception is if
2417 the native OpenGL has been destroyed outside Qt's control, for
2418 instance through EGL_CONTEXT_LOST.
2419
2420 This signal will be emitted from the scene graph rendering thread.
2421 */
2422
2423/*!
2424 \qmlsignal QtQuick::Window::sceneGraphInvalidated()
2425 \internal
2426 */
2427
2428/*!
2429 \fn void QQuickWindow::sceneGraphError(SceneGraphError error, const QString &message)
2430
2431 This signal is emitted when an \a error occurred during scene graph initialization.
2432
2433 Applications should connect to this signal if they wish to handle errors,
2434 like graphics context creation failures, in a custom way. When no slot is
2435 connected to the signal, the behavior will be different: Quick will print
2436 the \a message, or show a message box, and terminate the application.
2437
2438 This signal will be emitted from the GUI thread.
2439
2440 \since 5.3
2441 */
2442
2443/*!
2444 \qmlsignal QtQuick::Window::sceneGraphError(SceneGraphError error, QString message)
2445
2446 This signal is emitted when an \a error occurred during scene graph initialization.
2447
2448 You can implement onSceneGraphError(error, message) to handle errors,
2449 such as graphics context creation failures, in a custom way.
2450 If no handler is connected to this signal, Quick will print the \a message,
2451 or show a message box, and terminate the application.
2452
2453 \since 5.3
2454 */
2455
2456/*!
2457 \class QQuickCloseEvent
2458 \internal
2459 \since 5.1
2460
2461 \inmodule QtQuick
2462
2463 \brief Notification that a \l QQuickWindow is about to be closed
2464*/
2465/*!
2466 \qmltype CloseEvent
2467 \nativetype QQuickCloseEvent
2468 \inqmlmodule QtQuick
2469 \ingroup qtquick-visual
2470 \brief Notification that a \l Window is about to be closed.
2471 \since 5.1
2472
2473 Notification that a window is about to be closed by the windowing system
2474 (e.g. the user clicked the title bar close button). The CloseEvent contains
2475 an accepted property which can be set to false to abort closing the window.
2476*/
2477
2478/*!
2479 \qmlproperty bool CloseEvent::accepted
2480
2481 This property indicates whether the application will allow the user to
2482 close the window. It is true by default.
2483*/
2484
2485/*!
2486 \internal
2487 \fn void QQuickWindow::closing(QQuickCloseEvent *close)
2488 \since 5.1
2489
2490 This signal is emitted when the window receives the event \a close from
2491 the windowing system.
2492
2493 On \macOs, Qt will create a menu item \c Quit if there is no menu item
2494 whose text is "quit" or "exit". This menu item calls the \c QCoreApplication::quit
2495 signal, not the \c QQuickWindow::closing() signal.
2496
2497 \sa {QMenuBar as a Global Menu Bar}
2498*/
2499
2500/*!
2501 \qmlsignal QtQuick::Window::closing(CloseEvent close)
2502 \since 5.1
2503
2504 This signal is emitted when the user tries to close the window.
2505
2506 This signal includes a \a close parameter. The \c {close.accepted}
2507 property is true by default so that the window is allowed to close; but you
2508 can implement an \c onClosing handler and set \c {close.accepted = false} if
2509 you need to do something else before the window can be closed.
2510 */
2511
2512/*!
2513 Sets the render target for this window to be \a target.
2514
2515 A QQuickRenderTarget serves as an opaque handle for a renderable native
2516 object, most commonly a 2D texture, and associated metadata, such as the
2517 size in pixels.
2518
2519 A default constructed QQuickRenderTarget means no redirection. A valid
2520 \a target, created via one of the static QQuickRenderTarget factory functions,
2521 on the other hand, enables redirection of the rendering of the Qt Quick
2522 scene: it will no longer target the color buffers for the surface
2523 associated with the window, but rather the textures or other graphics
2524 objects specified in \a target.
2525
2526 For example, assuming the scenegraph is using Vulkan to render, one can
2527 redirect its output into a \c VkImage. For graphics APIs like Vulkan, the
2528 image layout must be provided as well. QQuickRenderTarget instances are
2529 implicitly shared and are copyable and can be passed by value. They do not
2530 own the associated native objects (such as, the VkImage in the example),
2531 however.
2532
2533 \badcode
2534 QQuickRenderTarget rt = QQuickRenderTarget::fromVulkanImage(vulkanImage, VK_IMAGE_LAYOUT_PREINITIALIZED, pixelSize);
2535 quickWindow->setRenderTarget(rt);
2536 \endcode
2537
2538 This function is very often used in combination with QQuickRenderControl
2539 and an invisible QQuickWindow, in order to render Qt Quick content into a
2540 texture, without creating an on-screen native window for this QQuickWindow.
2541
2542 When the desired target, or associated data, such as the size, changes,
2543 call this function with a new QQuickRenderTarget. Constructing
2544 QQuickRenderTarget instances and calling this function is cheap, but be
2545 aware that setting a new \a target with a different native object or other
2546 data may lead to potentially expensive initialization steps when the
2547 scenegraph is about to render the next frame. Therefore change the target
2548 only when necessary.
2549
2550 \note The window does not take ownership of any native objects referenced
2551 in \a target.
2552
2553 \note It is the caller's responsibility to ensure the native objects
2554 referred to in \a target are valid for the scenegraph renderer too. For
2555 instance, with Vulkan, Metal, and Direct3D this implies that the texture or
2556 image is created on the same graphics device that is used by the scenegraph
2557 internally. Therefore, when texture objects created on an already existing
2558 device or context are involved, this function is often used in combination
2559 with setGraphicsDevice().
2560
2561 \note With graphics APIs where relevant, the application must pay attention
2562 to image layout transitions performed by the scenegraph. For example, once
2563 a VkImage is associated with the scenegraph by calling this function, its
2564 layout will transition to \c VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL when
2565 rendering a frame.
2566
2567 \warning This function can only be called from the thread doing the
2568 rendering.
2569
2570 \since 6.0
2571
2572 \sa QQuickRenderControl, setGraphicsDevice(), setGraphicsApi()
2573 */
2574void QQuickWindow::setRenderTarget(const QQuickRenderTarget &target)
2575{
2576 Q_D(QQuickWindow);
2577 if (target != d->customRenderTarget) {
2578 d->customRenderTarget = target;
2579 d->redirect.renderTargetDirty = true;
2580 }
2581}
2582
2583/*!
2584 \return the QQuickRenderTarget passed to setRenderTarget(), or a default
2585 constructed one otherwise
2586
2587 \since 6.0
2588
2589 \sa setRenderTarget()
2590 */
2591QQuickRenderTarget QQuickWindow::renderTarget() const
2592{
2593 Q_D(const QQuickWindow);
2594 return d->customRenderTarget;
2595}
2596
2597#ifdef Q_OS_WEBOS
2598class GrabWindowForProtectedContent : public QRunnable
2599{
2600public:
2601 GrabWindowForProtectedContent(QQuickWindow *window, QImage *image, QWaitCondition *condition)
2602 : m_window(window)
2603 , m_image(image)
2604 , m_condition(condition)
2605 {
2606 }
2607
2608 bool checkGrabbable()
2609 {
2610 if (!m_window)
2611 return false;
2612 if (!m_image)
2613 return false;
2614 if (!QQuickWindowPrivate::get(m_window))
2615 return false;
2616
2617 return true;
2618 }
2619
2620 void run() override
2621 {
2622 if (!checkGrabbable())
2623 return;
2624
2625 *m_image = QSGRhiSupport::instance()->grabOffscreenForProtectedContent(m_window);
2626 if (m_condition)
2627 m_condition->wakeOne();
2628 return;
2629 }
2630
2631private:
2632 QQuickWindow *m_window;
2633 QImage *m_image;
2634 QWaitCondition *m_condition;
2635
2636};
2637#endif
2638
2639/*!
2640 Grabs the contents of the window and returns it as an image.
2641
2642 It is possible to call the grabWindow() function when the window is not
2643 visible. This requires that the window is \l{QWindow::create()} {created}
2644 and has a valid size and that no other QQuickWindow instances are rendering
2645 in the same process.
2646
2647 \note When using this window in combination with QQuickRenderControl, the
2648 result of this function is an empty image, unless the \c software backend
2649 is in use. This is because when redirecting the output to an
2650 application-managed graphics resource (such as, a texture) by using
2651 QQuickRenderControl and setRenderTarget(), the application is better suited
2652 for managing and executing an eventual read back operation, since it is in
2653 full control of the resource to begin with.
2654
2655 \warning Calling this function will cause performance problems.
2656
2657 \warning This function can only be called from the GUI thread.
2658 */
2659QImage QQuickWindow::grabWindow()
2660{
2661 Q_D(QQuickWindow);
2662
2663 if (!d->isRenderable() && !d->renderControl) {
2664 // backends like software can grab regardless of the window state
2665 if (d->windowManager && (d->windowManager->flags() & QSGRenderLoop::SupportsGrabWithoutExpose))
2666 return d->windowManager->grab(window: this);
2667
2668 if (!isSceneGraphInitialized()) {
2669 // We do not have rendering up and running. Forget the render loop,
2670 // do a frame completely offscreen and synchronously into a
2671 // texture. This can be *very* slow due to all the device/context
2672 // and resource initialization but the documentation warns for it,
2673 // and is still important for some use cases.
2674 Q_ASSERT(!d->rhi);
2675 return QSGRhiSupport::instance()->grabOffscreen(window: this);
2676 }
2677 }
2678
2679#ifdef Q_OS_WEBOS
2680 if (requestedFormat().testOption(QSurfaceFormat::ProtectedContent)) {
2681 QImage image;
2682 QMutex mutex;
2683 QWaitCondition condition;
2684 mutex.lock();
2685 GrabWindowForProtectedContent *job = new GrabWindowForProtectedContent(this, &image, &condition);
2686 if (!job) {
2687 qWarning("QQuickWindow::grabWindow: Failed to create a job for capturing protected content");
2688 mutex.unlock();
2689 return QImage();
2690 }
2691 scheduleRenderJob(job, QQuickWindow::NoStage);
2692 condition.wait(&mutex);
2693 mutex.unlock();
2694 return image;
2695 }
2696#endif
2697 // The common case: we have an exposed window with an initialized
2698 // scenegraph, meaning we can request grabbing via the render loop, or we
2699 // are not targeting the window, in which case the request is to be
2700 // forwarded to the rendercontrol.
2701 if (d->renderControl)
2702 return QQuickRenderControlPrivate::get(renderControl: d->renderControl)->grab();
2703 else if (d->windowManager)
2704 return d->windowManager->grab(window: this);
2705
2706 return QImage();
2707}
2708
2709/*!
2710 Returns an incubation controller that splices incubation between frames
2711 for this window. QQuickView automatically installs this controller for you,
2712 otherwise you will need to install it yourself using \l{QQmlEngine::setIncubationController()}.
2713
2714 The controller is owned by the window and will be destroyed when the window
2715 is deleted.
2716*/
2717QQmlIncubationController *QQuickWindow::incubationController() const
2718{
2719 Q_D(const QQuickWindow);
2720
2721 if (!d->windowManager)
2722 return nullptr; // TODO: make sure that this is safe
2723
2724 if (!d->incubationController)
2725 d->incubationController = new QQuickWindowIncubationController(d->windowManager);
2726 return d->incubationController;
2727}
2728
2729
2730
2731/*!
2732 \enum QQuickWindow::CreateTextureOption
2733
2734 The CreateTextureOption enums are used to customize a texture is wrapped.
2735
2736 \value TextureHasAlphaChannel The texture has an alpha channel and should
2737 be drawn using blending.
2738
2739 \value TextureHasMipmaps The texture has mipmaps and can be drawn with
2740 mipmapping enabled.
2741
2742 \value TextureOwnsGLTexture As of Qt 6.0, this flag is not used in practice
2743 and is ignored. Native graphics resource ownership is not transferable to
2744 the wrapping QSGTexture, because Qt Quick may not have the necessary details
2745 on how such an object and the associated memory should be freed.
2746
2747 \value TextureCanUseAtlas The image can be uploaded into a texture atlas.
2748
2749 \value TextureIsOpaque The texture will return false for
2750 QSGTexture::hasAlphaChannel() and will not be blended. This flag was added
2751 in Qt 5.6.
2752
2753 */
2754
2755/*!
2756 \enum QQuickWindow::SceneGraphError
2757
2758 This enum describes the error in a sceneGraphError() signal.
2759
2760 \value ContextNotAvailable graphics context creation failed. This typically means that
2761 no suitable OpenGL implementation was found, for example because no graphics drivers
2762 are installed and so no OpenGL 2 support is present. On mobile and embedded boards
2763 that use OpenGL ES such an error is likely to indicate issues in the windowing system
2764 integration and possibly an incorrect configuration of Qt.
2765
2766 \since 5.3
2767 */
2768
2769/*!
2770 \enum QQuickWindow::TextRenderType
2771 \since 5.10
2772
2773 This enum describes the default render type of text-like elements in Qt
2774 Quick (\l Text, \l TextInput, etc.).
2775
2776 Select NativeTextRendering if you prefer text to look native on the target
2777 platform and do not require advanced features such as transformation of the
2778 text. Using such features in combination with the NativeTextRendering
2779 render type will lend poor and sometimes pixelated results.
2780
2781 Both \c QtTextRendering and \c CurveTextRendering are hardware-accelerated techniques.
2782 \c QtTextRendering is the faster of the two, but uses more memory and will exhibit rendering
2783 artifacts at large sizes. \c CurveTextRendering should be considered as an alternative in cases
2784 where \c QtTextRendering does not give good visual results or where reducing graphics memory
2785 consumption is a priority.
2786
2787 \value QtTextRendering Use Qt's own rasterization algorithm.
2788 \value NativeTextRendering Use the operating system's native rasterizer for text.
2789 \value CurveTextRendering Text is rendered using a curve rasterizer running directly on
2790 the graphics hardware. (Introduced in Qt 6.7.0.)
2791*/
2792
2793/*!
2794 \fn void QQuickWindow::beforeSynchronizing()
2795
2796 This signal is emitted before the scene graph is synchronized with the QML state.
2797
2798 Even though the signal is emitted from the scene graph rendering thread,
2799 the GUI thread is guaranteed to be blocked, like it is in
2800 QQuickItem::updatePaintNode(). Therefore, it is safe to access GUI thread
2801 thread data in a slot or lambda that is connected with
2802 Qt::DirectConnection.
2803
2804 This signal can be used to do any preparation required before calls to
2805 QQuickItem::updatePaintNode().
2806
2807 When using OpenGL, the QOpenGLContext used for rendering by the scene graph
2808 will be bound at this point.
2809
2810 \warning This signal is emitted from the scene graph rendering thread. If your
2811 slot function needs to finish before execution continues, you must make sure that
2812 the connection is direct (see Qt::ConnectionType).
2813
2814 \warning When using OpenGL, be aware that setting OpenGL 3.x or 4.x specific
2815 states and leaving these enabled or set to non-default values when returning
2816 from the connected slot can interfere with the scene graph's rendering.
2817*/
2818
2819/*!
2820 \qmlsignal QtQuick::Window::beforeSynchronizing()
2821 \internal
2822*/
2823
2824/*!
2825 \fn void QQuickWindow::afterSynchronizing()
2826
2827 This signal is emitted after the scene graph is synchronized with the QML state.
2828
2829 This signal can be used to do preparation required after calls to
2830 QQuickItem::updatePaintNode(), while the GUI thread is still locked.
2831
2832 When using OpenGL, the QOpenGLContext used for rendering by the scene graph
2833 will be bound at this point.
2834
2835 \warning This signal is emitted from the scene graph rendering thread. If your
2836 slot function needs to finish before execution continues, you must make sure that
2837 the connection is direct (see Qt::ConnectionType).
2838
2839 \warning When using OpenGL, be aware that setting OpenGL 3.x or 4.x specific
2840 states and leaving these enabled or set to non-default values when returning
2841 from the connected slot can interfere with the scene graph's rendering.
2842
2843 \since 5.3
2844 */
2845
2846/*!
2847 \qmlsignal QtQuick::Window::afterSynchronizing()
2848 \internal
2849 \since 5.3
2850 */
2851
2852/*!
2853 \fn void QQuickWindow::beforeRendering()
2854
2855 This signal is emitted after the preparations for the frame have been done,
2856 meaning there is a command buffer in recording mode, where applicable. If
2857 desired, the slot function connected to this signal can query native
2858 resources like the command before via QSGRendererInterface. Note however
2859 that the recording of the main render pass is not yet started at this point
2860 and it is not possible to add commands within that pass. Starting a pass
2861 means clearing the color, depth, and stencil buffers so it is not possible
2862 to achieve an underlay type of rendering by just connecting to this
2863 signal. Rather, connect to beforeRenderPassRecording(). However, connecting
2864 to this signal is still important if the recording of copy type of commands
2865 is desired since those cannot be enqueued within a render pass.
2866
2867 \warning This signal is emitted from the scene graph rendering thread. If your
2868 slot function needs to finish before execution continues, you must make sure that
2869 the connection is direct (see Qt::ConnectionType).
2870
2871 \note When using OpenGL, be aware that setting OpenGL 3.x or 4.x specific
2872 states and leaving these enabled or set to non-default values when
2873 returning from the connected slot can interfere with the scene graph's
2874 rendering. The QOpenGLContext used for rendering by the scene graph will be
2875 bound when the signal is emitted.
2876
2877 \sa rendererInterface(), {Scene Graph - RHI Under QML}, {Scene Graph -
2878 OpenGL Under QML}, {Scene Graph - Metal Under QML}, {Scene Graph - Vulkan
2879 Under QML}, {Scene Graph - Direct3D 11 Under QML}
2880*/
2881
2882/*!
2883 \qmlsignal QtQuick::Window::beforeRendering()
2884 \internal
2885*/
2886
2887/*!
2888 \fn void QQuickWindow::afterRendering()
2889
2890 The signal is emitted after scene graph has added its commands to the
2891 command buffer, which is not yet submitted to the graphics queue. If
2892 desired, the slot function connected to this signal can query native
2893 resources, like the command buffer, before via QSGRendererInterface. Note
2894 however that the render pass (or passes) are already recorded at this point
2895 and it is not possible to add more commands within the scenegraph's
2896 pass. Instead, use afterRenderPassRecording() for that. This signal has
2897 therefore limited use in Qt 6, unlike in Qt 5. Rather, it is the combination
2898 of beforeRendering() and beforeRenderPassRecording(), or beforeRendering()
2899 and afterRenderPassRecording(), that is typically used to achieve under- or
2900 overlaying of the custom rendering.
2901
2902 \warning This signal is emitted from the scene graph rendering thread. If your
2903 slot function needs to finish before execution continues, you must make sure that
2904 the connection is direct (see Qt::ConnectionType).
2905
2906 \note When using OpenGL, be aware that setting OpenGL 3.x or 4.x specific
2907 states and leaving these enabled or set to non-default values when
2908 returning from the connected slot can interfere with the scene graph's
2909 rendering. The QOpenGLContext used for rendering by the scene graph will be
2910 bound when the signal is emitted.
2911
2912 \sa rendererInterface(), {Scene Graph - RHI Under QML}, {Scene Graph -
2913 OpenGL Under QML}, {Scene Graph - Metal Under QML}, {Scene Graph - Vulkan
2914 Under QML}, {Scene Graph - Direct3D 11 Under QML}
2915 */
2916
2917/*!
2918 \qmlsignal QtQuick::Window::afterRendering()
2919 \internal
2920 */
2921
2922/*!
2923 \fn void QQuickWindow::beforeRenderPassRecording()
2924
2925 This signal is emitted before the scenegraph starts recording commands for
2926 the main render pass. (Layers have their own passes and are fully recorded
2927 by the time this signal is emitted.) The render pass is already active on
2928 the command buffer when the signal is emitted.
2929
2930 This signal is emitted later than beforeRendering() and it guarantees that
2931 not just the frame, but also the recording of the scenegraph's main render
2932 pass is active. This allows inserting commands without having to generate an
2933 entire, separate render pass (which would typically clear the attached
2934 images). The native graphics objects can be queried via
2935 QSGRendererInterface.
2936
2937 \note Resource updates (uploads, copies) typically cannot be enqueued from
2938 within a render pass. Therefore, more complex user rendering will need to
2939 connect to both beforeRendering() and this signal.
2940
2941 \warning This signal is emitted from the scene graph rendering thread. If your
2942 slot function needs to finish before execution continues, you must make sure that
2943 the connection is direct (see Qt::ConnectionType).
2944
2945 \sa rendererInterface()
2946
2947 \since 5.14
2948
2949 \sa {Scene Graph - RHI Under QML}
2950*/
2951
2952/*!
2953 \qmlsignal QtQuick::Window::beforeRenderPassRecording()
2954 \internal
2955 \since 5.14
2956*/
2957
2958/*!
2959 \fn void QQuickWindow::afterRenderPassRecording()
2960
2961 This signal is emitted after the scenegraph has recorded the commands for
2962 its main render pass, but the pass is not yet finalized on the command
2963 buffer.
2964
2965 This signal is emitted earlier than afterRendering(), and it guarantees that
2966 not just the frame but also the recording of the scenegraph's main render
2967 pass is still active. This allows inserting commands without having to
2968 generate an entire, separate render pass (which would typically clear the
2969 attached images). The native graphics objects can be queried via
2970 QSGRendererInterface.
2971
2972 \note Resource updates (uploads, copies) typically cannot be enqueued from
2973 within a render pass. Therefore, more complex user rendering will need to
2974 connect to both beforeRendering() and this signal.
2975
2976 \warning This signal is emitted from the scene graph rendering thread. If your
2977 slot function needs to finish before execution continues, you must make sure that
2978 the connection is direct (see Qt::ConnectionType).
2979
2980 \sa rendererInterface()
2981
2982 \since 5.14
2983
2984 \sa {Scene Graph - RHI Under QML}
2985*/
2986
2987/*!
2988 \fn void QQuickWindow::beforeFrameBegin()
2989
2990 This signal is emitted before the scene graph starts preparing the frame.
2991 This precedes signals like beforeSynchronizing() or beforeRendering(). It is
2992 the earliest signal that is emitted by the scene graph rendering thread
2993 when starting to prepare a new frame.
2994
2995 This signal is relevant for lower level graphics frameworks that need to
2996 execute certain operations, such as resource cleanup, at a stage where Qt
2997 Quick has not initiated the recording of a new frame via the underlying
2998 rendering hardware interface APIs.
2999
3000 \warning This signal is emitted from the scene graph rendering thread. If your
3001 slot function needs to finish before execution continues, you must make sure that
3002 the connection is direct (see Qt::ConnectionType).
3003
3004 \since 6.0
3005
3006 \sa afterFrameEnd(), rendererInterface()
3007*/
3008
3009/*!
3010 \qmlsignal QtQuick::Window::beforeFrameBegin()
3011 \internal
3012*/
3013
3014/*!
3015 \fn void QQuickWindow::afterFrameEnd()
3016
3017 This signal is emitted when the scene graph has submitted a frame. This is
3018 emitted after all other related signals, such as afterRendering(). It is
3019 the last signal that is emitted by the scene graph rendering thread when
3020 rendering a frame.
3021
3022 \note Unlike frameSwapped(), this signal is guaranteed to be emitted also
3023 when the Qt Quick output is redirected via QQuickRenderControl.
3024
3025 \warning This signal is emitted from the scene graph rendering thread. If your
3026 slot function needs to finish before execution continues, you must make sure that
3027 the connection is direct (see Qt::ConnectionType).
3028
3029 \since 6.0
3030
3031 \sa beforeFrameBegin(), rendererInterface()
3032*/
3033
3034/*!
3035 \qmlsignal QtQuick::Window::afterFrameEnd()
3036 \internal
3037*/
3038
3039/*!
3040 \qmlsignal QtQuick::Window::afterRenderPassRecording()
3041 \internal
3042 \since 5.14
3043*/
3044
3045/*!
3046 \fn void QQuickWindow::afterAnimating()
3047
3048 This signal is emitted on the GUI thread before requesting the render thread to
3049 perform the synchronization of the scene graph.
3050
3051 Unlike the other similar signals, this one is emitted on the GUI thread
3052 instead of the render thread. It can be used to synchronize external
3053 animation systems with the QML content. At the same time this means that
3054 this signal is not suitable for triggering graphics operations.
3055
3056 \since 5.3
3057 */
3058
3059/*!
3060 \qmlsignal QtQuick::Window::afterAnimating()
3061
3062 This signal is emitted on the GUI thread before requesting the render thread to
3063 perform the synchronization of the scene graph.
3064
3065 You can implement onAfterAnimating to do additional processing after each animation step.
3066
3067 \since 5.3
3068 */
3069
3070/*!
3071 \fn void QQuickWindow::sceneGraphAboutToStop()
3072
3073 This signal is emitted on the render thread when the scene graph is
3074 about to stop rendering. This happens usually because the window
3075 has been hidden.
3076
3077 Applications may use this signal to release resources, but should be
3078 prepared to reinstantiated them again fast. The scene graph and the
3079 graphics context are not released at this time.
3080
3081 \warning This signal is emitted from the scene graph rendering thread. If your
3082 slot function needs to finish before execution continues, you must make sure that
3083 the connection is direct (see Qt::ConnectionType).
3084
3085 \warning Make very sure that a signal handler for sceneGraphAboutToStop() leaves the
3086 graphics context in the same state as it was when the signal handler was entered.
3087 Failing to do so can result in the scene not rendering properly.
3088
3089 \sa sceneGraphInvalidated()
3090 \since 5.3
3091 */
3092
3093/*!
3094 \qmlsignal QtQuick::Window::sceneGraphAboutToStop()
3095 \internal
3096 \since 5.3
3097 */
3098
3099/*!
3100 \overload
3101 */
3102
3103QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const
3104{
3105 return createTextureFromImage(image, options: {});
3106}
3107
3108
3109/*!
3110 Creates a new QSGTexture from the supplied \a image. If the image has an
3111 alpha channel, the corresponding texture will have an alpha channel.
3112
3113 The caller of the function is responsible for deleting the returned texture.
3114 The underlying native texture object is then destroyed together with the
3115 QSGTexture.
3116
3117 When \a options contains TextureCanUseAtlas, the engine may put the image
3118 into a texture atlas. Textures in an atlas need to rely on
3119 QSGTexture::normalizedTextureSubRect() for their geometry and will not
3120 support QSGTexture::Repeat. Other values from CreateTextureOption are
3121 ignored.
3122
3123 When \a options contains TextureIsOpaque, the engine will create an RGB
3124 texture which returns false for QSGTexture::hasAlphaChannel(). Opaque
3125 textures will in most cases be faster to render. When this flag is not set,
3126 the texture will have an alpha channel based on the image's format.
3127
3128 When \a options contains TextureHasMipmaps, the engine will create a texture
3129 which can use mipmap filtering. Mipmapped textures can not be in an atlas.
3130
3131 Setting TextureHasAlphaChannel in \a options serves no purpose for this
3132 function since assuming an alpha channel and blending is the default. To opt
3133 out, set TextureIsOpaque.
3134
3135 When the scene graph uses OpenGL, the returned texture will be using \c
3136 GL_TEXTURE_2D as texture target and \c GL_RGBA as internal format. With
3137 other graphics APIs, the texture format is typically \c RGBA8. Reimplement
3138 QSGTexture to create textures with different parameters.
3139
3140 \warning This function will return 0 if the scene graph has not yet been
3141 initialized.
3142
3143 \warning The returned texture is not memory managed by the scene graph and
3144 must be explicitly deleted by the caller on the rendering thread. This is
3145 achieved by deleting the texture from a QSGNode destructor or by using
3146 deleteLater() in the case where the texture already has affinity to the
3147 rendering thread.
3148
3149 This function can be called from both the main and the render thread.
3150
3151 \sa sceneGraphInitialized(), QSGTexture
3152 */
3153
3154QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateTextureOptions options) const
3155{
3156 Q_D(const QQuickWindow);
3157 if (!isSceneGraphInitialized()) // check both for d->context and d->context->isValid()
3158 return nullptr;
3159 uint flags = 0;
3160 if (options & TextureCanUseAtlas) flags |= QSGRenderContext::CreateTexture_Atlas;
3161 if (options & TextureHasMipmaps) flags |= QSGRenderContext::CreateTexture_Mipmap;
3162 if (!(options & TextureIsOpaque)) flags |= QSGRenderContext::CreateTexture_Alpha;
3163 return d->context->createTexture(image, flags);
3164}
3165
3166/*!
3167 Creates a new QSGTexture from the supplied \a texture.
3168
3169 Use \a options to customize the texture attributes. Only the
3170 TextureHasAlphaChannel flag is taken into account by this function. When
3171 set, the resulting QSGTexture is always treated by the scene graph renderer
3172 as needing blending. For textures that are fully opaque, not setting the
3173 flag can save the cost of performing alpha blending during rendering. The
3174 flag has no direct correspondence to the \l{QRhiTexture::format()}{format}
3175 of the QRhiTexture, i.e. not setting the flag while having a texture format
3176 such as the commonly used \l QRhiTexture::RGBA8 is perfectly normal.
3177
3178 Mipmapping is not controlled by \a options since \a texture is already
3179 created and has the presence or lack of mipmaps baked in.
3180
3181 The returned QSGTexture owns the QRhiTexture, meaning \a texture is
3182 destroyed together with the returned QSGTexture.
3183
3184 If \a texture owns its underlying native graphics resources (OpenGL texture
3185 object, Vulkan image, etc.), that depends on how the QRhiTexture was created
3186 (\l{QRhiTexture::create()} or \l{QRhiTexture::createFrom()}), and that is
3187 not controlled or changed by this function.
3188
3189 \note This is only functional when the scene graph has already initialized
3190 and is using the default, \l{QRhi}-based \l{Scene Graph
3191 Adaptations}{adaptation}. The return value is \nullptr otherwise.
3192
3193 \note This function can only be called on the scene graph render thread.
3194
3195 \since 6.6
3196
3197 \sa createTextureFromImage(), sceneGraphInitialized(), QSGTexture
3198 */
3199QSGTexture *QQuickWindow::createTextureFromRhiTexture(QRhiTexture *texture, CreateTextureOptions options) const
3200{
3201 Q_D(const QQuickWindow);
3202 if (!d->rhi)
3203 return nullptr;
3204
3205 QSGPlainTexture *t = new QSGPlainTexture;
3206 t->setOwnsTexture(true);
3207 t->setTexture(texture);
3208 t->setHasAlphaChannel(options & QQuickWindow::TextureHasAlphaChannel);
3209 t->setTextureSize(texture->pixelSize());
3210 return t;
3211}
3212
3213// Legacy, private alternative to createTextureFromRhiTexture() that internally
3214// creates a QRhiTexture wrapping the existing native graphics resource.
3215// New code should prefer using the public API.
3216QSGTexture *QQuickWindowPrivate::createTextureFromNativeTexture(quint64 nativeObjectHandle,
3217 int nativeLayoutOrState,
3218 uint nativeFormat,
3219 const QSize &size,
3220 QQuickWindow::CreateTextureOptions options,
3221 TextureFromNativeTextureFlags flags) const
3222{
3223 if (!rhi)
3224 return nullptr;
3225
3226 QSGPlainTexture *texture = new QSGPlainTexture;
3227 texture->setTextureFromNativeTexture(rhi, nativeObjectHandle, nativeLayoutOrState, nativeFormat,
3228 size, options, flags);
3229 texture->setHasAlphaChannel(options & QQuickWindow::TextureHasAlphaChannel);
3230 // note that the QRhiTexture does not (and cannot) own the native object
3231 texture->setOwnsTexture(true); // texture meaning the QRhiTexture here, not the native object
3232 texture->setTextureSize(size);
3233 return texture;
3234}
3235
3236/*!
3237 \qmlproperty color Window::color
3238
3239 The background color for the window.
3240
3241 Setting this property is more efficient than using a separate Rectangle.
3242
3243 \note If you set the color to \c "transparent" or to a color with alpha translucency,
3244 you should also set suitable \l flags such as \c {flags: Qt.FramelessWindowHint}.
3245 Otherwise, window translucency may not be enabled consistently on all platforms.
3246*/
3247
3248/*!
3249 \property QQuickWindow::color
3250 \brief The color used to clear the color buffer at the beginning of each frame.
3251
3252 By default, the clear color is white.
3253
3254 \sa setDefaultAlphaBuffer()
3255 */
3256
3257void QQuickWindow::setColor(const QColor &color)
3258{
3259 Q_D(QQuickWindow);
3260 if (color == d->clearColor)
3261 return;
3262
3263 if (color.alpha() != d->clearColor.alpha()) {
3264 QSurfaceFormat fmt = requestedFormat();
3265 if (color.alpha() < 255)
3266 fmt.setAlphaBufferSize(8);
3267 else
3268 fmt.setAlphaBufferSize(-1);
3269 setFormat(fmt);
3270 }
3271 d->clearColor = color;
3272 emit colorChanged(color);
3273 update();
3274}
3275
3276QColor QQuickWindow::color() const
3277{
3278 return d_func()->clearColor;
3279}
3280
3281/*!
3282 \brief Returns whether to use alpha transparency on newly created windows.
3283
3284 \since 5.1
3285 \sa setDefaultAlphaBuffer()
3286 */
3287bool QQuickWindow::hasDefaultAlphaBuffer()
3288{
3289 return QQuickWindowPrivate::defaultAlphaBuffer;
3290}
3291
3292/*!
3293 \brief \a useAlpha specifies whether to use alpha transparency on newly created windows.
3294 \since 5.1
3295
3296 In any application which expects to create translucent windows, it's necessary to set
3297 this to true before creating the first QQuickWindow. The default value is false.
3298
3299 \sa hasDefaultAlphaBuffer()
3300 */
3301void QQuickWindow::setDefaultAlphaBuffer(bool useAlpha)
3302{
3303 QQuickWindowPrivate::defaultAlphaBuffer = useAlpha;
3304}
3305
3306/*!
3307 \struct QQuickWindow::GraphicsStateInfo
3308 \inmodule QtQuick
3309 \since 5.14
3310
3311 \brief Describes some of the RHI's graphics state at the point of a
3312 \l{QQuickWindow::beginExternalCommands()}{beginExternalCommands()} call.
3313 */
3314
3315/*!
3316 \variable QQuickWindow::GraphicsStateInfo::currentFrameSlot
3317 \since 5.14
3318 \brief the current frame slot index while recording a frame.
3319
3320 When the scenegraph renders with lower level 3D APIs such as Vulkan or
3321 Metal, it is the Qt's responsibility to ensure blocking whenever starting a
3322 new frame and finding the CPU is already a certain number of frames ahead
3323 of the GPU (because the command buffer submitted in frame no. \c{current} -
3324 \c{FramesInFlight} has not yet completed). With other graphics APIs, such
3325 as OpenGL or Direct 3D 11 this level of control is not exposed to the API
3326 client but rather handled by the implementation of the graphics API.
3327
3328 By extension, this also means that the appropriate double (or triple)
3329 buffering of resources, such as buffers, is up to the graphics API client
3330 to manage. Most commonly, a uniform buffer where the data changes between
3331 frames cannot simply change its contents when submitting a frame, given
3332 that the frame may still be active ("in flight") when starting to record
3333 the next frame. To avoid stalling the pipeline, one way is to have multiple
3334 buffers (and memory allocations) under the hood, thus realizing at least a
3335 double buffered scheme for such resources.
3336
3337 Applications that integrate rendering done directly with a graphics API
3338 such as Vulkan may want to perform a similar double or triple buffering of
3339 their own graphics resources, in a way that is compatible with the Qt
3340 rendering engine's frame submission process. That then involves knowing the
3341 values for the maximum number of in-flight frames (which is typically 2 or
3342 3) and the current frame slot index, which is a number running 0, 1, ..,
3343 FramesInFlight-1, and then wrapping around. The former is exposed in the
3344 \l{QQuickWindow::GraphicsStateInfo::framesInFlight}{framesInFlight}
3345 variable. The latter, current index, is this value.
3346
3347 For an example of using these values in practice, refer to the {Scene Graph
3348 - Vulkan Under QML} and {Scene Graph - Vulkan Texture Import} examples.
3349 */
3350
3351/*!
3352 \variable QQuickWindow::GraphicsStateInfo::framesInFlight
3353 \since 5.14
3354 \brief the maximum number of frames kept in flight.
3355
3356 See \l{QQuickWindow::GraphicsStateInfo::currentFrameSlot}{currentFrameSlot}
3357 for a detailed description.
3358 */
3359
3360/*!
3361 \return a reference to a GraphicsStateInfo struct describing some of the
3362 RHI's internal state, in particular, the double or tripple buffering status
3363 of the backend (such as, the Vulkan or Metal integrations). This is
3364 relevant when the underlying graphics APIs is Vulkan or Metal, and the
3365 external rendering code wishes to perform double or tripple buffering of
3366 its own often-changing resources, such as, uniform buffers, in order to
3367 avoid stalling the pipeline.
3368 */
3369const QQuickWindow::GraphicsStateInfo &QQuickWindow::graphicsStateInfo()
3370{
3371 Q_D(QQuickWindow);
3372 if (d->rhi) {
3373 d->rhiStateInfo.currentFrameSlot = d->rhi->currentFrameSlot();
3374 d->rhiStateInfo.framesInFlight = d->rhi->resourceLimit(limit: QRhi::FramesInFlight);
3375 }
3376 return d->rhiStateInfo;
3377}
3378
3379/*!
3380 When mixing raw graphics (OpenGL, Vulkan, Metal, etc.) commands with scene
3381 graph rendering, it is necessary to call this function before recording
3382 commands to the command buffer used by the scene graph to render its main
3383 render pass. This is to avoid clobbering state.
3384
3385 In practice this function is often called from a slot connected to the
3386 beforeRenderPassRecording() or afterRenderPassRecording() signals.
3387
3388 The function does not need to be called when recording commands to the
3389 application's own command buffer (such as, a VkCommandBuffer or
3390 MTLCommandBuffer + MTLRenderCommandEncoder created and managed by the
3391 application, not retrieved from the scene graph). With graphics APIs where
3392 no native command buffer concept is exposed (OpenGL, Direct 3D 11),
3393 beginExternalCommands() and endExternalCommands() together provide a
3394 replacement for the Qt 5 resetOpenGLState() function.
3395
3396 Calling this function and endExternalCommands() is not necessary within the
3397 \l{QSGRenderNode::render()}{render()} implementation of a QSGRenderNode
3398 because the scene graph performs the necessary steps implicitly for render
3399 nodes.
3400
3401 Native graphics objects (such as, graphics device, command buffer or
3402 encoder) are accessible via QSGRendererInterface::getResource().
3403
3404 \warning Watch out for the fact that
3405 QSGRendererInterface::CommandListResource may return a different object
3406 between beginExternalCommands() - endExternalCommands(). This can happen
3407 when the underlying implementation provides a dedicated secondary command
3408 buffer for recording external graphics commands within a render pass.
3409 Therefore, always query CommandListResource after calling this function. Do
3410 not attempt to reuse an object from an earlier query.
3411
3412 \note When the scenegraph is using OpenGL, pay attention to the fact that
3413 the OpenGL state in the context can have arbitrary settings, and this
3414 function does not perform any resetting of the state back to defaults.
3415
3416 \sa endExternalCommands(), QQuickOpenGLUtils::resetOpenGLState()
3417
3418 \since 5.14
3419 */
3420void QQuickWindow::beginExternalCommands()
3421{
3422 Q_D(QQuickWindow);
3423 if (d->rhi && d->context && d->context->isValid()) {
3424 QSGDefaultRenderContext *rc = static_cast<QSGDefaultRenderContext *>(d->context);
3425 QRhiCommandBuffer *cb = rc->currentFrameCommandBuffer();
3426 if (cb)
3427 cb->beginExternal();
3428 }
3429}
3430
3431/*!
3432 When mixing raw graphics (OpenGL, Vulkan, Metal, etc.) commands with scene
3433 graph rendering, it is necessary to call this function after recording
3434 commands to the command buffer used by the scene graph to render its main
3435 render pass. This is to avoid clobbering state.
3436
3437 In practice this function is often called from a slot connected to the
3438 beforeRenderPassRecording() or afterRenderPassRecording() signals.
3439
3440 The function does not need to be called when recording commands to the
3441 application's own command buffer (such as, a VkCommandBuffer or
3442 MTLCommandBuffer + MTLRenderCommandEncoder created and managed by the
3443 application, not retrieved from the scene graph). With graphics APIs where
3444 no native command buffer concept is exposed (OpenGL, Direct 3D 11),
3445 beginExternalCommands() and endExternalCommands() together provide a
3446 replacement for the Qt 5 resetOpenGLState() function.
3447
3448 Calling this function and beginExternalCommands() is not necessary within the
3449 \l{QSGRenderNode::render()}{render()} implementation of a QSGRenderNode
3450 because the scene graph performs the necessary steps implicitly for render
3451 nodes.
3452
3453 \sa beginExternalCommands(), QQuickOpenGLUtils::resetOpenGLState()
3454
3455 \since 5.14
3456 */
3457void QQuickWindow::endExternalCommands()
3458{
3459 Q_D(QQuickWindow);
3460 if (d->rhi && d->context && d->context->isValid()) {
3461 QSGDefaultRenderContext *rc = static_cast<QSGDefaultRenderContext *>(d->context);
3462 QRhiCommandBuffer *cb = rc->currentFrameCommandBuffer();
3463 if (cb)
3464 cb->endExternal();
3465 }
3466}
3467
3468/*!
3469 \qmlproperty string Window::title
3470
3471 The window's title in the windowing system.
3472
3473 The window title might appear in the title area of the window decorations,
3474 depending on the windowing system and the window flags. It might also
3475 be used by the windowing system to identify the window in other contexts,
3476 such as in the task switcher.
3477 */
3478
3479/*!
3480 \qmlproperty Qt::WindowModality Window::modality
3481
3482 The modality of the window.
3483
3484 A modal window prevents other windows from receiving input events.
3485 Possible values are Qt.NonModal (the default), Qt.WindowModal,
3486 and Qt.ApplicationModal.
3487 */
3488
3489/*!
3490 \qmlproperty Qt::WindowFlags Window::flags
3491
3492 The window flags of the window.
3493
3494 The window flags control the window's appearance in the windowing system,
3495 whether it's a dialog, popup, or a regular window, and whether it should
3496 have a title bar, etc.
3497
3498 The flags that you read from this property might differ from the ones
3499 that you set if the requested flags could not be fulfilled.
3500
3501 \snippet qml/splashWindow.qml entire
3502
3503 \sa Qt::WindowFlags, {Qt Quick Examples - Window and Screen}
3504 */
3505
3506/*!
3507 \qmlattachedproperty Window Window::window
3508 \since 5.7
3509
3510 This attached property holds the item's window.
3511 The Window attached property can be attached to any Item.
3512*/
3513
3514/*!
3515 \qmlattachedproperty int Window::width
3516 \qmlattachedproperty int Window::height
3517 \since 5.5
3518
3519 These attached properties hold the size of the item's window.
3520 The Window attached property can be attached to any Item.
3521*/
3522
3523/*!
3524 \qmlproperty int Window::x
3525 \qmlproperty int Window::y
3526 \qmlproperty int Window::width
3527 \qmlproperty int Window::height
3528
3529 Defines the window's position and size.
3530
3531 The (x,y) position is relative to the \l Screen if there is only one,
3532 or to the virtual desktop (arrangement of multiple screens).
3533
3534 \note Not all windowing systems support setting or querying top level
3535 window positions. On such a system, programmatically moving windows
3536 may not have any effect, and artificial values may be returned for
3537 the current positions, such as \c QPoint(0, 0).
3538
3539 \qml
3540 Window { x: 100; y: 100; width: 100; height: 100 }
3541 \endqml
3542
3543 \image screen-and-window-dimensions.jpg
3544 */
3545
3546/*!
3547 \qmlproperty int Window::minimumWidth
3548 \qmlproperty int Window::minimumHeight
3549 \since 5.1
3550
3551 Defines the window's minimum size.
3552
3553 This is a hint to the window manager to prevent resizing below the specified
3554 width and height.
3555 */
3556
3557/*!
3558 \qmlproperty int Window::maximumWidth
3559 \qmlproperty int Window::maximumHeight
3560 \since 5.1
3561
3562 Defines the window's maximum size.
3563
3564 This is a hint to the window manager to prevent resizing above the specified
3565 width and height.
3566 */
3567
3568/*!
3569 \qmlproperty bool Window::visible
3570
3571 Whether the window is visible on the screen.
3572
3573 Setting visible to false is the same as setting \l visibility to \l {QWindow::}{Hidden}.
3574
3575 The default value is \c false, unless overridden by setting \l visibility.
3576
3577 \sa visibility
3578 */
3579
3580/*!
3581 \keyword qml-window-visibility-prop
3582 \qmlproperty QWindow::Visibility Window::visibility
3583
3584 The screen-occupation state of the window.
3585
3586 Visibility is whether the window should appear in the windowing system as
3587 normal, minimized, maximized, fullscreen or hidden.
3588
3589 To set the visibility to \l {QWindow::}{AutomaticVisibility} means to give the
3590 window a default visible state, which might be \l {QWindow::}{FullScreen} or
3591 \l {QWindow::}{Windowed} depending on the platform. However when reading the
3592 visibility property you will always get the actual state, never
3593 \c AutomaticVisibility.
3594
3595 When a window is not visible, its visibility is \c Hidden, and setting
3596 visibility to \l {QWindow::}{Hidden} is the same as setting \l visible to \c false.
3597
3598 \snippet qml/windowVisibility.qml entire
3599
3600 \sa visible, {Qt Quick Examples - Window and Screen}
3601 \since 5.1
3602 */
3603
3604/*!
3605 \qmlattachedproperty QWindow::Visibility Window::visibility
3606 \readonly
3607 \since 5.4
3608
3609 This attached property holds whether the window is currently shown
3610 in the windowing system as normal, minimized, maximized, fullscreen or
3611 hidden. The \c Window attached property can be attached to any Item. If the
3612 item is not shown in any window, the value will be \l {QWindow::}{Hidden}.
3613
3614 \sa visible, {qml-window-visibility-prop}{visibility}
3615*/
3616
3617/*!
3618 \qmlproperty Item Window::contentItem
3619 \readonly
3620 \brief The invisible root item of the scene.
3621*/
3622
3623/*!
3624 \qmlproperty Qt::ScreenOrientation Window::contentOrientation
3625
3626 This is a hint to the window manager in case it needs to display
3627 additional content like popups, dialogs, status bars, or similar
3628 in relation to the window.
3629
3630 The recommended orientation is \l {Screen::orientation}{Screen.orientation}, but
3631 an application doesn't have to support all possible orientations,
3632 and thus can opt to ignore the current screen orientation.
3633
3634 The difference between the window and the content orientation
3635 determines how much to rotate the content by.
3636
3637 The default value is Qt::PrimaryOrientation.
3638
3639 \sa Screen
3640
3641 \since 5.1
3642 */
3643
3644/*!
3645 \qmlproperty real Window::opacity
3646
3647 The opacity of the window.
3648
3649 If the windowing system supports window opacity, this can be used to fade the
3650 window in and out, or to make it semitransparent.
3651
3652 A value of 1.0 or above is treated as fully opaque, whereas a value of 0.0 or below
3653 is treated as fully transparent. Values inbetween represent varying levels of
3654 translucency between the two extremes.
3655
3656 The default value is 1.0.
3657
3658 \since 5.1
3659 */
3660
3661/*!
3662 \qmlproperty variant Window::screen
3663
3664 The screen with which the window is associated.
3665
3666 If specified before showing a window, will result in the window being shown
3667 on that screen, unless an explicit window position has been set. The value
3668 must be an element from the Qt.application.screens array.
3669
3670 \note To ensure that the window is associated with the desired screen when
3671 the underlying native window is created, make sure this property is set as
3672 early as possible and that the setting of its value is not deferred. This
3673 can be particularly important on embedded platforms without a windowing system,
3674 where only one window per screen is allowed at a time. Setting the screen after
3675 a window has been created does not move the window if the new screen is part of
3676 the same virtual desktop as the old screen.
3677
3678 \since 5.9
3679
3680 \sa QWindow::setScreen(), QWindow::screen(), QScreen, {QtQml::Qt::application}{Qt.application}
3681 */
3682
3683/*!
3684 \qmlproperty QWindow Window::transientParent
3685 \since 5.13
3686
3687 The window for which this window is a transient pop-up.
3688
3689 This is a hint to the window manager that this window is a dialog or pop-up
3690 on behalf of the transient parent. It usually means that the transient
3691 window will be centered over its transient parent when it is initially
3692 shown, that minimizing the parent window will also minimize the transient
3693 window, and so on; however results vary somewhat from platform to platform.
3694
3695 Declaring a Window inside an Item or another Window, either via the
3696 \l{Window::data}{default property} or a dedicated property, will automatically
3697 set up a transient parent relationship to the containing window,
3698 unless the \l transientParent property is explicitly set. This applies
3699 when creating Window items via \l [QML] {QtQml::Qt::createComponent()}
3700 {Qt.createComponent} or \l [QML] {QtQml::Qt::createQmlObject()}
3701 {Qt.createQmlObject} as well, as long as an Item or Window is passed
3702 as the \c parent argument.
3703
3704 A Window with a transient parent will not be shown until its transient
3705 parent is shown, even if the \l visible property is \c true. This also
3706 applies for the automatic transient parent relationship described above.
3707 In particular, if the Window's containing element is an Item, the window
3708 will not be shown until the containing item is added to a scene, via its
3709 \l{Concepts - Visual Parent in Qt Quick}{visual parent hierarchy}. Setting
3710 the \l transientParent to \c null will override this behavior:
3711
3712 \snippet qml/nestedWindowTransientParent.qml 0
3713 \snippet qml/nestedWindowTransientParent.qml 1
3714
3715 In order to cause the window to be centered above its transient parent by
3716 default, depending on the window manager, it may also be necessary to set
3717 the \l Window::flags property with a suitable \l Qt::WindowType (such as
3718 \c Qt::Dialog).
3719
3720 \sa {QQuickWindow::}{parent()}
3721*/
3722
3723/*!
3724 \property QQuickWindow::transientParent
3725 \brief The window for which this window is a transient pop-up.
3726 \since 5.13
3727
3728 This is a hint to the window manager that this window is a dialog or pop-up
3729 on behalf of the transient parent, which may be any kind of \l QWindow.
3730
3731 In order to cause the window to be centered above its transient parent by
3732 default, depending on the window manager, it may also be necessary to set
3733 the \l flags property with a suitable \l Qt::WindowType (such as \c Qt::Dialog).
3734
3735 \sa parent()
3736 */
3737
3738/*!
3739 \qmlproperty Item Window::activeFocusItem
3740 \since 5.1
3741
3742 The item which currently has active focus or \c null if there is
3743 no item with active focus.
3744 */
3745
3746/*!
3747 \qmlattachedproperty Item Window::activeFocusItem
3748 \since 5.4
3749
3750 This attached property holds the item which currently has active focus or
3751 \c null if there is no item with active focus. The Window attached property
3752 can be attached to any Item.
3753*/
3754
3755/*!
3756 \qmlproperty bool Window::active
3757 \since 5.1
3758
3759 The active status of the window.
3760
3761 \snippet qml/windowPalette.qml declaration-and-color
3762 \snippet qml/windowPalette.qml closing-brace
3763
3764 \sa requestActivate()
3765 */
3766
3767/*!
3768 \qmlattachedproperty bool Window::active
3769 \since 5.4
3770
3771 This attached property tells whether the window is active. The Window
3772 attached property can be attached to any Item.
3773
3774 Here is an example which changes a label to show the active state of the
3775 window in which it is shown:
3776
3777 \snippet qml/windowActiveAttached.qml entire
3778*/
3779
3780/*!
3781 \qmlmethod QtQuick::Window::requestActivate()
3782 \since 5.1
3783
3784 Requests the window to be activated, i.e. receive keyboard focus.
3785 */
3786
3787/*!
3788 \qmlmethod QtQuick::Window::alert(int msec)
3789 \since 5.1
3790
3791 Causes an alert to be shown for \a msec milliseconds. If \a msec is \c 0
3792 (the default), then the alert is shown indefinitely until the window
3793 becomes active again.
3794
3795 In alert state, the window indicates that it demands attention, for example
3796 by flashing or bouncing the taskbar entry.
3797*/
3798
3799/*!
3800 \qmlmethod QtQuick::Window::close()
3801
3802 Closes the window.
3803
3804 When this method is called, or when the user tries to close the window by
3805 its title bar button, the \l closing signal will be emitted. If there is no
3806 handler, or the handler does not revoke permission to close, the window
3807 will subsequently close. If the QGuiApplication::quitOnLastWindowClosed
3808 property is \c true, and there are no other windows open, the application
3809 will quit.
3810*/
3811
3812/*!
3813 \qmlmethod QtQuick::Window::raise()
3814
3815 Raises the window in the windowing system.
3816
3817 Requests that the window be raised to appear above other windows.
3818*/
3819
3820/*!
3821 \qmlmethod QtQuick::Window::lower()
3822
3823 Lowers the window in the windowing system.
3824
3825 Requests that the window be lowered to appear below other windows.
3826*/
3827
3828/*!
3829 \qmlmethod QtQuick::Window::show()
3830
3831 Shows the window.
3832
3833 This is equivalent to calling showFullScreen(), showMaximized(), or showNormal(),
3834 depending on the platform's default behavior for the window type and flags.
3835
3836 \sa showFullScreen(), showMaximized(), showNormal(), hide(), QQuickItem::flags()
3837*/
3838
3839/*!
3840 \qmlmethod QtQuick::Window::hide()
3841
3842 Hides the window.
3843
3844 Equivalent to setting \l visible to \c false or \l visibility to \l {QWindow::}{Hidden}.
3845
3846 \sa show()
3847*/
3848
3849/*!
3850 \qmlmethod QtQuick::Window::showMinimized()
3851
3852 Shows the window as minimized.
3853
3854 Equivalent to setting \l visibility to \l {QWindow::}{Minimized}.
3855*/
3856
3857/*!
3858 \qmlmethod QtQuick::Window::showMaximized()
3859
3860 Shows the window as maximized.
3861
3862 Equivalent to setting \l visibility to \l {QWindow::}{Maximized}.
3863*/
3864
3865/*!
3866 \qmlmethod QtQuick::Window::showFullScreen()
3867
3868 Shows the window as fullscreen.
3869
3870 Equivalent to setting \l visibility to \l {QWindow::}{FullScreen}.
3871*/
3872
3873/*!
3874 \qmlmethod QtQuick::Window::showNormal()
3875
3876 Shows the window as normal, i.e. neither maximized, minimized, nor fullscreen.
3877
3878 Equivalent to setting \l visibility to \l {QWindow::}{Windowed}.
3879*/
3880
3881/*!
3882 \enum QQuickWindow::RenderStage
3883 \since 5.4
3884
3885 \value BeforeSynchronizingStage Before synchronization.
3886 \value AfterSynchronizingStage After synchronization.
3887 \value BeforeRenderingStage Before rendering.
3888 \value AfterRenderingStage After rendering.
3889 \value AfterSwapStage After the frame is swapped.
3890 \value NoStage As soon as possible. This value was added in Qt 5.6.
3891
3892 \sa {Scene Graph and Rendering}
3893 */
3894
3895/*!
3896 \since 5.4
3897
3898 Schedules \a job to run when the rendering of this window reaches
3899 the given \a stage.
3900
3901 This is a convenience to the equivalent signals in QQuickWindow for
3902 "one shot" tasks.
3903
3904 The window takes ownership over \a job and will delete it when the
3905 job is completed.
3906
3907 If rendering is shut down before \a job has a chance to run, the
3908 job will be run and then deleted as part of the scene graph cleanup.
3909 If the window is never shown and no rendering happens before the QQuickWindow
3910 is destroyed, all pending jobs will be destroyed without their run()
3911 method being called.
3912
3913 If the rendering is happening on a different thread, then the job
3914 will happen on the rendering thread.
3915
3916 If \a stage is \l NoStage, \a job will be run at the earliest opportunity
3917 whenever the render thread is not busy rendering a frame. If the window is
3918 not exposed, and is not renderable, at the time the job is either posted or
3919 handled, the job is deleted without executing the run() method. If a
3920 non-threaded renderer is in use, the run() method of the job is executed
3921 synchronously. When rendering with OpenGL, the OpenGL context is changed to
3922 the renderer's context before executing any job, including \l NoStage jobs.
3923
3924 \note This function does not trigger rendering; the jobs targeting any other
3925 stage than NoStage will be stored run until rendering is triggered elsewhere.
3926 To force the job to run earlier, call QQuickWindow::update();
3927
3928 \sa beforeRendering(), afterRendering(), beforeSynchronizing(),
3929 afterSynchronizing(), frameSwapped(), sceneGraphInvalidated()
3930 */
3931
3932void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage)
3933{
3934 Q_D(QQuickWindow);
3935
3936 d->renderJobMutex.lock();
3937 if (stage == BeforeSynchronizingStage) {
3938 d->beforeSynchronizingJobs << job;
3939 } else if (stage == AfterSynchronizingStage) {
3940 d->afterSynchronizingJobs << job;
3941 } else if (stage == BeforeRenderingStage) {
3942 d->beforeRenderingJobs << job;
3943 } else if (stage == AfterRenderingStage) {
3944 d->afterRenderingJobs << job;
3945 } else if (stage == AfterSwapStage) {
3946 d->afterSwapJobs << job;
3947 } else if (stage == NoStage) {
3948 if (d->renderControl && d->rhi && d->rhi->thread() == QThread::currentThread()) {
3949 job->run();
3950 delete job;
3951 } else if (isExposed()) {
3952 d->windowManager->postJob(window: this, job);
3953 } else {
3954 delete job;
3955 }
3956 }
3957 d->renderJobMutex.unlock();
3958}
3959
3960void QQuickWindowPrivate::runAndClearJobs(QList<QRunnable *> *jobs)
3961{
3962 renderJobMutex.lock();
3963 QList<QRunnable *> jobList = *jobs;
3964 jobs->clear();
3965 renderJobMutex.unlock();
3966
3967 for (QRunnable *r : std::as_const(t&: jobList)) {
3968 r->run();
3969 delete r;
3970 }
3971}
3972
3973void QQuickWindow::runJobsAfterSwap()
3974{
3975 Q_D(QQuickWindow);
3976 d->runAndClearJobs(jobs: &d->afterSwapJobs);
3977}
3978
3979/*!
3980 Returns the device pixel ratio for this window.
3981
3982 This is different from QWindow::devicePixelRatio() in that it supports
3983 redirected rendering via QQuickRenderControl and QQuickRenderTarget. When
3984 using a QQuickRenderControl, the QQuickWindow is often not fully created,
3985 meaning it is never shown and there is no underlying native window created
3986 in the windowing system. As a result, querying properties like the device
3987 pixel ratio cannot give correct results. This function takes into account
3988 both QQuickRenderControl::renderWindowFor() and
3989 QQuickRenderTarget::devicePixelRatio(). When no redirection is in effect,
3990 the result is same as QWindow::devicePixelRatio().
3991
3992 \sa QQuickRenderControl, QQuickRenderTarget, setRenderTarget(), QWindow::devicePixelRatio()
3993 */
3994qreal QQuickWindow::effectiveDevicePixelRatio() const
3995{
3996 Q_D(const QQuickWindow);
3997 QWindow *w = QQuickRenderControl::renderWindowFor(win: const_cast<QQuickWindow *>(this));
3998 if (w)
3999 return w->devicePixelRatio();
4000
4001 if (!d->customRenderTarget.isNull())
4002 return d->customRenderTarget.devicePixelRatio();
4003
4004 return devicePixelRatio();
4005}
4006
4007/*!
4008 \return the current renderer interface. The value is always valid and is never null.
4009
4010 \note This function can be called at any time after constructing the
4011 QQuickWindow, even while isSceneGraphInitialized() is still false. However,
4012 some renderer interface functions, in particular
4013 QSGRendererInterface::getResource() will not be functional until the
4014 scenegraph is up and running. Backend queries, like
4015 QSGRendererInterface::graphicsApi() or QSGRendererInterface::shaderType(),
4016 will always be functional on the other hand.
4017
4018 \note The ownership of the returned pointer stays with Qt. The returned
4019 instance may or may not be shared between different QQuickWindow instances,
4020 depending on the scenegraph backend in use. Therefore applications are
4021 expected to query the interface object for each QQuickWindow instead of
4022 reusing the already queried pointer.
4023
4024 \sa QSGRenderNode, QSGRendererInterface
4025
4026 \since 5.8
4027 */
4028QSGRendererInterface *QQuickWindow::rendererInterface() const
4029{
4030 Q_D(const QQuickWindow);
4031
4032 // no context validity check - it is essential to be able to return a
4033 // renderer interface instance before scenegraphInitialized() is emitted
4034 // (depending on the backend, that can happen way too late for some of the
4035 // rif use cases, like examining the graphics api or shading language in
4036 // use)
4037
4038 return d->context->sceneGraphContext()->rendererInterface(renderContext: d->context);
4039}
4040
4041/*!
4042 \return the QRhi object used by this window for rendering.
4043
4044 Available only when the window is using Qt's 3D API and shading language
4045 abstractions, meaning the result is always null when using the \c software
4046 adaptation.
4047
4048 The result is valid only when rendering has been initialized, which is
4049 indicated by the emission of the sceneGraphInitialized() signal. Before
4050 that point, the returned value is null. With a regular, on-screen
4051 QQuickWindow scenegraph initialization typically happens when the native
4052 window gets exposed (shown) the first time. When using QQuickRenderControl,
4053 initialization is done in the explicit
4054 \l{QQuickRenderControl::initialize()}{initialize()} call.
4055
4056 In practice this function is a shortcut to querying the QRhi via the
4057 QSGRendererInterface.
4058
4059 \since 6.6
4060 */
4061QRhi *QQuickWindow::rhi() const
4062{
4063 Q_D(const QQuickWindow);
4064 return d->rhi;
4065}
4066
4067/*!
4068 \return the QRhiSwapChain used by this window, if there is one.
4069
4070 \note Only on-screen windows backed by one of the standard render loops
4071 (such as, \c basic or \c threaded) will have a swapchain. Otherwise the
4072 returned value is null. For example, the result is always null when the
4073 window is used with QQuickRenderControl.
4074
4075 \since 6.6
4076 */
4077QRhiSwapChain *QQuickWindow::swapChain() const
4078{
4079 Q_D(const QQuickWindow);
4080 return d->swapchain;
4081}
4082
4083/*!
4084 Requests the specified graphics \a api.
4085
4086 When the built-in, default graphics adaptation is used, \a api specifies
4087 which graphics API (OpenGL, Vulkan, Metal, or Direct3D) the scene graph
4088 should use to render. In addition, the \c software backend is built-in as
4089 well, and can be requested by setting \a api to
4090 QSGRendererInterface::Software.
4091
4092 Unlike setSceneGraphBackend(), which can only be used to request a given
4093 backend (shipped either built-in or installed as dynamically loaded
4094 plugins), this function works with the higher level concept of graphics
4095 APIs. It covers the backends that ship with Qt Quick, and thus have
4096 corresponding values in the QSGRendererInterface::GraphicsApi enum.
4097
4098 When this function is not called at all, and the equivalent environment
4099 variable \c{QSG_RHI_BACKEND} is not set either, the scene graph will choose
4100 the graphics API to use based on the platform.
4101
4102 This function becomes important in applications that are only prepared for
4103 rendering with a given API. For example, if there is native OpenGL or
4104 Vulkan rendering done by the application, it will want to ensure Qt Quick
4105 is rendering using OpenGL or Vulkan too. Such applications are expected to
4106 call this function early in their main() function.
4107
4108 \note The call to the function must happen before constructing the first
4109 QQuickWindow in the application. The graphics API cannot be changed
4110 afterwards.
4111
4112 \note When used in combination with QQuickRenderControl, this rule is
4113 relaxed: it is possible to change the graphics API, but only when all
4114 existing QQuickRenderControl and QQuickWindow instances have been
4115 destroyed.
4116
4117 To query what graphics API the scene graph is using to render,
4118 QSGRendererInterface::graphicsApi() after the scene graph
4119 \l{QQuickWindow::isSceneGraphInitialized()}{has initialized}, which
4120 typically happens either when the window becomes visible for the first time, or
4121 when QQuickRenderControl::initialize() is called.
4122
4123 To switch back to the default behavior, where the scene graph chooses a
4124 graphics API based on the platform and other conditions, set \a api to
4125 QSGRendererInterface::Unknown.
4126
4127 \since 6.0
4128 */
4129void QQuickWindow::setGraphicsApi(QSGRendererInterface::GraphicsApi api)
4130{
4131 // Special cases: these are different scenegraph backends.
4132 switch (api) {
4133 case QSGRendererInterface::Software:
4134 setSceneGraphBackend(QStringLiteral("software"));
4135 break;
4136 case QSGRendererInterface::OpenVG:
4137 setSceneGraphBackend(QStringLiteral("openvg"));
4138 break;
4139 default:
4140 break;
4141 }
4142
4143 // Standard case: tell the QRhi-based default adaptation what graphics api
4144 // (QRhi backend) to use.
4145 if (QSGRendererInterface::isApiRhiBased(api) || api == QSGRendererInterface::Unknown)
4146 QSGRhiSupport::instance_internal()->configure(api);
4147}
4148
4149/*!
4150 \return the graphics API that would be used by the scene graph if it was
4151 initialized at this point in time.
4152
4153 The standard way to query the API used by the scene graph is to use
4154 QSGRendererInterface::graphicsApi() once the scene graph has initialized,
4155 for example when or after the sceneGraphInitialized() signal is emitted. In
4156 that case one gets the true, real result, because then it is known that
4157 everything was initialized correctly using that graphics API.
4158
4159 This is not always convenient. If the application needs to set up external
4160 frameworks, or needs to work with setGraphicsDevice() in a manner that
4161 depends on the scene graph's built in API selection logic, it is not always
4162 feasiable to defer such operations until after the QQuickWindow has been
4163 made visible or QQuickRenderControl::initialize() has been called.
4164
4165 Therefore, this static function is provided as a counterpart to
4166 setGraphicsApi(): it can be called at any time, and the result reflects
4167 what API the scene graph would choose if it was initialized at the point of
4168 the call.
4169
4170 \note This static function is intended to be called on the main (GUI)
4171 thread only. For querying the API when rendering, use QSGRendererInterface
4172 since that object lives on the render thread.
4173
4174 \note This function does not take scene graph backends into account.
4175
4176 \since 6.0
4177 */
4178QSGRendererInterface::GraphicsApi QQuickWindow::graphicsApi()
4179{
4180 // Note that this applies the settings e.g. from the env vars
4181 // (QSG_RHI_BACKEND) if it was not done at least once already. Whereas if
4182 // setGraphicsApi() was called before, or the scene graph is already
4183 // initialized, then this is just a simple query.
4184 return QSGRhiSupport::instance()->graphicsApi();
4185}
4186
4187/*!
4188 Requests a Qt Quick scenegraph \a backend. Backends can either be built-in
4189 or be installed in form of dynamically loaded plugins.
4190
4191 \overload
4192
4193 \note The call to the function must happen before constructing the first
4194 QQuickWindow in the application. It cannot be changed afterwards.
4195
4196 See \l{Switch Between Adaptations in Your Application} for more information
4197 about the list of backends. If \a backend is invalid or an error occurs, the
4198 request is ignored.
4199
4200 \note Calling this function is equivalent to setting the
4201 \c QT_QUICK_BACKEND or \c QMLSCENE_DEVICE environment variables. However, this
4202 API is safer to use in applications that spawn other processes as there is
4203 no need to worry about environment inheritance.
4204
4205 \since 5.8
4206 */
4207void QQuickWindow::setSceneGraphBackend(const QString &backend)
4208{
4209 QSGContext::setBackend(backend);
4210}
4211
4212/*!
4213 Returns the requested Qt Quick scenegraph backend.
4214
4215 \note The return value of this function may still be outdated by
4216 subsequent calls to setSceneGraphBackend() until the first QQuickWindow in the
4217 application has been constructed.
4218
4219 \note The value only reflects the request in the \c{QT_QUICK_BACKEND}
4220 environment variable after a QQuickWindow has been constructed.
4221
4222 \since 5.9
4223 */
4224QString QQuickWindow::sceneGraphBackend()
4225{
4226 return QSGContext::backend();
4227}
4228
4229/*!
4230 Sets the graphics device objects for this window. The scenegraph will use
4231 existing device, physical device, and other objects specified by \a device
4232 instead of creating new ones.
4233
4234 This function is very often used in combination with QQuickRenderControl
4235 and setRenderTarget(), in order to redirect Qt Quick rendering into a
4236 texture.
4237
4238 A default constructed QQuickGraphicsDevice does not change the default
4239 behavior in any way. Once a \a device created via one of the
4240 QQuickGraphicsDevice factory functions, such as,
4241 QQuickGraphicsDevice::fromDeviceObjects(), is passed in, and the scenegraph
4242 uses a matching graphics API (with the example of fromDeviceObjects(), that
4243 would be Vulkan), the scenegraph will use the existing device objects (such
4244 as, the \c VkPhysicalDevice, \c VkDevice, and graphics queue family index,
4245 in case of Vulkan) encapsulated by the QQuickGraphicsDevice. This allows
4246 using the same device, and so sharing resources, such as buffers and
4247 textures, between Qt Quick and native rendering engines.
4248
4249 \warning This function can only be called before initializing the
4250 scenegraph and will have no effect if called afterwards. In practice this
4251 typically means calling it right before QQuickRenderControl::initialize().
4252
4253 As an example, this time with Direct3D, the typical usage is expected to be
4254 the following:
4255
4256 \badcode
4257 // native graphics resources set up by a custom D3D rendering engine
4258 ID3D11Device *device;
4259 ID3D11DeviceContext *context;
4260 ID3D11Texture2D *texture;
4261 ...
4262 // now to redirect Qt Quick content into 'texture' we could do the following:
4263 QQuickRenderControl *renderControl = new QQuickRenderControl;
4264 QQuickWindow *window = new QQuickWindow(renderControl); // this window will never be shown on-screen
4265 ...
4266 window->setGraphicsDevice(QQuickGraphicsDevice::fromDeviceAndContext(device, context));
4267 renderControl->initialize();
4268 window->setRenderTarget(QQuickRenderTarget::fromD3D11Texture(texture, textureSize);
4269 ...
4270 \endcode
4271
4272 The key aspect of using this function is to ensure that resources or
4273 handles to resources, such as \c texture in the above example, are visible
4274 to and usable by both the external rendering engine and the scenegraph
4275 renderer. This requires using the same graphics device (or with OpenGL,
4276 OpenGL context).
4277
4278 QQuickGraphicsDevice instances are implicitly shared, copyable, and
4279 can be passed by value. They do not own the associated native objects (such
4280 as, the ID3D11Device in the example).
4281
4282 \note Using QQuickRenderControl does not always imply having to call this
4283 function. When adopting an existing device or context is not needed, this
4284 function should not be called, and the scene graph will then initialize its
4285 own devices and contexts normally, just as it would with an on-screen
4286 QQuickWindow.
4287
4288 \since 6.0
4289
4290 \sa QQuickRenderControl, setRenderTarget(), setGraphicsApi()
4291 */
4292void QQuickWindow::setGraphicsDevice(const QQuickGraphicsDevice &device)
4293{
4294 Q_D(QQuickWindow);
4295 d->customDeviceObjects = device;
4296}
4297
4298/*!
4299 \return the QQuickGraphicsDevice passed to setGraphicsDevice(), or a
4300 default constructed one otherwise
4301
4302 \since 6.0
4303
4304 \sa setGraphicsDevice()
4305 */
4306QQuickGraphicsDevice QQuickWindow::graphicsDevice() const
4307{
4308 Q_D(const QQuickWindow);
4309 return d->customDeviceObjects;
4310}
4311
4312/*!
4313 Sets the graphics configuration for this window. \a config contains various
4314 settings that may be taken into account by the scene graph when
4315 initializing the underlying graphics devices and contexts.
4316
4317 Such additional configuration, specifying for example what device
4318 extensions to enable for Vulkan, becomes relevant and essential when
4319 integrating native graphics rendering code that relies on certain
4320 extensions. The same is true when integrating with an external 3D or VR
4321 engines, such as OpenXR.
4322
4323 \note The configuration is ignored when adopting existing graphics devices
4324 via setGraphicsDevice() since the scene graph is then not in control of the
4325 actual construction of those objects.
4326
4327 QQuickGraphicsConfiguration instances are implicitly shared, copyable, and
4328 can be passed by value.
4329
4330 \warning Setting a QQuickGraphicsConfiguration on a QQuickWindow must
4331 happen early enough, before the scene graph is initialized for the first
4332 time for that window. With on-screen windows this means the call must be
4333 done before invoking show() on the QQuickWindow or QQuickView. With
4334 QQuickRenderControl the configuration must be finalized before calling
4335 \l{QQuickRenderControl::initialize()}{initialize()}.
4336
4337 \since 6.0
4338 */
4339void QQuickWindow::setGraphicsConfiguration(const QQuickGraphicsConfiguration &config)
4340{
4341 Q_D(QQuickWindow);
4342 d->graphicsConfig = config;
4343}
4344
4345/*!
4346 \return the QQuickGraphicsConfiguration passed to
4347 setGraphicsConfiguration(), or a default constructed one otherwise.
4348
4349 \since 6.0
4350
4351 \sa setGraphicsConfiguration()
4352 */
4353QQuickGraphicsConfiguration QQuickWindow::graphicsConfiguration() const
4354{
4355 Q_D(const QQuickWindow);
4356 return d->graphicsConfig;
4357}
4358
4359/*!
4360 Creates a text node. When the scenegraph is not initialized, the return value is null.
4361
4362 \since 6.7
4363 \sa QSGTextNode
4364 */
4365QSGTextNode *QQuickWindow::createTextNode() const
4366{
4367 Q_D(const QQuickWindow);
4368 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createTextNode(renderContext: d->context) : nullptr;
4369}
4370
4371/*!
4372 Creates a simple rectangle node. When the scenegraph is not initialized, the return value is null.
4373
4374 This is cross-backend alternative to constructing a QSGSimpleRectNode directly.
4375
4376 \since 5.8
4377 \sa QSGRectangleNode
4378 */
4379QSGRectangleNode *QQuickWindow::createRectangleNode() const
4380{
4381 Q_D(const QQuickWindow);
4382 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createRectangleNode() : nullptr;
4383}
4384
4385/*!
4386 Creates a simple image node. When the scenegraph is not initialized, the return value is null.
4387
4388 This is cross-backend alternative to constructing a QSGSimpleTextureNode directly.
4389
4390 \since 5.8
4391 \sa QSGImageNode
4392 */
4393QSGImageNode *QQuickWindow::createImageNode() const
4394{
4395 Q_D(const QQuickWindow);
4396 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createImageNode() : nullptr;
4397}
4398
4399/*!
4400 Creates a nine patch node. When the scenegraph is not initialized, the return value is null.
4401
4402 \since 5.8
4403 */
4404QSGNinePatchNode *QQuickWindow::createNinePatchNode() const
4405{
4406 Q_D(const QQuickWindow);
4407 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createNinePatchNode() : nullptr;
4408}
4409
4410/*!
4411 \since 5.10
4412
4413 Returns the render type of text-like elements in Qt Quick.
4414 The default is QQuickWindow::QtTextRendering.
4415
4416 \sa setTextRenderType()
4417*/
4418QQuickWindow::TextRenderType QQuickWindow::textRenderType()
4419{
4420 return QQuickWindowPrivate::textRenderType;
4421}
4422
4423/*!
4424 \since 5.10
4425
4426 Sets the default render type of text-like elements in Qt Quick to \a renderType.
4427
4428 \note setting the render type will only affect elements created afterwards;
4429 the render type of existing elements will not be modified.
4430
4431 \sa textRenderType()
4432*/
4433void QQuickWindow::setTextRenderType(QQuickWindow::TextRenderType renderType)
4434{
4435 QQuickWindowPrivate::textRenderType = renderType;
4436}
4437
4438
4439/*!
4440 \since 6.0
4441 \qmlproperty Palette Window::palette
4442
4443 This property holds the palette currently set for the window.
4444
4445 The default palette depends on the system environment. QGuiApplication maintains a system/theme
4446 palette which serves as a default for all application windows. You can also set the default palette
4447 for windows by passing a custom palette to QGuiApplication::setPalette(), before loading any QML.
4448
4449 Window propagates explicit palette properties to child items and controls,
4450 overriding any system defaults for that property.
4451
4452 \snippet qml/windowPalette.qml entire
4453
4454 \sa Item::palette, Popup::palette, ColorGroup, SystemPalette
4455 //! internal \sa QQuickAbstractPaletteProvider, QQuickPalette
4456*/
4457
4458#ifndef QT_NO_DEBUG_STREAM
4459QDebug operator<<(QDebug debug, const QQuickWindow *win)
4460{
4461 QDebugStateSaver saver(debug);
4462 debug.nospace();
4463 if (!win) {
4464 debug << "QQuickWindow(nullptr)";
4465 return debug;
4466 }
4467
4468 debug << win->metaObject()->className() << '(' << static_cast<const void *>(win);
4469 if (win->isActive())
4470 debug << " active";
4471 if (win->isExposed())
4472 debug << " exposed";
4473 debug << ", visibility=" << win->visibility() << ", flags=" << win->flags();
4474 if (!win->title().isEmpty())
4475 debug << ", title=" << win->title();
4476 if (!win->objectName().isEmpty())
4477 debug << ", name=" << win->objectName();
4478 if (win->parent())
4479 debug << ", parent=" << static_cast<const void *>(win->parent());
4480 if (win->transientParent())
4481 debug << ", transientParent=" << static_cast<const void *>(win->transientParent());
4482 debug << ", geometry=";
4483 QtDebugUtils::formatQRect(debug, rect: win->geometry());
4484 debug << ')';
4485 return debug;
4486}
4487#endif
4488
4489QT_END_NAMESPACE
4490
4491#include "qquickwindow.moc"
4492#include "moc_qquickwindow_p.cpp"
4493#include "moc_qquickwindow.cpp"
4494

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtdeclarative/src/quick/items/qquickwindow.cpp