Split window texture provider from window texture node
Currently, the WindowThumbnail item puts both the texture provider and the scene graph node in a single object.
It uses QPointer to detect if the scene graph node has been deleted. However, that seems to break if QtQuick passes null oldNode while the real old node is still alive.
Because the WindowThumbnail caches the old node, it may not see that QtQuick wants a new scene graph node. With debug build, it's going to trigger an assert in QQuickWindowPrivate::updateDirtyNode() that checks if the paint node is either new or belongs to the child container node. With a release build, it's undefined behavior.
In order to make the WindowThumbnail item handle the case where oldNode is null while the cached old node is still alive, this change decouples texture provider bits from the scene graph node and ports the item to QSGImageNode, which we need to do anyway.
* thread #42, name = 'QSGRenderThread', stop reason = signal SIGABRT
* frame #0: 0x00007fc096f54d22 libc.so.6`raise + 322
frame #1: 0x00007fc096f3e862 libc.so.6`abort + 278
frame #2: 0x00007fc09751b99c libQt5Core.so.5`::qt_message_fatal((null)=QtFatalMsg, context=0x00007fbfedffa570, message=0x00007fbfedffa460) at qlogging.cpp:1914:15
frame #3: 0x00007fc097517ed6 libQt5Core.so.5`QMessageLogger::fatal(this=0x00007fbfedffa570, msg="ASSERT: \"%s\" in file %s, line %d") const at qlogging.cpp:893:21
frame #4: 0x00007fc09750e70c libQt5Core.so.5`qt_assert(assertion="itemPriv->paintNode == nullptr || itemPriv->paintNode->parent() == nullptr || itemPriv->paintNode->parent() == itemPriv->childContainerNode()", file="items/qquickwindow.cpp", line=3874) at qglobal.cpp:3358:46
frame #5: 0x00007fc09a5d879a libQt5Quick.so.5`QQuickWindowPrivate::updateDirtyNode(this=0x000056502e3ec510, item=0x0000565031984e00) at qquickwindow.cpp:3874:13
frame #6: 0x00007fc09a5d72a7 libQt5Quick.so.5`QQuickWindowPrivate::updateDirtyNodes(this=0x000056502e3ec510) at qquickwindow.cpp:3617:24
frame #7: 0x00007fc09a5c6f18 libQt5Quick.so.5`QQuickWindowPrivate::syncSceneGraph(this=0x000056502e3ec510) at qquickwindow.cpp:524:21
frame #8: 0x00007fc09a5483ff libQt5Quick.so.5`QSGRenderThread::sync(this=0x0000565031a8aa00, inExpose=true, inGrab=false) at qsgthreadedrenderloop.cpp:647:26
frame #9: 0x00007fc09a54901e libQt5Quick.so.5`QSGRenderThread::syncAndRender(this=0x0000565031a8aa00, grabImage=0x0000000000000000) at qsgthreadedrenderloop.cpp:778:13
frame #10: 0x00007fc09a54a6b6 libQt5Quick.so.5`QSGRenderThread::run(this=0x0000565031a8aa00) at qsgthreadedrenderloop.cpp:1043:30
frame #11: 0x00007fc0975274c4 libQt5Core.so.5`QThreadPrivate::start(arg=0x0000565031a8aa00) at qthread_unix.cpp:329:17
frame #12: 0x00007fc09670a259 libpthread.so.0`start_thread + 233
frame #13: 0x00007fc0970165e3 libc.so.6`__clone + 67
frame #5: 0x00007f208aac179a libQt5Quick.so.5`QQuickWindowPrivate::updateDirtyNode(this=0x0000560ad419d9c0, item=0x0000560ad74cfbf0) at qquickwindow.cpp:3874:13
3871 updatePaintNodeData.transformNode = itemPriv->itemNode();
3872 itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
3873
-> 3874 Q_ASSERT(itemPriv->paintNode == nullptr ||
3875 itemPriv->paintNode->parent() == nullptr ||
3876 itemPriv->paintNode->parent() == itemPriv->childContainerNode());
3877
(lldb) p itemPriv->paintNode
(Plasma::WindowTextureNode *) $0 = 0x00007f1f74ee06f0
(lldb) p itemPriv->paintNode->parent()
(QSGRootNode *) $1 = 0x00007f1f74cd51e0
(lldb) p itemPriv->childContainerNode()
(QSGRootNode *) $2 = 0x00007f1f9821f060