6#include "QskGestureRecognizer.h"
9#include "QskInternalMacros.h"
11#include <qcoreapplication.h>
12#include <qquickitem.h>
13#include <qquickwindow.h>
16#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
18 #include <private/qquickwindow_p.h>
22static QMouseEvent* qskClonedMouseEvent(
const QMouseEvent* event )
24 QMouseEvent* clonedEvent;
26#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
27 clonedEvent = QQuickWindowPrivate::cloneMouseEvent(
28 const_cast< QMouseEvent*
>( event ),
nullptr );
30 clonedEvent =
event->clone();
32 clonedEvent->setAccepted(
false );
37class QskGestureRecognizer::PrivateData
52 timeoutId = recognizer->startTimer( timeout );
59 recognizer->killTimer( timeoutId );
64 inline Qt::MouseButtons effectiveMouseButtons()
const
66 if ( buttons != Qt::NoButton )
69 return watchedItem->acceptedMouseButtons();
72 QPointer< QQuickItem > watchedItem =
nullptr;
73 QPointer< QQuickItem > targetItem =
nullptr;
75 QVector< QMouseEvent* > pendingEvents;
77 quint64 timestampStarted = 0;
78 quint64 timestampProcessed = 0;
83 Qt::MouseButtons buttons = Qt::NoButton;
85 unsigned char state = QskGestureRecognizer::Idle;
86 bool rejectOnTimeout =
true;
90QskGestureRecognizer::QskGestureRecognizer( QObject* parent )
92 , m_data( new PrivateData() )
96QskGestureRecognizer::~QskGestureRecognizer()
98 qDeleteAll( m_data->pendingEvents );
101void QskGestureRecognizer::setWatchedItem( QQuickItem* item )
103 if ( m_data->watchedItem )
105 m_data->watchedItem->removeEventFilter(
this );
109 m_data->watchedItem = item;
111 if ( m_data->watchedItem )
112 m_data->watchedItem->installEventFilter(
this );
121QQuickItem* QskGestureRecognizer::watchedItem()
const
123 return m_data->watchedItem;
126void QskGestureRecognizer::setTargetItem( QQuickItem* item )
128 m_data->targetItem = item;
131QQuickItem* QskGestureRecognizer::targetItem()
const
133 return m_data->targetItem;
136void QskGestureRecognizer::setAcceptedMouseButtons( Qt::MouseButtons buttons )
138 m_data->buttons = buttons;
141Qt::MouseButtons QskGestureRecognizer::acceptedMouseButtons()
const
143 return m_data->buttons;
146bool QskGestureRecognizer::isAcceptedPos(
const QPointF& pos )
const
148 return m_data->watchedItem && m_data->watchedItem->contains( pos );
151void QskGestureRecognizer::setRejectOnTimeout(
bool on )
153 m_data->rejectOnTimeout = on;
156bool QskGestureRecognizer::rejectOnTimeout()
const
158 return m_data->rejectOnTimeout;
161void QskGestureRecognizer::setTimeout(
int ms )
163 m_data->timeout = ms;
166int QskGestureRecognizer::timeout()
const
168 return m_data->timeout;
171void QskGestureRecognizer::timerEvent( QTimerEvent* event )
173 if ( event->timerId() == m_data->timeoutId )
175 m_data->stopTimer(
this );
177 if ( m_data->rejectOnTimeout )
180 m_data->expired =
true;
186 Inherited::timerEvent( event );
189quint64 QskGestureRecognizer::timestampStarted()
const
191 return m_data->timestampStarted;
194void QskGestureRecognizer::setState( State state )
196 if ( state != m_data->state )
198 const auto oldState =
static_cast< State
>( m_data->state );
199 m_data->state = state;
201 Q_EMIT stateChanged( oldState, state );
205QskGestureRecognizer::State QskGestureRecognizer::state()
const
207 return static_cast< QskGestureRecognizer::State
>( m_data->state );
210bool QskGestureRecognizer::eventFilter( QObject*
object, QEvent* event)
212 auto& watchedItem = m_data->watchedItem;
214 if ( (
object == watchedItem ) &&
215 (
static_cast< int >( event->type() ) == QskEvent::GestureFilter ) )
217 if ( !watchedItem->isEnabled() || !watchedItem->isVisible()
218 || watchedItem->window() ==
nullptr )
225 ev->setMaybeGesture( maybeGesture( ev->item(), ev->event() ) );
227 return ev->maybeGesture();
233bool QskGestureRecognizer::maybeGesture(
234 const QQuickItem* item,
const QEvent* event )
236 switch(
static_cast< int >( event->type() ) )
238 case QEvent::UngrabMouse:
240 if ( m_data->state != Idle )
249 case QEvent::MouseButtonPress:
251 if ( state() != Idle )
253 qWarning() <<
"QskGestureRecognizer: pressed, while not being idle";
257 const auto mouseEvent =
static_cast< const QMouseEvent*
>( event );
259 if ( mouseEvent->timestamp() > m_data->timestampProcessed )
261 m_data->timestampProcessed = mouseEvent->timestamp();
284 if ( item || !m_data->expired )
288 return processMouseEvent( item, mouseEvent );
290 case QEvent::MouseMove:
291 case QEvent::MouseButtonRelease:
293 if ( state() <= Idle )
296 const auto mouseEvent =
static_cast< const QMouseEvent*
>( event );
297 return processMouseEvent( item, mouseEvent );
304bool QskGestureRecognizer::processMouseEvent(
305 const QQuickItem* item,
const QMouseEvent* event )
307 auto& watchedItem = m_data->watchedItem;
309 const auto pos = watchedItem->mapFromScene( qskMouseScenePosition( event ) );
310 const auto timestamp =
event->timestamp();
312 if ( event->type() == QEvent::MouseButtonPress )
314 if ( !isAcceptedPos( pos ) )
317 if ( m_data->state != Idle )
320 qWarning() <<
"QskGestureRecognizer: pressed, while not being idle";
325 if ( !( m_data->effectiveMouseButtons() & event->button() ) )
332 if ( !qskGrabMouse( watchedItem ) )
335 m_data->timestampStarted = timestamp;
337 if ( m_data->timeout != 0 )
344 m_data->stopTimer(
this );
346 if ( m_data->timeout > 0 )
347 m_data->startTimer(
this );
357 if ( m_data->state <= Idle )
360 if ( m_data->state == Pending )
361 m_data->pendingEvents += qskClonedMouseEvent( event );
363 switch(
static_cast< int >( event->type() ) )
365 case QEvent::MouseButtonPress:
366 processPress( pos, timestamp, item ==
nullptr );
369 case QEvent::MouseMove:
370 processMove( pos, timestamp );
373 case QEvent::MouseButtonRelease:
375 if ( m_data->state == Pending )
381 processRelease( pos, timestamp );
391void QskGestureRecognizer::processPress(
392 const QPointF& pos, quint64 timestamp,
bool isFinal )
395 Q_UNUSED( timestamp );
399void QskGestureRecognizer::processMove(
const QPointF& pos, quint64 timestamp )
402 Q_UNUSED( timestamp );
405void QskGestureRecognizer::processRelease(
const QPointF& pos, quint64 timestamp )
408 Q_UNUSED( timestamp );
411void QskGestureRecognizer::accept()
413 m_data->stopTimer(
this );
415 qDeleteAll( m_data->pendingEvents );
416 m_data->pendingEvents.clear();
418 setState( Accepted );
421void QskGestureRecognizer::reject()
427 const auto events = m_data->pendingEvents;
428 m_data->pendingEvents.clear();
440 if ( !events.isEmpty() )
442 if (
auto watchedItem = m_data->watchedItem )
444 if (
const auto window = watchedItem->window() )
446 for (
auto event : events )
447 QCoreApplication::postEvent( window, event );
453 qDeleteAll( events );
458void QskGestureRecognizer::abort()
463void QskGestureRecognizer::reset()
465 m_data->stopTimer(
this );
466 qskUngrabMouse( m_data->watchedItem );
468 qDeleteAll( m_data->pendingEvents );
469 m_data->pendingEvents.clear();
471 m_data->timestampStarted = 0;
472 m_data->expired =
false;
477#include "moc_QskGestureRecognizer.cpp"