diff --git a/src/controls/QskGestureRecognizer.cpp b/src/controls/QskGestureRecognizer.cpp index 90253c21..da7d726e 100644 --- a/src/controls/QskGestureRecognizer.cpp +++ b/src/controls/QskGestureRecognizer.cpp @@ -1,5 +1,6 @@ #include "QskGestureRecognizer.h" #include "QskEvent.h" +#include "QskQuick.h" #include #include @@ -55,44 +56,6 @@ static inline QMouseEvent* qskClonedMouseEvent( return clonedEvent; } -static void qskGrabTouchMouse( QQuickItem* item ) -{ -#if QT_VERSION >= QT_VERSION_CHECK( 5, 8, 0 ) && QT_VERSION < QT_VERSION_CHECK( 6, 0, 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 { /* @@ -348,20 +311,6 @@ bool QskGestureRecognizer::processEvent( return false; } - auto mouseGrabber = watchedItem->window()->mouseGrabberItem(); - if ( mouseGrabber && ( mouseGrabber != watchedItem ) ) - { - if ( mouseGrabber->keepMouseGrab() || mouseGrabber->keepTouchGrab() ) - { - /* - Another child has grabbed mouse/touch and is not willing to - be intercepted: we respect this. - */ - - return false; - } - } - Qt::MouseButtons buttons = m_data->buttons; if ( buttons == Qt::NoButton ) buttons = watchedItem->acceptedMouseButtons(); @@ -371,11 +320,11 @@ bool QskGestureRecognizer::processEvent( return false; /* - 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. + We try to grab the mouse for watchedItem and indicate, that we want + to keep it. Then all mouse events should end up at watchedItem. */ - qskGrabTouchMouse( watchedItem ); - watchedItem->setKeepMouseGrab( true ); + if ( !qskGrabMouse( watchedItem ) ) + return false; m_data->timestamp = mouseEvent->timestamp(); @@ -509,11 +458,7 @@ void QskGestureRecognizer::reject() m_data->isReplayingEvents = true; - if ( window->mouseGrabberItem() == watchedItem ) - { - watchedItem->setKeepMouseGrab( false ); - watchedItem->ungrabMouse(); - } + qskUngrabMouse( watchedItem ); if ( !events.isEmpty() && ( events[ 0 ]->type() == QEvent::MouseButtonPress ) ) @@ -544,11 +489,7 @@ void QskGestureRecognizer::reset() { qskTimerTable->stopTimer( this ); - if ( auto item = m_data->watchedItem ) - { - item->setKeepMouseGrab( false ); - item->ungrabMouse(); - } + qskUngrabMouse( m_data->watchedItem ); m_data->pendingEvents.reset(); m_data->timestamp = 0; diff --git a/src/controls/QskQuick.cpp b/src/controls/QskQuick.cpp index 808238dc..b38266c4 100644 --- a/src/controls/QskQuick.cpp +++ b/src/controls/QskQuick.cpp @@ -640,3 +640,99 @@ void qskItemUpdateRecursive( QQuickItem* item ) for ( auto child : children ) qskItemUpdateRecursive( child ); } + +#if QT_VERSION >= QT_VERSION_CHECK( 5, 8, 0 ) && QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) + +static const QQuickPointerTouchEvent* qskPointerPressEvent( const QQuickWindowPrivate* wd ) +{ + for ( const auto event : wd->pointerEventInstances ) + { + if ( auto touchEvent = event->asPointerTouchEvent() ) + { + if ( touchEvent->isPressEvent() ) + return touchEvent; + } + } + + return nullptr; +} + +#endif + +bool qskGrabMouse( QQuickItem* item ) +{ + if ( item == nullptr || item->window() == nullptr ) + return false; + + if ( const auto mouseGrabber = item->window()->mouseGrabberItem() ) + { + if ( mouseGrabber == item ) + return true; + + if ( mouseGrabber->keepMouseGrab() ) + { + // we respect this + return false; + } + } + + item->setKeepMouseGrab( true ); + +#if QT_VERSION >= QT_VERSION_CHECK( 5, 8, 0 ) && QT_VERSION < QT_VERSION_CHECK( 6, 0, 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. As the mouse grabber is + stored depending on these attributes the following + mouse event callbacks will look for the grabber at a + a different place as it was stored. + */ + + if ( const auto event = qskPointerPressEvent( wd ) ) + { + if ( const auto p = event->point( 0 ) ) + { + wd->touchMouseDevice = event->device(); + wd->touchMouseId = p->pointId(); + + item->grabMouse(); + + wd->touchMouseDevice = nullptr; + wd->touchMouseId = -1; + + return true; + } + } + } +#endif + + item->grabMouse(); + return true; +} + +void qskUngrabMouse( QQuickItem* item ) +{ + if ( item ) + { + item->setKeepMouseGrab( false ); + + if ( qskIsMouseGrabber( item ) ) + item->ungrabMouse(); + + } +} + +bool qskIsMouseGrabber( const QQuickItem* item ) +{ + if ( item ) + { + if ( const auto window = item->window() ) + return window->mouseGrabberItem() == item; + } + + return false; +} diff --git a/src/controls/QskQuick.h b/src/controls/QskQuick.h index be88501f..1fa917e5 100644 --- a/src/controls/QskQuick.h +++ b/src/controls/QskQuick.h @@ -67,6 +67,10 @@ QSK_EXPORT const QSGNode* qskPaintNode( const QQuickItem* ); QSK_EXPORT void qskItemUpdateRecursive( QQuickItem* ); +QSK_EXPORT bool qskGrabMouse( QQuickItem* ); +QSK_EXPORT void qskUngrabMouse( QQuickItem* ); +QSK_EXPORT bool qskIsMouseGrabber( const QQuickItem* ); + inline void qskSetItemGeometry( QQuickItem* item, qreal x, qreal y, qreal width, qreal height ) { diff --git a/src/dialogs/QskDialogSubWindow.cpp b/src/dialogs/QskDialogSubWindow.cpp index d2149517..486255da 100644 --- a/src/dialogs/QskDialogSubWindow.cpp +++ b/src/dialogs/QskDialogSubWindow.cpp @@ -258,7 +258,7 @@ QskDialog::DialogCode QskDialogSubWindow::exec() // the mouse grabber has not yet been released. if( !qskIsAncestorOf( this, mouseGrabber ) ) - mouseGrabber->ungrabMouse(); + qskUngrabMouse( mouseGrabber ); } QEventLoop eventLoop;