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