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