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 return true;
1536 } else if (!synthMouse) {
1537 // clear passive grabbers unless it's a system synth-mouse event
1538 // QTBUG-104890: Windows sends synth mouse events (which should be ignored) after touch events
1539 for (const auto &pt : pe->points()) {
1540 if (pt.state() == QEventPoint::Pressed)
1541 pe->clearPassiveGrabbers(point: pt);
1542 }
1543 }
1544 }
1545
1546 // If it has no points, it's probably a TouchCancel, and DeliveryAgent needs to handle it.
1547 // If we didn't handle it in the block above, handle it now.
1548 // TODO should we deliver to all DAs at once then, since we don't know which one should get it?
1549 // or fix QTBUG-90851 so that the event always has points?
1550 bool ret = (da && da->event(ev: event));
1551
1552 d->deliveryAgentPrivate()->clearGrabbers(pointerEvent: pe);
1553
1554 if (ret)
1555 return true;
1556 } else if (event->isInputEvent()) {
1557 if (da && da->event(ev: event))
1558 return true;
1559 }
1560
1561 switch (event->type()) {
1562 // a few more types that are not QInputEvents, but QQuickDeliveryAgent needs to handle them anyway
1563 case QEvent::FocusAboutToChange:
1564 case QEvent::Enter:
1565 case QEvent::Leave:
1566 case QEvent::InputMethod:
1567 case QEvent::InputMethodQuery:
1568#if QT_CONFIG(quick_draganddrop)
1569 case QEvent::DragEnter:
1570 case QEvent::DragLeave:
1571 case QEvent::DragMove:
1572 case QEvent::Drop:
1573#endif
1574 if (d->inDestructor)
1575 return false;
1576 if (da && da->event(ev: event))
1577 return true;
1578 break;
1579 case QEvent::LanguageChange:
1580 case QEvent::LocaleChange:
1581 if (d->contentItem)
1582 QCoreApplication::sendEvent(receiver: d->contentItem, event);
1583 break;
1584 case QEvent::UpdateRequest:
1585 if (d->windowManager)
1586 d->windowManager->handleUpdateRequest(this);
1587 break;
1588 case QEvent::PlatformSurface:
1589 if ((static_cast<QPlatformSurfaceEvent *>(event))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) {
1590 // Ensure that the rendering thread is notified before
1591 // the QPlatformWindow is destroyed.
1592 if (d->windowManager)
1593 d->windowManager->hide(window: this);
1594 }
1595 break;
1596 case QEvent::WindowDeactivate:
1597 if (auto da = d->deliveryAgentPrivate())
1598 da->handleWindowDeactivate(win: this);
1599 Q_FALLTHROUGH();
1600 case QEvent::WindowActivate:
1601 if (d->contentItem)
1602 QCoreApplication::sendEvent(receiver: d->contentItem, event);
1603 break;
1604 case QEvent::ApplicationPaletteChange:
1605 d->inheritPalette(parentPalette: QGuiApplication::palette());
1606 if (d->contentItem)
1607 QCoreApplication::sendEvent(receiver: d->contentItem, event);
1608 break;
1609 case QEvent::DevicePixelRatioChange:
1610 physicalDpiChanged();
1611 break;
1612 case QEvent::ChildWindowAdded: {
1613 auto *childEvent = static_cast<QChildWindowEvent*>(event);
1614 auto *childWindow = childEvent->child();
1615 qCDebug(lcQuickWindow) << "Child window" << childWindow << "added to" << this;
1616 if (childWindow->handle()) {
1617 // The reparenting has already resulted in the native window
1618 // being added to its parent, on top of all other windows. We need
1619 // to do a synchronous re-stacking of the windows here, to avoid
1620 // leaving the window in the wrong position while waiting for the
1621 // asynchronous callback to QQuickWindow::polishItems().
1622 d->updateChildWindowStackingOrder();
1623 } else {
1624 qCDebug(lcQuickWindow) << "No platform window yet."
1625 << "Deferring child window stacking until surface creation";
1626 }
1627 break;
1628 }
1629 default:
1630 break;
1631 }
1632
1633 if (event->type() == QEvent::Type(QQuickWindowPrivate::FullUpdateRequest))
1634 update();
1635 else if (event->type() == QEvent::Type(QQuickWindowPrivate::TriggerContextCreationFailure))
1636 d->windowManager->handleContextCreationFailure(window: this);
1637
1638 if (event->isPointerEvent())
1639 return true;
1640 else
1641 return QWindow::event(event);
1642}
1643
1644void QQuickWindowPrivate::updateChildWindowStackingOrder(QQuickItem *item)
1645{
1646 Q_Q(QQuickWindow);
1647
1648 if (!item) {
1649 qCDebug(lcQuickWindow) << "Updating child window stacking order for" << q;
1650 item = contentItem;
1651 }
1652 auto *itemPrivate = QQuickItemPrivate::get(item);
1653 const auto paintOrderChildItems = itemPrivate->paintOrderChildItems();
1654 for (auto *child : paintOrderChildItems) {
1655 if (auto *windowContainer = qobject_cast<QQuickWindowContainer*>(object: child)) {
1656 auto *window = windowContainer->containedWindow();
1657 if (!window) {
1658 qCDebug(lcQuickWindow) << windowContainer << "has no contained window yet";
1659 continue;
1660 }
1661 if (window->parent() != q) {
1662 qCDebug(lcQuickWindow) << window << "is not yet child of this window";
1663 continue;
1664 }
1665 qCDebug(lcQuickWindow) << "Raising" << window << "owned by" << windowContainer;
1666 window->raise();
1667 }
1668
1669 updateChildWindowStackingOrder(item: child);
1670 }
1671}
1672
1673/*! \reimp */
1674void QQuickWindow::keyPressEvent(QKeyEvent *e)
1675{
1676 Q_D(QQuickWindow);
1677 if (d->windowEventDispatch)
1678 return;
1679 auto da = d->deliveryAgentPrivate();
1680 Q_ASSERT(da);
1681 da->deliverKeyEvent(e);
1682}
1683
1684/*! \reimp */
1685void QQuickWindow::keyReleaseEvent(QKeyEvent *e)
1686{
1687 Q_D(QQuickWindow);
1688 if (d->windowEventDispatch)
1689 return;
1690 auto da = d->deliveryAgentPrivate();
1691 Q_ASSERT(da);
1692 da->deliverKeyEvent(e);
1693}
1694
1695#if QT_CONFIG(wheelevent)
1696/*! \reimp */
1697void QQuickWindow::wheelEvent(QWheelEvent *event)
1698{
1699 Q_D(QQuickWindow);
1700 if (d->windowEventDispatch)
1701 return;
1702 auto da = d->deliveryAgentPrivate();
1703 Q_ASSERT(da);
1704 da->deliverSinglePointEventUntilAccepted(event);
1705}
1706#endif // wheelevent
1707
1708#if QT_CONFIG(tabletevent)
1709/*! \reimp */
1710void QQuickWindow::tabletEvent(QTabletEvent *event)
1711{
1712 Q_D(QQuickWindow);
1713 if (d->windowEventDispatch)
1714 return;
1715 auto da = d->deliveryAgentPrivate();
1716 Q_ASSERT(da);
1717 da->deliverPointerEvent(event);
1718}
1719#endif // tabletevent
1720
1721/*! \reimp */
1722void QQuickWindow::mousePressEvent(QMouseEvent *event)
1723{
1724 Q_D(QQuickWindow);
1725 if (d->windowEventDispatch)
1726 return;
1727 auto da = d->deliveryAgentPrivate();
1728 Q_ASSERT(da);
1729 da->handleMouseEvent(event);
1730}
1731/*! \reimp */
1732void QQuickWindow::mouseMoveEvent(QMouseEvent *event)
1733{
1734 Q_D(QQuickWindow);
1735 if (d->windowEventDispatch)
1736 return;
1737 auto da = d->deliveryAgentPrivate();
1738 Q_ASSERT(da);
1739 da->handleMouseEvent(event);
1740}
1741/*! \reimp */
1742void QQuickWindow::mouseDoubleClickEvent(QMouseEvent *event)
1743{
1744 Q_D(QQuickWindow);
1745 if (d->windowEventDispatch)
1746 return;
1747 auto da = d->deliveryAgentPrivate();
1748 Q_ASSERT(da);
1749 da->handleMouseEvent(event);
1750}
1751/*! \reimp */
1752void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
1753{
1754 Q_D(QQuickWindow);
1755 if (d->windowEventDispatch)
1756 return;
1757 auto da = d->deliveryAgentPrivate();
1758 Q_ASSERT(da);
1759 da->handleMouseEvent(event);
1760}
1761
1762#if QT_CONFIG(cursor)
1763void QQuickWindowPrivate::updateCursor(const QPointF &scenePos, QQuickItem *rootItem)
1764{
1765 Q_Q(QQuickWindow);
1766 if (!rootItem)
1767 rootItem = contentItem;
1768 auto cursorItemAndHandler = findCursorItemAndHandler(item: rootItem, scenePos);
1769 if (cursorItem != cursorItemAndHandler.first || cursorHandler != cursorItemAndHandler.second ||
1770 (cursorItemAndHandler.second && QQuickPointerHandlerPrivate::get(q: cursorItemAndHandler.second)->cursorDirty)) {
1771 QWindow *renderWindow = QQuickRenderControl::renderWindowFor(win: q);
1772 QWindow *window = renderWindow ? renderWindow : q;
1773 cursorItem = cursorItemAndHandler.first;
1774 cursorHandler = cursorItemAndHandler.second;
1775 if (cursorHandler)
1776 QQuickPointerHandlerPrivate::get(q: cursorItemAndHandler.second)->cursorDirty = false;
1777 if (cursorItem) {
1778 const auto cursor = QQuickItemPrivate::get(item: cursorItem)->effectiveCursor(handler: cursorHandler);
1779 qCDebug(lcHoverTrace) << "setting cursor" << cursor << "from" << cursorHandler << "or" << cursorItem;
1780 window->setCursor(cursor);
1781 } else {
1782 qCDebug(lcHoverTrace) << "unsetting cursor";
1783 window->unsetCursor();
1784 }
1785 }
1786}
1787
1788QPair<QQuickItem*, QQuickPointerHandler*> QQuickWindowPrivate::findCursorItemAndHandler(QQuickItem *item, const QPointF &scenePos) const
1789{
1790 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1791 if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1792 QPointF p = item->mapFromScene(point: scenePos);
1793 if (!item->contains(point: p))
1794 return {nullptr, nullptr};
1795 }
1796
1797 if (itemPrivate->subtreeCursorEnabled) {
1798 QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1799 for (int ii = children.size() - 1; ii >= 0; --ii) {
1800 QQuickItem *child = children.at(i: ii);
1801 if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(item: child)->culled)
1802 continue;
1803 auto ret = findCursorItemAndHandler(item: child, scenePos);
1804 if (ret.first)
1805 return ret;
1806 }
1807 if (itemPrivate->hasCursorHandler) {
1808 if (auto handler = itemPrivate->effectiveCursorHandler()) {
1809 if (handler->parentContains(scenePosition: scenePos))
1810 return {item, handler};
1811 }
1812 }
1813 if (itemPrivate->hasCursor) {
1814 QPointF p = item->mapFromScene(point: scenePos);
1815 if (item->contains(point: p))
1816 return {item, nullptr};
1817 }
1818 }
1819
1820 return {nullptr, nullptr};
1821}
1822#endif
1823
1824void QQuickWindowPrivate::clearFocusObject()
1825{
1826 if (auto da = deliveryAgentPrivate())
1827 da->clearFocusObject();
1828}
1829
1830void QQuickWindowPrivate::setFocusToTarget(FocusTarget target, Qt::FocusReason reason)
1831{
1832 if (!contentItem)
1833 return;
1834
1835 QQuickItem *newFocusItem = nullptr;
1836 switch (target) {
1837 case FocusTarget::First:
1838 case FocusTarget::Last: {
1839 const bool forward = (target == FocusTarget::First);
1840 newFocusItem = QQuickItemPrivate::nextPrevItemInTabFocusChain(item: contentItem, forward);
1841 if (newFocusItem) {
1842 const auto *itemPriv = QQuickItemPrivate::get(item: newFocusItem);
1843 if (itemPriv->subFocusItem && itemPriv->flags & QQuickItem::ItemIsFocusScope)
1844 clearFocusInScope(scope: newFocusItem, item: itemPriv->subFocusItem, reason);
1845 }
1846 break;
1847 }
1848 case FocusTarget::Next:
1849 case FocusTarget::Prev: {
1850 const auto da = deliveryAgentPrivate();
1851 Q_ASSERT(da);
1852 QQuickItem *focusItem = da->focusTargetItem() ? da->focusTargetItem() : contentItem;
1853 bool forward = (target == FocusTarget::Next);
1854 newFocusItem = QQuickItemPrivate::nextPrevItemInTabFocusChain(item: focusItem, forward);
1855 break;
1856 }
1857 default:
1858 break;
1859 }
1860
1861 if (newFocusItem)
1862 newFocusItem->forceActiveFocus(reason);
1863}
1864
1865/*!
1866 \qmlproperty list<QtObject> Window::data
1867 \qmldefault
1868
1869 The data property allows you to freely mix visual children, resources
1870 and other Windows in a Window.
1871
1872 If you assign another Window to the data list, the nested window will
1873 become "transient for" the outer Window.
1874
1875 If you assign an \l Item to the data list, it becomes a child of the
1876 Window's \l contentItem, so that it appears inside the window. The item's
1877 parent will be the window's contentItem, which is the root of the Item
1878 ownership tree within that Window.
1879
1880 If you assign any other object type, it is added as a resource.
1881
1882 It should not generally be necessary to refer to the \c data property,
1883 as it is the default property for Window and thus all child items are
1884 automatically assigned to this property.
1885
1886 \sa QWindow::transientParent()
1887 */
1888
1889void QQuickWindowPrivate::data_append(QQmlListProperty<QObject> *property, QObject *o)
1890{
1891 if (!o)
1892 return;
1893 QQuickWindow *that = static_cast<QQuickWindow *>(property->object);
1894 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(item: that->contentItem())->data();
1895 itemProperty.append(&itemProperty, o);
1896}
1897
1898qsizetype QQuickWindowPrivate::data_count(QQmlListProperty<QObject> *property)
1899{
1900 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1901 if (!win || !win->contentItem() || !QQuickItemPrivate::get(item: win->contentItem())->data().count)
1902 return 0;
1903 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(item: win->contentItem())->data();
1904 return itemProperty.count(&itemProperty);
1905}
1906
1907QObject *QQuickWindowPrivate::data_at(QQmlListProperty<QObject> *property, qsizetype i)
1908{
1909 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1910 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(item: win->contentItem())->data();
1911 return itemProperty.at(&itemProperty, i);
1912}
1913
1914void QQuickWindowPrivate::data_clear(QQmlListProperty<QObject> *property)
1915{
1916 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1917 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(item: win->contentItem())->data();
1918 itemProperty.clear(&itemProperty);
1919}
1920
1921void QQuickWindowPrivate::data_removeLast(QQmlListProperty<QObject> *property)
1922{
1923 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1924 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(item: win->contentItem())->data();
1925 itemProperty.removeLast(&itemProperty);
1926}
1927
1928bool QQuickWindowPrivate::isRenderable() const
1929{
1930 Q_Q(const QQuickWindow);
1931 return ((q->isExposed() && q->isVisible())) && q->geometry().isValid();
1932}
1933
1934void QQuickWindowPrivate::rhiCreationFailureMessage(const QString &backendName,
1935 QString *translatedMessage,
1936 QString *untranslatedMessage)
1937{
1938 const char msg[] = QT_TRANSLATE_NOOP("QQuickWindow",
1939 "Failed to initialize graphics backend for %1.");
1940 *translatedMessage = QQuickWindow::tr(s: msg).arg(a: backendName);
1941 *untranslatedMessage = QString::fromLatin1(ba: msg).arg(a: backendName);
1942}
1943
1944void QQuickWindowPrivate::cleanupNodes()
1945{
1946 qDeleteAll(c: std::exchange(obj&: cleanupNodeList, new_val: {}));
1947}
1948
1949void QQuickWindowPrivate::cleanupNodesOnShutdown(QQuickItem *item)
1950{
1951 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
1952 if (p->itemNodeInstance) {
1953 delete p->itemNodeInstance;
1954 p->itemNodeInstance = nullptr;
1955
1956 if (p->extra.isAllocated()) {
1957 p->extra->opacityNode = nullptr;
1958 p->extra->clipNode = nullptr;
1959 p->extra->rootNode = nullptr;
1960 }
1961
1962 p->paintNode = nullptr;
1963
1964 p->dirty(QQuickItemPrivate::Window);
1965 }
1966
1967 // Qt 7: Make invalidateSceneGraph a virtual member of QQuickItem
1968 if (p->flags & QQuickItem::ItemHasContents) {
1969 const QMetaObject *mo = item->metaObject();
1970 int index = mo->indexOfSlot(slot: "invalidateSceneGraph()");
1971 if (index >= 0) {
1972 const QMetaMethod &method = mo->method(index);
1973 // Skip functions named invalidateSceneGraph() in QML items.
1974 if (strstr(haystack: method.enclosingMetaObject()->className(), needle: "_QML_") == nullptr)
1975 method.invoke(obj: item, c: Qt::DirectConnection);
1976 }
1977 }
1978
1979 for (int ii = 0; ii < p->childItems.size(); ++ii)
1980 cleanupNodesOnShutdown(item: p->childItems.at(i: ii));
1981}
1982
1983// This must be called from the render thread, with the main thread frozen
1984void QQuickWindowPrivate::cleanupNodesOnShutdown()
1985{
1986 Q_Q(QQuickWindow);
1987 cleanupNodes();
1988 cleanupNodesOnShutdown(item: contentItem);
1989 for (QSet<QQuickItem *>::const_iterator it = parentlessItems.begin(), cend = parentlessItems.end(); it != cend; ++it)
1990 cleanupNodesOnShutdown(item: *it);
1991 animationController->windowNodesDestroyed();
1992 q->cleanupSceneGraph();
1993}
1994
1995void QQuickWindowPrivate::updateDirtyNodes()
1996{
1997 qCDebug(lcDirty) << "QQuickWindowPrivate::updateDirtyNodes():";
1998
1999 cleanupNodes();
2000
2001 QQuickItem *updateList = dirtyItemList;
2002 dirtyItemList = nullptr;
2003 if (updateList) QQuickItemPrivate::get(item: updateList)->prevDirtyItem = &updateList;
2004
2005 while (updateList) {
2006 QQuickItem *item = updateList;
2007 QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
2008 itemPriv->removeFromDirtyList();
2009
2010 qCDebug(lcDirty) << " QSGNode:" << item << qPrintable(itemPriv->dirtyToString());
2011 updateDirtyNode(item);
2012 }
2013}
2014
2015static inline QSGNode *qquickitem_before_paintNode(QQuickItemPrivate *d)
2016{
2017 const QList<QQuickItem *> childItems = d->paintOrderChildItems();
2018 QQuickItem *before = nullptr;
2019 for (int i=0; i<childItems.size(); ++i) {
2020 QQuickItemPrivate *dd = QQuickItemPrivate::get(item: childItems.at(i));
2021 // Perform the same check as the in fetchNextNode below.
2022 if (dd->z() < 0 && (dd->explicitVisible || (dd->extra.isAllocated() && dd->extra->effectRefCount)))
2023 before = childItems.at(i);
2024 else
2025 break;
2026 }
2027 return Q_UNLIKELY(before) ? QQuickItemPrivate::get(item: before)->itemNode() : nullptr;
2028}
2029
2030static QSGNode *fetchNextNode(QQuickItemPrivate *itemPriv, int &ii, bool &returnedPaintNode)
2031{
2032 QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
2033
2034 for (; ii < orderedChildren.size() && orderedChildren.at(i: ii)->z() < 0; ++ii) {
2035 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(item: orderedChildren.at(i: ii));
2036 if (!childPrivate->explicitVisible &&
2037 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2038 continue;
2039
2040 ii++;
2041 return childPrivate->itemNode();
2042 }
2043
2044 if (itemPriv->paintNode && !returnedPaintNode) {
2045 returnedPaintNode = true;
2046 return itemPriv->paintNode;
2047 }
2048
2049 for (; ii < orderedChildren.size(); ++ii) {
2050 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(item: orderedChildren.at(i: ii));
2051 if (!childPrivate->explicitVisible &&
2052 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2053 continue;
2054
2055 ii++;
2056 return childPrivate->itemNode();
2057 }
2058
2059 return nullptr;
2060}
2061
2062void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
2063{
2064 QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
2065 quint32 dirty = itemPriv->dirtyAttributes;
2066 itemPriv->dirtyAttributes = 0;
2067
2068 if ((dirty & QQuickItemPrivate::TransformUpdateMask) ||
2069 (dirty & QQuickItemPrivate::Size && itemPriv->origin() != QQuickItem::TopLeft &&
2070 (itemPriv->scale() != 1. || itemPriv->rotation() != 0.))) {
2071
2072 QMatrix4x4 matrix;
2073
2074 if (itemPriv->x != 0. || itemPriv->y != 0.)
2075 matrix.translate(x: itemPriv->x, y: itemPriv->y);
2076
2077 for (int ii = itemPriv->transforms.size() - 1; ii >= 0; --ii)
2078 itemPriv->transforms.at(i: ii)->applyTo(matrix: &matrix);
2079
2080 if (itemPriv->scale() != 1. || itemPriv->rotation() != 0.) {
2081 QPointF origin = item->transformOriginPoint();
2082 matrix.translate(x: origin.x(), y: origin.y());
2083 if (itemPriv->scale() != 1.)
2084 matrix.scale(x: itemPriv->scale(), y: itemPriv->scale());
2085 if (itemPriv->rotation() != 0.)
2086 matrix.rotate(angle: itemPriv->rotation(), x: 0, y: 0, z: 1);
2087 matrix.translate(x: -origin.x(), y: -origin.y());
2088 }
2089
2090 itemPriv->itemNode()->setMatrix(matrix);
2091 }
2092
2093 const bool clipEffectivelyChanged = dirty & (QQuickItemPrivate::Clip | QQuickItemPrivate::Window);
2094 if (clipEffectivelyChanged) {
2095 QSGNode *parent = itemPriv->opacityNode() ? (QSGNode *)itemPriv->opacityNode()
2096 : (QSGNode *)itemPriv->itemNode();
2097 QSGNode *child = itemPriv->rootNode();
2098
2099 if (bool initializeClipNode = item->clip() && itemPriv->clipNode() == nullptr;
2100 initializeClipNode) {
2101 QQuickDefaultClipNode *clip = new QQuickDefaultClipNode(item->clipRect());
2102 itemPriv->extra.value().clipNode = clip;
2103 clip->update();
2104
2105 if (!child) {
2106 parent->reparentChildNodesTo(newParent: clip);
2107 parent->appendChildNode(node: clip);
2108 } else {
2109 parent->removeChildNode(node: child);
2110 clip->appendChildNode(node: child);
2111 parent->appendChildNode(node: clip);
2112 }
2113
2114 } else if (bool updateClipNode = item->clip() && itemPriv->clipNode() != nullptr;
2115 updateClipNode) {
2116 QQuickDefaultClipNode *clip = itemPriv->clipNode();
2117 clip->setClipRect(item->clipRect());
2118 clip->update();
2119 } else if (bool removeClipNode = !item->clip() && itemPriv->clipNode() != nullptr;
2120 removeClipNode) {
2121 QQuickDefaultClipNode *clip = itemPriv->clipNode();
2122 parent->removeChildNode(node: clip);
2123 if (child) {
2124 clip->removeChildNode(node: child);
2125 parent->appendChildNode(node: child);
2126 } else {
2127 clip->reparentChildNodesTo(newParent: parent);
2128 }
2129
2130 delete itemPriv->clipNode();
2131 itemPriv->extra->clipNode = nullptr;
2132 }
2133 }
2134
2135 const int effectRefCount = itemPriv->extra.isAllocated() ? itemPriv->extra->effectRefCount : 0;
2136 const bool effectRefEffectivelyChanged =
2137 (dirty & (QQuickItemPrivate::EffectReference | QQuickItemPrivate::Window))
2138 && ((effectRefCount == 0) != (itemPriv->rootNode() == nullptr));
2139 if (effectRefEffectivelyChanged) {
2140 if (dirty & QQuickItemPrivate::ChildrenUpdateMask)
2141 itemPriv->childContainerNode()->removeAllChildNodes();
2142
2143 QSGNode *parent = itemPriv->clipNode();
2144 if (!parent)
2145 parent = itemPriv->opacityNode();
2146 if (!parent)
2147 parent = itemPriv->itemNode();
2148
2149 if (itemPriv->extra.isAllocated() && itemPriv->extra->effectRefCount) {
2150 Q_ASSERT(itemPriv->rootNode() == nullptr);
2151 QSGRootNode *root = new QSGRootNode();
2152 itemPriv->extra->rootNode = root;
2153 parent->reparentChildNodesTo(newParent: root);
2154 parent->appendChildNode(node: root);
2155 } else {
2156 Q_ASSERT(itemPriv->rootNode() != nullptr);
2157 QSGRootNode *root = itemPriv->rootNode();
2158 parent->removeChildNode(node: root);
2159 root->reparentChildNodesTo(newParent: parent);
2160 delete itemPriv->rootNode();
2161 itemPriv->extra->rootNode = nullptr;
2162 }
2163 }
2164
2165 if (dirty & QQuickItemPrivate::ChildrenUpdateMask) {
2166 int ii = 0;
2167 bool fetchedPaintNode = false;
2168 QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
2169 int desiredNodesSize = orderedChildren.size() + (itemPriv->paintNode ? 1 : 0);
2170
2171 // now start making current state match the promised land of
2172 // desiredNodes. in the case of our current state matching desiredNodes
2173 // (though why would we get ChildrenUpdateMask with no changes?) then we
2174 // should make no changes at all.
2175
2176 // how many nodes did we process, when examining changes
2177 int desiredNodesProcessed = 0;
2178
2179 // currentNode is how far, in our present tree, we have processed. we
2180 // make use of this later on to trim the current child list if the
2181 // desired list is shorter.
2182 QSGNode *groupNode = itemPriv->childContainerNode();
2183 QSGNode *currentNode = groupNode->firstChild();
2184 QSGNode *desiredNode = nullptr;
2185
2186 while (currentNode && (desiredNode = fetchNextNode(itemPriv, ii, returnedPaintNode&: fetchedPaintNode))) {
2187 if (currentNode != desiredNode) {
2188 // uh oh... reality and our utopic paradise are diverging!
2189 // we need to reconcile this...
2190 if (currentNode->nextSibling() == desiredNode) {
2191 // nice and simple: a node was removed, and the next in line is correct.
2192 groupNode->removeChildNode(node: currentNode);
2193 } else {
2194 // a node needs to be added..
2195 // remove it from any pre-existing parent, and push it before currentNode,
2196 // so it's in the correct place...
2197 if (desiredNode->parent()) {
2198 desiredNode->parent()->removeChildNode(node: desiredNode);
2199 }
2200 groupNode->insertChildNodeBefore(node: desiredNode, before: currentNode);
2201 }
2202
2203 // continue iteration at the correct point, now desiredNode is in place...
2204 currentNode = desiredNode;
2205 }
2206
2207 currentNode = currentNode->nextSibling();
2208 desiredNodesProcessed++;
2209 }
2210
2211 // if we didn't process as many nodes as in the new list, then we have
2212 // more nodes at the end of desiredNodes to append to our list.
2213 // this will be the case when adding new nodes, for instance.
2214 if (desiredNodesProcessed < desiredNodesSize) {
2215 while ((desiredNode = fetchNextNode(itemPriv, ii, returnedPaintNode&: fetchedPaintNode))) {
2216 if (desiredNode->parent())
2217 desiredNode->parent()->removeChildNode(node: desiredNode);
2218 groupNode->appendChildNode(node: desiredNode);
2219 }
2220 } else if (currentNode) {
2221 // on the other hand, if we processed less than our current node
2222 // tree, then nodes have been _removed_ from the scene, and we need
2223 // to take care of that here.
2224 while (currentNode) {
2225 QSGNode *node = currentNode->nextSibling();
2226 groupNode->removeChildNode(node: currentNode);
2227 currentNode = node;
2228 }
2229 }
2230 }
2231
2232 if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode()) {
2233 itemPriv->clipNode()->setRect(item->clipRect());
2234 itemPriv->clipNode()->update();
2235 }
2236
2237 if (dirty & (QQuickItemPrivate::OpacityValue | QQuickItemPrivate::Visible
2238 | QQuickItemPrivate::HideReference | QQuickItemPrivate::Window))
2239 {
2240 qreal opacity = itemPriv->explicitVisible && (!itemPriv->extra.isAllocated() || itemPriv->extra->hideRefCount == 0)
2241 ? itemPriv->opacity() : qreal(0);
2242
2243 if (opacity != 1 && !itemPriv->opacityNode()) {
2244 QSGOpacityNode *node = new QSGOpacityNode;
2245 itemPriv->extra.value().opacityNode = node;
2246
2247 QSGNode *parent = itemPriv->itemNode();
2248 QSGNode *child = itemPriv->clipNode();
2249 if (!child)
2250 child = itemPriv->rootNode();
2251
2252 if (child) {
2253 parent->removeChildNode(node: child);
2254 node->appendChildNode(node: child);
2255 parent->appendChildNode(node);
2256 } else {
2257 parent->reparentChildNodesTo(newParent: node);
2258 parent->appendChildNode(node);
2259 }
2260 }
2261 if (itemPriv->opacityNode())
2262 itemPriv->opacityNode()->setOpacity(opacity);
2263 }
2264
2265 if (dirty & QQuickItemPrivate::ContentUpdateMask) {
2266
2267 if (itemPriv->flags & QQuickItem::ItemHasContents) {
2268 updatePaintNodeData.transformNode = itemPriv->itemNode();
2269 itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
2270
2271 Q_ASSERT(itemPriv->paintNode == nullptr ||
2272 itemPriv->paintNode->parent() == nullptr ||
2273 itemPriv->paintNode->parent() == itemPriv->childContainerNode());
2274
2275 if (itemPriv->paintNode && itemPriv->paintNode->parent() == nullptr) {
2276 QSGNode *before = qquickitem_before_paintNode(d: itemPriv);
2277 if (before && before->parent()) {
2278 Q_ASSERT(before->parent() == itemPriv->childContainerNode());
2279 itemPriv->childContainerNode()->insertChildNodeAfter(node: itemPriv->paintNode, after: before);
2280 } else {
2281 itemPriv->childContainerNode()->prependChildNode(node: itemPriv->paintNode);
2282 }
2283 }
2284 } else if (itemPriv->paintNode) {
2285 delete itemPriv->paintNode;
2286 itemPriv->paintNode = nullptr;
2287 }
2288 }
2289
2290#ifndef QT_NO_DEBUG
2291 // Check consistency.
2292
2293 QList<QSGNode *> nodes;
2294 nodes << itemPriv->itemNodeInstance
2295 << itemPriv->opacityNode()
2296 << itemPriv->clipNode()
2297 << itemPriv->rootNode()
2298 << itemPriv->paintNode;
2299 nodes.removeAll(t: nullptr);
2300
2301 Q_ASSERT(nodes.constFirst() == itemPriv->itemNodeInstance);
2302 for (int i=1; i<nodes.size(); ++i) {
2303 QSGNode *n = nodes.at(i);
2304 // Failing this means we messed up reparenting
2305 Q_ASSERT(n->parent() == nodes.at(i-1));
2306 // Only the paintNode and the one who is childContainer may have more than one child.
2307 Q_ASSERT(n == itemPriv->paintNode || n == itemPriv->childContainerNode() || n->childCount() == 1);
2308 }
2309#endif
2310
2311}
2312
2313bool QQuickWindowPrivate::emitError(QQuickWindow::SceneGraphError error, const QString &msg)
2314{
2315 Q_Q(QQuickWindow);
2316 static const QMetaMethod errorSignal = QMetaMethod::fromSignal(signal: &QQuickWindow::sceneGraphError);
2317 if (q->isSignalConnected(signal: errorSignal)) {
2318 emit q->sceneGraphError(error, message: msg);
2319 return true;
2320 }
2321 return false;
2322}
2323
2324void QQuickWindow::maybeUpdate()
2325{
2326 Q_D(QQuickWindow);
2327 if (d->renderControl)
2328 QQuickRenderControlPrivate::get(renderControl: d->renderControl)->maybeUpdate();
2329 else if (d->windowManager)
2330 d->windowManager->maybeUpdate(window: this);
2331}
2332
2333void QQuickWindow::cleanupSceneGraph()
2334{
2335 Q_D(QQuickWindow);
2336 if (!d->renderer)
2337 return;
2338
2339 delete d->renderer->rootNode();
2340 delete d->renderer;
2341 d->renderer = nullptr;
2342
2343 d->runAndClearJobs(jobs: &d->beforeSynchronizingJobs);
2344 d->runAndClearJobs(jobs: &d->afterSynchronizingJobs);
2345 d->runAndClearJobs(jobs: &d->beforeRenderingJobs);
2346 d->runAndClearJobs(jobs: &d->afterRenderingJobs);
2347 d->runAndClearJobs(jobs: &d->afterSwapJobs);
2348}
2349
2350QOpenGLContext *QQuickWindowPrivate::openglContext()
2351{
2352#if QT_CONFIG(opengl)
2353 if (context && context->isValid()) {
2354 QSGRendererInterface *rif = context->sceneGraphContext()->rendererInterface(renderContext: context);
2355 if (rif) {
2356 Q_Q(QQuickWindow);
2357 return reinterpret_cast<QOpenGLContext *>(rif->getResource(window: q, resource: QSGRendererInterface::OpenGLContextResource));
2358 }
2359 }
2360#endif
2361 return nullptr;
2362}
2363
2364/*!
2365 Returns true if the scene graph has been initialized; otherwise returns false.
2366 */
2367bool QQuickWindow::isSceneGraphInitialized() const
2368{
2369 Q_D(const QQuickWindow);
2370 return d->context != nullptr && d->context->isValid();
2371}
2372
2373/*!
2374 \fn void QQuickWindow::frameSwapped()
2375
2376 This signal is emitted when a frame has been queued for presenting. With
2377 vertical synchronization enabled the signal is emitted at most once per
2378 vsync interval in a continuously animating scene.
2379
2380 This signal will be emitted from the scene graph rendering thread.
2381*/
2382
2383/*!
2384 \qmlsignal QtQuick::Window::frameSwapped()
2385
2386 This signal is emitted when a frame has been queued for presenting. With
2387 vertical synchronization enabled the signal is emitted at most once per
2388 vsync interval in a continuously animating scene.
2389 */
2390
2391/*!
2392 \fn void QQuickWindow::sceneGraphInitialized()
2393
2394 This signal is emitted when the scene graph has been initialized.
2395
2396 This signal will be emitted from the scene graph rendering thread.
2397 */
2398
2399/*!
2400 \qmlsignal QtQuick::Window::sceneGraphInitialized()
2401 \internal
2402 */
2403
2404/*!
2405 \fn void QQuickWindow::sceneGraphInvalidated()
2406
2407 This signal is emitted when the scene graph has been invalidated.
2408
2409 This signal implies that the graphics rendering context used
2410 has been invalidated and all user resources tied to that context
2411 should be released.
2412
2413 When rendering with OpenGL, the QOpenGLContext of this window will
2414 be bound when this function is called. The only exception is if
2415 the native OpenGL has been destroyed outside Qt's control, for
2416 instance through EGL_CONTEXT_LOST.
2417
2418 This signal will be emitted from the scene graph rendering thread.
2419 */
2420
2421/*!
2422 \qmlsignal QtQuick::Window::sceneGraphInvalidated()
2423 \internal
2424 */
2425
2426/*!
2427 \fn void QQuickWindow::sceneGraphError(SceneGraphError error, const QString &message)
2428
2429 This signal is emitted when an \a error occurred during scene graph initialization.
2430
2431 Applications should connect to this signal if they wish to handle errors,
2432 like graphics context creation failures, in a custom way. When no slot is
2433 connected to the signal, the behavior will be different: Quick will print
2434 the \a message, or show a message box, and terminate the application.
2435
2436 This signal will be emitted from the GUI thread.
2437
2438 \since 5.3
2439 */
2440
2441/*!
2442 \qmlsignal QtQuick::Window::sceneGraphError(SceneGraphError error, QString message)
2443
2444 This signal is emitted when an \a error occurred during scene graph initialization.
2445
2446 You can implement onSceneGraphError(error, message) to handle errors,
2447 such as graphics context creation failures, in a custom way.
2448 If no handler is connected to this signal, Quick will print the \a message,
2449 or show a message box, and terminate the application.
2450
2451 \since 5.3
2452 */
2453
2454/*!
2455 \class QQuickCloseEvent
2456 \internal
2457 \since 5.1
2458
2459 \inmodule QtQuick
2460
2461 \brief Notification that a \l QQuickWindow is about to be closed
2462*/
2463/*!
2464 \qmltype CloseEvent
2465 \nativetype QQuickCloseEvent
2466 \inqmlmodule QtQuick
2467 \ingroup qtquick-visual
2468 \brief Notification that a \l Window is about to be closed.
2469 \since 5.1
2470
2471 Notification that a window is about to be closed by the windowing system
2472 (e.g. the user clicked the title bar close button). The CloseEvent contains
2473 an accepted property which can be set to false to abort closing the window.
2474*/
2475
2476/*!
2477 \qmlproperty bool CloseEvent::accepted
2478
2479 This property indicates whether the application will allow the user to
2480 close the window. It is true by default.
2481*/
2482
2483/*!
2484 \internal
2485 \fn void QQuickWindow::closing(QQuickCloseEvent *close)
2486 \since 5.1
2487
2488 This signal is emitted when the window receives the event \a close from
2489 the windowing system.
2490
2491 On \macOs, Qt will create a menu item \c Quit if there is no menu item
2492 whose text is "quit" or "exit". This menu item calls the \c QCoreApplication::quit
2493 signal, not the \c QQuickWindow::closing() signal.
2494
2495 \sa {QMenuBar as a Global Menu Bar}
2496*/
2497
2498/*!
2499 \qmlsignal QtQuick::Window::closing(CloseEvent close)
2500 \since 5.1
2501
2502 This signal is emitted when the user tries to close the window.
2503
2504 This signal includes a \a close parameter. The \c {close.accepted}
2505 property is true by default so that the window is allowed to close; but you
2506 can implement an \c onClosing handler and set \c {close.accepted = false} if
2507 you need to do something else before the window can be closed.
2508 */
2509
2510/*!
2511 Sets the render target for this window to be \a target.
2512
2513 A QQuickRenderTarget serves as an opaque handle for a renderable native
2514 object, most commonly a 2D texture, and associated metadata, such as the
2515 size in pixels.
2516
2517 A default constructed QQuickRenderTarget means no redirection. A valid
2518 \a target, created via one of the static QQuickRenderTarget factory functions,
2519 on the other hand, enables redirection of the rendering of the Qt Quick
2520 scene: it will no longer target the color buffers for the surface
2521 associated with the window, but rather the textures or other graphics
2522 objects specified in \a target.
2523
2524 For example, assuming the scenegraph is using Vulkan to render, one can
2525 redirect its output into a \c VkImage. For graphics APIs like Vulkan, the
2526 image layout must be provided as well. QQuickRenderTarget instances are
2527 implicitly shared and are copyable and can be passed by value. They do not
2528 own the associated native objects (such as, the VkImage in the example),
2529 however.
2530
2531 \badcode
2532 QQuickRenderTarget rt = QQuickRenderTarget::fromVulkanImage(vulkanImage, VK_IMAGE_LAYOUT_PREINITIALIZED, pixelSize);
2533 quickWindow->setRenderTarget(rt);
2534 \endcode
2535
2536 This function is very often used in combination with QQuickRenderControl
2537 and an invisible QQuickWindow, in order to render Qt Quick content into a
2538 texture, without creating an on-screen native window for this QQuickWindow.
2539
2540 When the desired target, or associated data, such as the size, changes,
2541 call this function with a new QQuickRenderTarget. Constructing
2542 QQuickRenderTarget instances and calling this function is cheap, but be
2543 aware that setting a new \a target with a different native object or other
2544 data may lead to potentially expensive initialization steps when the
2545 scenegraph is about to render the next frame. Therefore change the target
2546 only when necessary.
2547
2548 \note The window does not take ownership of any native objects referenced
2549 in \a target.
2550
2551 \note It is the caller's responsibility to ensure the native objects
2552 referred to in \a target are valid for the scenegraph renderer too. For
2553 instance, with Vulkan, Metal, and Direct3D this implies that the texture or
2554 image is created on the same graphics device that is used by the scenegraph
2555 internally. Therefore, when texture objects created on an already existing
2556 device or context are involved, this function is often used in combination
2557 with setGraphicsDevice().
2558
2559 \note With graphics APIs where relevant, the application must pay attention
2560 to image layout transitions performed by the scenegraph. For example, once
2561 a VkImage is associated with the scenegraph by calling this function, its
2562 layout will transition to \c VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL when
2563 rendering a frame.
2564
2565 \warning This function can only be called from the thread doing the
2566 rendering.
2567
2568 \since 6.0
2569
2570 \sa QQuickRenderControl, setGraphicsDevice(), setGraphicsApi()
2571 */
2572void QQuickWindow::setRenderTarget(const QQuickRenderTarget &target)
2573{
2574 Q_D(QQuickWindow);
2575 if (target != d->customRenderTarget) {
2576 d->customRenderTarget = target;
2577 d->redirect.renderTargetDirty = true;
2578 }
2579}
2580
2581/*!
2582 \return the QQuickRenderTarget passed to setRenderTarget(), or a default
2583 constructed one otherwise
2584
2585 \since 6.0
2586
2587 \sa setRenderTarget()
2588 */
2589QQuickRenderTarget QQuickWindow::renderTarget() const
2590{
2591 Q_D(const QQuickWindow);
2592 return d->customRenderTarget;
2593}
2594
2595#ifdef Q_OS_WEBOS
2596class GrabWindowForProtectedContent : public QRunnable
2597{
2598public:
2599 GrabWindowForProtectedContent(QQuickWindow *window, QImage *image, QWaitCondition *condition)
2600 : m_window(window)
2601 , m_image(image)
2602 , m_condition(condition)
2603 {
2604 }
2605
2606 bool checkGrabbable()
2607 {
2608 if (!m_window)
2609 return false;
2610 if (!m_image)
2611 return false;
2612 if (!QQuickWindowPrivate::get(m_window))
2613 return false;
2614
2615 return true;
2616 }
2617
2618 void run() override
2619 {
2620 if (!checkGrabbable())
2621 return;
2622
2623 *m_image = QSGRhiSupport::instance()->grabOffscreenForProtectedContent(m_window);
2624 if (m_condition)
2625 m_condition->wakeOne();
2626 return;
2627 }
2628
2629private:
2630 QQuickWindow *m_window;
2631 QImage *m_image;
2632 QWaitCondition *m_condition;
2633
2634};
2635#endif
2636
2637/*!
2638 Grabs the contents of the window and returns it as an image.
2639
2640 It is possible to call the grabWindow() function when the window is not
2641 visible. This requires that the window is \l{QWindow::create()} {created}
2642 and has a valid size and that no other QQuickWindow instances are rendering
2643 in the same process.
2644
2645 \note When using this window in combination with QQuickRenderControl, the
2646 result of this function is an empty image, unless the \c software backend
2647 is in use. This is because when redirecting the output to an
2648 application-managed graphics resource (such as, a texture) by using
2649 QQuickRenderControl and setRenderTarget(), the application is better suited
2650 for managing and executing an eventual read back operation, since it is in
2651 full control of the resource to begin with.
2652
2653 \warning Calling this function will cause performance problems.
2654
2655 \warning This function can only be called from the GUI thread.
2656 */
2657QImage QQuickWindow::grabWindow()
2658{
2659 Q_D(QQuickWindow);
2660
2661 if (!d->isRenderable() && !d->renderControl) {
2662 // backends like software can grab regardless of the window state
2663 if (d->windowManager && (d->windowManager->flags() & QSGRenderLoop::SupportsGrabWithoutExpose))
2664 return d->windowManager->grab(window: this);
2665
2666 if (!isSceneGraphInitialized()) {
2667 // We do not have rendering up and running. Forget the render loop,
2668 // do a frame completely offscreen and synchronously into a
2669 // texture. This can be *very* slow due to all the device/context
2670 // and resource initialization but the documentation warns for it,
2671 // and is still important for some use cases.
2672 Q_ASSERT(!d->rhi);
2673 return QSGRhiSupport::instance()->grabOffscreen(window: this);
2674 }
2675 }
2676
2677#ifdef Q_OS_WEBOS
2678 if (requestedFormat().testOption(QSurfaceFormat::ProtectedContent)) {
2679 QImage image;
2680 QMutex mutex;
2681 QWaitCondition condition;
2682 mutex.lock();
2683 GrabWindowForProtectedContent *job = new GrabWindowForProtectedContent(this, &image, &condition);
2684 if (!job) {
2685 qWarning("QQuickWindow::grabWindow: Failed to create a job for capturing protected content");
2686 mutex.unlock();
2687 return QImage();
2688 }
2689 scheduleRenderJob(job, QQuickWindow::NoStage);
2690 condition.wait(&mutex);
2691 mutex.unlock();
2692 return image;
2693 }
2694#endif
2695 // The common case: we have an exposed window with an initialized
2696 // scenegraph, meaning we can request grabbing via the render loop, or we
2697 // are not targeting the window, in which case the request is to be
2698 // forwarded to the rendercontrol.
2699 if (d->renderControl)
2700 return QQuickRenderControlPrivate::get(renderControl: d->renderControl)->grab();
2701 else if (d->windowManager)
2702 return d->windowManager->grab(window: this);
2703
2704 return QImage();
2705}
2706
2707/*!
2708 Returns an incubation controller that splices incubation between frames
2709 for this window. QQuickView automatically installs this controller for you,
2710 otherwise you will need to install it yourself using \l{QQmlEngine::setIncubationController()}.
2711
2712 The controller is owned by the window and will be destroyed when the window
2713 is deleted.
2714*/
2715QQmlIncubationController *QQuickWindow::incubationController() const
2716{
2717 Q_D(const QQuickWindow);
2718
2719 if (!d->windowManager)
2720 return nullptr; // TODO: make sure that this is safe
2721
2722 if (!d->incubationController)
2723 d->incubationController = new QQuickWindowIncubationController(d->windowManager);
2724 return d->incubationController;
2725}
2726
2727
2728
2729/*!
2730 \enum QQuickWindow::CreateTextureOption
2731
2732 The CreateTextureOption enums are used to customize a texture is wrapped.
2733
2734 \value TextureHasAlphaChannel The texture has an alpha channel and should
2735 be drawn using blending.
2736
2737 \value TextureHasMipmaps The texture has mipmaps and can be drawn with
2738 mipmapping enabled.
2739
2740 \value TextureOwnsGLTexture As of Qt 6.0, this flag is not used in practice
2741 and is ignored. Native graphics resource ownership is not transferable to
2742 the wrapping QSGTexture, because Qt Quick may not have the necessary details
2743 on how such an object and the associated memory should be freed.
2744
2745 \value TextureCanUseAtlas The image can be uploaded into a texture atlas.
2746
2747 \value TextureIsOpaque The texture will return false for
2748 QSGTexture::hasAlphaChannel() and will not be blended. This flag was added
2749 in Qt 5.6.
2750
2751 */
2752
2753/*!
2754 \enum QQuickWindow::SceneGraphError
2755
2756 This enum describes the error in a sceneGraphError() signal.
2757
2758 \value ContextNotAvailable graphics context creation failed. This typically means that
2759 no suitable OpenGL implementation was found, for example because no graphics drivers
2760 are installed and so no OpenGL 2 support is present. On mobile and embedded boards
2761 that use OpenGL ES such an error is likely to indicate issues in the windowing system
2762 integration and possibly an incorrect configuration of Qt.
2763
2764 \since 5.3
2765 */
2766
2767/*!
2768 \enum QQuickWindow::TextRenderType
2769 \since 5.10
2770
2771 This enum describes the default render type of text-like elements in Qt
2772 Quick (\l Text, \l TextInput, etc.).
2773
2774 Select NativeTextRendering if you prefer text to look native on the target
2775 platform and do not require advanced features such as transformation of the
2776 text. Using such features in combination with the NativeTextRendering
2777 render type will lend poor and sometimes pixelated results.
2778
2779 Both \c QtTextRendering and \c CurveTextRendering are hardware-accelerated techniques.
2780 \c QtTextRendering is the faster of the two, but uses more memory and will exhibit rendering
2781 artifacts at large sizes. \c CurveTextRendering should be considered as an alternative in cases
2782 where \c QtTextRendering does not give good visual results or where reducing graphics memory
2783 consumption is a priority.
2784
2785 \value QtTextRendering Use Qt's own rasterization algorithm.
2786 \value NativeTextRendering Use the operating system's native rasterizer for text.
2787 \value CurveTextRendering Text is rendered using a curve rasterizer running directly on
2788 the graphics hardware. (Introduced in Qt 6.7.0.)
2789*/
2790
2791/*!
2792 \fn void QQuickWindow::beforeSynchronizing()
2793
2794 This signal is emitted before the scene graph is synchronized with the QML state.
2795
2796 Even though the signal is emitted from the scene graph rendering thread,
2797 the GUI thread is guaranteed to be blocked, like it is in
2798 QQuickItem::updatePaintNode(). Therefore, it is safe to access GUI thread
2799 thread data in a slot or lambda that is connected with
2800 Qt::DirectConnection.
2801
2802 This signal can be used to do any preparation required before calls to
2803 QQuickItem::updatePaintNode().
2804
2805 When using OpenGL, the QOpenGLContext used for rendering by the scene graph
2806 will be bound at this point.
2807
2808 \warning This signal is emitted from the scene graph rendering thread. If your
2809 slot function needs to finish before execution continues, you must make sure that
2810 the connection is direct (see Qt::ConnectionType).
2811
2812 \warning When using OpenGL, be aware that setting OpenGL 3.x or 4.x specific
2813 states and leaving these enabled or set to non-default values when returning
2814 from the connected slot can interfere with the scene graph's rendering.
2815*/
2816
2817/*!
2818 \qmlsignal QtQuick::Window::beforeSynchronizing()
2819 \internal
2820*/
2821
2822/*!
2823 \fn void QQuickWindow::afterSynchronizing()
2824
2825 This signal is emitted after the scene graph is synchronized with the QML state.
2826
2827 This signal can be used to do preparation required after calls to
2828 QQuickItem::updatePaintNode(), while the GUI thread is still locked.
2829
2830 When using OpenGL, the QOpenGLContext used for rendering by the scene graph
2831 will be bound at this point.
2832
2833 \warning This signal is emitted from the scene graph rendering thread. If your
2834 slot function needs to finish before execution continues, you must make sure that
2835 the connection is direct (see Qt::ConnectionType).
2836
2837 \warning When using OpenGL, be aware that setting OpenGL 3.x or 4.x specific
2838 states and leaving these enabled or set to non-default values when returning
2839 from the connected slot can interfere with the scene graph's rendering.
2840
2841 \since 5.3
2842 */
2843
2844/*!
2845 \qmlsignal QtQuick::Window::afterSynchronizing()
2846 \internal
2847 \since 5.3
2848 */
2849
2850/*!
2851 \fn void QQuickWindow::beforeRendering()
2852
2853 This signal is emitted after the preparations for the frame have been done,
2854 meaning there is a command buffer in recording mode, where applicable. If
2855 desired, the slot function connected to this signal can query native
2856 resources like the command before via QSGRendererInterface. Note however
2857 that the recording of the main render pass is not yet started at this point
2858 and it is not possible to add commands within that pass. Starting a pass
2859 means clearing the color, depth, and stencil buffers so it is not possible
2860 to achieve an underlay type of rendering by just connecting to this
2861 signal. Rather, connect to beforeRenderPassRecording(). However, connecting
2862 to this signal is still important if the recording of copy type of commands
2863 is desired since those cannot be enqueued within a render pass.
2864
2865 \warning This signal is emitted from the scene graph rendering thread. If your
2866 slot function needs to finish before execution continues, you must make sure that
2867 the connection is direct (see Qt::ConnectionType).
2868
2869 \note When using OpenGL, be aware that setting OpenGL 3.x or 4.x specific
2870 states and leaving these enabled or set to non-default values when
2871 returning from the connected slot can interfere with the scene graph's
2872 rendering. The QOpenGLContext used for rendering by the scene graph will be
2873 bound when the signal is emitted.
2874
2875 \sa rendererInterface(), {Scene Graph - RHI Under QML}, {Scene Graph -
2876 OpenGL Under QML}, {Scene Graph - Metal Under QML}, {Scene Graph - Vulkan
2877 Under QML}, {Scene Graph - Direct3D 11 Under QML}
2878*/
2879
2880/*!
2881 \qmlsignal QtQuick::Window::beforeRendering()
2882 \internal
2883*/
2884
2885/*!
2886 \fn void QQuickWindow::afterRendering()
2887
2888 The signal is emitted after scene graph has added its commands to the
2889 command buffer, which is not yet submitted to the graphics queue. If
2890 desired, the slot function connected to this signal can query native
2891 resources, like the command buffer, before via QSGRendererInterface. Note
2892 however that the render pass (or passes) are already recorded at this point
2893 and it is not possible to add more commands within the scenegraph's
2894 pass. Instead, use afterRenderPassRecording() for that. This signal has
2895 therefore limited use in Qt 6, unlike in Qt 5. Rather, it is the combination
2896 of beforeRendering() and beforeRenderPassRecording(), or beforeRendering()
2897 and afterRenderPassRecording(), that is typically used to achieve under- or
2898 overlaying of the custom rendering.
2899
2900 \warning This signal is emitted from the scene graph rendering thread. If your
2901 slot function needs to finish before execution continues, you must make sure that
2902 the connection is direct (see Qt::ConnectionType).
2903
2904 \note When using OpenGL, be aware that setting OpenGL 3.x or 4.x specific
2905 states and leaving these enabled or set to non-default values when
2906 returning from the connected slot can interfere with the scene graph's
2907 rendering. The QOpenGLContext used for rendering by the scene graph will be
2908 bound when the signal is emitted.
2909
2910 \sa rendererInterface(), {Scene Graph - RHI Under QML}, {Scene Graph -
2911 OpenGL Under QML}, {Scene Graph - Metal Under QML}, {Scene Graph - Vulkan
2912 Under QML}, {Scene Graph - Direct3D 11 Under QML}
2913 */
2914
2915/*!
2916 \qmlsignal QtQuick::Window::afterRendering()
2917 \internal
2918 */
2919
2920/*!
2921 \fn void QQuickWindow::beforeRenderPassRecording()
2922
2923 This signal is emitted before the scenegraph starts recording commands for
2924 the main render pass. (Layers have their own passes and are fully recorded
2925 by the time this signal is emitted.) The render pass is already active on
2926 the command buffer when the signal is emitted.
2927
2928 This signal is emitted later than beforeRendering() and it guarantees that
2929 not just the frame, but also the recording of the scenegraph's main render
2930 pass is active. This allows inserting commands without having to generate an
2931 entire, separate render pass (which would typically clear the attached
2932 images). The native graphics objects can be queried via
2933 QSGRendererInterface.
2934
2935 \note Resource updates (uploads, copies) typically cannot be enqueued from
2936 within a render pass. Therefore, more complex user rendering will need to
2937 connect to both beforeRendering() and this signal.
2938
2939 \warning This signal is emitted from the scene graph rendering thread. If your
2940 slot function needs to finish before execution continues, you must make sure that
2941 the connection is direct (see Qt::ConnectionType).
2942
2943 \sa rendererInterface()
2944
2945 \since 5.14
2946
2947 \sa {Scene Graph - RHI Under QML}
2948*/
2949
2950/*!
2951 \qmlsignal QtQuick::Window::beforeRenderPassRecording()
2952 \internal
2953 \since 5.14
2954*/
2955
2956/*!
2957 \fn void QQuickWindow::afterRenderPassRecording()
2958
2959 This signal is emitted after the scenegraph has recorded the commands for
2960 its main render pass, but the pass is not yet finalized on the command
2961 buffer.
2962
2963 This signal is emitted earlier than afterRendering(), and it guarantees that
2964 not just the frame but also the recording of the scenegraph's main render
2965 pass is still active. This allows inserting commands without having to
2966 generate an entire, separate render pass (which would typically clear the
2967 attached images). The native graphics objects can be queried via
2968 QSGRendererInterface.
2969
2970 \note Resource updates (uploads, copies) typically cannot be enqueued from
2971 within a render pass. Therefore, more complex user rendering will need to
2972 connect to both beforeRendering() and this signal.
2973
2974 \warning This signal is emitted from the scene graph rendering thread. If your
2975 slot function needs to finish before execution continues, you must make sure that
2976 the connection is direct (see Qt::ConnectionType).
2977
2978 \sa rendererInterface()
2979
2980 \since 5.14
2981
2982 \sa {Scene Graph - RHI Under QML}
2983*/
2984
2985/*!
2986 \fn void QQuickWindow::beforeFrameBegin()
2987
2988 This signal is emitted before the scene graph starts preparing the frame.
2989 This precedes signals like beforeSynchronizing() or beforeRendering(). It is
2990 the earliest signal that is emitted by the scene graph rendering thread
2991 when starting to prepare a new frame.
2992
2993 This signal is relevant for lower level graphics frameworks that need to
2994 execute certain operations, such as resource cleanup, at a stage where Qt
2995 Quick has not initiated the recording of a new frame via the underlying
2996 rendering hardware interface APIs.
2997
2998 \warning This signal is emitted from the scene graph rendering thread. If your
2999 slot function needs to finish before execution continues, you must make sure that
3000 the connection is direct (see Qt::ConnectionType).
3001
3002 \since 6.0
3003
3004 \sa afterFrameEnd(), rendererInterface()
3005*/
3006
3007/*!
3008 \qmlsignal QtQuick::Window::beforeFrameBegin()
3009 \internal
3010*/
3011
3012/*!
3013 \fn void QQuickWindow::afterFrameEnd()
3014
3015 This signal is emitted when the scene graph has submitted a frame. This is
3016 emitted after all other related signals, such as afterRendering(). It is
3017 the last signal that is emitted by the scene graph rendering thread when
3018 rendering a frame.
3019
3020 \note Unlike frameSwapped(), this signal is guaranteed to be emitted also
3021 when the Qt Quick output is redirected via QQuickRenderControl.
3022
3023 \warning This signal is emitted from the scene graph rendering thread. If your
3024 slot function needs to finish before execution continues, you must make sure that
3025 the connection is direct (see Qt::ConnectionType).
3026
3027 \since 6.0
3028
3029 \sa beforeFrameBegin(), rendererInterface()
3030*/
3031
3032/*!
3033 \qmlsignal QtQuick::Window::afterFrameEnd()
3034 \internal
3035*/
3036
3037/*!
3038 \qmlsignal QtQuick::Window::afterRenderPassRecording()
3039 \internal
3040 \since 5.14
3041*/
3042
3043/*!
3044 \fn void QQuickWindow::afterAnimating()
3045
3046 This signal is emitted on the GUI thread before requesting the render thread to
3047 perform the synchronization of the scene graph.
3048
3049 Unlike the other similar signals, this one is emitted on the GUI thread
3050 instead of the render thread. It can be used to synchronize external
3051 animation systems with the QML content. At the same time this means that
3052 this signal is not suitable for triggering graphics operations.
3053
3054 \since 5.3
3055 */
3056
3057/*!
3058 \qmlsignal QtQuick::Window::afterAnimating()
3059
3060 This signal is emitted on the GUI thread before requesting the render thread to
3061 perform the synchronization of the scene graph.
3062
3063 You can implement onAfterAnimating to do additional processing after each animation step.
3064
3065 \since 5.3
3066 */
3067
3068/*!
3069 \fn void QQuickWindow::sceneGraphAboutToStop()
3070
3071 This signal is emitted on the render thread when the scene graph is
3072 about to stop rendering. This happens usually because the window
3073 has been hidden.
3074
3075 Applications may use this signal to release resources, but should be
3076 prepared to reinstantiated them again fast. The scene graph and the
3077 graphics context are not released at this time.
3078
3079 \warning This signal is emitted from the scene graph rendering thread. If your
3080 slot function needs to finish before execution continues, you must make sure that
3081 the connection is direct (see Qt::ConnectionType).
3082
3083 \warning Make very sure that a signal handler for sceneGraphAboutToStop() leaves the
3084 graphics context in the same state as it was when the signal handler was entered.
3085 Failing to do so can result in the scene not rendering properly.
3086
3087 \sa sceneGraphInvalidated()
3088 \since 5.3
3089 */
3090
3091/*!
3092 \qmlsignal QtQuick::Window::sceneGraphAboutToStop()
3093 \internal
3094 \since 5.3
3095 */
3096
3097/*!
3098 \overload
3099 */
3100
3101QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const
3102{
3103 return createTextureFromImage(image, options: {});
3104}
3105
3106
3107/*!
3108 Creates a new QSGTexture from the supplied \a image. If the image has an
3109 alpha channel, the corresponding texture will have an alpha channel.
3110
3111 The caller of the function is responsible for deleting the returned texture.
3112 The underlying native texture object is then destroyed together with the
3113 QSGTexture.
3114
3115 When \a options contains TextureCanUseAtlas, the engine may put the image
3116 into a texture atlas. Textures in an atlas need to rely on
3117 QSGTexture::normalizedTextureSubRect() for their geometry and will not
3118 support QSGTexture::Repeat. Other values from CreateTextureOption are
3119 ignored.
3120
3121 When \a options contains TextureIsOpaque, the engine will create an RGB
3122 texture which returns false for QSGTexture::hasAlphaChannel(). Opaque
3123 textures will in most cases be faster to render. When this flag is not set,
3124 the texture will have an alpha channel based on the image's format.
3125
3126 When \a options contains TextureHasMipmaps, the engine will create a texture
3127 which can use mipmap filtering. Mipmapped textures can not be in an atlas.
3128
3129 Setting TextureHasAlphaChannel in \a options serves no purpose for this
3130 function since assuming an alpha channel and blending is the default. To opt
3131 out, set TextureIsOpaque.
3132
3133 When the scene graph uses OpenGL, the returned texture will be using \c
3134 GL_TEXTURE_2D as texture target and \c GL_RGBA as internal format. With
3135 other graphics APIs, the texture format is typically \c RGBA8. Reimplement
3136 QSGTexture to create textures with different parameters.
3137
3138 \warning This function will return 0 if the scene graph has not yet been
3139 initialized.
3140
3141 \warning The returned texture is not memory managed by the scene graph and
3142 must be explicitly deleted by the caller on the rendering thread. This is
3143 achieved by deleting the texture from a QSGNode destructor or by using
3144 deleteLater() in the case where the texture already has affinity to the
3145 rendering thread.
3146
3147 This function can be called from both the main and the render thread.
3148
3149 \sa sceneGraphInitialized(), QSGTexture
3150 */
3151
3152QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateTextureOptions options) const
3153{
3154 Q_D(const QQuickWindow);
3155 if (!isSceneGraphInitialized()) // check both for d->context and d->context->isValid()
3156 return nullptr;
3157 uint flags = 0;
3158 if (options & TextureCanUseAtlas) flags |= QSGRenderContext::CreateTexture_Atlas;
3159 if (options & TextureHasMipmaps) flags |= QSGRenderContext::CreateTexture_Mipmap;
3160 if (!(options & TextureIsOpaque)) flags |= QSGRenderContext::CreateTexture_Alpha;
3161 return d->context->createTexture(image, flags);
3162}
3163
3164/*!
3165 Creates a new QSGTexture from the supplied \a texture.
3166
3167 Use \a options to customize the texture attributes. Only the
3168 TextureHasAlphaChannel flag is taken into account by this function. When
3169 set, the resulting QSGTexture is always treated by the scene graph renderer
3170 as needing blending. For textures that are fully opaque, not setting the
3171 flag can save the cost of performing alpha blending during rendering. The
3172 flag has no direct correspondence to the \l{QRhiTexture::format()}{format}
3173 of the QRhiTexture, i.e. not setting the flag while having a texture format
3174 such as the commonly used \l QRhiTexture::RGBA8 is perfectly normal.
3175
3176 Mipmapping is not controlled by \a options since \a texture is already
3177 created and has the presence or lack of mipmaps baked in.
3178
3179 The returned QSGTexture owns the QRhiTexture, meaning \a texture is
3180 destroyed together with the returned QSGTexture.
3181
3182 If \a texture owns its underlying native graphics resources (OpenGL texture
3183 object, Vulkan image, etc.), that depends on how the QRhiTexture was created
3184 (\l{QRhiTexture::create()} or \l{QRhiTexture::createFrom()}), and that is
3185 not controlled or changed by this function.
3186
3187 \note This is only functional when the scene graph has already initialized
3188 and is using the default, \l{QRhi}-based \l{Scene Graph
3189 Adaptations}{adaptation}. The return value is \nullptr otherwise.
3190
3191 \note This function can only be called on the scene graph render thread.
3192
3193 \since 6.6
3194
3195 \sa createTextureFromImage(), sceneGraphInitialized(), QSGTexture
3196 */
3197QSGTexture *QQuickWindow::createTextureFromRhiTexture(QRhiTexture *texture, CreateTextureOptions options) const
3198{
3199 Q_D(const QQuickWindow);
3200 if (!d->rhi)
3201 return nullptr;
3202
3203 QSGPlainTexture *t = new QSGPlainTexture;
3204 t->setOwnsTexture(true);
3205 t->setTexture(texture);
3206 t->setHasAlphaChannel(options & QQuickWindow::TextureHasAlphaChannel);
3207 t->setTextureSize(texture->pixelSize());
3208 return t;
3209}
3210
3211// Legacy, private alternative to createTextureFromRhiTexture() that internally
3212// creates a QRhiTexture wrapping the existing native graphics resource.
3213// New code should prefer using the public API.
3214QSGTexture *QQuickWindowPrivate::createTextureFromNativeTexture(quint64 nativeObjectHandle,
3215 int nativeLayoutOrState,
3216 uint nativeFormat,
3217 const QSize &size,
3218 QQuickWindow::CreateTextureOptions options,
3219 TextureFromNativeTextureFlags flags) const
3220{
3221 if (!rhi)
3222 return nullptr;
3223
3224 QSGPlainTexture *texture = new QSGPlainTexture;
3225 texture->setTextureFromNativeTexture(rhi, nativeObjectHandle, nativeLayoutOrState, nativeFormat,
3226 size, options, flags);
3227 texture->setHasAlphaChannel(options & QQuickWindow::TextureHasAlphaChannel);
3228 // note that the QRhiTexture does not (and cannot) own the native object
3229 texture->setOwnsTexture(true); // texture meaning the QRhiTexture here, not the native object
3230 texture->setTextureSize(size);
3231 return texture;
3232}
3233
3234/*!
3235 \qmlproperty color Window::color
3236
3237 The background color for the window.
3238
3239 Setting this property is more efficient than using a separate Rectangle.
3240
3241 \note If you set the color to \c "transparent" or to a color with alpha translucency,
3242 you should also set suitable \l flags such as \c {flags: Qt.FramelessWindowHint}.
3243 Otherwise, window translucency may not be enabled consistently on all platforms.
3244*/
3245
3246/*!
3247 \property QQuickWindow::color
3248 \brief The color used to clear the color buffer at the beginning of each frame.
3249
3250 By default, the clear color is white.
3251
3252 \sa setDefaultAlphaBuffer()
3253 */
3254
3255void QQuickWindow::setColor(const QColor &color)
3256{
3257 Q_D(QQuickWindow);
3258 if (color == d->clearColor)
3259 return;
3260
3261 if (color.alpha() != d->clearColor.alpha()) {
3262 QSurfaceFormat fmt = requestedFormat();
3263 if (color.alpha() < 255)
3264 fmt.setAlphaBufferSize(8);
3265 else
3266 fmt.setAlphaBufferSize(-1);
3267 setFormat(fmt);
3268 }
3269 d->clearColor = color;
3270 emit colorChanged(color);
3271 update();
3272}
3273
3274QColor QQuickWindow::color() const
3275{
3276 return d_func()->clearColor;
3277}
3278
3279/*!
3280 \brief Returns whether to use alpha transparency on newly created windows.
3281
3282 \since 5.1
3283 \sa setDefaultAlphaBuffer()
3284 */
3285bool QQuickWindow::hasDefaultAlphaBuffer()
3286{
3287 return QQuickWindowPrivate::defaultAlphaBuffer;
3288}
3289
3290/*!
3291 \brief \a useAlpha specifies whether to use alpha transparency on newly created windows.
3292 \since 5.1
3293
3294 In any application which expects to create translucent windows, it's necessary to set
3295 this to true before creating the first QQuickWindow. The default value is false.
3296
3297 \sa hasDefaultAlphaBuffer()
3298 */
3299void QQuickWindow::setDefaultAlphaBuffer(bool useAlpha)
3300{
3301 QQuickWindowPrivate::defaultAlphaBuffer = useAlpha;
3302}
3303
3304/*!
3305 \struct QQuickWindow::GraphicsStateInfo
3306 \inmodule QtQuick
3307 \since 5.14
3308
3309 \brief Describes some of the RHI's graphics state at the point of a
3310 \l{QQuickWindow::beginExternalCommands()}{beginExternalCommands()} call.
3311 */
3312
3313/*!
3314 \variable QQuickWindow::GraphicsStateInfo::currentFrameSlot
3315 \since 5.14
3316 \brief the current frame slot index while recording a frame.
3317
3318 When the scenegraph renders with lower level 3D APIs such as Vulkan or
3319 Metal, it is the Qt's responsibility to ensure blocking whenever starting a
3320 new frame and finding the CPU is already a certain number of frames ahead
3321 of the GPU (because the command buffer submitted in frame no. \c{current} -
3322 \c{FramesInFlight} has not yet completed). With other graphics APIs, such
3323 as OpenGL or Direct 3D 11 this level of control is not exposed to the API
3324 client but rather handled by the implementation of the graphics API.
3325
3326 By extension, this also means that the appropriate double (or triple)
3327 buffering of resources, such as buffers, is up to the graphics API client
3328 to manage. Most commonly, a uniform buffer where the data changes between
3329 frames cannot simply change its contents when submitting a frame, given
3330 that the frame may still be active ("in flight") when starting to record
3331 the next frame. To avoid stalling the pipeline, one way is to have multiple
3332 buffers (and memory allocations) under the hood, thus realizing at least a
3333 double buffered scheme for such resources.
3334
3335 Applications that integrate rendering done directly with a graphics API
3336 such as Vulkan may want to perform a similar double or triple buffering of
3337 their own graphics resources, in a way that is compatible with the Qt
3338 rendering engine's frame submission process. That then involves knowing the
3339 values for the maximum number of in-flight frames (which is typically 2 or
3340 3) and the current frame slot index, which is a number running 0, 1, ..,
3341 FramesInFlight-1, and then wrapping around. The former is exposed in the
3342 \l{QQuickWindow::GraphicsStateInfo::framesInFlight}{framesInFlight}
3343 variable. The latter, current index, is this value.
3344
3345 For an example of using these values in practice, refer to the {Scene Graph
3346 - Vulkan Under QML} and {Scene Graph - Vulkan Texture Import} examples.
3347 */
3348
3349/*!
3350 \variable QQuickWindow::GraphicsStateInfo::framesInFlight
3351 \since 5.14
3352 \brief the maximum number of frames kept in flight.
3353
3354 See \l{QQuickWindow::GraphicsStateInfo::currentFrameSlot}{currentFrameSlot}
3355 for a detailed description.
3356 */
3357
3358/*!
3359 \return a reference to a GraphicsStateInfo struct describing some of the
3360 RHI's internal state, in particular, the double or tripple buffering status
3361 of the backend (such as, the Vulkan or Metal integrations). This is
3362 relevant when the underlying graphics APIs is Vulkan or Metal, and the
3363 external rendering code wishes to perform double or tripple buffering of
3364 its own often-changing resources, such as, uniform buffers, in order to
3365 avoid stalling the pipeline.
3366 */
3367const QQuickWindow::GraphicsStateInfo &QQuickWindow::graphicsStateInfo()
3368{
3369 Q_D(QQuickWindow);
3370 if (d->rhi) {
3371 d->rhiStateInfo.currentFrameSlot = d->rhi->currentFrameSlot();
3372 d->rhiStateInfo.framesInFlight = d->rhi->resourceLimit(limit: QRhi::FramesInFlight);
3373 }
3374 return d->rhiStateInfo;
3375}
3376
3377/*!
3378 When mixing raw graphics (OpenGL, Vulkan, Metal, etc.) commands with scene
3379 graph rendering, it is necessary to call this function before recording
3380 commands to the command buffer used by the scene graph to render its main
3381 render pass. This is to avoid clobbering state.
3382
3383 In practice this function is often called from a slot connected to the
3384 beforeRenderPassRecording() or afterRenderPassRecording() signals.
3385
3386 The function does not need to be called when recording commands to the
3387 application's own command buffer (such as, a VkCommandBuffer or
3388 MTLCommandBuffer + MTLRenderCommandEncoder created and managed by the
3389 application, not retrieved from the scene graph). With graphics APIs where
3390 no native command buffer concept is exposed (OpenGL, Direct 3D 11),
3391 beginExternalCommands() and endExternalCommands() together provide a
3392 replacement for the Qt 5 resetOpenGLState() function.
3393
3394 Calling this function and endExternalCommands() is not necessary within the
3395 \l{QSGRenderNode::render()}{render()} implementation of a QSGRenderNode
3396 because the scene graph performs the necessary steps implicitly for render
3397 nodes.
3398
3399 Native graphics objects (such as, graphics device, command buffer or
3400 encoder) are accessible via QSGRendererInterface::getResource().
3401
3402 \warning Watch out for the fact that
3403 QSGRendererInterface::CommandListResource may return a different object
3404 between beginExternalCommands() - endExternalCommands(). This can happen
3405 when the underlying implementation provides a dedicated secondary command
3406 buffer for recording external graphics commands within a render pass.
3407 Therefore, always query CommandListResource after calling this function. Do
3408 not attempt to reuse an object from an earlier query.
3409
3410 \note When the scenegraph is using OpenGL, pay attention to the fact that
3411 the OpenGL state in the context can have arbitrary settings, and this
3412 function does not perform any resetting of the state back to defaults.
3413
3414 \sa endExternalCommands(), QQuickOpenGLUtils::resetOpenGLState()
3415
3416 \since 5.14
3417 */
3418void QQuickWindow::beginExternalCommands()
3419{
3420 Q_D(QQuickWindow);
3421 if (d->rhi && d->context && d->context->isValid()) {
3422 QSGDefaultRenderContext *rc = static_cast<QSGDefaultRenderContext *>(d->context);
3423 QRhiCommandBuffer *cb = rc->currentFrameCommandBuffer();
3424 if (cb)
3425 cb->beginExternal();
3426 }
3427}
3428
3429/*!
3430 When mixing raw graphics (OpenGL, Vulkan, Metal, etc.) commands with scene
3431 graph rendering, it is necessary to call this function after recording
3432 commands to the command buffer used by the scene graph to render its main
3433 render pass. This is to avoid clobbering state.
3434
3435 In practice this function is often called from a slot connected to the
3436 beforeRenderPassRecording() or afterRenderPassRecording() signals.
3437
3438 The function does not need to be called when recording commands to the
3439 application's own command buffer (such as, a VkCommandBuffer or
3440 MTLCommandBuffer + MTLRenderCommandEncoder created and managed by the
3441 application, not retrieved from the scene graph). With graphics APIs where
3442 no native command buffer concept is exposed (OpenGL, Direct 3D 11),
3443 beginExternalCommands() and endExternalCommands() together provide a
3444 replacement for the Qt 5 resetOpenGLState() function.
3445
3446 Calling this function and beginExternalCommands() is not necessary within the
3447 \l{QSGRenderNode::render()}{render()} implementation of a QSGRenderNode
3448 because the scene graph performs the necessary steps implicitly for render
3449 nodes.
3450
3451 \sa beginExternalCommands(), QQuickOpenGLUtils::resetOpenGLState()
3452
3453 \since 5.14
3454 */
3455void QQuickWindow::endExternalCommands()
3456{
3457 Q_D(QQuickWindow);
3458 if (d->rhi && d->context && d->context->isValid()) {
3459 QSGDefaultRenderContext *rc = static_cast<QSGDefaultRenderContext *>(d->context);
3460 QRhiCommandBuffer *cb = rc->currentFrameCommandBuffer();
3461 if (cb)
3462 cb->endExternal();
3463 }
3464}
3465
3466/*!
3467 \qmlproperty string Window::title
3468
3469 The window's title in the windowing system.
3470
3471 The window title might appear in the title area of the window decorations,
3472 depending on the windowing system and the window flags. It might also
3473 be used by the windowing system to identify the window in other contexts,
3474 such as in the task switcher.
3475 */
3476
3477/*!
3478 \qmlproperty Qt::WindowModality Window::modality
3479
3480 The modality of the window.
3481
3482 A modal window prevents other windows from receiving input events.
3483 Possible values are Qt.NonModal (the default), Qt.WindowModal,
3484 and Qt.ApplicationModal.
3485 */
3486
3487/*!
3488 \qmlproperty Qt::WindowFlags Window::flags
3489
3490 The window flags of the window.
3491
3492 The window flags control the window's appearance in the windowing system,
3493 whether it's a dialog, popup, or a regular window, and whether it should
3494 have a title bar, etc.
3495
3496 The flags that you read from this property might differ from the ones
3497 that you set if the requested flags could not be fulfilled.
3498
3499 \snippet qml/splashWindow.qml entire
3500
3501 \sa Qt::WindowFlags, {Qt Quick Examples - Window and Screen}
3502 */
3503
3504/*!
3505 \qmlattachedproperty Window Window::window
3506 \since 5.7
3507
3508 This attached property holds the item's window.
3509 The Window attached property can be attached to any Item.
3510*/
3511
3512/*!
3513 \qmlattachedproperty int Window::width
3514 \qmlattachedproperty int Window::height
3515 \since 5.5
3516
3517 These attached properties hold the size of the item's window.
3518 The Window attached property can be attached to any Item.
3519*/
3520
3521/*!
3522 \qmlproperty int Window::x
3523 \qmlproperty int Window::y
3524 \qmlproperty int Window::width
3525 \qmlproperty int Window::height
3526
3527 Defines the window's position and size.
3528
3529 The (x,y) position is relative to the \l Screen if there is only one,
3530 or to the virtual desktop (arrangement of multiple screens).
3531
3532 \note Not all windowing systems support setting or querying top level
3533 window positions. On such a system, programmatically moving windows
3534 may not have any effect, and artificial values may be returned for
3535 the current positions, such as \c QPoint(0, 0).
3536
3537 \qml
3538 Window { x: 100; y: 100; width: 100; height: 100 }
3539 \endqml
3540
3541 \image screen-and-window-dimensions.jpg
3542 */
3543
3544/*!
3545 \qmlproperty int Window::minimumWidth
3546 \qmlproperty int Window::minimumHeight
3547 \since 5.1
3548
3549 Defines the window's minimum size.
3550
3551 This is a hint to the window manager to prevent resizing below the specified
3552 width and height.
3553 */
3554
3555/*!
3556 \qmlproperty int Window::maximumWidth
3557 \qmlproperty int Window::maximumHeight
3558 \since 5.1
3559
3560 Defines the window's maximum size.
3561
3562 This is a hint to the window manager to prevent resizing above the specified
3563 width and height.
3564 */
3565
3566/*!
3567 \qmlproperty bool Window::visible
3568
3569 Whether the window is visible on the screen.
3570
3571 Setting visible to false is the same as setting \l visibility to \l {QWindow::}{Hidden}.
3572
3573 The default value is \c false, unless overridden by setting \l visibility.
3574
3575 \sa visibility
3576 */
3577
3578/*!
3579 \keyword qml-window-visibility-prop
3580 \qmlproperty QWindow::Visibility Window::visibility
3581
3582 The screen-occupation state of the window.
3583
3584 Visibility is whether the window should appear in the windowing system as
3585 normal, minimized, maximized, fullscreen or hidden.
3586
3587 To set the visibility to \l {QWindow::}{AutomaticVisibility} means to give the
3588 window a default visible state, which might be \l {QWindow::}{FullScreen} or
3589 \l {QWindow::}{Windowed} depending on the platform. However when reading the
3590 visibility property you will always get the actual state, never
3591 \c AutomaticVisibility.
3592
3593 When a window is not visible, its visibility is \c Hidden, and setting
3594 visibility to \l {QWindow::}{Hidden} is the same as setting \l visible to \c false.
3595
3596 \snippet qml/windowVisibility.qml entire
3597
3598 \sa visible, {Qt Quick Examples - Window and Screen}
3599 \since 5.1
3600 */
3601
3602/*!
3603 \qmlattachedproperty QWindow::Visibility Window::visibility
3604 \readonly
3605 \since 5.4
3606
3607 This attached property holds whether the window is currently shown
3608 in the windowing system as normal, minimized, maximized, fullscreen or
3609 hidden. The \c Window attached property can be attached to any Item. If the
3610 item is not shown in any window, the value will be \l {QWindow::}{Hidden}.
3611
3612 \sa visible, {qml-window-visibility-prop}{visibility}
3613*/
3614
3615/*!
3616 \qmlproperty Item Window::contentItem
3617 \readonly
3618 \brief The invisible root item of the scene.
3619*/
3620
3621/*!
3622 \qmlproperty Qt::ScreenOrientation Window::contentOrientation
3623
3624 This is a hint to the window manager in case it needs to display
3625 additional content like popups, dialogs, status bars, or similar
3626 in relation to the window.
3627
3628 The recommended orientation is \l {Screen::orientation}{Screen.orientation}, but
3629 an application doesn't have to support all possible orientations,
3630 and thus can opt to ignore the current screen orientation.
3631
3632 The difference between the window and the content orientation
3633 determines how much to rotate the content by.
3634
3635 The default value is Qt::PrimaryOrientation.
3636
3637 \sa Screen
3638
3639 \since 5.1
3640 */
3641
3642/*!
3643 \qmlproperty real Window::opacity
3644
3645 The opacity of the window.
3646
3647 If the windowing system supports window opacity, this can be used to fade the
3648 window in and out, or to make it semitransparent.
3649
3650 A value of 1.0 or above is treated as fully opaque, whereas a value of 0.0 or below
3651 is treated as fully transparent. Values inbetween represent varying levels of
3652 translucency between the two extremes.
3653
3654 The default value is 1.0.
3655
3656 \since 5.1
3657 */
3658
3659/*!
3660 \qmlproperty variant Window::screen
3661
3662 The screen with which the window is associated.
3663
3664 If specified before showing a window, will result in the window being shown
3665 on that screen, unless an explicit window position has been set. The value
3666 must be an element from the Qt.application.screens array.
3667
3668 \note To ensure that the window is associated with the desired screen when
3669 the underlying native window is created, make sure this property is set as
3670 early as possible and that the setting of its value is not deferred. This
3671 can be particularly important on embedded platforms without a windowing system,
3672 where only one window per screen is allowed at a time. Setting the screen after
3673 a window has been created does not move the window if the new screen is part of
3674 the same virtual desktop as the old screen.
3675
3676 \since 5.9
3677
3678 \sa QWindow::setScreen(), QWindow::screen(), QScreen, {QtQml::Qt::application}{Qt.application}
3679 */
3680
3681/*!
3682 \qmlproperty QWindow Window::transientParent
3683 \since 5.13
3684
3685 The window for which this window is a transient pop-up.
3686
3687 This is a hint to the window manager that this window is a dialog or pop-up
3688 on behalf of the transient parent. It usually means that the transient
3689 window will be centered over its transient parent when it is initially
3690 shown, that minimizing the parent window will also minimize the transient
3691 window, and so on; however results vary somewhat from platform to platform.
3692
3693 Declaring a Window inside an Item or another Window, either via the
3694 \l{Window::data}{default property} or a dedicated property, will automatically
3695 set up a transient parent relationship to the containing window,
3696 unless the \l transientParent property is explicitly set. This applies
3697 when creating Window items via \l [QML] {QtQml::Qt::createComponent()}
3698 {Qt.createComponent} or \l [QML] {QtQml::Qt::createQmlObject()}
3699 {Qt.createQmlObject} as well, as long as an Item or Window is passed
3700 as the \c parent argument.
3701
3702 A Window with a transient parent will not be shown until its transient
3703 parent is shown, even if the \l visible property is \c true. This also
3704 applies for the automatic transient parent relationship described above.
3705 In particular, if the Window's containing element is an Item, the window
3706 will not be shown until the containing item is added to a scene, via its
3707 \l{Concepts - Visual Parent in Qt Quick}{visual parent hierarchy}. Setting
3708 the \l transientParent to \c null will override this behavior:
3709
3710 \snippet qml/nestedWindowTransientParent.qml 0
3711 \snippet qml/nestedWindowTransientParent.qml 1
3712
3713 In order to cause the window to be centered above its transient parent by
3714 default, depending on the window manager, it may also be necessary to set
3715 the \l Window::flags property with a suitable \l Qt::WindowType (such as
3716 \c Qt::Dialog).
3717
3718 \sa {QQuickWindow::}{parent()}
3719*/
3720
3721/*!
3722 \property QQuickWindow::transientParent
3723 \brief The window for which this window is a transient pop-up.
3724 \since 5.13
3725
3726 This is a hint to the window manager that this window is a dialog or pop-up
3727 on behalf of the transient parent, which may be any kind of \l QWindow.
3728
3729 In order to cause the window to be centered above its transient parent by
3730 default, depending on the window manager, it may also be necessary to set
3731 the \l flags property with a suitable \l Qt::WindowType (such as \c Qt::Dialog).
3732
3733 \sa parent()
3734 */
3735
3736/*!
3737 \qmlproperty Item Window::activeFocusItem
3738 \since 5.1
3739
3740 The item which currently has active focus or \c null if there is
3741 no item with active focus.
3742 */
3743
3744/*!
3745 \qmlattachedproperty Item Window::activeFocusItem
3746 \since 5.4
3747
3748 This attached property holds the item which currently has active focus or
3749 \c null if there is no item with active focus. The Window attached property
3750 can be attached to any Item.
3751*/
3752
3753/*!
3754 \qmlproperty bool Window::active
3755 \since 5.1
3756
3757 The active status of the window.
3758
3759 \snippet qml/windowPalette.qml declaration-and-color
3760 \snippet qml/windowPalette.qml closing-brace
3761
3762 \sa requestActivate()
3763 */
3764
3765/*!
3766 \qmlattachedproperty bool Window::active
3767 \since 5.4
3768
3769 This attached property tells whether the window is active. The Window
3770 attached property can be attached to any Item.
3771
3772 Here is an example which changes a label to show the active state of the
3773 window in which it is shown:
3774
3775 \snippet qml/windowActiveAttached.qml entire
3776*/
3777
3778/*!
3779 \qmlmethod QtQuick::Window::requestActivate()
3780 \since 5.1
3781
3782 Requests the window to be activated, i.e. receive keyboard focus.
3783 */
3784
3785/*!
3786 \qmlmethod QtQuick::Window::alert(int msec)
3787 \since 5.1
3788
3789 Causes an alert to be shown for \a msec milliseconds. If \a msec is \c 0
3790 (the default), then the alert is shown indefinitely until the window
3791 becomes active again.
3792
3793 In alert state, the window indicates that it demands attention, for example
3794 by flashing or bouncing the taskbar entry.
3795*/
3796
3797/*!
3798 \qmlmethod QtQuick::Window::close()
3799
3800 Closes the window.
3801
3802 When this method is called, or when the user tries to close the window by
3803 its title bar button, the \l closing signal will be emitted. If there is no
3804 handler, or the handler does not revoke permission to close, the window
3805 will subsequently close. If the QGuiApplication::quitOnLastWindowClosed
3806 property is \c true, and there are no other windows open, the application
3807 will quit.
3808*/
3809
3810/*!
3811 \qmlmethod QtQuick::Window::raise()
3812
3813 Raises the window in the windowing system.
3814
3815 Requests that the window be raised to appear above other windows.
3816*/
3817
3818/*!
3819 \qmlmethod QtQuick::Window::lower()
3820
3821 Lowers the window in the windowing system.
3822
3823 Requests that the window be lowered to appear below other windows.
3824*/
3825
3826/*!
3827 \qmlmethod QtQuick::Window::show()
3828
3829 Shows the window.
3830
3831 This is equivalent to calling showFullScreen(), showMaximized(), or showNormal(),
3832 depending on the platform's default behavior for the window type and flags.
3833
3834 \sa showFullScreen(), showMaximized(), showNormal(), hide(), QQuickItem::flags()
3835*/
3836
3837/*!
3838 \qmlmethod QtQuick::Window::hide()
3839
3840 Hides the window.
3841
3842 Equivalent to setting \l visible to \c false or \l visibility to \l {QWindow::}{Hidden}.
3843
3844 \sa show()
3845*/
3846
3847/*!
3848 \qmlmethod QtQuick::Window::showMinimized()
3849
3850 Shows the window as minimized.
3851
3852 Equivalent to setting \l visibility to \l {QWindow::}{Minimized}.
3853*/
3854
3855/*!
3856 \qmlmethod QtQuick::Window::showMaximized()
3857
3858 Shows the window as maximized.
3859
3860 Equivalent to setting \l visibility to \l {QWindow::}{Maximized}.
3861*/
3862
3863/*!
3864 \qmlmethod QtQuick::Window::showFullScreen()
3865
3866 Shows the window as fullscreen.
3867
3868 Equivalent to setting \l visibility to \l {QWindow::}{FullScreen}.
3869*/
3870
3871/*!
3872 \qmlmethod QtQuick::Window::showNormal()
3873
3874 Shows the window as normal, i.e. neither maximized, minimized, nor fullscreen.
3875
3876 Equivalent to setting \l visibility to \l {QWindow::}{Windowed}.
3877*/
3878
3879/*!
3880 \enum QQuickWindow::RenderStage
3881 \since 5.4
3882
3883 \value BeforeSynchronizingStage Before synchronization.
3884 \value AfterSynchronizingStage After synchronization.
3885 \value BeforeRenderingStage Before rendering.
3886 \value AfterRenderingStage After rendering.
3887 \value AfterSwapStage After the frame is swapped.
3888 \value NoStage As soon as possible. This value was added in Qt 5.6.
3889
3890 \sa {Scene Graph and Rendering}
3891 */
3892
3893/*!
3894 \since 5.4
3895
3896 Schedules \a job to run when the rendering of this window reaches
3897 the given \a stage.
3898
3899 This is a convenience to the equivalent signals in QQuickWindow for
3900 "one shot" tasks.
3901
3902 The window takes ownership over \a job and will delete it when the
3903 job is completed.
3904
3905 If rendering is shut down before \a job has a chance to run, the
3906 job will be run and then deleted as part of the scene graph cleanup.
3907 If the window is never shown and no rendering happens before the QQuickWindow
3908 is destroyed, all pending jobs will be destroyed without their run()
3909 method being called.
3910
3911 If the rendering is happening on a different thread, then the job
3912 will happen on the rendering thread.
3913
3914 If \a stage is \l NoStage, \a job will be run at the earliest opportunity
3915 whenever the render thread is not busy rendering a frame. If the window is
3916 not exposed, and is not renderable, at the time the job is either posted or
3917 handled, the job is deleted without executing the run() method. If a
3918 non-threaded renderer is in use, the run() method of the job is executed
3919 synchronously. When rendering with OpenGL, the OpenGL context is changed to
3920 the renderer's context before executing any job, including \l NoStage jobs.
3921
3922 \note This function does not trigger rendering; the jobs targeting any other
3923 stage than NoStage will be stored run until rendering is triggered elsewhere.
3924 To force the job to run earlier, call QQuickWindow::update();
3925
3926 \sa beforeRendering(), afterRendering(), beforeSynchronizing(),
3927 afterSynchronizing(), frameSwapped(), sceneGraphInvalidated()
3928 */
3929
3930void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage)
3931{
3932 Q_D(QQuickWindow);
3933
3934 d->renderJobMutex.lock();
3935 if (stage == BeforeSynchronizingStage) {
3936 d->beforeSynchronizingJobs << job;
3937 } else if (stage == AfterSynchronizingStage) {
3938 d->afterSynchronizingJobs << job;
3939 } else if (stage == BeforeRenderingStage) {
3940 d->beforeRenderingJobs << job;
3941 } else if (stage == AfterRenderingStage) {
3942 d->afterRenderingJobs << job;
3943 } else if (stage == AfterSwapStage) {
3944 d->afterSwapJobs << job;
3945 } else if (stage == NoStage) {
3946 if (d->renderControl && d->rhi && d->rhi->thread() == QThread::currentThread()) {
3947 job->run();
3948 delete job;
3949 } else if (isExposed()) {
3950 d->windowManager->postJob(window: this, job);
3951 } else {
3952 delete job;
3953 }
3954 }
3955 d->renderJobMutex.unlock();
3956}
3957
3958void QQuickWindowPrivate::runAndClearJobs(QList<QRunnable *> *jobs)
3959{
3960 renderJobMutex.lock();
3961 QList<QRunnable *> jobList = *jobs;
3962 jobs->clear();
3963 renderJobMutex.unlock();
3964
3965 for (QRunnable *r : std::as_const(t&: jobList)) {
3966 r->run();
3967 delete r;
3968 }
3969}
3970
3971void QQuickWindow::runJobsAfterSwap()
3972{
3973 Q_D(QQuickWindow);
3974 d->runAndClearJobs(jobs: &d->afterSwapJobs);
3975}
3976
3977/*!
3978 Returns the device pixel ratio for this window.
3979
3980 This is different from QWindow::devicePixelRatio() in that it supports
3981 redirected rendering via QQuickRenderControl and QQuickRenderTarget. When
3982 using a QQuickRenderControl, the QQuickWindow is often not fully created,
3983 meaning it is never shown and there is no underlying native window created
3984 in the windowing system. As a result, querying properties like the device
3985 pixel ratio cannot give correct results. This function takes into account
3986 both QQuickRenderControl::renderWindowFor() and
3987 QQuickRenderTarget::devicePixelRatio(). When no redirection is in effect,
3988 the result is same as QWindow::devicePixelRatio().
3989
3990 \sa QQuickRenderControl, QQuickRenderTarget, setRenderTarget(), QWindow::devicePixelRatio()
3991 */
3992qreal QQuickWindow::effectiveDevicePixelRatio() const
3993{
3994 Q_D(const QQuickWindow);
3995 QWindow *w = QQuickRenderControl::renderWindowFor(win: const_cast<QQuickWindow *>(this));
3996 if (w)
3997 return w->devicePixelRatio();
3998
3999 if (!d->customRenderTarget.isNull())
4000 return d->customRenderTarget.devicePixelRatio();
4001
4002 return devicePixelRatio();
4003}
4004
4005/*!
4006 \return the current renderer interface. The value is always valid and is never null.
4007
4008 \note This function can be called at any time after constructing the
4009 QQuickWindow, even while isSceneGraphInitialized() is still false. However,
4010 some renderer interface functions, in particular
4011 QSGRendererInterface::getResource() will not be functional until the
4012 scenegraph is up and running. Backend queries, like
4013 QSGRendererInterface::graphicsApi() or QSGRendererInterface::shaderType(),
4014 will always be functional on the other hand.
4015
4016 \note The ownership of the returned pointer stays with Qt. The returned
4017 instance may or may not be shared between different QQuickWindow instances,
4018 depending on the scenegraph backend in use. Therefore applications are
4019 expected to query the interface object for each QQuickWindow instead of
4020 reusing the already queried pointer.
4021
4022 \sa QSGRenderNode, QSGRendererInterface
4023
4024 \since 5.8
4025 */
4026QSGRendererInterface *QQuickWindow::rendererInterface() const
4027{
4028 Q_D(const QQuickWindow);
4029
4030 // no context validity check - it is essential to be able to return a
4031 // renderer interface instance before scenegraphInitialized() is emitted
4032 // (depending on the backend, that can happen way too late for some of the
4033 // rif use cases, like examining the graphics api or shading language in
4034 // use)
4035
4036 return d->context->sceneGraphContext()->rendererInterface(renderContext: d->context);
4037}
4038
4039/*!
4040 \return the QRhi object used by this window for rendering.
4041
4042 Available only when the window is using Qt's 3D API and shading language
4043 abstractions, meaning the result is always null when using the \c software
4044 adaptation.
4045
4046 The result is valid only when rendering has been initialized, which is
4047 indicated by the emission of the sceneGraphInitialized() signal. Before
4048 that point, the returned value is null. With a regular, on-screen
4049 QQuickWindow scenegraph initialization typically happens when the native
4050 window gets exposed (shown) the first time. When using QQuickRenderControl,
4051 initialization is done in the explicit
4052 \l{QQuickRenderControl::initialize()}{initialize()} call.
4053
4054 In practice this function is a shortcut to querying the QRhi via the
4055 QSGRendererInterface.
4056
4057 \since 6.6
4058 */
4059QRhi *QQuickWindow::rhi() const
4060{
4061 Q_D(const QQuickWindow);
4062 return d->rhi;
4063}
4064
4065/*!
4066 \return the QRhiSwapChain used by this window, if there is one.
4067
4068 \note Only on-screen windows backed by one of the standard render loops
4069 (such as, \c basic or \c threaded) will have a swapchain. Otherwise the
4070 returned value is null. For example, the result is always null when the
4071 window is used with QQuickRenderControl.
4072
4073 \since 6.6
4074 */
4075QRhiSwapChain *QQuickWindow::swapChain() const
4076{
4077 Q_D(const QQuickWindow);
4078 return d->swapchain;
4079}
4080
4081/*!
4082 Requests the specified graphics \a api.
4083
4084 When the built-in, default graphics adaptation is used, \a api specifies
4085 which graphics API (OpenGL, Vulkan, Metal, or Direct3D) the scene graph
4086 should use to render. In addition, the \c software backend is built-in as
4087 well, and can be requested by setting \a api to
4088 QSGRendererInterface::Software.
4089
4090 Unlike setSceneGraphBackend(), which can only be used to request a given
4091 backend (shipped either built-in or installed as dynamically loaded
4092 plugins), this function works with the higher level concept of graphics
4093 APIs. It covers the backends that ship with Qt Quick, and thus have
4094 corresponding values in the QSGRendererInterface::GraphicsApi enum.
4095
4096 When this function is not called at all, and the equivalent environment
4097 variable \c{QSG_RHI_BACKEND} is not set either, the scene graph will choose
4098 the graphics API to use based on the platform.
4099
4100 This function becomes important in applications that are only prepared for
4101 rendering with a given API. For example, if there is native OpenGL or
4102 Vulkan rendering done by the application, it will want to ensure Qt Quick
4103 is rendering using OpenGL or Vulkan too. Such applications are expected to
4104 call this function early in their main() function.
4105
4106 \note The call to the function must happen before constructing the first
4107 QQuickWindow in the application. The graphics API cannot be changed
4108 afterwards.
4109
4110 \note When used in combination with QQuickRenderControl, this rule is
4111 relaxed: it is possible to change the graphics API, but only when all
4112 existing QQuickRenderControl and QQuickWindow instances have been
4113 destroyed.
4114
4115 To query what graphics API the scene graph is using to render,
4116 QSGRendererInterface::graphicsApi() after the scene graph
4117 \l{QQuickWindow::isSceneGraphInitialized()}{has initialized}, which
4118 typically happens either when the window becomes visible for the first time, or
4119 when QQuickRenderControl::initialize() is called.
4120
4121 To switch back to the default behavior, where the scene graph chooses a
4122 graphics API based on the platform and other conditions, set \a api to
4123 QSGRendererInterface::Unknown.
4124
4125 \since 6.0
4126 */
4127void QQuickWindow::setGraphicsApi(QSGRendererInterface::GraphicsApi api)
4128{
4129 // Special cases: these are different scenegraph backends.
4130 switch (api) {
4131 case QSGRendererInterface::Software:
4132 setSceneGraphBackend(QStringLiteral("software"));
4133 break;
4134 case QSGRendererInterface::OpenVG:
4135 setSceneGraphBackend(QStringLiteral("openvg"));
4136 break;
4137 default:
4138 break;
4139 }
4140
4141 // Standard case: tell the QRhi-based default adaptation what graphics api
4142 // (QRhi backend) to use.
4143 if (QSGRendererInterface::isApiRhiBased(api) || api == QSGRendererInterface::Unknown)
4144 QSGRhiSupport::instance_internal()->configure(api);
4145}
4146
4147/*!
4148 \return the graphics API that would be used by the scene graph if it was
4149 initialized at this point in time.
4150
4151 The standard way to query the API used by the scene graph is to use
4152 QSGRendererInterface::graphicsApi() once the scene graph has initialized,
4153 for example when or after the sceneGraphInitialized() signal is emitted. In
4154 that case one gets the true, real result, because then it is known that
4155 everything was initialized correctly using that graphics API.
4156
4157 This is not always convenient. If the application needs to set up external
4158 frameworks, or needs to work with setGraphicsDevice() in a manner that
4159 depends on the scene graph's built in API selection logic, it is not always
4160 feasiable to defer such operations until after the QQuickWindow has been
4161 made visible or QQuickRenderControl::initialize() has been called.
4162
4163 Therefore, this static function is provided as a counterpart to
4164 setGraphicsApi(): it can be called at any time, and the result reflects
4165 what API the scene graph would choose if it was initialized at the point of
4166 the call.
4167
4168 \note This static function is intended to be called on the main (GUI)
4169 thread only. For querying the API when rendering, use QSGRendererInterface
4170 since that object lives on the render thread.
4171
4172 \note This function does not take scene graph backends into account.
4173
4174 \since 6.0
4175 */
4176QSGRendererInterface::GraphicsApi QQuickWindow::graphicsApi()
4177{
4178 // Note that this applies the settings e.g. from the env vars
4179 // (QSG_RHI_BACKEND) if it was not done at least once already. Whereas if
4180 // setGraphicsApi() was called before, or the scene graph is already
4181 // initialized, then this is just a simple query.
4182 return QSGRhiSupport::instance()->graphicsApi();
4183}
4184
4185/*!
4186 Requests a Qt Quick scenegraph \a backend. Backends can either be built-in
4187 or be installed in form of dynamically loaded plugins.
4188
4189 \overload
4190
4191 \note The call to the function must happen before constructing the first
4192 QQuickWindow in the application. It cannot be changed afterwards.
4193
4194 See \l{Switch Between Adaptations in Your Application} for more information
4195 about the list of backends. If \a backend is invalid or an error occurs, the
4196 request is ignored.
4197
4198 \note Calling this function is equivalent to setting the
4199 \c QT_QUICK_BACKEND or \c QMLSCENE_DEVICE environment variables. However, this
4200 API is safer to use in applications that spawn other processes as there is
4201 no need to worry about environment inheritance.
4202
4203 \since 5.8
4204 */
4205void QQuickWindow::setSceneGraphBackend(const QString &backend)
4206{
4207 QSGContext::setBackend(backend);
4208}
4209
4210/*!
4211 Returns the requested Qt Quick scenegraph backend.
4212
4213 \note The return value of this function may still be outdated by
4214 subsequent calls to setSceneGraphBackend() until the first QQuickWindow in the
4215 application has been constructed.
4216
4217 \note The value only reflects the request in the \c{QT_QUICK_BACKEND}
4218 environment variable after a QQuickWindow has been constructed.
4219
4220 \since 5.9
4221 */
4222QString QQuickWindow::sceneGraphBackend()
4223{
4224 return QSGContext::backend();
4225}
4226
4227/*!
4228 Sets the graphics device objects for this window. The scenegraph will use
4229 existing device, physical device, and other objects specified by \a device
4230 instead of creating new ones.
4231
4232 This function is very often used in combination with QQuickRenderControl
4233 and setRenderTarget(), in order to redirect Qt Quick rendering into a
4234 texture.
4235
4236 A default constructed QQuickGraphicsDevice does not change the default
4237 behavior in any way. Once a \a device created via one of the
4238 QQuickGraphicsDevice factory functions, such as,
4239 QQuickGraphicsDevice::fromDeviceObjects(), is passed in, and the scenegraph
4240 uses a matching graphics API (with the example of fromDeviceObjects(), that
4241 would be Vulkan), the scenegraph will use the existing device objects (such
4242 as, the \c VkPhysicalDevice, \c VkDevice, and graphics queue family index,
4243 in case of Vulkan) encapsulated by the QQuickGraphicsDevice. This allows
4244 using the same device, and so sharing resources, such as buffers and
4245 textures, between Qt Quick and native rendering engines.
4246
4247 \warning This function can only be called before initializing the
4248 scenegraph and will have no effect if called afterwards. In practice this
4249 typically means calling it right before QQuickRenderControl::initialize().
4250
4251 As an example, this time with Direct3D, the typical usage is expected to be
4252 the following:
4253
4254 \badcode
4255 // native graphics resources set up by a custom D3D rendering engine
4256 ID3D11Device *device;
4257 ID3D11DeviceContext *context;
4258 ID3D11Texture2D *texture;
4259 ...
4260 // now to redirect Qt Quick content into 'texture' we could do the following:
4261 QQuickRenderControl *renderControl = new QQuickRenderControl;
4262 QQuickWindow *window = new QQuickWindow(renderControl); // this window will never be shown on-screen
4263 ...
4264 window->setGraphicsDevice(QQuickGraphicsDevice::fromDeviceAndContext(device, context));
4265 renderControl->initialize();
4266 window->setRenderTarget(QQuickRenderTarget::fromD3D11Texture(texture, textureSize);
4267 ...
4268 \endcode
4269
4270 The key aspect of using this function is to ensure that resources or
4271 handles to resources, such as \c texture in the above example, are visible
4272 to and usable by both the external rendering engine and the scenegraph
4273 renderer. This requires using the same graphics device (or with OpenGL,
4274 OpenGL context).
4275
4276 QQuickGraphicsDevice instances are implicitly shared, copyable, and
4277 can be passed by value. They do not own the associated native objects (such
4278 as, the ID3D11Device in the example).
4279
4280 \note Using QQuickRenderControl does not always imply having to call this
4281 function. When adopting an existing device or context is not needed, this
4282 function should not be called, and the scene graph will then initialize its
4283 own devices and contexts normally, just as it would with an on-screen
4284 QQuickWindow.
4285
4286 \since 6.0
4287
4288 \sa QQuickRenderControl, setRenderTarget(), setGraphicsApi()
4289 */
4290void QQuickWindow::setGraphicsDevice(const QQuickGraphicsDevice &device)
4291{
4292 Q_D(QQuickWindow);
4293 d->customDeviceObjects = device;
4294}
4295
4296/*!
4297 \return the QQuickGraphicsDevice passed to setGraphicsDevice(), or a
4298 default constructed one otherwise
4299
4300 \since 6.0
4301
4302 \sa setGraphicsDevice()
4303 */
4304QQuickGraphicsDevice QQuickWindow::graphicsDevice() const
4305{
4306 Q_D(const QQuickWindow);
4307 return d->customDeviceObjects;
4308}
4309
4310/*!
4311 Sets the graphics configuration for this window. \a config contains various
4312 settings that may be taken into account by the scene graph when
4313 initializing the underlying graphics devices and contexts.
4314
4315 Such additional configuration, specifying for example what device
4316 extensions to enable for Vulkan, becomes relevant and essential when
4317 integrating native graphics rendering code that relies on certain
4318 extensions. The same is true when integrating with an external 3D or VR
4319 engines, such as OpenXR.
4320
4321 \note The configuration is ignored when adopting existing graphics devices
4322 via setGraphicsDevice() since the scene graph is then not in control of the
4323 actual construction of those objects.
4324
4325 QQuickGraphicsConfiguration instances are implicitly shared, copyable, and
4326 can be passed by value.
4327
4328 \warning Setting a QQuickGraphicsConfiguration on a QQuickWindow must
4329 happen early enough, before the scene graph is initialized for the first
4330 time for that window. With on-screen windows this means the call must be
4331 done before invoking show() on the QQuickWindow or QQuickView. With
4332 QQuickRenderControl the configuration must be finalized before calling
4333 \l{QQuickRenderControl::initialize()}{initialize()}.
4334
4335 \since 6.0
4336 */
4337void QQuickWindow::setGraphicsConfiguration(const QQuickGraphicsConfiguration &config)
4338{
4339 Q_D(QQuickWindow);
4340 d->graphicsConfig = config;
4341}
4342
4343/*!
4344 \return the QQuickGraphicsConfiguration passed to
4345 setGraphicsConfiguration(), or a default constructed one otherwise.
4346
4347 \since 6.0
4348
4349 \sa setGraphicsConfiguration()
4350 */
4351QQuickGraphicsConfiguration QQuickWindow::graphicsConfiguration() const
4352{
4353 Q_D(const QQuickWindow);
4354 return d->graphicsConfig;
4355}
4356
4357/*!
4358 Creates a text node. When the scenegraph is not initialized, the return value is null.
4359
4360 \since 6.7
4361 \sa QSGTextNode
4362 */
4363QSGTextNode *QQuickWindow::createTextNode() const
4364{
4365 Q_D(const QQuickWindow);
4366 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createTextNode(renderContext: d->context) : nullptr;
4367}
4368
4369/*!
4370 Creates a simple rectangle node. When the scenegraph is not initialized, the return value is null.
4371
4372 This is cross-backend alternative to constructing a QSGSimpleRectNode directly.
4373
4374 \since 5.8
4375 \sa QSGRectangleNode
4376 */
4377QSGRectangleNode *QQuickWindow::createRectangleNode() const
4378{
4379 Q_D(const QQuickWindow);
4380 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createRectangleNode() : nullptr;
4381}
4382
4383/*!
4384 Creates a simple image node. When the scenegraph is not initialized, the return value is null.
4385
4386 This is cross-backend alternative to constructing a QSGSimpleTextureNode directly.
4387
4388 \since 5.8
4389 \sa QSGImageNode
4390 */
4391QSGImageNode *QQuickWindow::createImageNode() const
4392{
4393 Q_D(const QQuickWindow);
4394 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createImageNode() : nullptr;
4395}
4396
4397/*!
4398 Creates a nine patch node. When the scenegraph is not initialized, the return value is null.
4399
4400 \since 5.8
4401 */
4402QSGNinePatchNode *QQuickWindow::createNinePatchNode() const
4403{
4404 Q_D(const QQuickWindow);
4405 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createNinePatchNode() : nullptr;
4406}
4407
4408/*!
4409 \since 5.10
4410
4411 Returns the render type of text-like elements in Qt Quick.
4412 The default is QQuickWindow::QtTextRendering.
4413
4414 \sa setTextRenderType()
4415*/
4416QQuickWindow::TextRenderType QQuickWindow::textRenderType()
4417{
4418 return QQuickWindowPrivate::textRenderType;
4419}
4420
4421/*!
4422 \since 5.10
4423
4424 Sets the default render type of text-like elements in Qt Quick to \a renderType.
4425
4426 \note setting the render type will only affect elements created afterwards;
4427 the render type of existing elements will not be modified.
4428
4429 \sa textRenderType()
4430*/
4431void QQuickWindow::setTextRenderType(QQuickWindow::TextRenderType renderType)
4432{
4433 QQuickWindowPrivate::textRenderType = renderType;
4434}
4435
4436
4437/*!
4438 \since 6.0
4439 \qmlproperty Palette Window::palette
4440
4441 This property holds the palette currently set for the window.
4442
4443 The default palette depends on the system environment. QGuiApplication maintains a system/theme
4444 palette which serves as a default for all application windows. You can also set the default palette
4445 for windows by passing a custom palette to QGuiApplication::setPalette(), before loading any QML.
4446
4447 Window propagates explicit palette properties to child items and controls,
4448 overriding any system defaults for that property.
4449
4450 \snippet qml/windowPalette.qml entire
4451
4452 \sa Item::palette, Popup::palette, ColorGroup, SystemPalette
4453 //! internal \sa QQuickAbstractPaletteProvider, QQuickPalette
4454*/
4455
4456#ifndef QT_NO_DEBUG_STREAM
4457QDebug operator<<(QDebug debug, const QQuickWindow *win)
4458{
4459 QDebugStateSaver saver(debug);
4460 debug.nospace();
4461 if (!win) {
4462 debug << "QQuickWindow(nullptr)";
4463 return debug;
4464 }
4465
4466 debug << win->metaObject()->className() << '(' << static_cast<const void *>(win);
4467 if (win->isActive())
4468 debug << " active";
4469 if (win->isExposed())
4470 debug << " exposed";
4471 debug << ", visibility=" << win->visibility() << ", flags=" << win->flags();
4472 if (!win->title().isEmpty())
4473 debug << ", title=" << win->title();
4474 if (!win->objectName().isEmpty())
4475 debug << ", name=" << win->objectName();
4476 if (win->parent())
4477 debug << ", parent=" << static_cast<const void *>(win->parent());
4478 if (win->transientParent())
4479 debug << ", transientParent=" << static_cast<const void *>(win->transientParent());
4480 debug << ", geometry=";
4481 QtDebugUtils::formatQRect(debug, rect: win->geometry());
4482 debug << ')';
4483 return debug;
4484}
4485#endif
4486
4487QT_END_NAMESPACE
4488
4489#include "qquickwindow.moc"
4490#include "moc_qquickwindow_p.cpp"
4491#include "moc_qquickwindow.cpp"
4492

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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