workarounds for mouse grabbing
This commit is contained in:
parent
b1c750744c
commit
d1f2677c01
@ -1,5 +1,6 @@
|
||||
#include "QskGestureRecognizer.h"
|
||||
#include "QskEvent.h"
|
||||
#include "QskQuick.h"
|
||||
|
||||
#include <qbasictimer.h>
|
||||
#include <qcoreapplication.h>
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user