添加触摸相关的patch
This commit is contained in:
parent
94a17c302c
commit
7fd2ef7c6a
|
@ -47,12 +47,14 @@
|
||||||
#include "qgraphicssceneevent.h"
|
#include "qgraphicssceneevent.h"
|
||||||
#include "qgraphicsview.h"
|
#include "qgraphicsview.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "qstylehints.h"
|
||||||
#include "qscroller.h"
|
#include "qscroller.h"
|
||||||
#include <QtGui/qtouchdevice.h>
|
#include <QtGui/qtouchdevice.h>
|
||||||
#include "private/qapplication_p.h"
|
#include "private/qapplication_p.h"
|
||||||
#include "private/qevent_p.h"
|
#include "private/qevent_p.h"
|
||||||
#include "private/qflickgesture_p.h"
|
#include "private/qflickgesture_p.h"
|
||||||
#include "qdebug.h"
|
#include "qdebug.h"
|
||||||
|
#include "qtimer.h"
|
||||||
|
|
||||||
#ifndef QT_NO_GESTURES
|
#ifndef QT_NO_GESTURES
|
||||||
|
|
||||||
|
@ -68,13 +70,258 @@ QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
|
extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
|
||||||
|
|
||||||
static QMouseEvent *copyMouseEvent(QEvent *e)
|
QTimer* PressDelayHandler::m_pressDelayTimer;
|
||||||
|
bool PressDelayHandler::m_sendingEvent = false;
|
||||||
|
QScopedPointer<QEvent> PressDelayHandler::m_pressDelayEvent;
|
||||||
|
QPointer<QObject> PressDelayHandler::m_pressTarget;
|
||||||
|
|
||||||
|
PressDelayHandler::PressDelayHandler(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
PressDelayHandler* PressDelayHandler::create(Qt::MouseButton button)
|
||||||
|
{
|
||||||
|
switch (button) {
|
||||||
|
case Qt::LeftButton:
|
||||||
|
return new MousePressDelayHandler(QCoreApplication::instance());
|
||||||
|
break;
|
||||||
|
case Qt::NoButton:
|
||||||
|
return new TouchPressDelayHandler(QCoreApplication::instance());
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return new MousePressDelayHandler(QCoreApplication::instance());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PressDelayHandler::shouldEventBeIgnored() const
|
||||||
|
{
|
||||||
|
return m_sendingEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PressDelayHandler::isDelaying() const
|
||||||
|
{
|
||||||
|
return hasSavedDelayEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressDelayHandler::pressed(QEvent *e, int delay)
|
||||||
|
{
|
||||||
|
if (!hasSavedDelayEvent()) {
|
||||||
|
qFGDebug("QFG: consuming/delaying press");
|
||||||
|
m_pressDelayEvent.reset(copyEvent(e));
|
||||||
|
saveDelayEventInfo(e);
|
||||||
|
startTimer(delay);
|
||||||
|
} else {
|
||||||
|
qFGDebug("QFG: NOT consuming/delaying press");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PressDelayHandler::released(QEvent *e, bool scrollerWasActive, bool scrollerIsActive)
|
||||||
|
{
|
||||||
|
// stop the timer
|
||||||
|
stopTimer();
|
||||||
|
|
||||||
|
bool result = scrollerWasActive || scrollerIsActive;
|
||||||
|
|
||||||
|
// we still haven't even sent the press, so do it now
|
||||||
|
if (hasSavedDelayEvent() && pressTarget() && !scrollerIsActive) {
|
||||||
|
|
||||||
|
qFGDebug() << "QFG: re-sending press (due to release) for " << pressTarget();
|
||||||
|
sendSpontaneousEvent(m_pressDelayEvent.data(), pressTarget(), UngrabMouseBefore);
|
||||||
|
|
||||||
|
qFGDebug() << "QFG: faking release (due to release) for " << pressTarget();
|
||||||
|
sendSpontaneousEvent(e, pressTarget(), 0);
|
||||||
|
|
||||||
|
result = true; // consume this event
|
||||||
|
} else if (pressTarget() && scrollerIsActive) {
|
||||||
|
// we grabbed the mouse expicitly when the scroller became active, so undo that now
|
||||||
|
qFGDebug() << "QFG: ungrab mouse which grabbed when the scroller became active";
|
||||||
|
sendSpontaneousEvent(nullptr, pressTarget(), UngrabMouseBefore);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetDelayEvent();
|
||||||
|
resetPressTarget();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressDelayHandler::scrollerWasIntercepted()
|
||||||
|
{
|
||||||
|
qFGDebug("QFG: deleting delayed press, since scroller was only intercepted");
|
||||||
|
if (hasSavedDelayEvent()) {
|
||||||
|
// we still haven't even sent the press, so just throw it away now
|
||||||
|
stopTimer();
|
||||||
|
}
|
||||||
|
resetPressTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressDelayHandler::scrollerBecameActive()
|
||||||
|
{
|
||||||
|
if (hasSavedDelayEvent()) {
|
||||||
|
// we still haven't even sent the press, so just throw it away now
|
||||||
|
qFGDebug("QFG: deleting delayed mouse press, since scroller is active now");
|
||||||
|
stopTimer();
|
||||||
|
resetDelayEvent();
|
||||||
|
resetPressTarget();
|
||||||
|
} else if (pressTarget()) {
|
||||||
|
// we did send a press, so we need to fake a release now
|
||||||
|
releaseAllPressed();
|
||||||
|
// don't clear the pressTarget just yet, since we need to explicitly ungrab the mouse on release!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressDelayHandler::onDelayTimeout()
|
||||||
|
{
|
||||||
|
if (hasSavedDelayEvent() && pressTarget()) {
|
||||||
|
qFGDebug() << "QFG: timer event: re-sending press to " << pressTarget();
|
||||||
|
sendSpontaneousEvent(m_pressDelayEvent.data(), pressTarget(), UngrabMouseBefore);
|
||||||
|
}
|
||||||
|
resetDelayEvent();
|
||||||
|
|
||||||
|
stopTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressDelayHandler::stopTimer()
|
||||||
|
{
|
||||||
|
if (!m_pressDelayTimer)
|
||||||
|
return;
|
||||||
|
if (!m_pressDelayTimer->isActive())
|
||||||
|
return;
|
||||||
|
m_pressDelayTimer->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressDelayHandler::startTimer(int timeout)
|
||||||
|
{
|
||||||
|
if (!m_pressDelayTimer)
|
||||||
|
m_pressDelayTimer = new QTimer;
|
||||||
|
if (m_pressDelayTimer->isActive()) {
|
||||||
|
qFGDebug() << "QFG: timer is active, don't start again";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_pressDelayTimer->singleShot(timeout, this, &PressDelayHandler::onDelayTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressDelayHandler::sendSpontaneousEvent(QEvent *e, QObject *target, int flags)
|
||||||
|
{
|
||||||
|
#if QT_CONFIG(graphicsview)
|
||||||
|
if (flags & UngrabMouseBefore)
|
||||||
|
ungrabMouse(mouseGrabberItem());
|
||||||
|
#else
|
||||||
|
Q_UNUSED(flags);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_sendingEvent = true;
|
||||||
|
sendEvent(e, target);
|
||||||
|
m_sendingEvent = false;
|
||||||
|
|
||||||
|
#if QT_CONFIG(graphicsview)
|
||||||
|
if (flags & RegrabMouseAfterwards)
|
||||||
|
grabMouse(mouseGrabberItem());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointer<QObject> PressDelayHandler::pressTarget() const
|
||||||
|
{
|
||||||
|
return m_pressTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressDelayHandler::setPressTarget(QObject* pressTarget)
|
||||||
|
{
|
||||||
|
m_pressTarget = pressTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressDelayHandler::resetPressTarget()
|
||||||
|
{
|
||||||
|
m_pressTarget = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PressDelayHandler::hasSavedDelayEvent() const
|
||||||
|
{
|
||||||
|
return !m_pressDelayEvent.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressDelayHandler::resetDelayEvent()
|
||||||
|
{
|
||||||
|
m_pressDelayEvent.reset(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
QGraphicsItem* PressDelayHandler::mouseGrabberItem() const
|
||||||
|
{
|
||||||
|
QGraphicsItem *grabber = nullptr;
|
||||||
|
|
||||||
|
QWidget* targetWidget = nullptr;
|
||||||
|
if (pressTarget().data()->isWidgetType()) {
|
||||||
|
targetWidget = dynamic_cast<QWidget*>(pressTarget().data());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
targetWidget = QApplication::widgetAt(QCursor::pos());
|
||||||
|
}
|
||||||
|
if (!targetWidget)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (targetWidget->parentWidget()) {
|
||||||
|
if (QGraphicsView *gv = qobject_cast<QGraphicsView *>(targetWidget->parentWidget())) {
|
||||||
|
if (gv->scene())
|
||||||
|
grabber = gv->scene()->mouseGrabberItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return grabber;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressDelayHandler::grabMouse(QGraphicsItem* grabber) const
|
||||||
|
{
|
||||||
|
if (!grabber)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// GraphicsView Mouse Handling Workaround #2:
|
||||||
|
// we need to re-grab the mouse after sending a faked mouse
|
||||||
|
// release, since we still need the mouse moves for the gesture
|
||||||
|
// (the scene will clear the item's mouse grabber status on
|
||||||
|
// release).
|
||||||
|
qFGDebug() << "QFG: re-grabbing" << grabber;
|
||||||
|
grabber->grabMouse();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PressDelayHandler::ungrabMouse(QGraphicsItem* grabber) const
|
||||||
|
{
|
||||||
|
if (!grabber)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// GraphicsView Mouse Handling Workaround #1:
|
||||||
|
// we need to ungrab the mouse before re-sending the press,
|
||||||
|
// since the scene had already set the mouse grabber to the
|
||||||
|
// original (and consumed) event's receiver
|
||||||
|
qFGDebug() << "QFG: ungrabbing" << grabber;
|
||||||
|
grabber->ungrabMouse();
|
||||||
|
}
|
||||||
|
|
||||||
|
MousePressDelayHandler::MousePressDelayHandler(QObject *parent)
|
||||||
|
: PressDelayHandler(parent)
|
||||||
|
, m_mouseButton(Qt::NoButton)
|
||||||
|
, m_mouseEventSource(Qt::MouseEventNotSynthesized)
|
||||||
|
{
|
||||||
|
qFGDebug("QFG: create MousePressDelayHandler");
|
||||||
|
}
|
||||||
|
|
||||||
|
void MousePressDelayHandler::saveDelayEventInfo(QEvent* e)
|
||||||
|
{
|
||||||
|
QMouseEvent* me = dynamic_cast<QMouseEvent*>(e);
|
||||||
|
if (!me) {
|
||||||
|
qWarning() << "MousePressDelayHandler handling event not QMouseEvent";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPressTarget(QApplication::widgetAt(me->globalPos()));
|
||||||
|
m_mouseButton = me->button();
|
||||||
|
m_mouseEventSource = me->source();
|
||||||
|
}
|
||||||
|
|
||||||
|
QEvent* MousePressDelayHandler::copyEvent(QEvent *e)
|
||||||
{
|
{
|
||||||
switch (e->type()) {
|
switch (e->type()) {
|
||||||
case QEvent::MouseButtonPress:
|
case QEvent::MouseButtonPress:
|
||||||
case QEvent::MouseButtonRelease:
|
case QEvent::MouseButtonRelease:
|
||||||
case QEvent::MouseMove: {
|
case QEvent::MouseMove: {
|
||||||
QMouseEvent *me = static_cast<QMouseEvent *>(e);
|
QMouseEvent *me = dynamic_cast<QMouseEvent *>(e);
|
||||||
QMouseEvent *cme = new QMouseEvent(me->type(), QPoint(0, 0), me->windowPos(), me->screenPos(),
|
QMouseEvent *cme = new QMouseEvent(me->type(), QPoint(0, 0), me->windowPos(), me->screenPos(),
|
||||||
me->button(), me->buttons(), me->modifiers(), me->source());
|
me->button(), me->buttons(), me->modifiers(), me->source());
|
||||||
return cme;
|
return cme;
|
||||||
|
@ -83,7 +330,7 @@ static QMouseEvent *copyMouseEvent(QEvent *e)
|
||||||
case QEvent::GraphicsSceneMousePress:
|
case QEvent::GraphicsSceneMousePress:
|
||||||
case QEvent::GraphicsSceneMouseRelease:
|
case QEvent::GraphicsSceneMouseRelease:
|
||||||
case QEvent::GraphicsSceneMouseMove: {
|
case QEvent::GraphicsSceneMouseMove: {
|
||||||
QGraphicsSceneMouseEvent *me = static_cast<QGraphicsSceneMouseEvent *>(e);
|
QGraphicsSceneMouseEvent *me = dynamic_cast<QGraphicsSceneMouseEvent *>(e);
|
||||||
#if 1
|
#if 1
|
||||||
QEvent::Type met = me->type() == QEvent::GraphicsSceneMousePress ? QEvent::MouseButtonPress :
|
QEvent::Type met = me->type() == QEvent::GraphicsSceneMousePress ? QEvent::MouseButtonPress :
|
||||||
(me->type() == QEvent::GraphicsSceneMouseRelease ? QEvent::MouseButtonRelease : QEvent::MouseMove);
|
(me->type() == QEvent::GraphicsSceneMouseRelease ? QEvent::MouseButtonRelease : QEvent::MouseMove);
|
||||||
|
@ -118,216 +365,193 @@ static QMouseEvent *copyMouseEvent(QEvent *e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PressDelayHandler : public QObject
|
void MousePressDelayHandler::sendEvent(QEvent *e, QObject* target)
|
||||||
{
|
{
|
||||||
private:
|
QMouseEvent* me = dynamic_cast<QMouseEvent*>(e);
|
||||||
PressDelayHandler(QObject *parent = nullptr)
|
QWidget* targetWidget = dynamic_cast<QWidget*>(target);
|
||||||
: QObject(parent)
|
|
||||||
, pressDelayTimer(0)
|
|
||||||
, sendingEvent(false)
|
|
||||||
, mouseButton(Qt::NoButton)
|
|
||||||
, mouseTarget(nullptr)
|
|
||||||
, mouseEventSource(Qt::MouseEventNotSynthesized)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public:
|
if (!targetWidget) {
|
||||||
enum {
|
return;
|
||||||
UngrabMouseBefore = 1,
|
|
||||||
RegrabMouseAfterwards = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
static PressDelayHandler *instance()
|
|
||||||
{
|
|
||||||
static PressDelayHandler *inst = nullptr;
|
|
||||||
if (!inst)
|
|
||||||
inst = new PressDelayHandler(QCoreApplication::instance());
|
|
||||||
return inst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldEventBeIgnored(QEvent *) const
|
|
||||||
{
|
|
||||||
return sendingEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isDelaying() const
|
|
||||||
{
|
|
||||||
return !pressDelayEvent.isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pressed(QEvent *e, int delay)
|
|
||||||
{
|
|
||||||
if (!pressDelayEvent) {
|
|
||||||
pressDelayEvent.reset(copyMouseEvent(e));
|
|
||||||
pressDelayTimer = startTimer(delay);
|
|
||||||
mouseTarget = QApplication::widgetAt(pressDelayEvent->globalPos());
|
|
||||||
mouseButton = pressDelayEvent->button();
|
|
||||||
mouseEventSource = pressDelayEvent->source();
|
|
||||||
qFGDebug("QFG: consuming/delaying mouse press");
|
|
||||||
} else {
|
|
||||||
qFGDebug("QFG: NOT consuming/delaying mouse press");
|
|
||||||
}
|
|
||||||
e->setAccepted(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool released(QEvent *e, bool scrollerWasActive, bool scrollerIsActive)
|
|
||||||
{
|
|
||||||
// consume this event if the scroller was or is active
|
|
||||||
bool result = scrollerWasActive || scrollerIsActive;
|
|
||||||
|
|
||||||
// stop the timer
|
|
||||||
if (pressDelayTimer) {
|
|
||||||
killTimer(pressDelayTimer);
|
|
||||||
pressDelayTimer = 0;
|
|
||||||
}
|
|
||||||
// we still haven't even sent the press, so do it now
|
|
||||||
if (pressDelayEvent && mouseTarget && !scrollerIsActive) {
|
|
||||||
QScopedPointer<QMouseEvent> releaseEvent(copyMouseEvent(e));
|
|
||||||
|
|
||||||
qFGDebug() << "QFG: re-sending mouse press (due to release) for " << mouseTarget;
|
|
||||||
sendMouseEvent(pressDelayEvent.data(), UngrabMouseBefore);
|
|
||||||
|
|
||||||
qFGDebug() << "QFG: faking mouse release (due to release) for " << mouseTarget;
|
|
||||||
sendMouseEvent(releaseEvent.data());
|
|
||||||
|
|
||||||
result = true; // consume this event
|
|
||||||
} else if (mouseTarget && scrollerIsActive) {
|
|
||||||
// we grabbed the mouse expicitly when the scroller became active, so undo that now
|
|
||||||
sendMouseEvent(nullptr, UngrabMouseBefore);
|
|
||||||
}
|
|
||||||
pressDelayEvent.reset(nullptr);
|
|
||||||
mouseTarget = nullptr;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void scrollerWasIntercepted()
|
|
||||||
{
|
|
||||||
qFGDebug("QFG: deleting delayed mouse press, since scroller was only intercepted");
|
|
||||||
if (pressDelayEvent) {
|
|
||||||
// we still haven't even sent the press, so just throw it away now
|
|
||||||
if (pressDelayTimer) {
|
|
||||||
killTimer(pressDelayTimer);
|
|
||||||
pressDelayTimer = 0;
|
|
||||||
}
|
|
||||||
pressDelayEvent.reset(nullptr);
|
|
||||||
}
|
|
||||||
mouseTarget = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void scrollerBecameActive()
|
|
||||||
{
|
|
||||||
if (pressDelayEvent) {
|
|
||||||
// we still haven't even sent the press, so just throw it away now
|
|
||||||
qFGDebug("QFG: deleting delayed mouse press, since scroller is active now");
|
|
||||||
if (pressDelayTimer) {
|
|
||||||
killTimer(pressDelayTimer);
|
|
||||||
pressDelayTimer = 0;
|
|
||||||
}
|
|
||||||
pressDelayEvent.reset(nullptr);
|
|
||||||
mouseTarget = nullptr;
|
|
||||||
} else if (mouseTarget) {
|
|
||||||
// we did send a press, so we need to fake a release now
|
|
||||||
|
|
||||||
// release all pressed mouse buttons
|
|
||||||
/* Qt::MouseButtons mouseButtons = QGuiApplication::mouseButtons();
|
|
||||||
for (int i = 0; i < 32; ++i) {
|
|
||||||
if (mouseButtons & (1 << i)) {
|
|
||||||
Qt::MouseButton b = static_cast<Qt::MouseButton>(1 << i);
|
|
||||||
mouseButtons &= ~b;
|
|
||||||
QPoint farFarAway(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
|
|
||||||
|
|
||||||
qFGDebug() << "QFG: sending a fake mouse release at far-far-away to " << mouseTarget;
|
|
||||||
QMouseEvent re(QEvent::MouseButtonRelease, QPoint(), farFarAway,
|
|
||||||
b, mouseButtons, QGuiApplication::keyboardModifiers());
|
|
||||||
sendMouseEvent(&re);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
QPoint farFarAway(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
|
|
||||||
|
|
||||||
qFGDebug() << "QFG: sending a fake mouse release at far-far-away to " << mouseTarget;
|
|
||||||
QMouseEvent re(QEvent::MouseButtonRelease, QPoint(), farFarAway, farFarAway,
|
|
||||||
mouseButton, QGuiApplication::mouseButtons() & ~mouseButton,
|
|
||||||
QGuiApplication::keyboardModifiers(), mouseEventSource);
|
|
||||||
sendMouseEvent(&re, RegrabMouseAfterwards);
|
|
||||||
// don't clear the mouseTarget just yet, since we need to explicitly ungrab the mouse on release!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void timerEvent(QTimerEvent *e) override
|
|
||||||
{
|
|
||||||
if (e->timerId() == pressDelayTimer) {
|
|
||||||
if (pressDelayEvent && mouseTarget) {
|
|
||||||
qFGDebug() << "QFG: timer event: re-sending mouse press to " << mouseTarget;
|
|
||||||
sendMouseEvent(pressDelayEvent.data(), UngrabMouseBefore);
|
|
||||||
}
|
|
||||||
pressDelayEvent.reset(nullptr);
|
|
||||||
|
|
||||||
if (pressDelayTimer) {
|
|
||||||
killTimer(pressDelayTimer);
|
|
||||||
pressDelayTimer = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendMouseEvent(QMouseEvent *me, int flags = 0)
|
|
||||||
{
|
|
||||||
if (mouseTarget) {
|
|
||||||
sendingEvent = true;
|
|
||||||
|
|
||||||
#if QT_CONFIG(graphicsview)
|
|
||||||
QGraphicsItem *grabber = nullptr;
|
|
||||||
if (mouseTarget->parentWidget()) {
|
|
||||||
if (QGraphicsView *gv = qobject_cast<QGraphicsView *>(mouseTarget->parentWidget())) {
|
|
||||||
if (gv->scene())
|
|
||||||
grabber = gv->scene()->mouseGrabberItem();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grabber && (flags & UngrabMouseBefore)) {
|
|
||||||
// GraphicsView Mouse Handling Workaround #1:
|
|
||||||
// we need to ungrab the mouse before re-sending the press,
|
|
||||||
// since the scene had already set the mouse grabber to the
|
|
||||||
// original (and consumed) event's receiver
|
|
||||||
qFGDebug() << "QFG: ungrabbing" << grabber;
|
|
||||||
grabber->ungrabMouse();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
Q_UNUSED(flags);
|
|
||||||
#endif // QT_CONFIG(graphicsview)
|
|
||||||
|
|
||||||
if (me) {
|
if (me) {
|
||||||
QMouseEvent copy(me->type(), mouseTarget->mapFromGlobal(me->globalPos()),
|
QMouseEvent copy(me->type(), targetWidget->mapFromGlobal(me->globalPos()),
|
||||||
mouseTarget->topLevelWidget()->mapFromGlobal(me->globalPos()), me->screenPos(),
|
targetWidget->topLevelWidget()->mapFromGlobal(me->globalPos()), me->screenPos(),
|
||||||
me->button(), me->buttons(), me->modifiers(), me->source());
|
me->button(), me->buttons(), me->modifiers(), me->source());
|
||||||
qt_sendSpontaneousEvent(mouseTarget, ©);
|
qt_sendSpontaneousEvent(targetWidget, ©);
|
||||||
}
|
|
||||||
|
|
||||||
#if QT_CONFIG(graphicsview)
|
|
||||||
if (grabber && (flags & RegrabMouseAfterwards)) {
|
|
||||||
// GraphicsView Mouse Handling Workaround #2:
|
|
||||||
// we need to re-grab the mouse after sending a faked mouse
|
|
||||||
// release, since we still need the mouse moves for the gesture
|
|
||||||
// (the scene will clear the item's mouse grabber status on
|
|
||||||
// release).
|
|
||||||
qFGDebug() << "QFG: re-grabbing" << grabber;
|
|
||||||
grabber->grabMouse();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
sendingEvent = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MousePressDelayHandler::releaseAllPressed()
|
||||||
|
{
|
||||||
|
QPoint farFarAway(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
|
||||||
|
|
||||||
private:
|
qFGDebug() << "QFG: sending a fake mouse release at far-far-away to " << pressTarget();
|
||||||
int pressDelayTimer;
|
QMouseEvent re(QEvent::MouseButtonRelease, QPoint(), farFarAway, farFarAway,
|
||||||
QScopedPointer<QMouseEvent> pressDelayEvent;
|
m_mouseButton, QApplication::mouseButtons() & ~m_mouseButton,
|
||||||
bool sendingEvent;
|
QApplication::keyboardModifiers(), m_mouseEventSource);
|
||||||
Qt::MouseButton mouseButton;
|
sendSpontaneousEvent(&re, pressTarget(), RegrabMouseAfterwards);
|
||||||
QPointer<QWidget> mouseTarget;
|
}
|
||||||
Qt::MouseEventSource mouseEventSource;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
TouchPressDelayHandler::TouchPressDelayHandler(QObject *parent)
|
||||||
|
: PressDelayHandler(parent)
|
||||||
|
{
|
||||||
|
qFGDebug("QFG: create TouchPressDelayHandler");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchPressDelayHandler::saveDelayEventInfo(QEvent* e)
|
||||||
|
{
|
||||||
|
QTouchEvent* te = dynamic_cast<QTouchEvent*>(e);
|
||||||
|
if (!te) {
|
||||||
|
qWarning() << "TouchPressDelayHandler handling event not QTouchEvent";
|
||||||
|
}
|
||||||
|
setPressTarget(te->window());
|
||||||
|
m_touchBeginPoint = te->touchPoints().at(0);
|
||||||
|
m_device = te->device();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchPressDelayHandler::releaseAllPressed()
|
||||||
|
{
|
||||||
|
qFGDebug() << "QFG: sending a fake touch cancel to " << pressTarget();
|
||||||
|
QTouchEvent te(QEvent::TouchCancel, m_device, QApplication::keyboardModifiers(),
|
||||||
|
Qt::TouchPointReleased, QList<QTouchEvent::TouchPoint>{m_touchBeginPoint});
|
||||||
|
te.setWindow(dynamic_cast<QWindow*>(pressTarget().data()));
|
||||||
|
sendSpontaneousEvent(&te, pressTarget(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchPressDelayHandler::sendEvent(QEvent *e, QObject* target)
|
||||||
|
{
|
||||||
|
QTouchEvent* te = dynamic_cast<QTouchEvent*>(e);
|
||||||
|
QWindow* targetWindow = dynamic_cast<QWindow*>(target);
|
||||||
|
|
||||||
|
if (!targetWindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!te) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// map to window pos for send to window
|
||||||
|
QTouchEvent::TouchPoint touchPoint = (!te->touchPoints().empty()) ? te->touchPoints().at(0) : QTouchEvent::TouchPoint();
|
||||||
|
const QPointF screenPos = touchPoint.screenPos();
|
||||||
|
const QPointF delta = screenPos - screenPos.toPoint();
|
||||||
|
const QPointF windowPos = targetWindow->mapFromGlobal(screenPos.toPoint()) + delta;
|
||||||
|
const QPointF startPos = targetWindow->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta;
|
||||||
|
const QPointF lastPos = targetWindow->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta;
|
||||||
|
|
||||||
|
touchPoint.setPos(windowPos);
|
||||||
|
touchPoint.setStartPos(startPos);
|
||||||
|
touchPoint.setLastPos(lastPos);
|
||||||
|
|
||||||
|
qFGDebug() << "QFG: sending" << te->type() << "event to" << targetWindow;
|
||||||
|
// send touch event to window because there is a grab mechanism for touch events
|
||||||
|
QTouchEvent copy(te->type(), te->device(), te->modifiers(),
|
||||||
|
te->touchPointStates(), QList<QTouchEvent::TouchPoint>{touchPoint});
|
||||||
|
copy.setWindow(targetWindow);
|
||||||
|
qt_sendSpontaneousEvent(targetWindow, ©);
|
||||||
|
|
||||||
|
// when Qt::AA_SynthesizeMouseForUnhandledTouchEvents is set,
|
||||||
|
// Qt will send a fake mouse eventif touch event not accept.
|
||||||
|
// The touch event we send here will not send the fake mouse event,
|
||||||
|
// so send it here.
|
||||||
|
if ((qApp->testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents) && !copy.isAccepted())
|
||||||
|
|| copy.type() == QEvent::TouchCancel) {
|
||||||
|
sendMouseEventFromTouch(©, targetWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TouchPressDelayHandler::sendMouseEventFromTouch(QTouchEvent *te, QWindow *target)
|
||||||
|
{
|
||||||
|
if (te->type() == QEvent::TouchCancel) {
|
||||||
|
QPoint farFarAway(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
|
||||||
|
|
||||||
|
qFGDebug() << "QFG: sending a fake mouse release at far-far-away to " << pressTarget();
|
||||||
|
QMouseEvent fake(QEvent::MouseButtonRelease, QPoint(), farFarAway, farFarAway,
|
||||||
|
Qt::LeftButton, QApplication::mouseButtons() & ~Qt::LeftButton,
|
||||||
|
QApplication::keyboardModifiers(), Qt::MouseEventSynthesizedByQt);
|
||||||
|
qt_sendSpontaneousEvent(target, &fake);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTouchEvent::TouchPoint touchPoint = te->touchPoints().at(0);
|
||||||
|
const QPointF screenPos = touchPoint.screenPos();
|
||||||
|
const QPointF delta = screenPos - screenPos.toPoint();
|
||||||
|
const QPointF pos = target->mapFromGlobal(screenPos.toPoint()) + delta;
|
||||||
|
|
||||||
|
QEvent::Type mouseEventType = QEvent::MouseMove;
|
||||||
|
Qt::MouseButton button = Qt::NoButton;
|
||||||
|
Qt::MouseButtons buttons = Qt::LeftButton;
|
||||||
|
|
||||||
|
switch (touchPoint.state()) {
|
||||||
|
case Qt::TouchPointPressed:
|
||||||
|
if (isDoubleClick()) {
|
||||||
|
mouseEventType = QEvent::MouseButtonDblClick;
|
||||||
|
button = Qt::NoButton;
|
||||||
|
m_mousePressTime = QTime();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mouseEventType = QEvent::MouseButtonPress;
|
||||||
|
button = Qt::LeftButton;
|
||||||
|
m_mousePressTime = QTime::currentTime();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Qt::TouchPointReleased:
|
||||||
|
mouseEventType = QEvent::MouseButtonRelease;
|
||||||
|
button = Qt::LeftButton;
|
||||||
|
buttons = Qt::NoButton;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouseEventType == QEvent::MouseButtonPress) {
|
||||||
|
qFGDebug() << "QFG: send fake move event to" << target;
|
||||||
|
QMouseEvent fake(QEvent::MouseMove, pos, pos, screenPos,
|
||||||
|
Qt::NoButton, Qt::NoButton,
|
||||||
|
QApplication::keyboardModifiers(), Qt::MouseEventSynthesizedByQt);
|
||||||
|
qt_sendSpontaneousEvent(target, &fake);
|
||||||
|
}
|
||||||
|
|
||||||
|
// will not synthesize QEvent::NonClientAreaMouseButtonDblClick from touch
|
||||||
|
qFGDebug() << "QFG: send fake " << mouseEventType << "to" << target;
|
||||||
|
QMouseEvent fake(mouseEventType, pos, pos, screenPos,
|
||||||
|
button, buttons, QApplication::keyboardModifiers(), Qt::MouseEventSynthesizedByQt);
|
||||||
|
qt_sendSpontaneousEvent(target, &fake);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TouchPressDelayHandler::isDoubleClick() const
|
||||||
|
{
|
||||||
|
// if not save time, return false then save current time
|
||||||
|
if (m_mousePressTime.isNull())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int doubleClickInterval = static_cast<int>(QGuiApplication::styleHints()->mouseDoubleClickInterval());
|
||||||
|
int elapsed = m_mousePressTime.msecsTo(QTime::currentTime());
|
||||||
|
bool doubleClick = elapsed < doubleClickInterval;
|
||||||
|
|
||||||
|
return doubleClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
QEvent* TouchPressDelayHandler::copyEvent(QEvent *e)
|
||||||
|
{
|
||||||
|
switch (e->type()) {
|
||||||
|
case QEvent::TouchBegin:
|
||||||
|
case QEvent::TouchUpdate:
|
||||||
|
case QEvent::TouchEnd:
|
||||||
|
case QEvent::TouchCancel: {
|
||||||
|
QTouchEvent* te = dynamic_cast<QTouchEvent*>(e);
|
||||||
|
QTouchEvent* copy = new QTouchEvent(te->type(), te->device(), te->modifiers(),
|
||||||
|
te->touchPointStates(), te->touchPoints());
|
||||||
|
copy->setWindow(te->window());
|
||||||
|
return copy;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
|
@ -350,15 +574,16 @@ QFlickGesture::QFlickGesture(QObject *receiver, Qt::MouseButton button, QObject
|
||||||
{
|
{
|
||||||
d_func()->q_ptr = this;
|
d_func()->q_ptr = this;
|
||||||
d_func()->receiver = receiver;
|
d_func()->receiver = receiver;
|
||||||
d_func()->receiverScroller = (receiver && QScroller::hasScroller(receiver)) ? QScroller::scroller(receiver) : nullptr;
|
d_func()->receiverScroller = (receiver && QScroller::hasScroller(receiver)) ? QScroller::scroller(receiver) : 0;
|
||||||
d_func()->button = button;
|
d_func()->button = button;
|
||||||
|
d_func()->pressDelayHandler = PressDelayHandler::create(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
QFlickGesture::~QFlickGesture()
|
QFlickGesture::~QFlickGesture()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
QFlickGesturePrivate::QFlickGesturePrivate()
|
QFlickGesturePrivate::QFlickGesturePrivate()
|
||||||
: receiverScroller(nullptr), button(Qt::NoButton), macIgnoreWheel(false)
|
: receiverScroller(0), button(Qt::NoButton), macIgnoreWheel(false), pressDelayHandler(nullptr)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
@ -415,16 +640,16 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// this is only set for events that we inject into the event loop via sendEvent()
|
// this is only set for events that we inject into the event loop via sendEvent()
|
||||||
if (PressDelayHandler::instance()->shouldEventBeIgnored(event)) {
|
if (d->pressDelayHandler->shouldEventBeIgnored()) {
|
||||||
//qFGDebug() << state << "QFG: ignored event: " << event->type();
|
//qFGDebug() << state << "QFG: ignored event: " << event->type();
|
||||||
return Ignore;
|
return Ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QMouseEvent *me = nullptr;
|
const QMouseEvent *me = 0;
|
||||||
#if QT_CONFIG(graphicsview)
|
#if QT_CONFIG(graphicsview)
|
||||||
const QGraphicsSceneMouseEvent *gsme = nullptr;
|
const QGraphicsSceneMouseEvent *gsme = 0;
|
||||||
#endif
|
#endif
|
||||||
const QTouchEvent *te = nullptr;
|
const QTouchEvent *te = 0;
|
||||||
QPoint globalPos;
|
QPoint globalPos;
|
||||||
|
|
||||||
// qFGDebug() << "FlickGesture "<<state<<"watched:"<<watched<<"receiver"<<d->receiver<<"event"<<event->type()<<"button"<<button;
|
// qFGDebug() << "FlickGesture "<<state<<"watched:"<<watched<<"receiver"<<d->receiver<<"event"<<event->type()<<"button"<<button;
|
||||||
|
@ -620,7 +845,7 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state,
|
||||||
#if QT_CONFIG(graphicsview)
|
#if QT_CONFIG(graphicsview)
|
||||||
|| gsme
|
|| gsme
|
||||||
#endif
|
#endif
|
||||||
) && scrollerIsActive)
|
|| te) && scrollerIsActive)
|
||||||
result |= ConsumeEventHint;
|
result |= ConsumeEventHint;
|
||||||
|
|
||||||
// The only problem with this approach is that we consume the
|
// The only problem with this approach is that we consume the
|
||||||
|
@ -632,11 +857,11 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state,
|
||||||
#if QT_CONFIG(graphicsview)
|
#if QT_CONFIG(graphicsview)
|
||||||
|| gsme
|
|| gsme
|
||||||
#endif
|
#endif
|
||||||
) {
|
|| te) {
|
||||||
if (!scrollerWasDragging && !scrollerWasScrolling && scrollerIsActive)
|
if (!scrollerWasDragging && !scrollerWasScrolling && scrollerIsActive)
|
||||||
PressDelayHandler::instance()->scrollerBecameActive();
|
d->pressDelayHandler->scrollerBecameActive();
|
||||||
else if (scrollerWasScrolling && (scroller->state() == QScroller::Dragging || scroller->state() == QScroller::Inactive))
|
else if (scrollerWasScrolling && (scroller->state() == QScroller::Dragging || scroller->state() == QScroller::Inactive))
|
||||||
PressDelayHandler::instance()->scrollerWasIntercepted();
|
d->pressDelayHandler->scrollerWasIntercepted();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inputType) {
|
if (!inputType) {
|
||||||
|
@ -644,6 +869,7 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state,
|
||||||
} else {
|
} else {
|
||||||
switch (event->type()) {
|
switch (event->type()) {
|
||||||
case QEvent::MouseButtonPress:
|
case QEvent::MouseButtonPress:
|
||||||
|
case QEvent::TouchBegin:
|
||||||
#if QT_CONFIG(graphicsview)
|
#if QT_CONFIG(graphicsview)
|
||||||
case QEvent::GraphicsSceneMousePress:
|
case QEvent::GraphicsSceneMousePress:
|
||||||
#endif
|
#endif
|
||||||
|
@ -652,24 +878,21 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state,
|
||||||
if (pressDelay > 0) {
|
if (pressDelay > 0) {
|
||||||
result |= ConsumeEventHint;
|
result |= ConsumeEventHint;
|
||||||
|
|
||||||
PressDelayHandler::instance()->pressed(event, pressDelay);
|
d->pressDelayHandler->pressed(event, pressDelay);
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Q_FALLTHROUGH();
|
|
||||||
case QEvent::TouchBegin:
|
|
||||||
q->setHotSpot(globalPos);
|
q->setHotSpot(globalPos);
|
||||||
result |= scrollerIsActive ? TriggerGesture : MayBeGesture;
|
result |= scrollerIsActive ? TriggerGesture : MayBeGesture;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QEvent::MouseMove:
|
case QEvent::MouseMove:
|
||||||
|
case QEvent::TouchUpdate:
|
||||||
#if QT_CONFIG(graphicsview)
|
#if QT_CONFIG(graphicsview)
|
||||||
case QEvent::GraphicsSceneMouseMove:
|
case QEvent::GraphicsSceneMouseMove:
|
||||||
#endif
|
#endif
|
||||||
if (PressDelayHandler::instance()->isDelaying())
|
if (d->pressDelayHandler->isDelaying())
|
||||||
result |= ConsumeEventHint;
|
result |= ConsumeEventHint;
|
||||||
Q_FALLTHROUGH();
|
|
||||||
case QEvent::TouchUpdate:
|
|
||||||
result |= scrollerIsActive ? TriggerGesture : Ignore;
|
result |= scrollerIsActive ? TriggerGesture : Ignore;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -677,10 +900,9 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state,
|
||||||
case QEvent::GraphicsSceneMouseRelease:
|
case QEvent::GraphicsSceneMouseRelease:
|
||||||
#endif
|
#endif
|
||||||
case QEvent::MouseButtonRelease:
|
case QEvent::MouseButtonRelease:
|
||||||
if (PressDelayHandler::instance()->released(event, scrollerWasDragging || scrollerWasScrolling, scrollerIsActive))
|
|
||||||
result |= ConsumeEventHint;
|
|
||||||
Q_FALLTHROUGH();
|
|
||||||
case QEvent::TouchEnd:
|
case QEvent::TouchEnd:
|
||||||
|
if (d->pressDelayHandler->released(event, scrollerWasDragging || scrollerWasScrolling, scrollerIsActive))
|
||||||
|
result |= ConsumeEventHint;
|
||||||
result |= scrollerIsActive ? FinishGesture : CancelGesture;
|
result |= scrollerIsActive ? FinishGesture : CancelGesture;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -71,12 +71,65 @@ class Q_WIDGETS_EXPORT QFlickGesture : public QGesture
|
||||||
Q_DECLARE_PRIVATE(QFlickGesture)
|
Q_DECLARE_PRIVATE(QFlickGesture)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QFlickGesture(QObject *receiver, Qt::MouseButton button, QObject *parent = nullptr);
|
QFlickGesture(QObject *receiver, Qt::MouseButton button, QObject *parent = 0);
|
||||||
~QFlickGesture();
|
~QFlickGesture();
|
||||||
|
|
||||||
friend class QFlickGestureRecognizer;
|
friend class QFlickGestureRecognizer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PressDelayHandler : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
PressDelayHandler(QObject *parent = nullptr);
|
||||||
|
enum {
|
||||||
|
UngrabMouseBefore = 1,
|
||||||
|
RegrabMouseAfterwards = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
static PressDelayHandler* create(Qt::MouseButton button = Qt::LeftButton);
|
||||||
|
|
||||||
|
bool shouldEventBeIgnored() const;
|
||||||
|
bool isDelaying() const;
|
||||||
|
|
||||||
|
void pressed(QEvent *e, int delay);
|
||||||
|
bool released(QEvent *e, bool scrollerWasActive, bool scrollerIsActive);
|
||||||
|
|
||||||
|
void scrollerWasIntercepted();
|
||||||
|
void scrollerBecameActive();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void sendSpontaneousEvent(QEvent *e, QObject *target, int flags);
|
||||||
|
QPointer<QObject> pressTarget() const;
|
||||||
|
void setPressTarget(QObject* pressTarget);
|
||||||
|
void resetPressTarget();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onDelayTimeout();
|
||||||
|
private:
|
||||||
|
virtual void saveDelayEventInfo(QEvent* e) = 0;
|
||||||
|
virtual QEvent* copyEvent(QEvent* e) = 0;
|
||||||
|
|
||||||
|
virtual void sendEvent(QEvent *e, QObject* target) = 0;
|
||||||
|
virtual void releaseAllPressed() = 0;
|
||||||
|
|
||||||
|
QGraphicsItem* mouseGrabberItem() const;
|
||||||
|
void grabMouse(QGraphicsItem* grabber) const;
|
||||||
|
void ungrabMouse(QGraphicsItem* grabber) const;
|
||||||
|
|
||||||
|
bool hasSavedDelayEvent() const;
|
||||||
|
void resetDelayEvent();
|
||||||
|
void stopTimer();
|
||||||
|
void startTimer(int timeout);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// there will only be one QScroller active at same time
|
||||||
|
static QTimer* m_pressDelayTimer;
|
||||||
|
static bool m_sendingEvent;
|
||||||
|
static QScopedPointer<QEvent> m_pressDelayEvent;
|
||||||
|
static QPointer<QObject> m_pressTarget;
|
||||||
|
};
|
||||||
|
|
||||||
class QFlickGesturePrivate : public QGesturePrivate
|
class QFlickGesturePrivate : public QGesturePrivate
|
||||||
{
|
{
|
||||||
Q_DECLARE_PUBLIC(QFlickGesture)
|
Q_DECLARE_PUBLIC(QFlickGesture)
|
||||||
|
@ -87,6 +140,7 @@ public:
|
||||||
QScroller *receiverScroller;
|
QScroller *receiverScroller;
|
||||||
Qt::MouseButton button; // NoButton == Touch
|
Qt::MouseButton button; // NoButton == Touch
|
||||||
bool macIgnoreWheel;
|
bool macIgnoreWheel;
|
||||||
|
PressDelayHandler *pressDelayHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QFlickGestureRecognizer : public QGestureRecognizer
|
class QFlickGestureRecognizer : public QGestureRecognizer
|
||||||
|
@ -102,6 +156,43 @@ private:
|
||||||
Qt::MouseButton button; // NoButton == Touch
|
Qt::MouseButton button; // NoButton == Touch
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MousePressDelayHandler : public PressDelayHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MousePressDelayHandler(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void saveDelayEventInfo(QEvent* e) override;
|
||||||
|
|
||||||
|
QEvent* copyEvent(QEvent *e) override;
|
||||||
|
void sendEvent(QEvent *e, QObject* target) override;
|
||||||
|
void releaseAllPressed() override;
|
||||||
|
|
||||||
|
Qt::MouseButton m_mouseButton;
|
||||||
|
Qt::MouseEventSource m_mouseEventSource;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TouchPressDelayHandler : public PressDelayHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TouchPressDelayHandler(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void saveDelayEventInfo(QEvent* e) override;
|
||||||
|
|
||||||
|
QEvent* copyEvent(QEvent *e) override;
|
||||||
|
void sendEvent(QEvent *e, QObject* target) override;
|
||||||
|
void releaseAllPressed() override;
|
||||||
|
|
||||||
|
void sendMouseEventFromTouch(QTouchEvent *te, QWindow *target);
|
||||||
|
bool isDoubleClick() const;
|
||||||
|
|
||||||
|
QPointer<QWidget> m_targetWidget;
|
||||||
|
QTouchDevice* m_device;
|
||||||
|
QTouchEvent::TouchPoint m_touchBeginPoint;
|
||||||
|
QTime m_mousePressTime;
|
||||||
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QT_NO_GESTURES
|
#endif // QT_NO_GESTURES
|
||||||
|
|
Loading…
Reference in New Issue