6#include "QskGestureRecognizer.h"
10#include <qcoreapplication.h>
11#include <qquickitem.h>
12#include <qquickwindow.h>
15#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
17 #include <private/qquickwindow_p.h>
21static QMouseEvent* qskClonedMouseEvent(
const QMouseEvent* event )
23 QMouseEvent* clonedEvent;
25#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
26 clonedEvent = QQuickWindowPrivate::cloneMouseEvent(
27 const_cast< QMouseEvent*
>( event ),
nullptr );
29 clonedEvent =
event->clone();
31 clonedEvent->setAccepted(
false );
36class QskGestureRecognizer::PrivateData
51 timeoutId = recognizer->startTimer( timeout );
58 recognizer->killTimer( timeoutId );
63 inline Qt::MouseButtons effectiveMouseButtons()
const
65 if ( buttons != Qt::NoButton )
68 return watchedItem->acceptedMouseButtons();
71 QPointer< QQuickItem > watchedItem =
nullptr;
72 QPointer< QQuickItem > targetItem =
nullptr;
74 QVector< QMouseEvent* > pendingEvents;
76 quint64 timestampStarted = 0;
77 quint64 timestampProcessed = 0;
82 Qt::MouseButtons buttons = Qt::NoButton;
84 unsigned char state = QskGestureRecognizer::Idle;
85 bool rejectOnTimeout =
true;
89QskGestureRecognizer::QskGestureRecognizer( QObject* parent )
91 , m_data( new PrivateData() )
95QskGestureRecognizer::~QskGestureRecognizer()
97 qDeleteAll( m_data->pendingEvents );
100void QskGestureRecognizer::setWatchedItem( QQuickItem* item )
102 if ( m_data->watchedItem )
104 m_data->watchedItem->removeEventFilter(
this );
108 m_data->watchedItem = item;
110 if ( m_data->watchedItem )
111 m_data->watchedItem->installEventFilter(
this );
120QQuickItem* QskGestureRecognizer::watchedItem()
const
122 return m_data->watchedItem;
125void QskGestureRecognizer::setTargetItem( QQuickItem* item )
127 m_data->targetItem = item;
130QQuickItem* QskGestureRecognizer::targetItem()
const
132 return m_data->targetItem;
135void QskGestureRecognizer::setAcceptedMouseButtons( Qt::MouseButtons buttons )
137 m_data->buttons = buttons;
140Qt::MouseButtons QskGestureRecognizer::acceptedMouseButtons()
const
142 return m_data->buttons;
145bool QskGestureRecognizer::isAcceptedPos(
const QPointF& pos )
const
147 return m_data->watchedItem && m_data->watchedItem->contains( pos );
150void QskGestureRecognizer::setRejectOnTimeout(
bool on )
152 m_data->rejectOnTimeout = on;
155bool QskGestureRecognizer::rejectOnTimeout()
const
157 return m_data->rejectOnTimeout;
160void QskGestureRecognizer::setTimeout(
int ms )
162 m_data->timeout = ms;
165int QskGestureRecognizer::timeout()
const
167 return m_data->timeout;
170void QskGestureRecognizer::timerEvent( QTimerEvent* event )
172 if ( event->timerId() == m_data->timeoutId )
174 m_data->stopTimer(
this );
176 if ( m_data->rejectOnTimeout )
179 m_data->expired =
true;
185 Inherited::timerEvent( event );
188quint64 QskGestureRecognizer::timestampStarted()
const
190 return m_data->timestampStarted;
193void QskGestureRecognizer::setState( State state )
195 if ( state != m_data->state )
197 const auto oldState =
static_cast< State
>( m_data->state );
198 m_data->state = state;
200 Q_EMIT stateChanged( oldState, state );
204QskGestureRecognizer::State QskGestureRecognizer::state()
const
206 return static_cast< QskGestureRecognizer::State
>( m_data->state );
209bool QskGestureRecognizer::eventFilter( QObject*
object, QEvent* event)
211 auto& watchedItem = m_data->watchedItem;
213 if ( (
object == watchedItem ) &&
214 (
static_cast< int >( event->type() ) == QskEvent::GestureFilter ) )
216 if ( !watchedItem->isEnabled() || !watchedItem->isVisible()
217 || watchedItem->window() ==
nullptr )
224 ev->setMaybeGesture( maybeGesture( ev->item(), ev->event() ) );
226 return ev->maybeGesture();
232bool QskGestureRecognizer::maybeGesture(
233 const QQuickItem* item,
const QEvent* event )
235 switch(
static_cast< int >( event->type() ) )
237 case QEvent::UngrabMouse:
239 if ( m_data->state != Idle )
248 case QEvent::MouseButtonPress:
250 if ( state() != Idle )
252 qWarning() <<
"QskGestureRecognizer: pressed, while not being idle";
256 const auto mouseEvent =
static_cast< const QMouseEvent*
>( event );
258 if ( mouseEvent->timestamp() > m_data->timestampProcessed )
260 m_data->timestampProcessed = mouseEvent->timestamp();
283 if ( item || !m_data->expired )
287 return processMouseEvent( item, mouseEvent );
289 case QEvent::MouseMove:
290 case QEvent::MouseButtonRelease:
292 if ( state() <= Idle )
295 const auto mouseEvent =
static_cast< const QMouseEvent*
>( event );
296 return processMouseEvent( item, mouseEvent );
303bool QskGestureRecognizer::processMouseEvent(
304 const QQuickItem* item,
const QMouseEvent* event )
306 auto& watchedItem = m_data->watchedItem;
308 const auto pos = watchedItem->mapFromScene( qskMouseScenePosition( event ) );
309 const auto timestamp =
event->timestamp();
311 if ( event->type() == QEvent::MouseButtonPress )
313 if ( !isAcceptedPos( pos ) )
316 if ( m_data->state != Idle )
319 qWarning() <<
"QskGestureRecognizer: pressed, while not being idle";
324 if ( !( m_data->effectiveMouseButtons() & event->button() ) )
331 if ( !qskGrabMouse( watchedItem ) )
334 m_data->timestampStarted = timestamp;
336 if ( m_data->timeout != 0 )
343 m_data->stopTimer(
this );
345 if ( m_data->timeout > 0 )
346 m_data->startTimer(
this );
356 if ( m_data->state <= Idle )
359 if ( m_data->state == Pending )
360 m_data->pendingEvents += qskClonedMouseEvent( event );
362 switch(
static_cast< int >( event->type() ) )
364 case QEvent::MouseButtonPress:
365 processPress( pos, timestamp, item ==
nullptr );
368 case QEvent::MouseMove:
369 processMove( pos, timestamp );
372 case QEvent::MouseButtonRelease:
374 if ( m_data->state == Pending )
380 processRelease( pos, timestamp );
390void QskGestureRecognizer::processPress(
391 const QPointF& pos, quint64 timestamp,
bool isFinal )
394 Q_UNUSED( timestamp );
398void QskGestureRecognizer::processMove(
const QPointF& pos, quint64 timestamp )
401 Q_UNUSED( timestamp );
404void QskGestureRecognizer::processRelease(
const QPointF& pos, quint64 timestamp )
407 Q_UNUSED( timestamp );
410void QskGestureRecognizer::accept()
412 m_data->stopTimer(
this );
414 qDeleteAll( m_data->pendingEvents );
415 m_data->pendingEvents.clear();
417 setState( Accepted );
420void QskGestureRecognizer::reject()
426 const auto events = m_data->pendingEvents;
427 m_data->pendingEvents.clear();
439 if ( !events.isEmpty() )
441 if (
auto watchedItem = m_data->watchedItem )
443 if (
const auto window = watchedItem->window() )
445 for (
auto event : events )
446 QCoreApplication::postEvent( window, event );
452 qDeleteAll( events );
457void QskGestureRecognizer::abort()
462void QskGestureRecognizer::reset()
464 m_data->stopTimer(
this );
465 qskUngrabMouse( m_data->watchedItem );
467 qDeleteAll( m_data->pendingEvents );
468 m_data->pendingEvents.clear();
470 m_data->timestampStarted = 0;
471 m_data->expired =
false;
476#include "moc_QskGestureRecognizer.cpp"