From e5f2be256fb3bb07a98693cb90a4d7e8bc63c508 Mon Sep 17 00:00:00 2001 From: Vova Mshanetskiy Date: Mon, 6 May 2019 19:10:09 +0300 Subject: QAndroidInputContext: Don't allow clearing selection by dragging handles Android's native text editing controls do not allow user to clear selection by dragging selection handles. Qt apps should behave in the same way. Change-Id: I9a7c3a2aafa484eed8ff2bbd46dd48c705195291 Reviewed-by: BogDan Vatra --- .../platforms/android/qandroidinputcontext.cpp | 66 +++++++++------------- 1 file changed, 27 insertions(+), 39 deletions(-) (limited to 'src/plugins/platforms/android/qandroidinputcontext.cpp') diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 4c0b3315be..4d9af18053 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -686,49 +686,15 @@ void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y) QCoreApplication::sendEvent(m_focusObject, &query); int cpos = query.value(Qt::ImCursorPosition).toInt(); int anchor = query.value(Qt::ImAnchorPosition).toInt(); - bool rtl = query.value(Qt::ImCurrentSelection).toString().isRightToLeft(); auto rightRect = im->anchorRectangle(); if (cpos > anchor) std::swap(leftRect, rightRect); - auto checkLeftHandle = [&rightRect](QPointF &handlePos) { - if (handlePos.y() > rightRect.center().y()) - handlePos.setY(rightRect.center().y()); // adjust Y handle pos - if (handlePos.y() >= rightRect.y() && handlePos.y() <= rightRect.bottom() && handlePos.x() >= rightRect.x()) - return false; // same line and wrong X pos ? - return true; - }; - - auto checkRtlRightHandle = [&rightRect](QPointF &handlePos) { - if (handlePos.y() > rightRect.center().y()) - handlePos.setY(rightRect.center().y()); // adjust Y handle pos - if (handlePos.y() >= rightRect.y() && handlePos.y() <= rightRect.bottom() && rightRect.x() >= handlePos.x()) - return false; // same line and wrong X pos ? - return true; - }; - - auto checkRightHandle = [&leftRect](QPointF &handlePos) { - if (handlePos.y() < leftRect.center().y()) - handlePos.setY(leftRect.center().y()); // adjust Y handle pos - if (handlePos.y() >= leftRect.y() && handlePos.y() <= leftRect.bottom() && leftRect.x() >= handlePos.x()) - return false; // same line and wrong X pos ? - return true; - }; - - auto checkRtlLeftHandle = [&leftRect](QPointF &handlePos) { - if (handlePos.y() < leftRect.center().y()) - handlePos.setY(leftRect.center().y()); // adjust Y handle pos - if (handlePos.y() >= leftRect.y() && handlePos.y() <= leftRect.bottom() && handlePos.x() >= leftRect.x()) - return false; // same line and wrong X pos ? - return true; - }; - - if (handleId == 2) { - if ((!rtl && !checkLeftHandle(point)) || (rtl && !checkRtlRightHandle(point))) - return; - } else if (handleId == 3) { - if ((!rtl && !checkRightHandle(point)) || (rtl && !checkRtlLeftHandle(point))) - return; + // Do not allow dragging left handle below right handle, or right handle above left handle + if (handleId == 2 && point.y() > rightRect.center().y()) { + point.setY(rightRect.center().y()); + } else if (handleId == 3 && point.y() < leftRect.center().y()) { + point.setY(leftRect.center().y()); } const QPointF pointLocal = im->inputItemTransform().inverted().map(point); @@ -752,6 +718,28 @@ void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y) newCpos = handlePos; } + /* + Do not allow clearing selection by dragging selection handles and do not allow swapping + selection handles for consistency with Android's native text editing controls. Ensure that at + least one symbol remains selected. + */ + if ((handleId == 2 || handleId == 3) && newCpos <= newAnchor) { + QTextBoundaryFinder finder(QTextBoundaryFinder::Grapheme, + query.value(Qt::ImCurrentSelection).toString()); + + const int oldSelectionStartPos = qMin(cpos, anchor); + + if (handleId == 2) { + finder.toEnd(); + finder.toPreviousBoundary(); + newAnchor = finder.position() + oldSelectionStartPos; + } else { + finder.toStart(); + finder.toNextBoundary(); + newCpos = finder.position() + oldSelectionStartPos; + } + } + // Check if handle has been dragged far enough if (m_composingText.isEmpty() && newCpos == cpos && newAnchor == anchor) return; -- cgit v1.2.3