Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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"
5#include "qquickwindow_p.h"
6
7#include "qquickitem.h"
8#include "qquickitem_p.h"
9#include "qquickevents_p_p.h"
12
13#include <QtQuick/private/qsgrenderer_p.h>
14#include <QtQuick/private/qsgplaintexture_p.h>
15#include <QtQuick/private/qquickpointerhandler_p.h>
16#include <QtQuick/private/qquickpointerhandler_p_p.h>
17#include <private/qsgrenderloop_p.h>
18#include <private/qsgrhisupport_p.h>
19#include <private/qquickrendercontrol_p.h>
20#include <private/qquickanimatorcontroller_p.h>
21#include <private/qquickprofiler_p.h>
22#include <private/qquicktextinterface_p.h>
23
24#include <private/qguiapplication_p.h>
25
26#include <private/qabstractanimation_p.h>
27
28#include <QtGui/qpainter.h>
29#include <QtGui/qevent.h>
30#include <QtGui/qmatrix4x4.h>
31#include <QtGui/private/qevent_p.h>
32#include <QtGui/private/qpointingdevice_p.h>
33#include <QtCore/qvarlengtharray.h>
34#include <QtCore/qabstractanimation.h>
35#include <QtCore/QLibraryInfo>
36#include <QtCore/QRunnable>
37#include <QtQml/qqmlincubator.h>
38#include <QtQml/qqmlinfo.h>
39#include <QtQml/private/qqmlmetatype_p.h>
40
41#include <QtQuick/private/qquickpixmap_p.h>
42
43#include <private/qqmldebugserviceinterfaces_p.h>
44#include <private/qqmldebugconnector_p.h>
45#include <private/qsgdefaultrendercontext_p.h>
46#if QT_CONFIG(opengl)
47#include <private/qopengl_p.h>
48#include <QOpenGLContext>
49#endif
50#ifndef QT_NO_DEBUG_STREAM
51#include <private/qdebug_p.h>
52#endif
53#include <QtCore/qpointer.h>
54
55#include <rhi/qrhi.h>
56
57#include <utility>
58#include <mutex>
59
61
66Q_LOGGING_CATEGORY(lcDirty, "qt.quick.dirty")
67Q_LOGGING_CATEGORY(lcQuickWindow, "qt.quick.window")
68Q_LOGGING_CATEGORY(lcTransient, "qt.quick.window.transient")
69
70bool QQuickWindowPrivate::defaultAlphaBuffer = false;
71
72#if defined(QT_QUICK_DEFAULT_TEXT_RENDER_TYPE)
73QQuickWindow::TextRenderType QQuickWindowPrivate::textRenderType = QQuickWindow::QT_QUICK_DEFAULT_TEXT_RENDER_TYPE;
74#else
75QQuickWindow::TextRenderType QQuickWindowPrivate::textRenderType = QQuickWindow::QtTextRendering;
76#endif
77
79{
81
82public:
84 : m_renderLoop(loop), m_timer(0)
85 {
86 // Allow incubation for 1/3 of a frame.
87 m_incubation_time = qMax(1, int(1000 / QGuiApplication::primaryScreen()->refreshRate()) / 3);
88
89 QAnimationDriver *animationDriver = m_renderLoop->animationDriver();
90 if (animationDriver) {
93 }
94 }
95
96protected:
97 void timerEvent(QTimerEvent *) override
98 {
99 killTimer(m_timer);
100 m_timer = 0;
101 incubate();
102 }
103
105 if (m_timer == 0) {
106 // Wait for a while before processing the next batch. Using a
107 // timer to avoid starvation of system events.
108 m_timer = startTimer(m_incubation_time);
109 }
110 }
111
112public slots:
113 void incubate() {
114 if (m_renderLoop && incubatingObjectCount()) {
115 if (m_renderLoop->interleaveIncubation()) {
116 incubateFor(m_incubation_time);
117 } else {
118 incubateFor(m_incubation_time * 2);
121 }
122 }
123 }
124
126
127protected:
129 {
130 if (count && m_renderLoop && !m_renderLoop->interleaveIncubation())
132 }
133
134private:
135 QPointer<QSGRenderLoop> m_renderLoop;
136 int m_incubation_time;
137 int m_timer;
138};
139
140#if QT_CONFIG(accessibility)
145QAccessibleInterface *QQuickWindow::accessibleRoot() const
146{
147 return QAccessible::queryAccessibleInterface(const_cast<QQuickWindow*>(this));
148}
149#endif
150
151
152/*
153Focus behavior
154==============
155
156Prior to being added to a valid window items can set and clear focus with no
157effect. Only once items are added to a window (by way of having a parent set that
158already belongs to a window) do the focus rules apply. Focus goes back to
159having no effect if an item is removed from a window.
160
161When an item is moved into a new focus scope (either being added to a window
162for the first time, or having its parent changed), if the focus scope already has
163a scope focused item that takes precedence over the item being added. Otherwise,
164the focus of the added tree is used. In the case of a tree of items being
165added to a window for the first time, which may have a conflicted focus state (two
166or more items in one scope having focus set), the same rule is applied item by item -
167thus the first item that has focus will get it (assuming the scope doesn't already
168have a scope focused item), and the other items will have their focus cleared.
169*/
170
172{
173 // child items with ItemObservesViewport can treat the window's content item
174 // as the ultimate viewport: avoid populating SG nodes that fall outside
176}
177
180{
181 Q_D(QQuickWindow);
182 if (d->windowManager)
183 d->windowManager->exposureChanged(this);
184}
185
188{
189 Q_D(QQuickWindow);
190 if (d->contentItem)
191 d->contentItem->setSize(ev->size());
192 if (d->windowManager)
193 d->windowManager->resize(this);
194}
195
198{
199 Q_D(QQuickWindow);
200 if (d->windowManager)
201 d->windowManager->show(this);
202}
203
206{
207 Q_D(QQuickWindow);
208 if (auto da = d->deliveryAgentPrivate())
209 da->handleWindowHidden(this);
210 if (d->windowManager)
211 d->windowManager->hide(this);
212}
213
216{
218 qev.setAccepted(e->isAccepted());
219 emit closing(&qev);
220 e->setAccepted(qev.isAccepted());
221}
222
225{
226 Q_D(QQuickWindow);
227 if (d->contentItem)
228 d->contentItem->setFocus(false, ev->reason());
229}
230
233{
234 Q_D(QQuickWindow);
235 if (d->inDestructor)
236 return;
237 if (d->contentItem)
238 d->contentItem->setFocus(true, ev->reason());
239 if (auto da = d->deliveryAgentPrivate())
240 da->updateFocusItemTransform();
241}
242
243#if QT_CONFIG(im)
244static bool transformDirtyOnItemOrAncestor(const QQuickItem *item)
245{
246 while (item) {
247 if (QQuickItemPrivate::get(item)->dirtyAttributes & (
255 return true;
256 }
257 item = item->parentItem();
258 }
259 return false;
260}
261#endif
262
280{
281 PolishLoopDetector(const QVector<QQuickItem*> &itemsToPolish)
283 {
284 }
285
286 /*
287 * returns true when it detected a likely infinite loop
288 * (suggests it should abort the polish loop)
289 **/
290 bool check(QQuickItem *item, int itemsRemainingBeforeUpdatePolish)
291 {
292 if (itemsToPolish.size() > itemsRemainingBeforeUpdatePolish) {
293 // Detected potential polish loop.
295 if (numPolishLoopsInSequence >= 1000) {
296 // Start to warn about polish loop after 1000 consecutive polish loops
297 if (numPolishLoopsInSequence == 100000) {
298 // We have looped 100,000 times without actually reducing the list of items to
299 // polish, give up for now.
300 // This is not a fix, just a remedy so that the application can be somewhat
301 // responsive.
303 return true;
304 } else if (numPolishLoopsInSequence < 1005) {
305 // Show the 5 next items involved in the polish loop.
306 // (most likely they will be the same 5 items...)
307 QQuickItem *guiltyItem = itemsToPolish.last();
308 qmlWarning(item) << "possible QQuickItem::polish() loop";
309
310 auto typeAndObjectName = [](QQuickItem *item) {
312 QString objName = item->objectName();
313 if (!objName.isNull())
314 return QLatin1String("%1(%2)").arg(typeName, objName);
315 return typeName;
316 };
317
318 qmlWarning(guiltyItem) << typeAndObjectName(guiltyItem)
319 << " called polish() inside updatePolish() of " << typeAndObjectName(item);
320
321 if (numPolishLoopsInSequence == 1004)
322 // Enough warnings. Reset counter in order to speed things up and re-detect
323 // more loops
325 }
326 }
327 } else {
329 }
330 return false;
331 }
332 const QVector<QQuickItem*> &itemsToPolish; // Just a ref to the one in polishItems()
334};
335
337{
338 if (QQuickItemPrivate::get(item)->dirtyAttributes
340 return item;
341 }
342
343 const auto childItems = item->childItems();
344 for (const auto *childItem : childItems) {
345 if (auto *dirtyItem = firstItemWithDirtyChildrenStacking(childItem))
346 return dirtyItem;
347 }
348
349 return nullptr;
350}
351
353{
354 // An item can trigger polish on another item, or itself for that matter,
355 // during its updatePolish() call. Because of this, we cannot simply
356 // iterate through the set, we must continue pulling items out until it
357 // is empty.
358 // In the case where polish is called from updatePolish() either directly
359 // or indirectly, we use a PolishLoopDetector to determine if a warning should
360 // be printed to the user.
361
362 PolishLoopDetector polishLoopDetector(itemsToPolish);
363 while (!itemsToPolish.isEmpty()) {
364 QQuickItem *item = itemsToPolish.takeLast();
366 itemPrivate->polishScheduled = false;
367 const int itemsRemaining = itemsToPolish.size();
368 itemPrivate->updatePolish();
369 item->updatePolish();
370 if (polishLoopDetector.check(item, itemsRemaining) == true)
371 break;
372 }
373
374#if QT_CONFIG(im)
375 if (QQuickItem *focusItem = q_func()->activeFocusItem()) {
376 // If the current focus item, or any of its anchestors, has changed location
377 // inside the window, we need inform IM about it. This to ensure that overlays
378 // such as selection handles will be updated.
379 const bool isActiveFocusItem = (focusItem == QGuiApplication::focusObject());
380 const bool hasImEnabled = focusItem->inputMethodQuery(Qt::ImEnabled).toBool();
381 if (isActiveFocusItem && hasImEnabled && transformDirtyOnItemOrAncestor(focusItem))
383 }
384#endif
385
387 qCDebug(lcQuickWindow) << dirtyItem << "has dirty child stacking order";
389 }
390}
391
400{
401 Q_D(QQuickWindow);
402 if (d->windowManager)
403 d->windowManager->update(this);
404 else if (d->renderControl)
405 QQuickRenderControlPrivate::get(d->renderControl)->update();
406}
407
408static void updatePixelRatioHelper(QQuickItem *item, float pixelRatio)
409{
413 }
414
415 QList <QQuickItem *> items = item->childItems();
416 for (int i = 0; i < items.size(); ++i)
417 updatePixelRatioHelper(items.at(i), pixelRatio);
418}
419
420void QQuickWindow::physicalDpiChanged()
421{
422 Q_D(QQuickWindow);
423 const qreal newPixelRatio = effectiveDevicePixelRatio();
424 if (qFuzzyCompare(newPixelRatio, d->lastReportedItemDevicePixelRatio))
425 return;
426 d->lastReportedItemDevicePixelRatio = newPixelRatio;
427 if (d->contentItem)
428 updatePixelRatioHelper(d->contentItem, newPixelRatio);
429 d->forcePolish();
430}
431
432void QQuickWindow::handleFontDatabaseChanged()
433{
434 Q_D(QQuickWindow);
435 d->pendingFontUpdate = true;
436}
437
439{
441 item->polish();
442 }
443
444 QList <QQuickItem *> items = item->childItems();
445 for (int i=0; i<items.size(); ++i)
447}
448
449void QQuickWindow::handleScreenChanged(QScreen *screen)
450{
451 Q_D(QQuickWindow);
452 Q_UNUSED(screen);
453 d->forcePolish();
454}
455
460{
461 Q_Q(QQuickWindow);
462 if (!q->screen())
463 return;
465}
466
468{
470 item->update();
472
473 QList <QQuickItem *> items = item->childItems();
474 for (int i=0; i<items.size(); ++i)
476}
477
479{
480 if (rhi) {
481 if (rt.owns)
482 delete rt.renderTarget;
483
484 delete res.texture;
485 delete res.renderBuffer;
486 delete res.rpDesc;
487 }
488
489 rt = {};
490 res = {};
491
493 implicitBuffers.reset(rhi);
494
495 if (sw.owns)
496 delete sw.paintDevice;
497
498 sw = {};
499}
500
502{
503 if (rhi) {
504 delete depthStencil;
505 delete depthStencilTexture;
506 delete multisampleTexture;
507 }
508 *this = {};
509}
510
512{
513 QQuickTextInterface *textItem = qobject_cast<QQuickTextInterface *>(item);
514 if (textItem != nullptr)
515 textItem->invalidate();
516
517 QList<QQuickItem *> children = item->childItems();
518 for (QQuickItem *child : children)
519 invalidateFontData(child);
520}
521
523{
524 // resolve() can be expensive when importing an existing native texture, so
525 // it is important to only do it when the QQuickRenderTarget was really changed.
526 if (!redirect.renderTargetDirty)
527 return;
528
529 redirect.renderTargetDirty = false;
530
532
533 if (!QQuickRenderTargetPrivate::get(&customRenderTarget)->resolve(rhi, &redirect.rt)) {
534 qWarning("Failed to set up render target redirection for QQuickWindow");
535 redirect.rt.reset(rhi);
536 }
537}
538
540{
541 // ownership not transferred
542 redirect.commandBuffer = cb;
543}
544
546{
547 Q_Q(QQuickWindow);
548
549 ensureCustomRenderTarget();
550
551 QRhiCommandBuffer *cb = nullptr;
552 if (rhi) {
553 if (redirect.commandBuffer)
554 cb = redirect.commandBuffer;
555 else
556 cb = swapchain->currentFrameCommandBuffer();
557 }
558 context->prepareSync(q->effectiveDevicePixelRatio(), cb, graphicsConfig);
559
560 animationController->beforeNodeSync();
561
562 emit q->beforeSynchronizing();
563 runAndClearJobs(&beforeSynchronizingJobs);
564
565 if (pendingFontUpdate) {
567 invalidateFontData(contentItem);
568 }
569
570 if (!renderer) {
571 forceUpdate(contentItem);
572
573 QSGRootNode *rootNode = new QSGRootNode;
574 rootNode->appendChildNode(QQuickItemPrivate::get(contentItem)->itemNode());
575 const bool useDepth = graphicsConfig.isDepthBufferEnabledFor2D();
578 renderer = context->createRenderer(renderMode);
579 renderer->setRootNode(rootNode);
580 }
581
582 updateDirtyNodes();
583
584 animationController->afterNodeSync();
585
586 renderer->setClearColor(clearColor);
587
588 renderer->setVisualizationMode(visualizationMode);
589
590 if (pendingFontUpdate) {
591 context->invalidateGlyphCaches();
592 pendingFontUpdate = false;
593 }
594
595 emit q->afterSynchronizing();
596 runAndClearJobs(&afterSynchronizingJobs);
597}
598
600{
601 QQuickWindow *w = reinterpret_cast<QQuickWindow *>(ud);
602 emit w->beforeRenderPassRecording();
603}
604
606{
607 QQuickWindow *w = reinterpret_cast<QQuickWindow *>(ud);
608 emit w->afterRenderPassRecording();
609}
610
612{
613 if (rhi) {
614 ensureCustomRenderTarget();
615 if (redirect.rt.rt.renderTarget)
616 return redirect.rt.rt.multiViewCount;
617 }
618
619 // Note that on QRhi level 0 and 1 are often used interchangeably, as both mean
620 // no-multiview. Here in Qt Quick let's always use 1 as the default
621 // (no-multiview), so that higher layers (effects, materials) do not need to
622 // handle both 0 and 1, only 1.
623 return 1;
624}
625
627{
628 if (rhi) {
629 ensureCustomRenderTarget();
630 return redirect.rt.rt.renderTarget;
631 }
632 return nullptr;
633}
634
636{
637 Q_Q(QQuickWindow);
638 if (!renderer)
639 return;
640
641 ensureCustomRenderTarget();
642
643 QSGRenderTarget sgRenderTarget;
644 if (rhi) {
648 if (redirect.rt.rt.renderTarget) {
649 rt = redirect.rt.rt.renderTarget;
650 rp = rt->renderPassDescriptor();
651 if (!rp) {
652 qWarning("Custom render target is set but no renderpass descriptor has been provided.");
653 return;
654 }
655 cb = redirect.commandBuffer;
656 if (!cb) {
657 qWarning("Custom render target is set but no command buffer has been provided.");
658 return;
659 }
660 } else {
661 if (!swapchain) {
662 qWarning("QQuickWindow: No render target (neither swapchain nor custom target was provided)");
663 return;
664 }
665 rt = swapchain->currentFrameRenderTarget();
666 rp = rpDescForSwapchain;
667 cb = swapchain->currentFrameCommandBuffer();
668 }
669 sgRenderTarget = QSGRenderTarget(rt, rp, cb);
670 sgRenderTarget.multiViewCount = multiViewCount();
671 } else {
672 sgRenderTarget = QSGRenderTarget(redirect.rt.sw.paintDevice);
673 }
674
675 context->beginNextFrame(renderer,
676 sgRenderTarget,
677 emitBeforeRenderPassRecording,
678 emitAfterRenderPassRecording,
679 q);
680
681 animationController->advance();
682 emit q->beforeRendering();
683 runAndClearJobs(&beforeRenderingJobs);
684
685 const qreal devicePixelRatio = q->effectiveDevicePixelRatio();
686 QSize pixelSize;
687 if (redirect.rt.rt.renderTarget)
688 pixelSize = redirect.rt.rt.renderTarget->pixelSize();
689 else if (redirect.rt.sw.paintDevice)
690 pixelSize = QSize(redirect.rt.sw.paintDevice->width(), redirect.rt.sw.paintDevice->height());
691 else if (rhi)
692 pixelSize = swapchain->currentPixelSize();
693 else // software or other backend
694 pixelSize = q->size() * devicePixelRatio;
695
696 renderer->setDevicePixelRatio(devicePixelRatio);
697 renderer->setDeviceRect(QRect(QPoint(0, 0), pixelSize));
698 renderer->setViewportRect(QRect(QPoint(0, 0), pixelSize));
699
700 QSGAbstractRenderer::MatrixTransformFlags matrixFlags;
701 bool flipY = rhi ? !rhi->isYUpInNDC() : false;
702 if (!customRenderTarget.isNull() && customRenderTarget.mirrorVertically())
703 flipY = !flipY;
704 if (flipY)
706
707 const QRectF rect(QPointF(0, 0), pixelSize / devicePixelRatio);
708 renderer->setProjectionMatrixToRect(rect, matrixFlags, rhi && !rhi->isYUpInNDC());
709
710 context->renderNextFrame(renderer);
711
712 emit q->afterRendering();
713 runAndClearJobs(&afterRenderingJobs);
714
715 context->endNextFrame(renderer);
716
717 if (renderer && renderer->hasVisualizationModeWithContinuousUpdate()) {
718 // For the overdraw visualizer. This update is not urgent so avoid a
719 // direct update() call, this is only here to keep the overdraw
720 // visualization box rotating even when the scene is static.
721 QCoreApplication::postEvent(q, new QEvent(QEvent::Type(FullUpdateRequest)));
722 }
723}
724
726 : contentItem(nullptr)
727 , dirtyItemList(nullptr)
728 , lastReportedItemDevicePixelRatio(0)
731 , windowManager(nullptr)
732 , renderControl(nullptr)
733 , clearColor(Qt::white)
734 , persistentGraphics(true)
735 , persistentSceneGraph(true)
736 , inDestructor(false)
737 , incubationController(nullptr)
738 , hasActiveSwapchain(false)
739 , hasRenderableSwapchain(false)
740 , swapchainJustBecameRenderable(false)
741 , updatesEnabled(true)
742{
743}
744
746{
747 inDestructor = true;
748 redirect.rt.reset(rhi);
749 if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
750 service->removeWindow(q_func());
751 deliveryAgent = nullptr;
752}
753
766
771
773{
774 Q_Q(QQuickWindow);
775 if (auto root = q->contentItem()) {
776 for (auto &&child: root->childItems()) {
778 }
779 }
780}
781
783{
784 q_ptr = c;
785
786
787 Q_Q(QQuickWindow);
788
790 contentItem->setObjectName(q->objectName());
794 contentItemPrivate->window = q;
795 contentItemPrivate->windowRefCount = 1;
796 contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
797 contentItem->setSize(q->size());
799
800 visualizationMode = qgetenv("QSG_VISUALIZE");
801 renderControl = control;
802 if (renderControl)
804
805 if (!renderControl)
807
809
812 q,
813 &QQuickWindow::handleFontDatabaseChanged);
814
815 if (q->screen()) {
816 lastReportedItemDevicePixelRatio = q->effectiveDevicePixelRatio();
817 }
818
819 QSGContext *sg;
820 if (renderControl) {
822 sg = renderControlPriv->sg;
823 context = renderControlPriv->rc;
824 } else {
828 }
829
831 q->setFormat(sg->defaultSurfaceFormat());
832 // When using Vulkan, associating a scenegraph-managed QVulkanInstance with
833 // the window (but only when not using renderControl) is deferred to
834 // QSGRhiSupport::createRhi(). This allows applications to set up their own
835 // QVulkanInstance and set that on the window, if they wish to.
836
838
841 QObject::connect(context, &QSGRenderContext::invalidated, q, &QQuickWindow::cleanupSceneGraph, Qt::DirectConnection);
842
843 QObject::connect(q, &QQuickWindow::focusObjectChanged, q, &QQuickWindow::activeFocusItemChanged);
844 QObject::connect(q, &QQuickWindow::screenChanged, q, &QQuickWindow::handleScreenChanged);
845 QObject::connect(qApp, &QGuiApplication::applicationStateChanged, q, &QQuickWindow::handleApplicationStateChanged);
846 QObject::connect(q, &QQuickWindow::frameSwapped, q, &QQuickWindow::runJobsAfterSwap, Qt::DirectConnection);
847
848 if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
849 service->addWindow(q);
850}
851
852void QQuickWindow::handleApplicationStateChanged(Qt::ApplicationState state)
853{
854 Q_D(QQuickWindow);
855 if (state != Qt::ApplicationActive && d->contentItem) {
856 auto da = d->deliveryAgentPrivate();
857 Q_ASSERT(da);
858 da->handleWindowDeactivate(this);
859 }
860}
861
877
879{
880 Q_Q(QQuickWindow);
881 q->maybeUpdate();
882}
883
888QQuickItem *QQuickWindow::mouseGrabberItem() const
889{
890 Q_D(const QQuickWindow);
891 auto da = const_cast<QQuickWindowPrivate *>(d)->deliveryAgentPrivate();
892 Q_ASSERT(da);
893 // The normal use case is to call this function while an event is being delivered;
894 // but if the caller knows about the event, it should call QPointerEvent::exclusiveGrabber() instead.
895 if (auto epd = da->mousePointData())
896 return qmlobject_cast<QQuickItem *>(epd->exclusiveGrabber);
897
898 if (Q_LIKELY(d->deliveryAgentPrivate()->eventsInDelivery.isEmpty()))
899 // mousePointData() checked that already: it's one reason epd can be null
900 qCDebug(lcMouse, "mouse grabber ambiguous: no event is currently being delivered");
901 // If no event is being delivered, we can return "the mouse" grabber,
902 // but in general there could be more than one mouse, could be only a touchscreen etc.
903 // That's why this function is obsolete.
905 firstPointExclusiveGrabber());
906}
907
909{
910 Q_Q(QQuickWindow);
911
914 q->maybeUpdate();
915}
916
1131QQuickWindow::QQuickWindow(QWindow *parent)
1132 : QQuickWindow(*new QQuickWindowPrivate, parent)
1133{
1134}
1135
1136
1137
1141QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent)
1142 : QWindow(dd, parent)
1143{
1144 Q_D(QQuickWindow);
1145 d->init(this);
1146}
1147
1155QQuickWindow::QQuickWindow(QQuickRenderControl *control)
1157{
1158 Q_D(QQuickWindow);
1159 d->init(this, control);
1160}
1161
1165QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control)
1166 : QWindow(dd, nullptr)
1167{
1168 Q_D(QQuickWindow);
1169 d->init(this, control);
1170}
1171
1176{
1177 Q_D(QQuickWindow);
1178 d->inDestructor = true;
1179 if (d->renderControl) {
1180 QQuickRenderControlPrivate::get(d->renderControl)->windowDestroyed();
1181 } else if (d->windowManager) {
1182 d->windowManager->removeWindow(this);
1183 d->windowManager->windowDestroyed(this);
1184 }
1185
1186 delete d->incubationController; d->incubationController = nullptr;
1187 QQuickRootItem *root = d->contentItem;
1188 d->contentItem = nullptr;
1189 root->setParent(nullptr); // avoid QChildEvent delivery during deletion
1190 delete root;
1191 d->deliveryAgent = nullptr; // avoid forwarding events there during destruction
1192
1193
1194 {
1195 const std::lock_guard locker(d->renderJobMutex);
1196 qDeleteAll(std::exchange(d->beforeSynchronizingJobs, {}));
1197 qDeleteAll(std::exchange(d->afterSynchronizingJobs, {}));
1198 qDeleteAll(std::exchange(d->beforeRenderingJobs, {}));
1199 qDeleteAll(std::exchange(d->afterRenderingJobs, {}));;
1200 qDeleteAll(std::exchange(d->afterSwapJobs, {}));
1201 }
1202
1203 // It is important that the pixmap cache is cleaned up during shutdown.
1204 // Besides playing nice, this also solves a practical problem that
1205 // QQuickTextureFactory implementations in other libraries need
1206 // have their destructors loaded while they the library is still
1207 // loaded into memory.
1209}
1210
1211#if QT_CONFIG(quick_shadereffect)
1213#endif
1214
1242{
1243 Q_D(QQuickWindow);
1244 if (d->windowManager)
1245 d->windowManager->releaseResources(this);
1247#if QT_CONFIG(quick_shadereffect)
1249#endif
1250}
1251
1252
1253
1282void QQuickWindow::setPersistentGraphics(bool persistent)
1283{
1284 Q_D(QQuickWindow);
1285 d->persistentGraphics = persistent;
1286}
1287
1288
1289
1299bool QQuickWindow::isPersistentGraphics() const
1300{
1301 Q_D(const QQuickWindow);
1302 return d->persistentGraphics;
1303}
1304
1305
1306
1329void QQuickWindow::setPersistentSceneGraph(bool persistent)
1330{
1331 Q_D(QQuickWindow);
1332 d->persistentSceneGraph = persistent;
1333}
1334
1335
1336
1345bool QQuickWindow::isPersistentSceneGraph() const
1346{
1347 Q_D(const QQuickWindow);
1348 return d->persistentSceneGraph;
1349}
1350
1369{
1370 Q_D(const QQuickWindow);
1371
1372 return d->contentItem;
1373}
1374
1384{
1385 Q_D(const QQuickWindow);
1386 auto da = d->deliveryAgentPrivate();
1387 Q_ASSERT(da);
1388 return da->activeFocusItem;
1389}
1390
1396{
1397 Q_D(const QQuickWindow);
1398 auto da = d->deliveryAgentPrivate();
1399 Q_ASSERT(da);
1400 if (!d->inDestructor && da->activeFocusItem)
1401 return da->activeFocusItem;
1402 return const_cast<QQuickWindow*>(this);
1403}
1404
1418{
1419 if (pointerEvent->isEndEvent()
1423 if (pointerEvent->isSinglePointEvent()) {
1424 if (static_cast<QSinglePointEvent *>(pointerEvent)->buttons() == Qt::NoButton) {
1425 auto &firstPt = pointerEvent->point(0);
1426 pointerEvent->setExclusiveGrabber(firstPt, nullptr);
1427 pointerEvent->clearPassiveGrabbers(firstPt);
1428 }
1429 } else {
1430 for (auto &point : pointerEvent->points()) {
1431 if (point.state() == QEventPoint::State::Released) {
1432 pointerEvent->setExclusiveGrabber(point, nullptr);
1433 pointerEvent->clearPassiveGrabbers(point);
1434 }
1435 }
1436 }
1437 }
1438}
1439
1442{
1443 Q_D(QQuickWindow);
1444
1445 // bypass QWindow::event dispatching of input events: deliveryAgent takes care of it
1446 QQuickDeliveryAgent *da = d->deliveryAgent;
1447 if (event->isPointerEvent()) {
1448 /*
1449 We can't bypass the virtual functions like mousePressEvent() tabletEvent() etc.,
1450 for the sake of code that subclasses QQuickWindow and overrides them, even though
1451 we no longer need them as entry points for Qt Quick event delivery.
1452 So dispatch to them now, ahead of normal delivery, and stop them from calling
1453 back into this function if they were called from here (avoid recursion).
1454 It could also be that user code expects them to work as entry points, too;
1455 in that case, windowEventDispatch _won't_ be set, so the event comes here and
1456 we'll dispatch it further below.
1457 */
1458 if (d->windowEventDispatch)
1459 return false;
1460 {
1461 const bool wasAccepted = event->isAccepted();
1462 QBoolBlocker windowEventDispatchGuard(d->windowEventDispatch, true);
1463 qCDebug(lcPtr) << "dispatching to window functions in case of override" << event;
1465 if (event->isAccepted() && !wasAccepted)
1466 return true;
1467 }
1468 /*
1469 QQuickWindow does not override touchEvent(). If the application has a subclass
1470 of QQuickWindow which allows the event to remain accepted, it means they want
1471 to stop propagation here, so return early (below). But otherwise we will call
1472 QWindow::touchEvent(), which will ignore(); in that case, we need to continue
1473 with the usual delivery below, so we need to undo the ignore().
1474 */
1475 auto pe = static_cast<QPointerEvent *>(event);
1477 event->accept();
1478 // end of dispatch to user-overridden virtual window functions
1479
1480 /*
1481 When delivering update and release events to existing grabbers,
1482 use the subscene delivery agent, if any. A possible scenario:
1483 1) Two touchpoints pressed on the main window: QQuickWindowPrivate::deliveryAgent delivers to QQuick3DViewport,
1484 which does picking and finds two subscenes ("root" Items mapped onto two different 3D objects) to deliver it to.
1485 2) The QTouchEvent is split up so that each subscene sees points relevant to it.
1486 3) During delivery to either subscene, an item in the subscene grabs.
1487 4) The user moves finger(s) generating a move event: the correct grabber item needs to get the update
1488 via the same subscene delivery agent from which it got the press, so that the coord transform will be done properly.
1489 5) Likewise with the touchpoint releases.
1490 With single-point events (mouse, or only one finger) it's simplified: there can only be one subscene of interest;
1491 for (pt : pe->points()) would only iterate once, so we might as well skip that logic.
1492 */
1493 if (pe->pointCount()) {
1494 const bool synthMouse = QQuickDeliveryAgentPrivate::isSynthMouse(pe);
1496 bool ret = false;
1497 // Split up the multi-point event according to the relevant QQuickDeliveryAgent that should deliver to each existing grabber
1498 // but send ungrabbed points to d->deliveryAgent()
1499 QFlatMap<QQuickDeliveryAgent*, QList<QEventPoint>> deliveryAgentsNeedingPoints;
1500 QEventPoint::States eventStates;
1501
1502 auto insert = [&](QQuickDeliveryAgent *ptda, const QEventPoint &pt) {
1503 if (pt.state() == QEventPoint::Pressed && !synthMouse)
1504 pe->clearPassiveGrabbers(pt);
1505 auto &ptList = deliveryAgentsNeedingPoints[ptda];
1506 auto idEquals = [](auto id) { return [id] (const auto &e) { return e.id() == id; }; };
1507 if (std::none_of(ptList.cbegin(), ptList.cend(), idEquals(pt.id())))
1508 ptList.append(pt);
1509 };
1510
1511 for (const auto &pt : pe->points()) {
1512 eventStates |= pt.state();
1513 auto epd = QPointingDevicePrivate::get(const_cast<QPointingDevice*>(pe->pointingDevice()))->queryPointById(pt.id());
1514 Q_ASSERT(epd);
1515 bool foundAgent = false;
1516 if (!epd->exclusiveGrabber.isNull() && !epd->exclusiveGrabberContext.isNull()) {
1517 if (auto ptda = qobject_cast<QQuickDeliveryAgent *>(epd->exclusiveGrabberContext.data())) {
1518 insert(ptda, pt);
1519 qCDebug(lcPtr) << pe->type() << "point" << pt.id() << pt.state()
1520 << "@" << pt.scenePosition() << "will be re-delivered via known grabbing agent" << ptda << "to" << epd->exclusiveGrabber.data();
1521 foundAgent = true;
1522 }
1523 }
1524 for (auto pgda : epd->passiveGrabbersContext) {
1525 if (auto ptda = qobject_cast<QQuickDeliveryAgent *>(pgda.data())) {
1526 insert(ptda, pt);
1527 qCDebug(lcPtr) << pe->type() << "point" << pt.id() << pt.state()
1528 << "@" << pt.scenePosition() << "will be re-delivered via known passive-grabbing agent" << ptda;
1529 foundAgent = true;
1530 }
1531 }
1532 // fallback: if we didn't find remembered/known grabber agent(s), expect the root DA to handle it
1533 if (!foundAgent)
1534 insert(da, pt);
1535 }
1536 for (auto daAndPoints : deliveryAgentsNeedingPoints) {
1537 if (pe->pointCount() > 1) {
1539 // if all points have the same state, set the event type accordingly
1540 QEvent::Type eventType = pe->type();
1541 switch (eventStates) {
1543 eventType = QEvent::TouchBegin;
1544 break;
1546 eventType = QEvent::TouchEnd;
1547 break;
1548 default:
1549 eventType = QEvent::TouchUpdate;
1550 break;
1551 }
1552 // Make a new touch event for the subscene, the same way QQuickItemPrivate::localizedTouchEvent() does it
1553 QMutableTouchEvent te(eventType, pe->pointingDevice(), pe->modifiers(), daAndPoints.second);
1554 te.setTimestamp(pe->timestamp());
1555 te.accept();
1556 qCDebug(lcTouch) << daAndPoints.first << "shall now receive" << &te;
1557 ret = daAndPoints.first->event(&te) || ret;
1558 } else {
1559 qCDebug(lcPtr) << daAndPoints.first << "shall now receive" << pe;
1560 ret = daAndPoints.first->event(pe) || ret;
1561 }
1562 }
1563
1564 if (ret)
1565 return true;
1566 } else if (!synthMouse) {
1567 // clear passive grabbers unless it's a system synth-mouse event
1568 // QTBUG-104890: Windows sends synth mouse events (which should be ignored) after touch events
1569 for (const auto &pt : pe->points()) {
1570 if (pt.state() == QEventPoint::Pressed)
1571 pe->clearPassiveGrabbers(pt);
1572 }
1573 }
1574 }
1575
1576 // If it has no points, it's probably a TouchCancel, and DeliveryAgent needs to handle it.
1577 // If we didn't handle it in the block above, handle it now.
1578 // TODO should we deliver to all DAs at once then, since we don't know which one should get it?
1579 // or fix QTBUG-90851 so that the event always has points?
1580 qCDebug(lcHoverTrace) << this << "some sort of event" << event;
1581 bool ret = (da && da->event(event));
1582
1583 d->clearGrabbers(pe);
1584
1585 if (ret)
1586 return true;
1587 } else if (event->isInputEvent()) {
1588 if (da && da->event(event))
1589 return true;
1590 }
1591
1592 switch (event->type()) {
1593 // a few more types that are not QInputEvents, but QQuickDeliveryAgent needs to handle them anyway
1595 case QEvent::Enter:
1596 case QEvent::Leave:
1599#if QT_CONFIG(quick_draganddrop)
1600 case QEvent::DragEnter:
1601 case QEvent::DragLeave:
1602 case QEvent::DragMove:
1603 case QEvent::Drop:
1604#endif
1605 if (d->inDestructor)
1606 return false;
1607 if (da && da->event(event))
1608 return true;
1609 break;
1612 if (d->contentItem)
1613 QCoreApplication::sendEvent(d->contentItem, event);
1614 break;
1616 if (d->windowManager)
1617 d->windowManager->handleUpdateRequest(this);
1618 break;
1620 if ((static_cast<QPlatformSurfaceEvent *>(event))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) {
1621 // Ensure that the rendering thread is notified before
1622 // the QPlatformWindow is destroyed.
1623 if (d->windowManager)
1624 d->windowManager->hide(this);
1625 }
1626 break;
1628 if (auto da = d->deliveryAgentPrivate())
1629 da->handleWindowDeactivate(this);
1630 Q_FALLTHROUGH();
1632 if (d->contentItem)
1633 QCoreApplication::sendEvent(d->contentItem, event);
1634 break;
1636 d->inheritPalette(QGuiApplication::palette());
1637 if (d->contentItem)
1638 QCoreApplication::sendEvent(d->contentItem, event);
1639 break;
1641 physicalDpiChanged();
1642 break;
1644 auto *childEvent = static_cast<QChildWindowEvent*>(event);
1645 auto *childWindow = childEvent->child();
1646 qCDebug(lcQuickWindow) << "Child window" << childWindow << "added to" << this;
1647 if (childWindow->handle()) {
1648 // The reparenting has already resulted in the native window
1649 // being added to its parent, on top of all other windows. We need
1650 // to do a synchronous re-stacking of the windows here, to avoid
1651 // leaving the window in the wrong position while waiting for the
1652 // asynchronous callback to QQuickWindow::polishItems().
1653 d->updateChildWindowStackingOrder();
1654 } else {
1655 qCDebug(lcQuickWindow) << "No platform window yet."
1656 << "Deferring child window stacking until surface creation";
1657 }
1658 break;
1659 }
1660 default:
1661 break;
1662 }
1663
1665 update();
1667 d->windowManager->handleContextCreationFailure(this);
1668
1669 if (event->isPointerEvent())
1670 return true;
1671 else
1672 return QWindow::event(event);
1673}
1674
1676{
1677 Q_Q(QQuickWindow);
1678
1679 if (!item) {
1680 qCDebug(lcQuickWindow) << "Updating child window stacking order for" << q;
1681 item = contentItem;
1682 }
1683 auto *itemPrivate = QQuickItemPrivate::get(item);
1684 const auto paintOrderChildItems = itemPrivate->paintOrderChildItems();
1685 for (auto *child : paintOrderChildItems) {
1686 if (auto *windowContainer = qobject_cast<QQuickWindowContainer*>(child)) {
1687 auto *window = windowContainer->containedWindow();
1688 if (!window) {
1689 qCDebug(lcQuickWindow) << windowContainer << "has no contained window yet";
1690 continue;
1691 }
1692 if (window->parent() != q) {
1693 qCDebug(lcQuickWindow) << window << "is not yet child of this window";
1694 continue;
1695 }
1696 qCDebug(lcQuickWindow) << "Raising" << window << "owned by" << windowContainer;
1697 window->raise();
1698 }
1699
1701 }
1702}
1703
1706{
1707 Q_D(QQuickWindow);
1708 if (d->windowEventDispatch)
1709 return;
1710 auto da = d->deliveryAgentPrivate();
1711 Q_ASSERT(da);
1712 da->deliverKeyEvent(e);
1713}
1714
1717{
1718 Q_D(QQuickWindow);
1719 if (d->windowEventDispatch)
1720 return;
1721 auto da = d->deliveryAgentPrivate();
1722 Q_ASSERT(da);
1723 da->deliverKeyEvent(e);
1724}
1725
1726#if QT_CONFIG(wheelevent)
1728void QQuickWindow::wheelEvent(QWheelEvent *event)
1729{
1730 Q_D(QQuickWindow);
1731 if (d->windowEventDispatch)
1732 return;
1733 auto da = d->deliveryAgentPrivate();
1734 Q_ASSERT(da);
1735 da->deliverSinglePointEventUntilAccepted(event);
1736}
1737#endif // wheelevent
1738
1739#if QT_CONFIG(tabletevent)
1741void QQuickWindow::tabletEvent(QTabletEvent *event)
1742{
1743 Q_D(QQuickWindow);
1744 if (d->windowEventDispatch)
1745 return;
1746 auto da = d->deliveryAgentPrivate();
1747 Q_ASSERT(da);
1748 da->deliverPointerEvent(event);
1749}
1750#endif // tabletevent
1751
1754{
1755 Q_D(QQuickWindow);
1756 if (d->windowEventDispatch)
1757 return;
1758 auto da = d->deliveryAgentPrivate();
1759 Q_ASSERT(da);
1760 da->handleMouseEvent(event);
1761}
1764{
1765 Q_D(QQuickWindow);
1766 if (d->windowEventDispatch)
1767 return;
1768 auto da = d->deliveryAgentPrivate();
1769 Q_ASSERT(da);
1770 da->handleMouseEvent(event);
1771}
1774{
1775 Q_D(QQuickWindow);
1776 if (d->windowEventDispatch)
1777 return;
1778 auto da = d->deliveryAgentPrivate();
1779 Q_ASSERT(da);
1780 da->handleMouseEvent(event);
1781}
1784{
1785 Q_D(QQuickWindow);
1786 if (d->windowEventDispatch)
1787 return;
1788 auto da = d->deliveryAgentPrivate();
1789 Q_ASSERT(da);
1790 da->handleMouseEvent(event);
1791}
1792
1793#if QT_CONFIG(cursor)
1794void QQuickWindowPrivate::updateCursor(const QPointF &scenePos, QQuickItem *rootItem)
1795{
1796 Q_Q(QQuickWindow);
1797 if (!rootItem)
1799 auto cursorItemAndHandler = findCursorItemAndHandler(rootItem, scenePos);
1800 if (cursorItem != cursorItemAndHandler.first || cursorHandler != cursorItemAndHandler.second ||
1801 (cursorItemAndHandler.second && QQuickPointerHandlerPrivate::get(cursorItemAndHandler.second)->cursorDirty)) {
1803 QWindow *window = renderWindow ? renderWindow : q;
1804 cursorItem = cursorItemAndHandler.first;
1805 cursorHandler = cursorItemAndHandler.second;
1806 if (cursorHandler)
1807 QQuickPointerHandlerPrivate::get(cursorItemAndHandler.second)->cursorDirty = false;
1808 if (cursorItem) {
1809 const auto cursor = QQuickItemPrivate::get(cursorItem)->effectiveCursor(cursorHandler);
1810 qCDebug(lcHoverTrace) << "setting cursor" << cursor << "from" << cursorHandler << "or" << cursorItem;
1811 window->setCursor(cursor);
1812 } else {
1813 qCDebug(lcHoverTrace) << "unsetting cursor";
1814 window->unsetCursor();
1815 }
1816 }
1817}
1818
1819QPair<QQuickItem*, QQuickPointerHandler*> QQuickWindowPrivate::findCursorItemAndHandler(QQuickItem *item, const QPointF &scenePos) const
1820{
1822 if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
1823 QPointF p = item->mapFromScene(scenePos);
1824 if (!item->contains(p))
1825 return {nullptr, nullptr};
1826 }
1827
1828 if (itemPrivate->subtreeCursorEnabled) {
1829 QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
1830 for (int ii = children.size() - 1; ii >= 0; --ii) {
1831 QQuickItem *child = children.at(ii);
1832 if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
1833 continue;
1834 auto ret = findCursorItemAndHandler(child, scenePos);
1835 if (ret.first)
1836 return ret;
1837 }
1838 if (itemPrivate->hasCursorHandler) {
1839 if (auto handler = itemPrivate->effectiveCursorHandler()) {
1840 if (handler->parentContains(scenePos))
1841 return {item, handler};
1842 }
1843 }
1844 if (itemPrivate->hasCursor) {
1845 QPointF p = item->mapFromScene(scenePos);
1846 if (item->contains(p))
1847 return {item, nullptr};
1848 }
1849 }
1850
1851 return {nullptr, nullptr};
1852}
1853#endif
1854
1856{
1857 if (auto da = deliveryAgentPrivate())
1858 da->clearFocusObject();
1859}
1860
1862{
1863 if (!contentItem)
1864 return;
1865
1866 QQuickItem *newFocusItem = nullptr;
1867 switch (target) {
1868 case FocusTarget::First:
1869 case FocusTarget::Last: {
1870 const bool forward = (target == FocusTarget::First);
1872 if (newFocusItem) {
1873 const auto *itemPriv = QQuickItemPrivate::get(newFocusItem);
1874 if (itemPriv->subFocusItem && itemPriv->flags & QQuickItem::ItemIsFocusScope)
1875 clearFocusInScope(newFocusItem, itemPriv->subFocusItem, reason);
1876 }
1877 break;
1878 }
1879 case FocusTarget::Next:
1880 case FocusTarget::Prev: {
1881 const auto da = deliveryAgentPrivate();
1882 Q_ASSERT(da);
1883 QQuickItem *focusItem = da->focusTargetItem() ? da->focusTargetItem() : contentItem;
1884 bool forward = (target == FocusTarget::Next);
1885 newFocusItem = QQuickItemPrivate::nextPrevItemInTabFocusChain(focusItem, forward);
1886 break;
1887 }
1888 default:
1889 break;
1890 }
1891
1892 if (newFocusItem)
1893 newFocusItem->forceActiveFocus(reason);
1894}
1895
1920void QQuickWindowPrivate::data_append(QQmlListProperty<QObject> *property, QObject *o)
1921{
1922 if (!o)
1923 return;
1924 QQuickWindow *that = static_cast<QQuickWindow *>(property->object);
1925 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(that->contentItem())->data();
1926 itemProperty.append(&itemProperty, o);
1927}
1928
1930{
1931 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1932 if (!win || !win->contentItem() || !QQuickItemPrivate::get(win->contentItem())->data().count)
1933 return 0;
1934 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
1935 return itemProperty.count(&itemProperty);
1936}
1937
1939{
1940 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1941 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
1942 return itemProperty.at(&itemProperty, i);
1943}
1944
1945void QQuickWindowPrivate::data_clear(QQmlListProperty<QObject> *property)
1946{
1947 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1948 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
1949 itemProperty.clear(&itemProperty);
1950}
1951
1953{
1954 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1955 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
1956 itemProperty.replace(&itemProperty, i, o);
1957}
1958
1959void QQuickWindowPrivate::data_removeLast(QQmlListProperty<QObject> *property)
1960{
1961 QQuickWindow *win = static_cast<QQuickWindow*>(property->object);
1962 QQmlListProperty<QObject> itemProperty = QQuickItemPrivate::get(win->contentItem())->data();
1963 itemProperty.removeLast(&itemProperty);
1964}
1965
1967{
1968 Q_Q(const QQuickWindow);
1969 return ((q->isExposed() && q->isVisible())) && q->geometry().isValid();
1970}
1971
1973 QString *translatedMessage,
1974 QString *untranslatedMessage)
1975{
1976 const char msg[] = QT_TRANSLATE_NOOP("QQuickWindow",
1977 "Failed to initialize graphics backend for %1.");
1978 *translatedMessage = QQuickWindow::tr(msg).arg(backendName);
1979 *untranslatedMessage = QString::fromLatin1(msg).arg(backendName);
1980}
1981
1983{
1984 qDeleteAll(std::exchange(cleanupNodeList, {}));
1985}
1986
1988{
1990 if (p->itemNodeInstance) {
1991 delete p->itemNodeInstance;
1992 p->itemNodeInstance = nullptr;
1993
1994 if (p->extra.isAllocated()) {
1995 p->extra->opacityNode = nullptr;
1996 p->extra->clipNode = nullptr;
1997 p->extra->rootNode = nullptr;
1998 }
1999
2000 p->paintNode = nullptr;
2001
2003 }
2004
2005 // Qt 7: Make invalidateSceneGraph a virtual member of QQuickItem
2006 if (p->flags & QQuickItem::ItemHasContents) {
2007 const QMetaObject *mo = item->metaObject();
2008 int index = mo->indexOfSlot("invalidateSceneGraph()");
2009 if (index >= 0) {
2010 const QMetaMethod &method = mo->method(index);
2011 // Skip functions named invalidateSceneGraph() in QML items.
2012 if (strstr(method.enclosingMetaObject()->className(), "_QML_") == nullptr)
2014 }
2015 }
2016
2017 for (int ii = 0; ii < p->childItems.size(); ++ii)
2018 cleanupNodesOnShutdown(p->childItems.at(ii));
2019}
2020
2021// This must be called from the render thread, with the main thread frozen
2032
2034{
2035 qCDebug(lcDirty) << "QQuickWindowPrivate::updateDirtyNodes():";
2036
2037 cleanupNodes();
2038
2039 QQuickItem *updateList = dirtyItemList;
2040 dirtyItemList = nullptr;
2041 if (updateList) QQuickItemPrivate::get(updateList)->prevDirtyItem = &updateList;
2042
2043 while (updateList) {
2044 QQuickItem *item = updateList;
2046 itemPriv->removeFromDirtyList();
2047
2048 qCDebug(lcDirty) << " QSGNode:" << item << qPrintable(itemPriv->dirtyToString());
2050 }
2051}
2052
2054{
2055 const QList<QQuickItem *> childItems = d->paintOrderChildItems();
2056 QQuickItem *before = nullptr;
2057 for (int i=0; i<childItems.size(); ++i) {
2058 QQuickItemPrivate *dd = QQuickItemPrivate::get(childItems.at(i));
2059 // Perform the same check as the in fetchNextNode below.
2060 if (dd->z() < 0 && (dd->explicitVisible || (dd->extra.isAllocated() && dd->extra->effectRefCount)))
2061 before = childItems.at(i);
2062 else
2063 break;
2064 }
2065 return Q_UNLIKELY(before) ? QQuickItemPrivate::get(before)->itemNode() : nullptr;
2066}
2067
2068static QSGNode *fetchNextNode(QQuickItemPrivate *itemPriv, int &ii, bool &returnedPaintNode)
2069{
2070 QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
2071
2072 for (; ii < orderedChildren.size() && orderedChildren.at(ii)->z() < 0; ++ii) {
2073 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
2074 if (!childPrivate->explicitVisible &&
2075 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2076 continue;
2077
2078 ii++;
2079 return childPrivate->itemNode();
2080 }
2081
2082 if (itemPriv->paintNode && !returnedPaintNode) {
2083 returnedPaintNode = true;
2084 return itemPriv->paintNode;
2085 }
2086
2087 for (; ii < orderedChildren.size(); ++ii) {
2088 QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
2089 if (!childPrivate->explicitVisible &&
2090 (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
2091 continue;
2092
2093 ii++;
2094 return childPrivate->itemNode();
2095 }
2096
2097 return nullptr;
2098}
2099
2101{
2103 quint32 dirty = itemPriv->dirtyAttributes;
2104 itemPriv->dirtyAttributes = 0;
2105
2107 (dirty & QQuickItemPrivate::Size && itemPriv->origin() != QQuickItem::TopLeft &&
2108 (itemPriv->scale() != 1. || itemPriv->rotation() != 0.))) {
2109
2111
2112 if (itemPriv->x != 0. || itemPriv->y != 0.)
2113 matrix.translate(itemPriv->x, itemPriv->y);
2114
2115 for (int ii = itemPriv->transforms.size() - 1; ii >= 0; --ii)
2116 itemPriv->transforms.at(ii)->applyTo(&matrix);
2117
2118 if (itemPriv->scale() != 1. || itemPriv->rotation() != 0.) {
2119 QPointF origin = item->transformOriginPoint();
2120 matrix.translate(origin.x(), origin.y());
2121 if (itemPriv->scale() != 1.)
2122 matrix.scale(itemPriv->scale(), itemPriv->scale());
2123 if (itemPriv->rotation() != 0.)
2124 matrix.rotate(itemPriv->rotation(), 0, 0, 1);
2125 matrix.translate(-origin.x(), -origin.y());
2126 }
2127
2128 itemPriv->itemNode()->setMatrix(matrix);
2129 }
2130
2131 const bool clipEffectivelyChanged = dirty & (QQuickItemPrivate::Clip | QQuickItemPrivate::Window);
2132 if (clipEffectivelyChanged) {
2133 QSGNode *parent = itemPriv->opacityNode() ? (QSGNode *)itemPriv->opacityNode()
2134 : (QSGNode *)itemPriv->itemNode();
2135 QSGNode *child = itemPriv->rootNode();
2136
2137 if (bool initializeClipNode = item->clip() && itemPriv->clipNode() == nullptr;
2138 initializeClipNode) {
2139 QQuickDefaultClipNode *clip = new QQuickDefaultClipNode(item->clipRect());
2140 itemPriv->extra.value().clipNode = clip;
2141 clip->update();
2142
2143 if (!child) {
2144 parent->reparentChildNodesTo(clip);
2145 parent->appendChildNode(clip);
2146 } else {
2147 parent->removeChildNode(child);
2148 clip->appendChildNode(child);
2149 parent->appendChildNode(clip);
2150 }
2151
2152 } else if (bool updateClipNode = item->clip() && itemPriv->clipNode() != nullptr;
2153 updateClipNode) {
2154 QQuickDefaultClipNode *clip = itemPriv->clipNode();
2155 clip->setClipRect(item->clipRect());
2156 clip->update();
2157 } else if (bool removeClipNode = !item->clip() && itemPriv->clipNode() != nullptr;
2158 removeClipNode) {
2159 QQuickDefaultClipNode *clip = itemPriv->clipNode();
2160 parent->removeChildNode(clip);
2161 if (child) {
2162 clip->removeChildNode(child);
2163 parent->appendChildNode(child);
2164 } else {
2166 }
2167
2168 delete itemPriv->clipNode();
2169 itemPriv->extra->clipNode = nullptr;
2170 }
2171 }
2172
2173 const int effectRefCount = itemPriv->extra.isAllocated() ? itemPriv->extra->effectRefCount : 0;
2174 const bool effectRefEffectivelyChanged =
2176 && ((effectRefCount == 0) != (itemPriv->rootNode() == nullptr));
2177 if (effectRefEffectivelyChanged) {
2179 itemPriv->childContainerNode()->removeAllChildNodes();
2180
2181 QSGNode *parent = itemPriv->clipNode();
2182 if (!parent)
2183 parent = itemPriv->opacityNode();
2184 if (!parent)
2185 parent = itemPriv->itemNode();
2186
2187 if (itemPriv->extra.isAllocated() && itemPriv->extra->effectRefCount) {
2188 Q_ASSERT(itemPriv->rootNode() == nullptr);
2189 QSGRootNode *root = new QSGRootNode();
2190 itemPriv->extra->rootNode = root;
2191 parent->reparentChildNodesTo(root);
2192 parent->appendChildNode(root);
2193 } else {
2194 Q_ASSERT(itemPriv->rootNode() != nullptr);
2195 QSGRootNode *root = itemPriv->rootNode();
2196 parent->removeChildNode(root);
2198 delete itemPriv->rootNode();
2199 itemPriv->extra->rootNode = nullptr;
2200 }
2201 }
2202
2204 int ii = 0;
2205 bool fetchedPaintNode = false;
2206 QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
2207 int desiredNodesSize = orderedChildren.size() + (itemPriv->paintNode ? 1 : 0);
2208
2209 // now start making current state match the promised land of
2210 // desiredNodes. in the case of our current state matching desiredNodes
2211 // (though why would we get ChildrenUpdateMask with no changes?) then we
2212 // should make no changes at all.
2213
2214 // how many nodes did we process, when examining changes
2215 int desiredNodesProcessed = 0;
2216
2217 // currentNode is how far, in our present tree, we have processed. we
2218 // make use of this later on to trim the current child list if the
2219 // desired list is shorter.
2220 QSGNode *groupNode = itemPriv->childContainerNode();
2221 QSGNode *currentNode = groupNode->firstChild();
2222 QSGNode *desiredNode = nullptr;
2223
2224 while (currentNode && (desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) {
2225 if (currentNode != desiredNode) {
2226 // uh oh... reality and our utopic paradise are diverging!
2227 // we need to reconcile this...
2228 if (currentNode->nextSibling() == desiredNode) {
2229 // nice and simple: a node was removed, and the next in line is correct.
2230 groupNode->removeChildNode(currentNode);
2231 } else {
2232 // a node needs to be added..
2233 // remove it from any pre-existing parent, and push it before currentNode,
2234 // so it's in the correct place...
2235 if (desiredNode->parent()) {
2236 desiredNode->parent()->removeChildNode(desiredNode);
2237 }
2238 groupNode->insertChildNodeBefore(desiredNode, currentNode);
2239 }
2240
2241 // continue iteration at the correct point, now desiredNode is in place...
2242 currentNode = desiredNode;
2243 }
2244
2245 currentNode = currentNode->nextSibling();
2246 desiredNodesProcessed++;
2247 }
2248
2249 // if we didn't process as many nodes as in the new list, then we have
2250 // more nodes at the end of desiredNodes to append to our list.
2251 // this will be the case when adding new nodes, for instance.
2252 if (desiredNodesProcessed < desiredNodesSize) {
2253 while ((desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) {
2254 if (desiredNode->parent())
2255 desiredNode->parent()->removeChildNode(desiredNode);
2256 groupNode->appendChildNode(desiredNode);
2257 }
2258 } else if (currentNode) {
2259 // on the other hand, if we processed less than our current node
2260 // tree, then nodes have been _removed_ from the scene, and we need
2261 // to take care of that here.
2262 while (currentNode) {
2263 QSGNode *node = currentNode->nextSibling();
2264 groupNode->removeChildNode(currentNode);
2265 currentNode = node;
2266 }
2267 }
2268 }
2269
2270 if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode()) {
2271 itemPriv->clipNode()->setRect(item->clipRect());
2272 itemPriv->clipNode()->update();
2273 }
2274
2277 {
2278 qreal opacity = itemPriv->explicitVisible && (!itemPriv->extra.isAllocated() || itemPriv->extra->hideRefCount == 0)
2279 ? itemPriv->opacity() : qreal(0);
2280
2281 if (opacity != 1 && !itemPriv->opacityNode()) {
2282 QSGOpacityNode *node = new QSGOpacityNode;
2283 itemPriv->extra.value().opacityNode = node;
2284
2285 QSGNode *parent = itemPriv->itemNode();
2286 QSGNode *child = itemPriv->clipNode();
2287 if (!child)
2288 child = itemPriv->rootNode();
2289
2290 if (child) {
2291 parent->removeChildNode(child);
2292 node->appendChildNode(child);
2293 parent->appendChildNode(node);
2294 } else {
2295 parent->reparentChildNodesTo(node);
2296 parent->appendChildNode(node);
2297 }
2298 }
2299 if (itemPriv->opacityNode())
2300 itemPriv->opacityNode()->setOpacity(opacity);
2301 }
2302
2304
2305 if (itemPriv->flags & QQuickItem::ItemHasContents) {
2306 updatePaintNodeData.transformNode = itemPriv->itemNode();
2307 itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
2308
2309 Q_ASSERT(itemPriv->paintNode == nullptr ||
2310 itemPriv->paintNode->parent() == nullptr ||
2311 itemPriv->paintNode->parent() == itemPriv->childContainerNode());
2312
2313 if (itemPriv->paintNode && itemPriv->paintNode->parent() == nullptr) {
2314 QSGNode *before = qquickitem_before_paintNode(itemPriv);
2315 if (before && before->parent()) {
2316 Q_ASSERT(before->parent() == itemPriv->childContainerNode());
2317 itemPriv->childContainerNode()->insertChildNodeAfter(itemPriv->paintNode, before);
2318 } else {
2319 itemPriv->childContainerNode()->prependChildNode(itemPriv->paintNode);
2320 }
2321 }
2322 } else if (itemPriv->paintNode) {
2323 delete itemPriv->paintNode;
2324 itemPriv->paintNode = nullptr;
2325 }
2326 }
2327
2328#ifndef QT_NO_DEBUG
2329 // Check consistency.
2330
2331 QList<QSGNode *> nodes;
2332 nodes << itemPriv->itemNodeInstance
2333 << itemPriv->opacityNode()
2334 << itemPriv->clipNode()
2335 << itemPriv->rootNode()
2336 << itemPriv->paintNode;
2337 nodes.removeAll(nullptr);
2338
2339 Q_ASSERT(nodes.constFirst() == itemPriv->itemNodeInstance);
2340 for (int i=1; i<nodes.size(); ++i) {
2341 QSGNode *n = nodes.at(i);
2342 // Failing this means we messed up reparenting
2343 Q_ASSERT(n->parent() == nodes.at(i-1));
2344 // Only the paintNode and the one who is childContainer may have more than one child.
2345 Q_ASSERT(n == itemPriv->paintNode || n == itemPriv->childContainerNode() || n->childCount() == 1);
2346 }
2347#endif
2348
2349}
2350
2351bool QQuickWindowPrivate::emitError(QQuickWindow::SceneGraphError error, const QString &msg)
2352{
2353 Q_Q(QQuickWindow);
2354 static const QMetaMethod errorSignal = QMetaMethod::fromSignal(&QQuickWindow::sceneGraphError);
2355 if (q->isSignalConnected(errorSignal)) {
2356 emit q->sceneGraphError(error, msg);
2357 return true;
2358 }
2359 return false;
2360}
2361
2362void QQuickWindow::maybeUpdate()
2363{
2364 Q_D(QQuickWindow);
2365 if (d->renderControl)
2366 QQuickRenderControlPrivate::get(d->renderControl)->maybeUpdate();
2367 else if (d->windowManager)
2368 d->windowManager->maybeUpdate(this);
2369}
2370
2371void QQuickWindow::cleanupSceneGraph()
2372{
2373 Q_D(QQuickWindow);
2374 if (!d->renderer)
2375 return;
2376
2377 delete d->renderer->rootNode();
2378 delete d->renderer;
2379 d->renderer = nullptr;
2380
2381 d->runAndClearJobs(&d->beforeSynchronizingJobs);
2382 d->runAndClearJobs(&d->afterSynchronizingJobs);
2383 d->runAndClearJobs(&d->beforeRenderingJobs);
2384 d->runAndClearJobs(&d->afterRenderingJobs);
2385 d->runAndClearJobs(&d->afterSwapJobs);
2386}
2387
2389{
2390#if QT_CONFIG(opengl)
2391 if (context && context->isValid()) {
2393 if (rif) {
2394 Q_Q(QQuickWindow);
2395 return reinterpret_cast<QOpenGLContext *>(rif->getResource(q, QSGRendererInterface::OpenGLContextResource));
2396 }
2397 }
2398#endif
2399 return nullptr;
2400}
2401
2405bool QQuickWindow::isSceneGraphInitialized() const
2406{
2407 Q_D(const QQuickWindow);
2408 return d->context != nullptr && d->context->isValid();
2409}
2410
2610void QQuickWindow::setRenderTarget(const QQuickRenderTarget &target)
2611{
2612 Q_D(QQuickWindow);
2613 if (target != d->customRenderTarget) {
2614 d->customRenderTarget = target;
2615 d->redirect.renderTargetDirty = true;
2616 }
2617}
2618
2627QQuickRenderTarget QQuickWindow::renderTarget() const
2628{
2629 Q_D(const QQuickWindow);
2630 return d->customRenderTarget;
2631}
2632
2633#ifdef Q_OS_WEBOS
2634class GrabWindowForProtectedContent : public QRunnable
2635{
2636public:
2637 GrabWindowForProtectedContent(QQuickWindow *window, QImage *image, QWaitCondition *condition)
2638 : m_window(window)
2639 , m_image(image)
2640 , m_condition(condition)
2641 {
2642 }
2643
2644 bool checkGrabbable()
2645 {
2646 if (!m_window)
2647 return false;
2648 if (!m_image)
2649 return false;
2650 if (!QQuickWindowPrivate::get(m_window))
2651 return false;
2652
2653 return true;
2654 }
2655
2656 void run() override
2657 {
2658 if (!checkGrabbable())
2659 return;
2660
2661 *m_image = QSGRhiSupport::instance()->grabOffscreenForProtectedContent(m_window);
2662 if (m_condition)
2663 m_condition->wakeOne();
2664 return;
2665 }
2666
2667private:
2668 QQuickWindow *m_window;
2669 QImage *m_image;
2670 QWaitCondition *m_condition;
2671
2672};
2673#endif
2674
2695QImage QQuickWindow::grabWindow()
2696{
2697 Q_D(QQuickWindow);
2698
2699 if (!d->isRenderable() && !d->renderControl) {
2700 // backends like software can grab regardless of the window state
2701 if (d->windowManager && (d->windowManager->flags() & QSGRenderLoop::SupportsGrabWithoutExpose))
2702 return d->windowManager->grab(this);
2703
2704 if (!isSceneGraphInitialized()) {
2705 // We do not have rendering up and running. Forget the render loop,
2706 // do a frame completely offscreen and synchronously into a
2707 // texture. This can be *very* slow due to all the device/context
2708 // and resource initialization but the documentation warns for it,
2709 // and is still important for some use cases.
2710 Q_ASSERT(!d->rhi);
2711 return QSGRhiSupport::instance()->grabOffscreen(this);
2712 }
2713 }
2714
2715#ifdef Q_OS_WEBOS
2716 if (requestedFormat().testOption(QSurfaceFormat::ProtectedContent)) {
2717 QImage image;
2718 QMutex mutex;
2720 mutex.lock();
2721 GrabWindowForProtectedContent *job = new GrabWindowForProtectedContent(this, &image, &condition);
2722 if (!job) {
2723 qWarning("QQuickWindow::grabWindow: Failed to create a job for capturing protected content");
2724 mutex.unlock();
2725 return QImage();
2726 }
2727 scheduleRenderJob(job, QQuickWindow::NoStage);
2728 condition.wait(&mutex);
2729 mutex.unlock();
2730 return image;
2731 }
2732#endif
2733 // The common case: we have an exposed window with an initialized
2734 // scenegraph, meaning we can request grabbing via the render loop, or we
2735 // are not targeting the window, in which case the request is to be
2736 // forwarded to the rendercontrol.
2737 if (d->renderControl)
2738 return QQuickRenderControlPrivate::get(d->renderControl)->grab();
2739 else if (d->windowManager)
2740 return d->windowManager->grab(this);
2741
2742 return QImage();
2743}
2744
2753QQmlIncubationController *QQuickWindow::incubationController() const
2754{
2755 Q_D(const QQuickWindow);
2756
2757 if (!d->windowManager)
2758 return nullptr; // TODO: make sure that this is safe
2759
2760 if (!d->incubationController)
2761 d->incubationController = new QQuickWindowIncubationController(d->windowManager);
2762 return d->incubationController;
2763}
2764
2765
2766
3139QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const
3140{
3141 return createTextureFromImage(image, {});
3142}
3143
3144
3190QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateTextureOptions options) const
3191{
3192 Q_D(const QQuickWindow);
3193 if (!isSceneGraphInitialized()) // check both for d->context and d->context->isValid()
3194 return nullptr;
3195 uint flags = 0;
3196 if (options & TextureCanUseAtlas) flags |= QSGRenderContext::CreateTexture_Atlas;
3197 if (options & TextureHasMipmaps) flags |= QSGRenderContext::CreateTexture_Mipmap;
3198 if (!(options & TextureIsOpaque)) flags |= QSGRenderContext::CreateTexture_Alpha;
3199 return d->context->createTexture(image, flags);
3200}
3201
3235QSGTexture *QQuickWindow::createTextureFromRhiTexture(QRhiTexture *texture, CreateTextureOptions options) const
3236{
3237 Q_D(const QQuickWindow);
3238 if (!d->rhi)
3239 return nullptr;
3240
3242 t->setOwnsTexture(true);
3243 t->setTexture(texture);
3244 t->setHasAlphaChannel(options & QQuickWindow::TextureHasAlphaChannel);
3245 t->setTextureSize(texture->pixelSize());
3246 return t;
3247}
3248
3249// Legacy, private alternative to createTextureFromRhiTexture() that internally
3250// creates a QRhiTexture wrapping the existing native graphics resource.
3251// New code should prefer using the public API.
3253 int nativeLayoutOrState,
3254 uint nativeFormat,
3255 const QSize &size,
3256 QQuickWindow::CreateTextureOptions options,
3257 TextureFromNativeTextureFlags flags) const
3258{
3259 if (!rhi)
3260 return nullptr;
3261
3263 texture->setTextureFromNativeTexture(rhi, nativeObjectHandle, nativeLayoutOrState, nativeFormat,
3264 size, options, flags);
3265 texture->setHasAlphaChannel(options & QQuickWindow::TextureHasAlphaChannel);
3266 // note that the QRhiTexture does not (and cannot) own the native object
3267 texture->setOwnsTexture(true); // texture meaning the QRhiTexture here, not the native object
3268 texture->setTextureSize(size);
3269 return texture;
3270}
3271
3293void QQuickWindow::setColor(const QColor &color)
3294{
3295 Q_D(QQuickWindow);
3296 if (color == d->clearColor)
3297 return;
3298
3299 if (color.alpha() != d->clearColor.alpha()) {
3300 QSurfaceFormat fmt = requestedFormat();
3301 if (color.alpha() < 255)
3302 fmt.setAlphaBufferSize(8);
3303 else
3304 fmt.setAlphaBufferSize(-1);
3305 setFormat(fmt);
3306 }
3307 d->clearColor = color;
3309 update();
3310}
3311
3313{
3314 return d_func()->clearColor;
3315}
3316
3323bool QQuickWindow::hasDefaultAlphaBuffer()
3324{
3326}
3327
3337void QQuickWindow::setDefaultAlphaBuffer(bool useAlpha)
3338{
3340}
3341
3405const QQuickWindow::GraphicsStateInfo &QQuickWindow::graphicsStateInfo()
3406{
3407 Q_D(QQuickWindow);
3408 if (d->rhi) {
3409 d->rhiStateInfo.currentFrameSlot = d->rhi->currentFrameSlot();
3410 d->rhiStateInfo.framesInFlight = d->rhi->resourceLimit(QRhi::FramesInFlight);
3411 }
3412 return d->rhiStateInfo;
3413}
3414
3456void QQuickWindow::beginExternalCommands()
3457{
3458 Q_D(QQuickWindow);
3459 if (d->rhi && d->context && d->context->isValid()) {
3460 QSGDefaultRenderContext *rc = static_cast<QSGDefaultRenderContext *>(d->context);
3462 if (cb)
3463 cb->beginExternal();
3464 }
3465}
3466
3493void QQuickWindow::endExternalCommands()
3494{
3495 Q_D(QQuickWindow);
3496 if (d->rhi && d->context && d->context->isValid()) {
3497 QSGDefaultRenderContext *rc = static_cast<QSGDefaultRenderContext *>(d->context);
3499 if (cb)
3500 cb->endExternal();
3501 }
3502}
3503
3971void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage)
3972{
3973 Q_D(QQuickWindow);
3974
3975 d->renderJobMutex.lock();
3976 if (stage == BeforeSynchronizingStage) {
3977 d->beforeSynchronizingJobs << job;
3978 } else if (stage == AfterSynchronizingStage) {
3979 d->afterSynchronizingJobs << job;
3980 } else if (stage == BeforeRenderingStage) {
3981 d->beforeRenderingJobs << job;
3982 } else if (stage == AfterRenderingStage) {
3983 d->afterRenderingJobs << job;
3984 } else if (stage == AfterSwapStage) {
3985 d->afterSwapJobs << job;
3986 } else if (stage == NoStage) {
3987 if (d->renderControl && d->rhi && d->rhi->thread() == QThread::currentThread()) {
3988 job->run();
3989 delete job;
3990 } else if (isExposed()) {
3991 d->windowManager->postJob(this, job);
3992 } else {
3993 delete job;
3994 }
3995 }
3996 d->renderJobMutex.unlock();
3997}
3998
3999void QQuickWindowPrivate::runAndClearJobs(QList<QRunnable *> *jobs)
4000{
4002 QList<QRunnable *> jobList = *jobs;
4003 jobs->clear();
4005
4006 for (QRunnable *r : std::as_const(jobList)) {
4007 r->run();
4008 delete r;
4009 }
4010}
4011
4012void QQuickWindow::runJobsAfterSwap()
4013{
4014 Q_D(QQuickWindow);
4015 d->runAndClearJobs(&d->afterSwapJobs);
4016}
4017
4033qreal QQuickWindow::effectiveDevicePixelRatio() const
4034{
4035 Q_D(const QQuickWindow);
4037 if (w)
4038 return w->devicePixelRatio();
4039
4040 if (!d->customRenderTarget.isNull())
4041 return d->customRenderTarget.devicePixelRatio();
4042
4043 return devicePixelRatio();
4044}
4045
4067QSGRendererInterface *QQuickWindow::rendererInterface() const
4068{
4069 Q_D(const QQuickWindow);
4070
4071 // no context validity check - it is essential to be able to return a
4072 // renderer interface instance before scenegraphInitialized() is emitted
4073 // (depending on the backend, that can happen way too late for some of the
4074 // rif use cases, like examining the graphics api or shading language in
4075 // use)
4076
4077 return d->context->sceneGraphContext()->rendererInterface(d->context);
4078}
4079
4100QRhi *QQuickWindow::rhi() const
4101{
4102 Q_D(const QQuickWindow);
4103 return d->rhi;
4104}
4105
4116QRhiSwapChain *QQuickWindow::swapChain() const
4117{
4118 Q_D(const QQuickWindow);
4119 return d->swapchain;
4120}
4121
4168void QQuickWindow::setGraphicsApi(QSGRendererInterface::GraphicsApi api)
4169{
4170 // Special cases: these are different scenegraph backends.
4171 switch (api) {
4173 setSceneGraphBackend(QStringLiteral("software"));
4174 break;
4176 setSceneGraphBackend(QStringLiteral("openvg"));
4177 break;
4178 default:
4179 break;
4180 }
4181
4182 // Standard case: tell the QRhi-based default adaptation what graphics api
4183 // (QRhi backend) to use.
4186}
4187
4217QSGRendererInterface::GraphicsApi QQuickWindow::graphicsApi()
4218{
4219 // Note that this applies the settings e.g. from the env vars
4220 // (QSG_RHI_BACKEND) if it was not done at least once already. Whereas if
4221 // setGraphicsApi() was called before, or the scene graph is already
4222 // initialized, then this is just a simple query.
4223 return QSGRhiSupport::instance()->graphicsApi();
4224}
4225
4246void QQuickWindow::setSceneGraphBackend(const QString &backend)
4247{
4248 QSGContext::setBackend(backend);
4249}
4250
4263QString QQuickWindow::sceneGraphBackend()
4264{
4265 return QSGContext::backend();
4266}
4267
4331void QQuickWindow::setGraphicsDevice(const QQuickGraphicsDevice &device)
4332{
4333 Q_D(QQuickWindow);
4334 d->customDeviceObjects = device;
4335}
4336
4345QQuickGraphicsDevice QQuickWindow::graphicsDevice() const
4346{
4347 Q_D(const QQuickWindow);
4348 return d->customDeviceObjects;
4349}
4350
4378void QQuickWindow::setGraphicsConfiguration(const QQuickGraphicsConfiguration &config)
4379{
4380 Q_D(QQuickWindow);
4381 d->graphicsConfig = config;
4382}
4383
4392QQuickGraphicsConfiguration QQuickWindow::graphicsConfiguration() const
4393{
4394 Q_D(const QQuickWindow);
4395 return d->graphicsConfig;
4396}
4397
4404QSGTextNode *QQuickWindow::createTextNode() const
4405{
4406 Q_D(const QQuickWindow);
4407 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createTextNode(d->context) : nullptr;
4408}
4409
4418QSGRectangleNode *QQuickWindow::createRectangleNode() const
4419{
4420 Q_D(const QQuickWindow);
4421 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createRectangleNode() : nullptr;
4422}
4423
4432QSGImageNode *QQuickWindow::createImageNode() const
4433{
4434 Q_D(const QQuickWindow);
4435 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createImageNode() : nullptr;
4436}
4437
4443QSGNinePatchNode *QQuickWindow::createNinePatchNode() const
4444{
4445 Q_D(const QQuickWindow);
4446 return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createNinePatchNode() : nullptr;
4447}
4448
4457QQuickWindow::TextRenderType QQuickWindow::textRenderType()
4458{
4460}
4461
4472void QQuickWindow::setTextRenderType(QQuickWindow::TextRenderType renderType)
4473{
4475}
4476
4477
4495
4497#ifndef QT_NO_DEBUG_STREAM
4499{
4500 QDebugStateSaver saver(debug);
4501 debug.nospace();
4502 if (!win) {
4503 debug << "QQuickWindow(nullptr)";
4504 return debug;
4505 }
4506
4507 debug << win->metaObject()->className() << '(' << static_cast<const void *>(win);
4508 if (win->isActive())
4509 debug << " active";
4510 if (win->isExposed())
4511 debug << " exposed";
4512 debug << ", visibility=" << win->visibility() << ", flags=" << win->flags();
4513 if (!win->title().isEmpty())
4514 debug << ", title=" << win->title();
4515 if (!win->objectName().isEmpty())
4516 debug << ", name=" << win->objectName();
4517 if (win->parent())
4518 debug << ", parent=" << static_cast<const void *>(win->parent());
4519 if (win->transientParent())
4520 debug << ", transientParent=" << static_cast<const void *>(win->transientParent());
4521 debug << ", geometry=";
4523 debug << ')';
4524 return debug;
4525}
4526#endif
4527
4529
4530#include "qquickwindow.moc"
4531#include "moc_qquickwindow_p.cpp"
4532#include "moc_qquickwindow.cpp"
IOBluetoothDevice * device
\inmodule QtCore
void stopped()
This signal is emitted by the animation framework to notify the driver that continuous animation has ...
\inmodule QtGui
Definition qevent.h:1025
The QCloseEvent class contains parameters that describe a close event.
Definition qevent.h:562
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
\inmodule QtCore
\inmodule QtCore
The QEventPoint class provides information about a point in a QPointerEvent.
Definition qeventpoint.h:20
\inmodule QtCore
Definition qcoreevent.h:45
virtual void setAccepted(bool accepted)
Definition qcoreevent.h:307
bool isSinglePointEvent() const noexcept
Definition qcoreevent.h:315
Type
This enum type defines the valid event types in Qt.
Definition qcoreevent.h:51
@ ApplicationPaletteChange
Definition qcoreevent.h:93
@ DevicePixelRatioChange
Definition qcoreevent.h:287
@ FocusAboutToChange
Definition qcoreevent.h:68
@ InputMethod
Definition qcoreevent.h:120
@ DragEnter
Definition qcoreevent.h:101
@ LocaleChange
Definition qcoreevent.h:122
@ InputMethodQuery
Definition qcoreevent.h:261
@ TouchUpdate
Definition qcoreevent.h:242
@ TouchBegin
Definition qcoreevent.h:241
@ WindowActivate
Definition qcoreevent.h:83
@ LanguageChange
Definition qcoreevent.h:123
@ UpdateRequest
Definition qcoreevent.h:113
@ DragLeave
Definition qcoreevent.h:103
@ PlatformSurface
Definition qcoreevent.h:278
@ ChildWindowAdded
Definition qcoreevent.h:289
@ WindowDeactivate
Definition qcoreevent.h:84
bool isAccepted() const
Definition qcoreevent.h:308
void accept()
Sets the accept flag of the event object, the equivalent of calling setAccepted(true).
Definition qcoreevent.h:310
The QExposeEvent class contains event parameters for expose events. \inmodule QtGui.
Definition qevent.h:515
The QFocusEvent class contains event parameters for widget focus events.
Definition qevent.h:470
static void cleanup()
Definition qfont.cpp:2259
virtual bool contains(const QPointF &point) const
Returns true if this item contains point, which is in local coordinates; otherwise,...
void update(const QRectF &rect=QRectF())
Schedules a redraw of the area covered by rect in this item.
QList< QGraphicsItem * > childItems() const
QPointF transformOriginPoint() const
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const
This method is only relevant for input items.
QGraphicsItem * parentItem() const
Returns a pointer to this item's parent item.
GraphicsItemFlags flags() const
Returns this item's flags.
QPointF mapFromScene(const QPointF &point) const
Maps the point point, which is in this item's scene's coordinate system, to this item's coordinate sy...
\macro qGuiApp
QScreen * primaryScreen
the primary (or default) screen of the application.
static QPalette palette()
Returns the current application palette.
static QObject * focusObject()
Returns the QObject in currently active window that will be final receiver of events tied to focus,...
void applicationStateChanged(Qt::ApplicationState state)
void fontDatabaseChanged()
This signal is emitted when the available fonts have changed.
The QHideEvent class provides an event which is sent after a widget is hidden.
Definition qevent.h:586
\inmodule QtGui
Definition qimage.h:37
static void setObjectOwnership(QObject *, ObjectOwnership)
Sets the ownership of object.
The QKeyEvent class describes a key event.
Definition qevent.h:424
QString arg(Args &&...args) const
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void append(parameter_type t)
Definition qlist.h:458
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
void translate(const QVector3D &vector)
Multiplies this matrix by another that translates coordinates by the components of vector.
\inmodule QtCore
Definition qmetaobject.h:19
static QMetaMethod fromSignal(PointerToMemberFunction signal)
\inmodule QtGui
Definition qevent.h:196
\inmodule QtCore
Definition qmutex.h:281
void unlock() noexcept
Unlocks the mutex.
Definition qmutex.h:289
void lock() noexcept
Locks the mutex.
Definition qmutex.h:286
QObject * q_ptr
Definition qobject.h:72
QObjectList children
Definition qobject.h:74
QObject * parent
Definition qobject.h:73
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:299
\inmodule QtCore
Definition qobject.h:103
int startTimer(int interval, Qt::TimerType timerType=Qt::CoarseTimer)
This is an overloaded function that will start a timer of type timerType and a timeout of interval mi...
Definition qobject.cpp:1817
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
virtual void childEvent(QChildEvent *event)
This event handler can be reimplemented in a subclass to receive child events.
Definition qobject.cpp:1508
QString objectName
the name of this object
Definition qobject.h:107
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
Q_WEAK_OVERLOAD void setObjectName(const QString &name)
Sets the object's name to name.
Definition qobject.h:127
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition qobject.cpp:1912
\inmodule QtGui
The QPalette class contains color groups for each widget state.
Definition qpalette.h:19
The QPlatformSurfaceEvent class is used to notify about native platform surface events....
Definition qevent.h:531
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
\inmodule QtCore\reentrant
Definition qpoint.h:25
A base class for pointer events.
Definition qevent.h:73
virtual bool isEndEvent() const
Definition qevent.h:92
void clearPassiveGrabbers(const QEventPoint &point)
Removes all passive grabbers from the given point.
Definition qevent.cpp:433
void setExclusiveGrabber(const QEventPoint &point, QObject *exclusiveGrabber)
Informs the delivery logic that the given exclusiveGrabber is to receive all future update events and...
Definition qevent.cpp:369
QEventPoint & point(qsizetype i)
Returns a QEventPoint reference for the point at index i.
Definition qevent.cpp:240
const QList< QEventPoint > & points() const
Returns a list of points in this pointer event.
Definition qevent.h:87
static QPointingDevicePrivate * get(QPointingDevice *q)
The QPointingDevice class describes a device from which mouse, touch or tablet events originate.
static const QPointingDevice * primaryPointingDevice(const QString &seatName=QString())
Returns the primary pointing device (the core pointer, traditionally assumed to be a mouse) on the gi...
QQmlIncubationController instances drive the progress of QQmlIncubators.
void incubateFor(int msecs)
Incubate objects for msecs, or until there are no more objects to incubate.
int incubatingObjectCount() const
Return the number of objects currently incubating.
static QString prettyTypeName(const QObject *object)
Returns the pretty QML type name (e.g.
\qmlsignal QtQuick::Window::sceneGraphError(SceneGraphError error, QString message)
void setAccepted(bool accepted)
static bool isTabletEvent(const QPointerEvent *ev)
static bool isSynthMouse(const QPointerEvent *ev)
static bool isTouchEvent(const QPointerEvent *ev)
QQuickGraphicsConfiguration controls lower level graphics settings for the QQuickWindow.
The QQuickGraphicsDevice class provides an opaque container for native graphics objects representing ...
QLazilyAllocated< ExtraData, ExtraDataTags > extra
virtual void updatePolish()
QList< QQuickItem * > paintOrderChildItems() const
quint32 subtreeCursorEnabled
static QQuickItem * nextPrevItemInTabFocusChain(QQuickItem *item, bool forward, bool wrap=true)
void itemChange(QQuickItem::ItemChange, const QQuickItem::ItemChangeData &)
qreal z() const
static QQuickItemPrivate * get(QQuickItem *item)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
void setSize(const QSizeF &size)
void setFlag(Flag flag, bool enabled=true)
Enables the specified flag for this item if enabled is true; if enabled is false, the flag is disable...
@ ItemDevicePixelRatioHasChanged
Definition qquickitem.h:154
@ ItemClipsChildrenToShape
Definition qquickitem.h:130
Contains color groups for each QML item state. \inmodule QtQuick.
static void purgeCache()
static QQuickPointerHandlerPrivate * get(QQuickPointerHandler *q)
static QQuickRenderControlPrivate * get(QQuickRenderControl *renderControl)
The QQuickRenderControl class provides a mechanism for rendering the Qt Quick scenegraph onto an offs...
static QWindow * renderWindowFor(QQuickWindow *win, QPoint *offset=nullptr)
Returns the real window that win is being rendered to, if any.
static QQuickRenderTargetPrivate * get(QQuickRenderTarget *rt)
The QQuickRenderTarget class provides an opaque container for native graphics resources specifying a ...
void incubatingObjectCountChanged(int count) override
Called when the number of incubating objects changes.
void timerEvent(QTimerEvent *) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
QQuickWindowIncubationController(QSGRenderLoop *loop)
~QQuickWindowPrivate() override
void init(QQuickWindow *, QQuickRenderControl *control=nullptr)
QByteArray visualizationMode
bool emitError(QQuickWindow::SceneGraphError error, const QString &msg)
QQuickItem::UpdatePaintNodeData updatePaintNodeData
static void data_clear(QQmlListProperty< QObject > *)
static void data_replace(QQmlListProperty< QObject > *, qsizetype, QObject *)
QQuickRootItem * contentItem
void dirtyItem(QQuickItem *)
void clearFocusObject() override
static QQuickWindowPrivate * get(QQuickWindow *c)
static QQuickWindow::TextRenderType textRenderType
QSGRenderContext * context
QQuickRenderControl * renderControl
void runAndClearJobs(QList< QRunnable * > *jobs)
QVector< QQuickItem * > itemsToPolish
QQuickItem * dirtyItemList
void updateDirtyNode(QQuickItem *)
void clearGrabbers(QPointerEvent *event)
static void rhiCreationFailureMessage(const QString &backendName, QString *translatedMessage, QString *untranslatedMessage)
static void emitBeforeRenderPassRecording(void *ud)
static bool defaultAlphaBuffer
void setCustomCommandBuffer(QRhiCommandBuffer *cb)
QPointer< QQuickPalette > windowPaletteRef
static void data_append(QQmlListProperty< QObject > *, QObject *)
\qmlproperty list<QtObject> Window::data \qmldefault
void invalidateFontData(QQuickItem *item)
void setPalette(QQuickPalette *p) override
void cleanup(QSGNode *)
QQuickDeliveryAgentPrivate * deliveryAgentPrivate() const
QQmlListProperty< QObject > data()
QSet< QQuickItem * > parentlessItems
void updateChildrenPalettes(const QPalette &parentPalette) override
qreal lastReportedItemDevicePixelRatio
QScopedPointer< QQuickAnimatorController > animationController
QSGTexture * createTextureFromNativeTexture(quint64 nativeObjectHandle, int nativeLayoutOrState, uint nativeFormat, const QSize &size, QQuickWindow::CreateTextureOptions options, TextureFromNativeTextureFlags flags={}) const
void forcePolish()
Schedules polish events on all items in the scene.
static void data_removeLast(QQmlListProperty< QObject > *)
void setFocusToTarget(FocusTarget, Qt::FocusReason) override
struct QQuickWindowPrivate::Redirect redirect
static void emitAfterRenderPassRecording(void *ud)
void clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason)
QRhiRenderTarget * activeCustomRhiRenderTarget()
QSGRenderLoop * windowManager
bool isRenderable() const
void updateChildWindowStackingOrder(QQuickItem *item=nullptr)
QList< QSGNode * > cleanupNodeList
QOpenGLContext * openglContext()
QQuickDeliveryAgent * deliveryAgent
static QObject * data_at(QQmlListProperty< QObject > *, qsizetype)
static qsizetype data_count(QQmlListProperty< QObject > *)
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
void focusOutEvent(QFocusEvent *) override
\reimp
void frameSwapped()
This signal is emitted when a frame has been queued for presenting.
void mousePressEvent(QMouseEvent *) override
\reimp
void resizeEvent(QResizeEvent *) override
\reimp
void update()
Schedules the window to render another frame.
void mouseReleaseEvent(QMouseEvent *) override
\reimp
void exposeEvent(QExposeEvent *) override
\reimp
QQuickItem * contentItem
\qmlattachedproperty Item Window::contentItem
void focusInEvent(QFocusEvent *) override
\reimp
void sceneGraphInitialized()
\qmlsignal QtQuick::Window::frameSwapped()
bool event(QEvent *) override
\reimp
QColor color
\qmlproperty color Window::color
void closeEvent(QCloseEvent *) override
\reimp
~QQuickWindow() override
Destroys the window.
void sceneGraphInvalidated()
\qmlsignal QtQuick::Window::sceneGraphInitialized()
void mouseMoveEvent(QMouseEvent *) override
\reimp
QQuickItem * activeFocusItem
The item which currently has active focus or null if there is no item with active focus.
QObject * focusObject() const override
void releaseResources()
This function tries to release redundant resources currently held by the QML scene.
void hideEvent(QHideEvent *) override
\reimp
void showEvent(QShowEvent *) override
\reimp
void keyReleaseEvent(QKeyEvent *) override
\reimp
void mouseDoubleClickEvent(QMouseEvent *) override
\reimp
void keyPressEvent(QKeyEvent *) override
\reimp
\inmodule QtCore\reentrant
Definition qrect.h:484
\inmodule QtCore\reentrant
Definition qrect.h:30
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:548
\inmodule QtGui
Definition qrhi.h:1651
\inmodule QtGui
Definition qrhi.h:1142
\inmodule QtGui
Definition qrhi.h:1158
\inmodule QtGui
Definition qrhi.h:1549
\inmodule QtGui
Definition qrhi.h:895
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
Definition qrhi.h:1804
@ FramesInFlight
Definition qrhi.h:1890
\inmodule QtCore
Definition qrunnable.h:18
virtual void run()=0
Implement this pure virtual function in your subclass.
void setClipRect(const QRectF &)
Sets the clip rect of this clip node to rect.
Definition qsgnode.cpp:1101
The QSGContext holds the scene graph entry points for one QML engine.
static QString backend()
virtual QSGRendererInterface * rendererInterface(QSGRenderContext *renderContext)
Returns a pointer to the (presumably) global renderer interface.
static void setBackend(const QString &backend)
virtual QSurfaceFormat defaultSurfaceFormat() const =0
QRhiCommandBuffer * currentFrameCommandBuffer() const
The QSGImageNode class is provided for convenience to easily draw textured content using the QML scen...
\inmodule QtQuick
\group qtquick-scenegraph-nodes \title Qt Quick Scene Graph Node classes
Definition qsgnode.h:37
void removeChildNode(QSGNode *node)
Removes node from this node's list of children.
Definition qsgnode.cpp:500
QSGNode * nextSibling() const
Returns the node after this in the parent's list of children.
Definition qsgnode.h:107
void reparentChildNodesTo(QSGNode *newParent)
Definition qsgnode.cpp:547
void appendChildNode(QSGNode *node)
Appends node to this node's list of children.
Definition qsgnode.cpp:398
QSGNode * parent() const
Returns the parent node of this node.
Definition qsgnode.h:93
QSGNode * firstChild() const
Returns the first child of this node.
Definition qsgnode.h:105
The QSGOpacityNode class is used to change opacity of nodes.
Definition qsgnode.h:276
void setTextureFromNativeTexture(QRhi *rhi, quint64 nativeObjectHandle, int nativeLayoutOrState, uint nativeFormat, const QSize &size, QQuickWindow::CreateTextureOptions options, QQuickWindowPrivate::TextureFromNativeTextureFlags flags)
void setOwnsTexture(bool owns)
The QSGRectangleNode class is a convenience class for drawing solid filled rectangles using scenegrap...
QSGContext * sceneGraphContext() const
virtual bool isValid() const
static QSGRenderLoop * instance()
void timeToIncubate()
void addWindow(QQuickWindow *win)
virtual QAnimationDriver * animationDriver() const =0
virtual QSurface::SurfaceType windowSurfaceType() const
virtual QSGRenderContext * createRenderContext(QSGContext *) const =0
virtual QSGContext * sceneGraphContext() const =0
virtual bool interleaveIncubation() const
An interface providing access to some of the graphics API specific internals of the scenegraph.
RenderMode
\value RenderMode2D Normal 2D rendering \value RenderMode2DNoDepthBuffer Normal 2D rendering with dep...
static bool isApiRhiBased(GraphicsApi api)
GraphicsApi
\value Unknown An unknown graphics API is in use \value Software The Qt Quick 2D Renderer is in use \...
static QSGRhiSupport * instance_internal()
static QSGRhiSupport * instance()
The QSGRootNode is the toplevel root of any scene graph.
Definition qsgnode.h:259
The QSGTextNode class is a class for drawing text layouts and text documents in the Qt Quick scene gr...
Definition qsgtextnode.h:14
\inmodule QtQuick
Definition qsgtexture.h:20
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition qscreen.h:32
iterator begin()
Definition qset.h:136
iterator end()
Definition qset.h:140
The QShowEvent class provides an event that is sent when a widget is shown.
Definition qevent.h:578
A base class for pointer events containing a single point, such as mouse events.
Definition qevent.h:109
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
The QSurfaceFormat class represents the format of a QSurface. \inmodule QtGui.
@ OpenGLSurface
Definition qsurface.h:32
static QThread * currentThread()
Definition qthread.cpp:1039
\inmodule QtCore
Definition qcoreevent.h:366
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition qwidget.h:106
QCursor cursor
Definition qwindow_p.h:154
\inmodule QtGui
Definition qwindow.h:63
virtual QAccessibleInterface * accessibleRoot() const
Returns the accessibility interface for the object that the window represents.
Definition qwindow.cpp:2222
void focusObjectChanged(QObject *object)
This signal is emitted when the final receiver of events tied to focus is changed to object.
virtual bool event(QEvent *) override
Override this to handle any event (ev) sent to the window.
Definition qwindow.cpp:2511
void screenChanged(QScreen *screen)
This signal is emitted when a window's screen changes, either by being set explicitly with setScreen(...
widget setFormat(format)
void colorChanged()
qDeleteAll(list.begin(), list.end())
cache insert(employee->id(), employee)
QSet< QString >::iterator it
auto mo
[7]
rect
[4]
else opt state
[0]
Combined button and popup list for selecting options.
QTCONCURRENT_RUN_NODISCARD auto run(QThreadPool *pool, Function &&f, Args &&...args)
static void formatQRect(QDebug &debug, const Rect &rect)
Definition qdebug_p.h:45
Definition qcompare.h:63
@ ImEnabled
@ NoButton
Definition qnamespace.h:57
@ AA_SynthesizeMouseForUnhandledTabletEvents
Definition qnamespace.h:459
ApplicationState
Definition qnamespace.h:262
@ ApplicationActive
Definition qnamespace.h:266
@ DirectConnection
FocusReason
Definition image.cpp:4
static void * context
#define Q_FALLTHROUGH()
#define Q_UNLIKELY(x)
#define Q_LIKELY(x)
#define qApp
DBusConnection const char DBusError * error
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
EGLConfig config
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
static QString backendName
#define qWarning
Definition qlogging.h:166
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
return ret
const char * typeName
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLenum condition
GLboolean r
[2]
GLenum GLuint id
[7]
GLenum GLenum GLsizei count
GLuint color
[2]
GLenum target
GLbitfield flags
GLenum GLuint texture
GLfloat n
struct _cl_event * event
GLuint res
const GLubyte * c
GLuint GLenum matrix
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLfloat GLfloat p
[1]
void QQml_setParent_noEvent(QObject *object, QObject *parent)
Makes the object a child of parent.
QQuickItem * qmlobject_cast< QQuickItem * >(QObject *object)
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
static const QQmlJSScope * resolve(const QQmlJSScope *current, const QStringList &names)
const QQuickItem * rootItem(const I &item)
void qtquick_shadereffect_purge_gui_thread_shader_cache()
static void updatePixelRatioHelper(QQuickItem *item, float pixelRatio)
static const QQuickItem * firstItemWithDirtyChildrenStacking(const QQuickItem *item)
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)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define qPrintable(string)
Definition qstring.h:1531
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
QScreen * screen
[1]
Definition main.cpp:29
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
#define Q_OBJECT
#define slots
#define emit
#define Q_UNUSED(x)
#define QT_TRANSLATE_NOOP(scope, x)
unsigned int quint32
Definition qtypes.h:50
unsigned long long quint64
Definition qtypes.h:61
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
QVideoFrameFormat::PixelFormat fmt
const char property[13]
Definition qwizard.cpp:101
QWidget * win
Definition settings.cpp:6
QObject::connect nullptr
myObject disconnect()
[26]
QMutex mutex
[2]
QGraphicsItem * item
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QNetworkRequestFactory api
[0]
QSvgRenderer * renderer
[0]
bool check(QQuickItem *item, int itemsRemainingBeforeUpdatePolish)
const QVector< QQuickItem * > & itemsToPolish
PolishLoopDetector(const QVector< QQuickItem * > &itemsToPolish)
bool contains(const AT &t) const noexcept
Definition qlist.h:45
\inmodule QtCore
QSGTransformNode * transformNode
Definition qquickitem.h:372
struct QQuickWindowRenderTarget::@696 rt
struct QQuickWindowRenderTarget::@698 sw
void reset(QRhi *rhi, ResetFlags flags={})
struct QQuickWindowRenderTarget::ImplicitBuffers implicitBuffers