diff options
author | Gabriel de Dietrich <gabriel.dedietrich@theqtcompany.com> | 2015-09-15 11:40:43 +0200 |
---|---|---|
committer | Gabriel de Dietrich <gabriel.dedietrich@theqtcompany.com> | 2015-09-15 13:25:52 +0000 |
commit | b47ac20e368dce3bbf89bc724600703cd33cb168 (patch) | |
tree | b8b3ef1eb6afe4f9c78ccfcaa5925db2a1536fb6 /src/controls | |
parent | 175dc7d516740a8964a859e4d7b5daaf41ef98d0 (diff) |
Ensure press-and-hold event keeps selection
This concerns TextField and TextArea.
It is an almost universal UX pattern on touch platforms where
the user long presses to pop the context menu up. In many
cases the context menu is used for copy and cut operations,
which means that poping it up should keep the selection.
The implementation works by not forwarding the initial mouse
press event to the parent class until we're sure it's not going
to be a long press. If the long press timer is cancelled for any
reason, we will then send the delayed mouse press event to the
parent class followed by whichever event triggered the cancellation.
Auto-tests refactored and updated.
Change-Id: If3aa8075f07a80929f4bd723895d9599bf8d169e
Reviewed-by: J-P Nurmi <jpnurmi@theqtcompany.com>
Diffstat (limited to 'src/controls')
-rw-r--r-- | src/controls/qquickpressandholdhelper.cpp | 25 | ||||
-rw-r--r-- | src/controls/qquickpressandholdhelper_p.h | 4 | ||||
-rw-r--r-- | src/controls/qquicktextarea.cpp | 22 | ||||
-rw-r--r-- | src/controls/qquicktextfield.cpp | 22 |
4 files changed, 64 insertions, 9 deletions
diff --git a/src/controls/qquickpressandholdhelper.cpp b/src/controls/qquickpressandholdhelper.cpp index 088a402b..38cd871c 100644 --- a/src/controls/qquickpressandholdhelper.cpp +++ b/src/controls/qquickpressandholdhelper.cpp @@ -45,17 +45,22 @@ QT_BEGIN_NAMESPACE QQuickPressAndHoldHelper::QQuickPressAndHoldHelper() - : control(Q_NULLPTR), longPress(false), pressAndHoldSignalIndex(-1) + : control(Q_NULLPTR) + , longPress(false) + , pressAndHoldSignalIndex(-1) + , delayedMousePressEvent(Q_NULLPTR) { } void QQuickPressAndHoldHelper::mousePressEvent(QMouseEvent *event) { longPress = false; pressPos = event->localPos(); - if (Qt::LeftButton == (event->buttons() & Qt::LeftButton)) + if (Qt::LeftButton == (event->buttons() & Qt::LeftButton)) { timer.start(QGuiApplication::styleHints()->mousePressAndHoldInterval(), control); - else + delayedMousePressEvent = new QMouseEvent(event->type(), event->pos(), event->button(), event->buttons(), event->modifiers()); + } else { timer.stop(); + } } void QQuickPressAndHoldHelper::mouseMoveEvent(QMouseEvent *event) @@ -73,6 +78,7 @@ void QQuickPressAndHoldHelper::mouseReleaseEvent(QMouseEvent *) void QQuickPressAndHoldHelper::timerEvent(QTimerEvent *) { timer.stop(); + clearDelayedMouseEvent(); if (pressAndHoldSignalIndex == -1) pressAndHoldSignalIndex = control->metaObject()->indexOfSignal("pressAndHold(QQuickMouseEvent*)"); @@ -92,4 +98,17 @@ void QQuickPressAndHoldHelper::timerEvent(QTimerEvent *) } } +void QQuickPressAndHoldHelper::clearDelayedMouseEvent() +{ + if (delayedMousePressEvent) { + delete delayedMousePressEvent; + delayedMousePressEvent = 0; + } +} + +bool QQuickPressAndHoldHelper::isActive() +{ + return !(timer.isActive() || longPress); +} + QT_END_NAMESPACE diff --git a/src/controls/qquickpressandholdhelper_p.h b/src/controls/qquickpressandholdhelper_p.h index 6c0dc5ae..0ac84494 100644 --- a/src/controls/qquickpressandholdhelper_p.h +++ b/src/controls/qquickpressandholdhelper_p.h @@ -55,11 +55,15 @@ struct QQuickPressAndHoldHelper void mouseReleaseEvent(QMouseEvent *event); void timerEvent(QTimerEvent *event); + void clearDelayedMouseEvent(); + bool isActive(); + QQuickItem *control; QBasicTimer timer; QPointF pressPos; bool longPress; int pressAndHoldSignalIndex; + QMouseEvent *delayedMousePressEvent; }; QT_END_NAMESPACE diff --git a/src/controls/qquicktextarea.cpp b/src/controls/qquicktextarea.cpp index 5427358b..d46702e2 100644 --- a/src/controls/qquicktextarea.cpp +++ b/src/controls/qquicktextarea.cpp @@ -260,23 +260,39 @@ void QQuickTextArea::mousePressEvent(QMouseEvent *event) { Q_D(QQuickTextArea); d->pressAndHoldHelper.mousePressEvent(event); - QQuickTextEdit::mousePressEvent(event); + if (d->pressAndHoldHelper.isActive()) { + if (d->pressAndHoldHelper.delayedMousePressEvent) { + QQuickTextEdit::mousePressEvent(d->pressAndHoldHelper.delayedMousePressEvent); + d->pressAndHoldHelper.clearDelayedMouseEvent(); + } + QQuickTextEdit::mousePressEvent(event); + } } void QQuickTextArea::mouseMoveEvent(QMouseEvent *event) { Q_D(QQuickTextArea); d->pressAndHoldHelper.mouseMoveEvent(event); - if (!d->pressAndHoldHelper.timer.isActive()) + if (d->pressAndHoldHelper.isActive()) { + if (d->pressAndHoldHelper.delayedMousePressEvent) { + QQuickTextEdit::mousePressEvent(d->pressAndHoldHelper.delayedMousePressEvent); + d->pressAndHoldHelper.clearDelayedMouseEvent(); + } QQuickTextEdit::mouseMoveEvent(event); + } } void QQuickTextArea::mouseReleaseEvent(QMouseEvent *event) { Q_D(QQuickTextArea); d->pressAndHoldHelper.mouseReleaseEvent(event); - if (!d->pressAndHoldHelper.longPress) + if (d->pressAndHoldHelper.isActive()) { + if (d->pressAndHoldHelper.delayedMousePressEvent) { + QQuickTextEdit::mousePressEvent(d->pressAndHoldHelper.delayedMousePressEvent); + d->pressAndHoldHelper.clearDelayedMouseEvent(); + } QQuickTextEdit::mouseReleaseEvent(event); + } } void QQuickTextArea::timerEvent(QTimerEvent *event) diff --git a/src/controls/qquicktextfield.cpp b/src/controls/qquicktextfield.cpp index cf8f24a2..7cf5f3c1 100644 --- a/src/controls/qquicktextfield.cpp +++ b/src/controls/qquicktextfield.cpp @@ -292,23 +292,39 @@ void QQuickTextField::mousePressEvent(QMouseEvent *event) { Q_D(QQuickTextField); d->pressAndHoldHelper.mousePressEvent(event); - QQuickTextInput::mousePressEvent(event); + if (d->pressAndHoldHelper.isActive()) { + if (d->pressAndHoldHelper.delayedMousePressEvent) { + QQuickTextInput::mousePressEvent(d->pressAndHoldHelper.delayedMousePressEvent); + d->pressAndHoldHelper.clearDelayedMouseEvent(); + } + QQuickTextInput::mousePressEvent(event); + } } void QQuickTextField::mouseMoveEvent(QMouseEvent *event) { Q_D(QQuickTextField); d->pressAndHoldHelper.mouseMoveEvent(event); - if (!d->pressAndHoldHelper.timer.isActive()) + if (d->pressAndHoldHelper.isActive()) { + if (d->pressAndHoldHelper.delayedMousePressEvent) { + QQuickTextInput::mousePressEvent(d->pressAndHoldHelper.delayedMousePressEvent); + d->pressAndHoldHelper.clearDelayedMouseEvent(); + } QQuickTextInput::mouseMoveEvent(event); + } } void QQuickTextField::mouseReleaseEvent(QMouseEvent *event) { Q_D(QQuickTextField); d->pressAndHoldHelper.mouseReleaseEvent(event); - if (!d->pressAndHoldHelper.longPress) + if (d->pressAndHoldHelper.isActive()) { + if (d->pressAndHoldHelper.delayedMousePressEvent) { + QQuickTextInput::mousePressEvent(d->pressAndHoldHelper.delayedMousePressEvent); + d->pressAndHoldHelper.clearDelayedMouseEvent(); + } QQuickTextInput::mouseReleaseEvent(event); + } } void QQuickTextField::timerEvent(QTimerEvent *event) |