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