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