corner case for simultaneous mouse press events on different screens

fixed
This commit is contained in:
Uwe Rathmann 2018-06-14 11:35:47 +02:00
parent b0a87163bf
commit db3f1e3c19
1 changed files with 78 additions and 21 deletions

View File

@ -6,6 +6,7 @@
#include <QBasicTimer> #include <QBasicTimer>
#include <QScopedPointer> #include <QScopedPointer>
#include <QMouseEvent> #include <QMouseEvent>
#include <QVector>
QSK_QT_PRIVATE_BEGIN QSK_QT_PRIVATE_BEGIN
#include <private/qquickwindow_p.h> #include <private/qquickwindow_p.h>
@ -33,38 +34,37 @@ static inline QMouseEvent* qskClonedMouseEvent(
namespace namespace
{ {
// again we try to avoid creating unnecessary QObjects by /*
// using the same timer Object for all gesture recognizers As we don't want QskGestureRecognizer being a QObject
we need some extra timers - usually one per screen.
*/
class Timer final : public QObject class Timer final : public QObject
{ {
public: public:
static Timer* instance() Timer():
m_recognizer( nullptr )
{ {
// ther should be only one mouse being pressed at the same time
static Timer timer;
return &timer;
} }
void start( int ms, QskGestureRecognizer* recognizer ) void start( int ms, QskGestureRecognizer* recognizer )
{ {
if ( m_recognizer && m_recognizer != recognizer ) if ( m_timer.isActive() )
{ qWarning() << "QskGestureRecognizer: resetting an active timer";
qWarning() << "QskGestureRecognizer: running more than one recognizer at the same time";
m_recognizer->reject(); // should never happen
}
m_recognizer = recognizer; m_recognizer = recognizer;
m_timer.start( ms, this ); m_timer.start( ms, this );
} }
void stop( const QskGestureRecognizer* recognizer ) void stop()
{
if ( recognizer == m_recognizer )
{ {
m_timer.stop(); m_timer.stop();
m_recognizer = nullptr; m_recognizer = nullptr;
} }
const QskGestureRecognizer* recognizer() const
{
return m_recognizer;
} }
protected: protected:
@ -85,6 +85,60 @@ namespace
QskGestureRecognizer* m_recognizer; QskGestureRecognizer* m_recognizer;
}; };
class TimerTable
{
public:
~TimerTable()
{
qDeleteAll( m_table );
}
void startTimer( int ms, QskGestureRecognizer* recognizer )
{
Timer* timer = nullptr;
for ( auto t : qskAsConst( m_table ) )
{
if ( t->recognizer() == nullptr
|| t->recognizer() == recognizer )
{
timer = t;
break;
}
}
if ( timer == nullptr )
{
timer = new Timer();
m_table += timer;
}
timer->start( ms, recognizer );
}
void stopTimer( const QskGestureRecognizer* recognizer )
{
for ( auto timer : qskAsConst( m_table ) )
{
if ( timer->recognizer() == recognizer )
{
// we keep the timer to be used later again
timer->stop();
return;
}
}
}
private:
/*
Usually we have not more than one entry.
Only when having more than one screen we
might have mouse events to be processed
simultaneously.
*/
QVector< Timer* > m_table;
};
class PendingEvents : public QVector< QMouseEvent* > class PendingEvents : public QVector< QMouseEvent* >
{ {
public: public:
@ -101,6 +155,8 @@ namespace
}; };
} }
Q_GLOBAL_STATIC( TimerTable, qskTimerTable )
class QskGestureRecognizer::PrivateData class QskGestureRecognizer::PrivateData
{ {
public: public:
@ -136,7 +192,7 @@ QskGestureRecognizer::QskGestureRecognizer():
QskGestureRecognizer::~QskGestureRecognizer() QskGestureRecognizer::~QskGestureRecognizer()
{ {
Timer::instance()->stop( this ); qskTimerTable->stopTimer( this );
} }
void QskGestureRecognizer::setWatchedItem( QQuickItem* item ) void QskGestureRecognizer::setWatchedItem( QQuickItem* item )
@ -286,7 +342,7 @@ bool QskGestureRecognizer::processEvent(
*/ */
if ( m_data->timeout > 0 ) if ( m_data->timeout > 0 )
Timer::instance()->start( m_data->timeout, this ); qskTimerTable->startTimer( m_data->timeout, this );
setState( Pending ); setState( Pending );
} }
@ -370,7 +426,7 @@ void QskGestureRecognizer::stateChanged( State from, State to )
void QskGestureRecognizer::accept() void QskGestureRecognizer::accept()
{ {
Timer::instance()->stop( this ); qskTimerTable->stopTimer( this );
m_data->pendingEvents.reset(); m_data->pendingEvents.reset();
setState( Accepted ); setState( Accepted );
@ -426,7 +482,8 @@ void QskGestureRecognizer::abort()
void QskGestureRecognizer::reset() void QskGestureRecognizer::reset()
{ {
Timer::instance()->stop( this ); qskTimerTable->stopTimer( this );
m_data->watchedItem->setKeepMouseGrab( false ); m_data->watchedItem->setKeepMouseGrab( false );
m_data->pendingEvents.reset(); m_data->pendingEvents.reset();