update debian/changelog to 5.15.8+dfsg-ok2.2

rebuild

Signed-off-by: hanpinlong <hanpinlong@kylinos.cn>
This commit is contained in:
hanpinlong 2023-10-30 02:00:55 +00:00 committed by openkylin-cibot
parent 55e75603ae
commit 7faab2c757
3 changed files with 926 additions and 0 deletions

9
debian/changelog vendored
View File

@ -1,3 +1,12 @@
qtbase-opensource-src (5.15.8+dfsg-ok2.2) nile; urgency=medium
* BUG号
* 需求号:无
* 其他更改合并触摸相关Patch
-- hanpinlong <hanpinlong@kylinos.cn> Mon, 30 Oct 2023 09:49:49 +0800
qtbase-opensource-src (5.15.8+dfsg-ok1.9) nile; urgency=medium
* BUG号

View File

@ -0,0 +1,916 @@
From: hanpinlong <hanpinlong@kylinos.cn>
Date: Mon, 30 Oct 2023 02:00:55 +0000
Subject: update debian/changelog to 5.15.8+dfsg-ok2.2 rebuild
Signed-off-by: hanpinlong <hanpinlong@kylinos.cn>
---
src/widgets/util/qflickgesture.cpp | 634 +++++++++++++++++++++++++------------
src/widgets/util/qflickgesture_p.h | 93 +++++-
2 files changed, 520 insertions(+), 207 deletions(-)
diff --git a/src/widgets/util/qflickgesture.cpp b/src/widgets/util/qflickgesture.cpp
index 064be87..e970a85 100644
--- a/src/widgets/util/qflickgesture.cpp
+++ b/src/widgets/util/qflickgesture.cpp
@@ -47,12 +47,14 @@
#include "qgraphicssceneevent.h"
#include "qgraphicsview.h"
#endif
+#include "qstylehints.h"
#include "qscroller.h"
#include <QtGui/qtouchdevice.h>
#include "private/qapplication_p.h"
#include "private/qevent_p.h"
#include "private/qflickgesture_p.h"
#include "qdebug.h"
+#include "qtimer.h"
#ifndef QT_NO_GESTURES
@@ -68,13 +70,258 @@ QT_BEGIN_NAMESPACE
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()) {
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
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(),
me->button(), me->buttons(), me->modifiers(), me->source());
return cme;
@@ -83,10 +330,10 @@ static QMouseEvent *copyMouseEvent(QEvent *e)
case QEvent::GraphicsSceneMousePress:
case QEvent::GraphicsSceneMouseRelease:
case QEvent::GraphicsSceneMouseMove: {
- QGraphicsSceneMouseEvent *me = static_cast<QGraphicsSceneMouseEvent *>(e);
+ QGraphicsSceneMouseEvent *me = dynamic_cast<QGraphicsSceneMouseEvent *>(e);
#if 1
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);
QMouseEvent *cme = new QMouseEvent(met, QPoint(0, 0), QPoint(0, 0), me->screenPos(),
me->button(), me->buttons(), me->modifiers(), me->source());
return cme;
@@ -118,216 +365,193 @@ static QMouseEvent *copyMouseEvent(QEvent *e)
}
}
-class PressDelayHandler : public QObject
+void MousePressDelayHandler::sendEvent(QEvent *e, QObject* target)
{
-private:
- PressDelayHandler(QObject *parent = nullptr)
- : QObject(parent)
- , pressDelayTimer(0)
- , sendingEvent(false)
- , mouseButton(Qt::NoButton)
- , mouseTarget(nullptr)
- , mouseEventSource(Qt::MouseEventNotSynthesized)
- { }
+ QMouseEvent* me = dynamic_cast<QMouseEvent*>(e);
+ QWidget* targetWidget = dynamic_cast<QWidget*>(target);
-public:
- enum {
- UngrabMouseBefore = 1,
- RegrabMouseAfterwards = 2
- };
-
- static PressDelayHandler *instance()
- {
- static PressDelayHandler *inst = nullptr;
- if (!inst)
- inst = new PressDelayHandler(QCoreApplication::instance());
- return inst;
+ if (!targetWidget) {
+ return;
}
- bool shouldEventBeIgnored(QEvent *) const
- {
- return sendingEvent;
+ if (me) {
+ QMouseEvent copy(me->type(), targetWidget->mapFromGlobal(me->globalPos()),
+ targetWidget->topLevelWidget()->mapFromGlobal(me->globalPos()), me->screenPos(),
+ me->button(), me->buttons(), me->modifiers(), me->source());
+ qt_sendSpontaneousEvent(targetWidget, &copy);
}
+}
- bool isDelaying() const
- {
- return !pressDelayEvent.isNull();
- }
+void MousePressDelayHandler::releaseAllPressed()
+{
+ QPoint farFarAway(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
- 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);
- }
+ qFGDebug() << "QFG: sending a fake mouse release at far-far-away to " << pressTarget();
+ QMouseEvent re(QEvent::MouseButtonRelease, QPoint(), farFarAway, farFarAway,
+ m_mouseButton, QApplication::mouseButtons() & ~m_mouseButton,
+ QApplication::keyboardModifiers(), m_mouseEventSource);
+ sendSpontaneousEvent(&re, pressTarget(), RegrabMouseAfterwards);
+}
- bool released(QEvent *e, bool scrollerWasActive, bool scrollerIsActive)
- {
- // consume this event if the scroller was or is active
- bool result = scrollerWasActive || scrollerIsActive;
+TouchPressDelayHandler::TouchPressDelayHandler(QObject *parent)
+ : PressDelayHandler(parent)
+{
+ qFGDebug("QFG: create TouchPressDelayHandler");
+}
- // 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));
+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();
+}
- qFGDebug() << "QFG: re-sending mouse press (due to release) for " << mouseTarget;
- sendMouseEvent(pressDelayEvent.data(), UngrabMouseBefore);
+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);
+}
- qFGDebug() << "QFG: faking mouse release (due to release) for " << mouseTarget;
- sendMouseEvent(releaseEvent.data());
+void TouchPressDelayHandler::sendEvent(QEvent *e, QObject* target)
+{
+ QTouchEvent* te = dynamic_cast<QTouchEvent*>(e);
+ QWindow* targetWindow = dynamic_cast<QWindow*>(target);
- 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;
+ if (!targetWindow) {
+ return;
+ }
+ if (!te) {
+ return;
}
- 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);
- }
- }*/
+ // 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, &copy);
+
+ // 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(&copy, targetWindow);
+ }
+}
- QPoint farFarAway(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
+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;
+ }
- 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!
+ 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;
}
-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;
- }
- }
+ 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);
}
- void sendMouseEvent(QMouseEvent *me, int flags = 0)
- {
- if (mouseTarget) {
- sendingEvent = true;
+ // 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);
+}
-#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();
- }
- }
+bool TouchPressDelayHandler::isDoubleClick() const
+{
+ // if not save time, return false then save current time
+ if (m_mousePressTime.isNull())
+ return false;
- 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)
+ int doubleClickInterval = static_cast<int>(QGuiApplication::styleHints()->mouseDoubleClickInterval());
+ int elapsed = m_mousePressTime.msecsTo(QTime::currentTime());
+ bool doubleClick = elapsed < doubleClickInterval;
- if (me) {
- QMouseEvent copy(me->type(), mouseTarget->mapFromGlobal(me->globalPos()),
- mouseTarget->topLevelWidget()->mapFromGlobal(me->globalPos()), me->screenPos(),
- me->button(), me->buttons(), me->modifiers(), me->source());
- qt_sendSpontaneousEvent(mouseTarget, &copy);
- }
+ return doubleClick;
+}
-#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;
- }
+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;
}
-
-private:
- int pressDelayTimer;
- QScopedPointer<QMouseEvent> pressDelayEvent;
- bool sendingEvent;
- Qt::MouseButton mouseButton;
- QPointer<QWidget> mouseTarget;
- Qt::MouseEventSource mouseEventSource;
-};
-
+ return nullptr;
+}
/*!
\internal
@@ -350,15 +574,16 @@ QFlickGesture::QFlickGesture(QObject *receiver, Qt::MouseButton button, QObject
{
d_func()->q_ptr = this;
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()->pressDelayHandler = PressDelayHandler::create(button);
}
QFlickGesture::~QFlickGesture()
{ }
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
// 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();
return Ignore;
}
- const QMouseEvent *me = nullptr;
+ const QMouseEvent *me = 0;
#if QT_CONFIG(graphicsview)
- const QGraphicsSceneMouseEvent *gsme = nullptr;
+ const QGraphicsSceneMouseEvent *gsme = 0;
#endif
- const QTouchEvent *te = nullptr;
+ const QTouchEvent *te = 0;
QPoint globalPos;
// 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)
|| gsme
#endif
- ) && scrollerIsActive)
+ || te) && scrollerIsActive)
result |= ConsumeEventHint;
// 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)
|| gsme
#endif
- ) {
+ || te) {
if (!scrollerWasDragging && !scrollerWasScrolling && scrollerIsActive)
- PressDelayHandler::instance()->scrollerBecameActive();
+ d->pressDelayHandler->scrollerBecameActive();
else if (scrollerWasScrolling && (scroller->state() == QScroller::Dragging || scroller->state() == QScroller::Inactive))
- PressDelayHandler::instance()->scrollerWasIntercepted();
+ d->pressDelayHandler->scrollerWasIntercepted();
}
if (!inputType) {
@@ -644,6 +869,7 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state,
} else {
switch (event->type()) {
case QEvent::MouseButtonPress:
+ case QEvent::TouchBegin:
#if QT_CONFIG(graphicsview)
case QEvent::GraphicsSceneMousePress:
#endif
@@ -652,24 +878,21 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state,
if (pressDelay > 0) {
result |= ConsumeEventHint;
- PressDelayHandler::instance()->pressed(event, pressDelay);
+ d->pressDelayHandler->pressed(event, pressDelay);
event->accept();
}
}
- Q_FALLTHROUGH();
- case QEvent::TouchBegin:
q->setHotSpot(globalPos);
result |= scrollerIsActive ? TriggerGesture : MayBeGesture;
break;
case QEvent::MouseMove:
+ case QEvent::TouchUpdate:
#if QT_CONFIG(graphicsview)
case QEvent::GraphicsSceneMouseMove:
#endif
- if (PressDelayHandler::instance()->isDelaying())
+ if (d->pressDelayHandler->isDelaying())
result |= ConsumeEventHint;
- Q_FALLTHROUGH();
- case QEvent::TouchUpdate:
result |= scrollerIsActive ? TriggerGesture : Ignore;
break;
@@ -677,10 +900,9 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state,
case QEvent::GraphicsSceneMouseRelease:
#endif
case QEvent::MouseButtonRelease:
- if (PressDelayHandler::instance()->released(event, scrollerWasDragging || scrollerWasScrolling, scrollerIsActive))
- result |= ConsumeEventHint;
- Q_FALLTHROUGH();
case QEvent::TouchEnd:
+ if (d->pressDelayHandler->released(event, scrollerWasDragging || scrollerWasScrolling, scrollerIsActive))
+ result |= ConsumeEventHint;
result |= scrollerIsActive ? FinishGesture : CancelGesture;
break;
diff --git a/src/widgets/util/qflickgesture_p.h b/src/widgets/util/qflickgesture_p.h
index 0b47516..a41633d 100644
--- a/src/widgets/util/qflickgesture_p.h
+++ b/src/widgets/util/qflickgesture_p.h
@@ -71,12 +71,65 @@ class Q_WIDGETS_EXPORT QFlickGesture : public QGesture
Q_DECLARE_PRIVATE(QFlickGesture)
public:
- QFlickGesture(QObject *receiver, Qt::MouseButton button, QObject *parent = nullptr);
+ QFlickGesture(QObject *receiver, Qt::MouseButton button, QObject *parent = 0);
~QFlickGesture();
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
{
Q_DECLARE_PUBLIC(QFlickGesture)
@@ -87,6 +140,7 @@ public:
QScroller *receiverScroller;
Qt::MouseButton button; // NoButton == Touch
bool macIgnoreWheel;
+ PressDelayHandler *pressDelayHandler;
};
class QFlickGestureRecognizer : public QGestureRecognizer
@@ -102,6 +156,43 @@ private:
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
#endif // QT_NO_GESTURES

View File

@ -33,3 +33,4 @@ revert_startBlocking_removal.diff
0033-update-debian-changelog.patch
0034-update-debian-changelog.patch
0035-update-debian-changelog.patch
0036-update-debian-changelog-to-5.15.8-dfsg-ok2.2.patch