workround for broken mouse grabbing ( >= Qt 5.8 ) added

This commit is contained in:
Uwe Rathmann 2021-03-02 16:15:56 +01:00
parent e32c17df51
commit 5bf10f5cc5
1 changed files with 45 additions and 45 deletions

View File

@ -55,6 +55,44 @@ static inline QMouseEvent* qskClonedMouseEvent(
return clonedEvent; return clonedEvent;
} }
static void qskGrabTouchMouse( QQuickItem* item )
{
#if QT_VERSION >= QT_VERSION_CHECK( 5, 8, 0 )
auto wd = QQuickWindowPrivate::get( item->window() );
if ( wd->touchMouseDevice == nullptr )
{
/*
For synthesized mouse events QQuickWindow sends
an initial QEvent::MouseButtonPress before setting
touchMouseDevice/touchMouseId and a call of grabMouse
is stored in a pointerEvent for the generic mouse device.
Then all following synthesized mouse events are not grabbed
properly.
*/
for ( const auto event : wd->pointerEventInstances )
{
if ( auto touchEvent = event->asPointerTouchEvent() )
{
if ( touchEvent->isPressEvent() )
{
if ( const auto p = touchEvent->point( 0 ) )
{
wd->touchMouseDevice = touchEvent->device();
wd->touchMouseId = p->pointId();
}
break;
}
}
}
}
#endif
item->grabMouse();
}
namespace namespace
{ {
/* /*
@ -336,7 +374,7 @@ bool QskGestureRecognizer::processEvent(
We grab the mouse for watchedItem and indicate, that we want We grab the mouse for watchedItem and indicate, that we want
to keep it. From now on all mouse events should end up at watchedItem. to keep it. From now on all mouse events should end up at watchedItem.
*/ */
watchedItem->grabMouse(); qskGrabTouchMouse( watchedItem );
watchedItem->setKeepMouseGrab( true ); watchedItem->setKeepMouseGrab( true );
m_data->timestamp = mouseEvent->timestamp(); m_data->timestamp = mouseEvent->timestamp();
@ -403,30 +441,8 @@ bool QskGestureRecognizer::processEvent(
if ( m_data->state == Pending ) if ( m_data->state == Pending )
{ {
#if QT_VERSION >= QT_VERSION_CHECK( 5, 10, 0 )
if ( mouseEvent->source() == Qt::MouseEventSynthesizedByQt )
{
/*
When replaying mouse events inside of handling synthesized
mouse event Qt runs into a situation where
QQuickWindow::mouseGrabberItem() returns the value from the
wrong input device. So we can't call reject() immediately.
Unfortunately this introduces a gap where other events might
be delivered before the QEvent::timer gets processed.
In the long run it might be better to record and replay
real touch events - what is necessary for multi touch gestures
anyway.
*/
qskTimerTable->stopTimer( this );
qskTimerTable->startTimer( 0, this );
}
else
#endif
{
reject(); reject();
} }
}
else else
{ {
releaseEvent( mouseEvent ); releaseEvent( mouseEvent );
@ -509,18 +525,8 @@ void QskGestureRecognizer::reject()
m_data->timestampProcessed = events.last()->timestamp(); m_data->timestampProcessed = events.last()->timestamp();
QCoreApplication::sendEvent( window, events[ 0 ] ); for ( auto event : events )
QCoreApplication::sendEvent( window, event );
/*
After resending the initial press someone else
might be interested in this sequence.
*/
if ( window->mouseGrabberItem() )
{
for ( int i = 1; i < events.size(); i++ )
QCoreApplication::sendEvent( window, events[ i ] );
}
} }
m_data->isReplayingEvents = false; m_data->isReplayingEvents = false;
@ -535,19 +541,13 @@ void QskGestureRecognizer::reset()
{ {
qskTimerTable->stopTimer( this ); qskTimerTable->stopTimer( this );
if ( auto watchedItem = m_data->watchedItem ) if ( auto item = m_data->watchedItem )
{ {
watchedItem->setKeepMouseGrab( false ); item->setKeepMouseGrab( false );
item->ungrabMouse();
if ( auto window = watchedItem->window() )
{
if ( window->mouseGrabberItem() == m_data->watchedItem )
watchedItem->ungrabMouse();
}
} }
m_data->pendingEvents.reset(); m_data->pendingEvents.reset();
m_data->timestamp = 0; m_data->timestamp = 0;
setState( Idle ); setState( Idle );