QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskInputGrabber.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskInputGrabber.h"
7#include "QskWindow.h"
8#include "QskEvent.h"
9
10#include <qpointer.h>
11
12QSK_QT_PRIVATE_BEGIN
13#include <private/qquickitem_p.h>
14#include <private/qquickitemchangelistener_p.h>
15QSK_QT_PRIVATE_END
16
17class QskInputGrabber::PrivateData final : public QQuickItemChangeListener
18{
19 public:
20 PrivateData( QskInputGrabber* grabber )
21 : m_grabber( grabber )
22 {
23 }
24
25 inline QRectF grabberRect() const
26 {
27 if ( itemBelow && itemAbove )
28 {
29 const auto pos = itemBelow->mapToItem( itemAbove, QPointF() );
30 return QRectF( pos.x(), pos.y(), itemBelow->width(), itemBelow->height() );
31 }
32
33 return QRectF();
34 }
35
36 void enableListener( QQuickItem* item,
37 QQuickItemPrivate::ChangeTypes types, bool on )
38 {
39 if ( item )
40 {
41 auto d = QQuickItemPrivate::get( item );
42
43 if ( on )
44 d->addItemChangeListener( this, types );
45 else
46 d->removeItemChangeListener( this, types );
47 }
48 }
49
50 void setup( QQuickItem* item )
51 {
52 QQuickItem* newItemBelow = item ? item->parentItem() : nullptr;
53 QQuickItem* newItemAbove = item;
54
55 if ( newItemBelow != itemBelow )
56 {
57 const auto changeTypes = QQuickItemPrivate::Geometry;
58
59 enableListener( itemBelow, changeTypes, false );
60 enableListener( newItemBelow, changeTypes, true );
61
62 itemBelow = newItemBelow;
63 }
64
65 if ( newItemAbove != itemAbove )
66 {
67 const auto changeTypes = QQuickItemPrivate::Geometry | QQuickItemPrivate::Parent;
68
69 enableListener( itemAbove, changeTypes, false );
70 enableListener( newItemAbove, changeTypes, true );
71
72 itemAbove = newItemAbove;
73 }
74 }
75
76 private:
77 void itemGeometryChanged( QQuickItem* item,
78 QQuickGeometryChange change, const QRectF& ) override
79 {
80 bool doUpdate = false;
81
82 if ( item == itemAbove )
83 doUpdate = change.positionChange();
84 else
85 doUpdate = change.sizeChange();
86
87 if ( doUpdate )
88 m_grabber->updateGeometry();
89 }
90
91 void itemParentChanged( QQuickItem* item, QQuickItem* parentItem ) override
92 {
93 if ( item == m_grabber && parentItem )
94 {
95 setup( parentItem );
96 m_grabber->updateGeometry();
97 }
98 }
99
100 QskInputGrabber* m_grabber;
101
102 public:
103 QPointer< QQuickItem > itemAbove;
104 QPointer< QQuickItem > itemBelow;
105};
106
107QskInputGrabber::QskInputGrabber( QQuickItem* parent )
108 : Inherited( parent )
109 , m_data( new PrivateData( this ) )
110{
111 setAcceptedMouseButtons( Qt::AllButtons );
112 setAcceptTouchEvents( true );
113 setAcceptHoverEvents( true );
114
115 setPlacementPolicy( QskPlacementPolicy::Ignore );
116 setFlag( QQuickItem::ItemHasContents, false );
117
118 m_data->setup( parent );
119 updateGeometry();
120}
121
122QskInputGrabber::~QskInputGrabber()
123{
124 m_data->setup( nullptr );
125}
126
127bool QskInputGrabber::event( QEvent* event )
128{
129 bool doBlock = false;
130
131 switch ( static_cast< int >( event->type() ) )
132 {
133 case QEvent::MouseButtonPress:
134 case QEvent::MouseMove:
135 case QEvent::MouseButtonRelease:
136 {
137 const auto mouseEvent = static_cast< QMouseEvent* >( event );
138 doBlock = isBlocking( qskMousePosition( mouseEvent ) );
139 break;
140 }
141#ifndef QT_NO_WHEELEVENT
142 case QEvent::Wheel:
143 {
144 const auto wheelEvent = static_cast< QWheelEvent* >( event );
145 doBlock = isBlocking( qskWheelPosition( wheelEvent ) );
146 break;
147 }
148#endif
149 case QEvent::HoverEnter:
150 case QEvent::HoverLeave:
151 {
152 const auto ev = static_cast< QHoverEvent* >( event );
153 doBlock = isBlocking( qskHoverPosition( ev ) );
154 break;
155 }
156 }
157
158 if ( doBlock )
159 {
160 event->accept();
161
162 if ( auto w = qobject_cast< QskWindow* >( window() ) )
163 w->setEventAcceptance( QskWindow::EventPropagationStopped );
164
165 return true;
166 }
167
168 return Inherited::event( event );
169}
170
171bool QskInputGrabber::isBlocking( const QPointF& pos ) const
172{
173 if ( const auto item = parentItem() )
174 return !item->contains( position() + pos );
175
176 return true;
177}
178
179QRectF QskInputGrabber::grabberRect() const
180{
181 return m_data->grabberRect();
182}
183
184void QskInputGrabber::updateGeometry()
185{
186 const QRectF rect = grabberRect();
187 if ( rect != geometry() )
188 setGeometry( rect );
189}
190
191#include "moc_QskInputGrabber.cpp"
QRectF rect
Definition QskItem.h:21
QRectF geometry
Definition QskItem.h:20
void setGeometry(qreal x, qreal y, qreal width, qreal height)
Definition QskItem.cpp:330