diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2022-02-24 20:40:14 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2022-07-23 00:37:07 +0200 |
commit | 90d3fac73a10b9363fd34e6757cc730d7a0c086c (patch) | |
tree | db03aae65be7e727b218a6a3a821424d24546eeb /src/quick/items/qquicktextcontrol.cpp | |
parent | c2805daaa58f222d6d19ac939c78e981ba907867 (diff) |
TextEdit: selectByMouse default=true, but not on touchscreens
When you drag a finger across a TextEdit, it should not select text.
- your finger probably covers several characters, so you can't see where
you're selecting until afterwards
- if the item is in a Flickable, flicking by touch should be prioritized
- if flicking happens, the text cursor should not move; but to avoid
losing too much functionality, we allow it to move on release, if
the TextEdit gets the release (i.e. if it still has the exclusive
grab)
So now we distinguish mouse events that are synthesized from non-mouse
devices and avoid mouse-like behaviors as described above, but there is
no behavior change if the event comes from an actual mouse or touchpad.
Since most users want selecting text by mouse to "just work", and an
actual mouse is precise enough to do so, and dragging a Flickable with
the mouse is unintuitive (since most UIs don't allow it and most mice
have wheels), selectByMouse now defaults to true, and has the stricter
meaning that its name implies. To select text on a touchscreen, the
end-user needs to rely on text-selection handles, which are provided on
touch-centric mobile platforms, and could also be implemented from
scratch if someone builds a custom text field using TextInput.
In QQuickPressHandler::mousePressEvent() we give the original event's
device to the delayed press event, now that we check the device to
distinguish "real" mouse events from those that are synthesized from
touch.
[ChangeLog][QtQuick][TextEdit] The selectByMouse property is now enabled
by default, but no longer enables selecting by dragging your finger
across text on a touchscreen. Platforms that are optimized for
touchscreens normally use special text-selection handles, which interact
with Qt via QInputMethod. You can opt out of the behavior change by
using an import version < 6.4.
Pick-to: 6.4
Task-number: QTBUG-10684
Task-number: QTBUG-38934
Task-number: QTBUG-90494
Task-number: QTBUG-101205
Change-Id: Ia96f53cd7c6db5f995aab5505f61c13f9a4c4c0a
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/quick/items/qquicktextcontrol.cpp')
-rw-r--r-- | src/quick/items/qquicktextcontrol.cpp | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index 40c9e21dc4..cbc9f10f9e 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -36,6 +36,7 @@ #include <qmetaobject.h> #include <private/qqmlglobal_p.h> +#include <private/qquickdeliveryagent_p_p.h> // ### these should come from QStyleHints const int textCursorWidth = 1; @@ -79,6 +80,7 @@ QQuickTextControlPrivate::QQuickTextControlPrivate() hasImState(false), cursorRectangleChanged(false), hoveredMarker(false), + selectByTouchDrag(false), lastSelectionStart(-1), lastSelectionEnd(-1) {} @@ -1004,6 +1006,9 @@ void QQuickTextControlPrivate::mousePressEvent(QMouseEvent *e, const QPointF &po cursor.clearSelection(); } } + + if (!selectByTouchDrag && !QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(e)) + return; if (interactionFlags & Qt::TextEditable) blockWithMarkerUnderMousePress = q->blockWithMarkerAt(pos); if (e->button() & Qt::MiddleButton) { @@ -1074,6 +1079,9 @@ void QQuickTextControlPrivate::mousePressEvent(QMouseEvent *e, const QPointF &po void QQuickTextControlPrivate::mouseMoveEvent(QMouseEvent *e, const QPointF &mousePos) { + if (!selectByTouchDrag && !QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(e)) + return; + Q_Q(QQuickTextControl); if ((e->buttons() & Qt::LeftButton)) { @@ -1154,6 +1162,7 @@ void QQuickTextControlPrivate::mouseReleaseEvent(QMouseEvent *e, const QPointF & const QTextCursor oldSelection = cursor; const int oldCursorPos = cursor.position(); + const bool isMouse = QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(e); if (mousePressed) { mousePressed = false; @@ -1169,6 +1178,8 @@ void QQuickTextControlPrivate::mouseReleaseEvent(QMouseEvent *e, const QPointF & q->insertFromMimeData(md); #endif } + if (!isMouse && !selectByTouchDrag && interactionFlags.testFlag(Qt::TextEditable)) + setCursorPosition(pos); repaintOldAndNewSelection(oldSelection); @@ -1177,7 +1188,8 @@ void QQuickTextControlPrivate::mouseReleaseEvent(QMouseEvent *e, const QPointF & q->updateCursorRectangle(true); } - if ((interactionFlags & Qt::TextEditable) && (e->button() & Qt::LeftButton) && blockWithMarkerUnderMousePress.isValid()) { + if ((isMouse || selectByTouchDrag) && interactionFlags.testFlag(Qt::TextEditable) && + (e->button() & Qt::LeftButton) && blockWithMarkerUnderMousePress.isValid()) { QTextBlock block = q->blockWithMarkerAt(pos); if (block == blockWithMarkerUnderMousePress) { auto fmt = block.blockFormat(); @@ -1215,7 +1227,8 @@ void QQuickTextControlPrivate::mouseDoubleClickEvent(QMouseEvent *e, const QPoin { Q_Q(QQuickTextControl); - if (e->button() == Qt::LeftButton && (interactionFlags & Qt::TextSelectableByMouse)) { + if (e->button() == Qt::LeftButton && (interactionFlags & Qt::TextSelectableByMouse) + && (selectByTouchDrag || QQuickDeliveryAgentPrivate::isEventFromMouseOrTouchpad(e))) { #if QT_CONFIG(im) commitPreedit(); #endif @@ -1609,6 +1622,14 @@ void QQuickTextControl::setWordSelectionEnabled(bool enabled) d->wordSelectionEnabled = enabled; } +#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) +void QQuickTextControl::setTouchDragSelectionEnabled(bool enabled) +{ + Q_D(QQuickTextControl); + d->selectByTouchDrag = enabled; +} +#endif + QMimeData *QQuickTextControl::createMimeDataFromSelection() const { Q_D(const QQuickTextControl); |