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