From 32cdf0ce0faaeb6fe8bbc2f3df27a597c0bb8a55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pekka=20Geh=C3=B6r?= Date: Wed, 24 Feb 2021 14:22:49 +0200 Subject: Android: Fix select handles misplacement on QDialog Get select handles {Left, Right}Point from a mapToGlobal with a cursorRectangleof anchorRectangle of the selected word/text. Task-number: QTBUG-90799 Change-Id: I4fed19a1d3bb2247656b052306307e6980074405 Reviewed-by: Rami Potinkara Reviewed-by: Ville Voutilainen --- .../platforms/android/qandroidinputcontext.cpp | 45 ++++++++++++++++++---- 1 file changed, 37 insertions(+), 8 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 eddc71477e..fb51e1dba1 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -92,6 +92,7 @@ private: static QAndroidInputContext *m_androidInputContext = nullptr; static char const *const QtNativeInputConnectionClassName = "org/qtproject/qt/android/QtNativeInputConnection"; static char const *const QtExtractedTextClassName = "org/qtproject/qt/android/QtExtractedText"; +static int m_selectHandleWidth = 0; static jclass m_extractedTextClass = 0; static jmethodID m_classConstructorMethodID = 0; static jfieldID m_partialEndOffsetFieldID = 0; @@ -609,7 +610,6 @@ void QAndroidInputContext::updateSelectionHandles() auto im = qGuiApp->inputMethod(); - QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImAnchorPosition | Qt::ImEnabled | Qt::ImCurrentSelection | Qt::ImHints | Qt::ImSurroundingText | Qt::ImReadOnly); @@ -619,6 +619,7 @@ void QAndroidInputContext::updateSelectionHandles() int anchor = query.value(Qt::ImAnchorPosition).toInt(); const QVariant readOnlyVariant = query.value(Qt::ImReadOnly); bool readOnly = readOnlyVariant.toBool(); + QPlatformWindow *qPlatformWindow = qGuiApp->focusWindow()->handle(); if ( cpos == anchor && (!readOnlyVariant.isValid() || readOnly)) { QtAndroidInput::updateHandles(Hidden); @@ -627,7 +628,7 @@ void QAndroidInputContext::updateSelectionHandles() if (cpos == anchor || im->anchorRectangle().isNull()) { auto curRect = cursorRectangle(); - QPoint cursorPoint = qGuiApp->focusWindow()->handle()->mapToGlobal(QPoint(curRect.x() + (curRect.width() / 2), curRect.y() + curRect.height())); + QPoint cursorPoint = qPlatformWindow->mapToGlobal(QPoint(curRect.x() + (curRect.width() / 2), curRect.y() + curRect.height())); QPoint editMenuPoint(cursorPoint.x(), cursorPoint.y()); m_handleMode &= ShowEditPopup; m_handleMode |= ShowCursor; @@ -646,14 +647,26 @@ void QAndroidInputContext::updateSelectionHandles() auto rightRect = anchorRectangle(); if (cpos > anchor) std::swap(leftRect, rightRect); - - QPoint leftPoint(leftRect.bottomLeft().toPoint()); - QPoint righPoint(rightRect.bottomRight().toPoint()); - QPoint editPoint(leftRect.united(rightRect).topLeft().toPoint()); + //Move the left or right select handle to the center from the screen edge + //the select handle is close to or over the screen edge. Otherwise, the + //select handle might go out of the screen and it would be impossible to drag. + QPoint leftPoint(qPlatformWindow->mapToGlobal(leftRect.bottomLeft().toPoint())); + QPoint rightPoint(qPlatformWindow->mapToGlobal(rightRect.bottomRight().toPoint())); + + if (m_selectHandleWidth == 0) + m_selectHandleWidth = QtAndroidInput::getSelectHandleWidth() / 2; + int rightSideOfScreen = QtAndroid::androidPlatformIntegration()->screen()->availableGeometry().right(); + if (leftPoint.x() < m_selectHandleWidth) + leftPoint.setX(m_selectHandleWidth); + + if (rightPoint.x() > rightSideOfScreen - m_selectHandleWidth) + rightPoint.setX(rightSideOfScreen - m_selectHandleWidth); + + QPoint editPoint(qPlatformWindow->mapToGlobal(leftRect.united(rightRect).topLeft().toPoint())); uint32_t buttons = readOnly ? EditContext::CopyButton | EditContext::SelectAllButton : EditContext::AllButtons; - QtAndroidInput::updateHandles(m_handleMode, editPoint, buttons, leftPoint, righPoint, + QtAndroidInput::updateHandles(m_handleMode, editPoint, buttons, leftPoint, rightPoint, query.value(Qt::ImCurrentSelection).toString().isRightToLeft()); m_hideCursorHandleTimer.stop(); } @@ -690,7 +703,23 @@ void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y) } bool ok; - const int handlePos = queryFocusObject(Qt::ImCursorPosition, point).toInt(&ok); + auto object = m_focusObject->parent(); + int dialogMoveX = 0; + while (object) { + if (QString::compare(object->metaObject()->className(), + "QDialog", Qt::CaseInsensitive) == 0) { + dialogMoveX += object->property("x").toInt(); + } + object = object->parent(); + }; + + auto position = + QPointF(QHighDpi::fromNativePixels(point, QGuiApplication::focusWindow())); + const QPointF fixedPosition = QPointF(position.x() - dialogMoveX, position.y()); + const QInputMethod *im = QGuiApplication::inputMethod(); + const QTransform mapToLocal = im->inputItemTransform().inverted(); + const int handlePos = im->queryFocusObject(Qt::ImCursorPosition, mapToLocal.map(fixedPosition)).toInt(&ok); + if (!ok) return; -- cgit v1.2.3