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