workarounds for mouse grabbing
This commit is contained in:
parent
b1c750744c
commit
d1f2677c01
|
@ -1,5 +1,6 @@
|
||||||
#include "QskGestureRecognizer.h"
|
#include "QskGestureRecognizer.h"
|
||||||
#include "QskEvent.h"
|
#include "QskEvent.h"
|
||||||
|
#include "QskQuick.h"
|
||||||
|
|
||||||
#include <qbasictimer.h>
|
#include <qbasictimer.h>
|
||||||
#include <qcoreapplication.h>
|
#include <qcoreapplication.h>
|
||||||
|
@ -55,44 +56,6 @@ static inline QMouseEvent* qskClonedMouseEvent(
|
||||||
return clonedEvent;
|
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
|
namespace
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -348,20 +311,6 @@ bool QskGestureRecognizer::processEvent(
|
||||||
return false;
|
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;
|
Qt::MouseButtons buttons = m_data->buttons;
|
||||||
if ( buttons == Qt::NoButton )
|
if ( buttons == Qt::NoButton )
|
||||||
buttons = watchedItem->acceptedMouseButtons();
|
buttons = watchedItem->acceptedMouseButtons();
|
||||||
|
@ -371,11 +320,11 @@ bool QskGestureRecognizer::processEvent(
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We grab the mouse for watchedItem and indicate, that we want
|
We try to 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. Then all mouse events should end up at watchedItem.
|
||||||
*/
|
*/
|
||||||
qskGrabTouchMouse( watchedItem );
|
if ( !qskGrabMouse( watchedItem ) )
|
||||||
watchedItem->setKeepMouseGrab( true );
|
return false;
|
||||||
|
|
||||||
m_data->timestamp = mouseEvent->timestamp();
|
m_data->timestamp = mouseEvent->timestamp();
|
||||||
|
|
||||||
|
@ -509,11 +458,7 @@ void QskGestureRecognizer::reject()
|
||||||
|
|
||||||
m_data->isReplayingEvents = true;
|
m_data->isReplayingEvents = true;
|
||||||
|
|
||||||
if ( window->mouseGrabberItem() == watchedItem )
|
qskUngrabMouse( watchedItem );
|
||||||
{
|
|
||||||
watchedItem->setKeepMouseGrab( false );
|
|
||||||
watchedItem->ungrabMouse();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !events.isEmpty() &&
|
if ( !events.isEmpty() &&
|
||||||
( events[ 0 ]->type() == QEvent::MouseButtonPress ) )
|
( events[ 0 ]->type() == QEvent::MouseButtonPress ) )
|
||||||
|
@ -544,11 +489,7 @@ void QskGestureRecognizer::reset()
|
||||||
{
|
{
|
||||||
qskTimerTable->stopTimer( this );
|
qskTimerTable->stopTimer( this );
|
||||||
|
|
||||||
if ( auto item = m_data->watchedItem )
|
qskUngrabMouse( m_data->watchedItem );
|
||||||
{
|
|
||||||
item->setKeepMouseGrab( false );
|
|
||||||
item->ungrabMouse();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_data->pendingEvents.reset();
|
m_data->pendingEvents.reset();
|
||||||
m_data->timestamp = 0;
|
m_data->timestamp = 0;
|
||||||
|
|
|
@ -640,3 +640,99 @@ void qskItemUpdateRecursive( QQuickItem* item )
|
||||||
for ( auto child : children )
|
for ( auto child : children )
|
||||||
qskItemUpdateRecursive( child );
|
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 void qskItemUpdateRecursive( QQuickItem* );
|
||||||
|
|
||||||
|
QSK_EXPORT bool qskGrabMouse( QQuickItem* );
|
||||||
|
QSK_EXPORT void qskUngrabMouse( QQuickItem* );
|
||||||
|
QSK_EXPORT bool qskIsMouseGrabber( const QQuickItem* );
|
||||||
|
|
||||||
inline void qskSetItemGeometry(
|
inline void qskSetItemGeometry(
|
||||||
QQuickItem* item, qreal x, qreal y, qreal width, qreal height )
|
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.
|
// the mouse grabber has not yet been released.
|
||||||
|
|
||||||
if( !qskIsAncestorOf( this, mouseGrabber ) )
|
if( !qskIsAncestorOf( this, mouseGrabber ) )
|
||||||
mouseGrabber->ungrabMouse();
|
qskUngrabMouse( mouseGrabber );
|
||||||
}
|
}
|
||||||
|
|
||||||
QEventLoop eventLoop;
|
QEventLoop eventLoop;
|
||||||
|
|
Loading…
Reference in New Issue