219 lines
5.4 KiB
C++
219 lines
5.4 KiB
C++
![]() |
/******************************************************************************
|
||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include "QskInputGrabber.h"
|
||
|
#include "QskWindow.h"
|
||
|
#include "QskQuick.h"
|
||
|
#include <QPointer>
|
||
|
|
||
|
QSK_QT_PRIVATE_BEGIN
|
||
|
#include <private/qquickitem_p.h>
|
||
|
#include <private/qquickitemchangelistener_p.h>
|
||
|
QSK_QT_PRIVATE_END
|
||
|
|
||
|
class QskInputGrabber::PrivateData : public QQuickItemChangeListener
|
||
|
{
|
||
|
public:
|
||
|
PrivateData( QskInputGrabber* grabber ):
|
||
|
m_grabber( grabber )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
inline QRectF grabberRect() const
|
||
|
{
|
||
|
if ( itemBelow && itemAbove )
|
||
|
{
|
||
|
const auto pos = itemBelow->mapToItem( itemAbove, QPointF() );
|
||
|
return QRectF( pos.x(), pos.y(), itemBelow->width(), itemBelow->height() );
|
||
|
}
|
||
|
|
||
|
return QRectF();
|
||
|
}
|
||
|
|
||
|
void enableListener( QQuickItem* item,
|
||
|
QQuickItemPrivate::ChangeTypes types, bool on )
|
||
|
{
|
||
|
if ( item )
|
||
|
{
|
||
|
auto d = QQuickItemPrivate::get( item );
|
||
|
|
||
|
if ( on )
|
||
|
d->addItemChangeListener( this, types );
|
||
|
else
|
||
|
d->removeItemChangeListener( this, types );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void setup( QQuickItem* item )
|
||
|
{
|
||
|
QQuickItem* newItemBelow = item ? item->parentItem() : nullptr;
|
||
|
QQuickItem* newItemAbove = item;
|
||
|
|
||
|
if ( newItemBelow != itemBelow )
|
||
|
{
|
||
|
const auto changeTypes = QQuickItemPrivate::Geometry;
|
||
|
|
||
|
enableListener( itemBelow, changeTypes, false );
|
||
|
enableListener( newItemBelow, changeTypes, true );
|
||
|
|
||
|
itemBelow = newItemBelow;
|
||
|
}
|
||
|
|
||
|
if ( newItemAbove != itemAbove )
|
||
|
{
|
||
|
const auto changeTypes = QQuickItemPrivate::Geometry | QQuickItemPrivate::Parent;
|
||
|
|
||
|
enableListener( itemAbove, changeTypes, false );
|
||
|
enableListener( newItemAbove, changeTypes, true );
|
||
|
|
||
|
itemAbove = newItemAbove;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
|
||
|
virtual void itemGeometryChanged( QQuickItem* item,
|
||
|
QQuickGeometryChange change, const QRectF& ) override final
|
||
|
{
|
||
|
bool doUpdate = false;
|
||
|
|
||
|
if ( item == itemAbove )
|
||
|
doUpdate = change.positionChange();
|
||
|
else
|
||
|
doUpdate = change.sizeChange();
|
||
|
|
||
|
if ( doUpdate )
|
||
|
m_grabber->updateGeometry();
|
||
|
|
||
|
}
|
||
|
#else
|
||
|
virtual void itemGeometryChanged(
|
||
|
QQuickItem* item, const QRectF& newRect, const QRectF& oldRect ) override
|
||
|
{
|
||
|
bool doUpdate = false;
|
||
|
|
||
|
if ( item == itemAbove )
|
||
|
doUpdate = newRect.size() != oldRect.size();
|
||
|
else
|
||
|
doUpdate = newRect.topLeft() != oldRect.topLeft();
|
||
|
|
||
|
if ( doUpdate )
|
||
|
m_grabber->updateGeometry();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
virtual void itemParentChanged( QQuickItem* item, QQuickItem* parentItem ) override
|
||
|
{
|
||
|
if ( item == m_grabber && parentItem )
|
||
|
{
|
||
|
setup( parentItem );
|
||
|
m_grabber->updateGeometry();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QskInputGrabber* m_grabber;
|
||
|
|
||
|
public:
|
||
|
QPointer< QQuickItem > itemAbove;
|
||
|
QPointer< QQuickItem > itemBelow;
|
||
|
};
|
||
|
|
||
|
QskInputGrabber::QskInputGrabber( QQuickItem* parent ) :
|
||
|
Inherited( parent ),
|
||
|
m_data( new PrivateData( this ) )
|
||
|
{
|
||
|
setAcceptedMouseButtons( Qt::AllButtons );
|
||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||
|
setAcceptTouchEvents( true );
|
||
|
#endif
|
||
|
setAcceptHoverEvents( true );
|
||
|
|
||
|
setTransparentForPositioner( true );
|
||
|
setFlag( QQuickItem::ItemHasContents, false );
|
||
|
|
||
|
m_data->setup( parent );
|
||
|
updateGeometry();
|
||
|
}
|
||
|
|
||
|
QskInputGrabber::~QskInputGrabber()
|
||
|
{
|
||
|
m_data->setup( nullptr );
|
||
|
}
|
||
|
|
||
|
bool QskInputGrabber::event( QEvent* event )
|
||
|
{
|
||
|
bool doBlock = false;
|
||
|
|
||
|
switch ( static_cast< int >( event->type() ) )
|
||
|
{
|
||
|
case QEvent::MouseButtonPress:
|
||
|
case QEvent::MouseMove:
|
||
|
case QEvent::MouseButtonRelease:
|
||
|
{
|
||
|
const auto ev = static_cast< QMouseEvent* > ( event );
|
||
|
doBlock = isBlocking( ev->localPos() );
|
||
|
break;
|
||
|
}
|
||
|
case QEvent::TouchBegin:
|
||
|
case QEvent::TouchUpdate:
|
||
|
case QEvent::TouchCancel:
|
||
|
{
|
||
|
#if 1
|
||
|
// TODO
|
||
|
doBlock = true;
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
case QEvent::Wheel:
|
||
|
{
|
||
|
const auto ev = static_cast< QWheelEvent* > ( event );
|
||
|
doBlock = isBlocking( ev->posF() );
|
||
|
break;
|
||
|
}
|
||
|
case QEvent::HoverEnter:
|
||
|
case QEvent::HoverLeave:
|
||
|
{
|
||
|
const auto ev = static_cast< QHoverEvent* > ( event );
|
||
|
doBlock = isBlocking( ev->posF() );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( doBlock )
|
||
|
{
|
||
|
event->accept();
|
||
|
|
||
|
if ( auto w = qobject_cast< QskWindow* >( window() ) )
|
||
|
w->setEventAcceptance( QskWindow::EventPropagationStopped );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return Inherited::event( event );
|
||
|
}
|
||
|
|
||
|
bool QskInputGrabber::isBlocking( const QPointF& pos ) const
|
||
|
{
|
||
|
if ( const auto item = parentItem() )
|
||
|
return !item->contains( position() + pos );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
QRectF QskInputGrabber::grabberRect() const
|
||
|
{
|
||
|
return m_data->grabberRect();
|
||
|
}
|
||
|
|
||
|
void QskInputGrabber::updateGeometry()
|
||
|
{
|
||
|
const QRectF rect = grabberRect();
|
||
|
if ( rect != geometry() )
|
||
|
setGeometry( rect );
|
||
|
}
|
||
|
|
||
|
#include "moc_QskInputGrabber.cpp"
|