diff options
author | Pekka Gehör <pekka.gehor@qt.io> | 2021-02-24 14:22:49 +0200 |
---|---|---|
committer | Pekka Gehör <pekka.gehor@qt.io> | 2021-05-25 08:45:39 +0300 |
commit | 32cdf0ce0faaeb6fe8bbc2f3df27a597c0bb8a55 (patch) | |
tree | 2f95b1f1a1ade182964ecf1507e188c6c1625653 /src/plugins/platforms/android | |
parent | 13c8db52a2e16ba525396bb7853de94ac50d6acf (diff) |
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 <rami.potinkara@qt.io>
Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
Diffstat (limited to 'src/plugins/platforms/android')
-rw-r--r-- | src/plugins/platforms/android/androidjniinput.cpp | 5 | ||||
-rw-r--r-- | src/plugins/platforms/android/androidjniinput.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/android/qandroidinputcontext.cpp | 45 |
3 files changed, 43 insertions, 8 deletions
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 5f803badf9..ebdc18cc07 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -121,6 +121,11 @@ namespace QtAndroidInput return m_softwareKeyboardRect; } + int getSelectHandleWidth() + { + return QJniObject::callStaticMethod<jint>(applicationClass(), "getSelectHandleWidth"); + } + void updateHandles(int mode, QPoint editMenuPos, uint32_t editButtons, QPoint cursor, QPoint anchor, bool rtl) { QJniObject::callStaticMethod<void>(applicationClass(), "updateHandles", "(IIIIIIIIZ)V", diff --git a/src/plugins/platforms/android/androidjniinput.h b/src/plugins/platforms/android/androidjniinput.h index 7a93e0214c..ceef2a826c 100644 --- a/src/plugins/platforms/android/androidjniinput.h +++ b/src/plugins/platforms/android/androidjniinput.h @@ -62,6 +62,7 @@ namespace QtAndroidInput // cursor/selection handles void updateHandles(int handleCount, QPoint editMenuPos = QPoint(), uint32_t editButtons = 0, QPoint cursor = QPoint(), QPoint anchor = QPoint(), bool rtl = false); + int getSelectHandleWidth(); bool registerNatives(JNIEnv *env); } 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; |