update debian/changelog to 5.15.8+dfsg-ok2.2
rebuild Signed-off-by: hanpinlong <hanpinlong@kylinos.cn>
This commit is contained in:
parent
55e75603ae
commit
7faab2c757
|
@ -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号:无
|
||||
|
|
|
@ -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, ©);
|
||||
}
|
||||
+}
|
||||
|
||||
- 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, ©);
|
||||
+
|
||||
+ // 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);
|
||||
+ }
|
||||
+}
|
||||
|
||||
- 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, ©);
|
||||
- }
|
||||
+ 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
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue