qskinny/playground/parrots/Overlay.cpp

154 lines
3.6 KiB
C++

/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "Overlay.h"
#include "BlurringNode.h"
#include "SceneTexture.h"
#include <QskTreeNode.h>
#include <private/qquickitem_p.h>
#include <private/qquickwindow_p.h>
#include <private/qsgrenderer_p.h>
#include <private/qquickitemchangelistener_p.h>
#include <qpointer.h>
class OverlayPrivate final : public QQuickItemPrivate, public QQuickItemChangeListener
{
public:
void itemGeometryChanged( QQuickItem*,
QQuickGeometryChange change, const QRectF& )
{
if ( change.sizeChange() )
q_func()->update();
}
void setAttached( bool on )
{
if ( grabbedItem )
{
auto d = QQuickItemPrivate::get( grabbedItem );
if ( on )
{
d->refFromEffectItem( false );
d->addItemChangeListener( this, Geometry );
}
else
{
d->removeItemChangeListener( this, Geometry );
d->derefFromEffectItem( false );
}
}
}
QSGRootNode* grabbedNode()
{
if ( grabbedItem )
return grabbedItem ? get( grabbedItem )->rootNode() : nullptr;
if ( auto window = q_func()->window() )
{
if ( auto renderer = QQuickWindowPrivate::get( window )->renderer )
return renderer->rootNode();
}
return nullptr;
}
QSGTransformNode* createTransformNode() override
{
return new QskItemNode();
}
QPointer< QQuickItem > grabbedItem;
Q_DECLARE_PUBLIC(Overlay)
};
Overlay::Overlay( QQuickItem* parent )
: QQuickItem( *new OverlayPrivate(), parent )
{
setFlag( ItemHasContents );
}
Overlay::~Overlay()
{
d_func()->setAttached( false );
}
QQuickItem*Overlay::grabbedItem() const
{
return d_func()->grabbedItem;
}
void Overlay::setGrabbedItem( QQuickItem* item )
{
Q_D( Overlay );
if ( item == d->grabbedItem )
return;
d->setAttached( false );
d->grabbedItem = item;
d->setAttached( true );
update();
}
void Overlay::geometryChange(
const QRectF& newGeometry, const QRectF& oldGeometry )
{
Inherited::geometryChange( newGeometry, oldGeometry );
update();
}
QSGNode* Overlay::updatePaintNode( QSGNode* oldNode, UpdatePaintNodeData* )
{
Q_D( Overlay );
auto grabbedNode = d->grabbedNode();
if ( grabbedNode == nullptr )
QMetaObject::invokeMethod( this, &QQuickItem::update );
if ( grabbedNode == nullptr || size().isEmpty() )
{
delete oldNode;
return nullptr;
}
auto node = static_cast< BlurringNode* >( oldNode );
if ( node == nullptr )
{
node = new BlurringNode();
auto texture = new SceneTexture( d->sceneGraphRenderContext() );
texture->setDevicePixelRatio( window()->effectiveDevicePixelRatio() );
node->setTexture( texture );
}
auto texture = static_cast< SceneTexture* >( node->texture() );
if ( !texture->isRendering() )
{
texture->setFiltering( smooth() ? QSGTexture::Linear : QSGTexture::Nearest );
texture->render( grabbedNode, d->itemNode(),
QRectF( x(), y(), width(), height() ) );
QMetaObject::invokeMethod( this, &QQuickItem::update );
}
node->setRect( QRectF( 0, 0, width(), height() ) );
return node;
}
#include "moc_Overlay.cpp"