summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android
diff options
context:
space:
mode:
authorPiotr Mikolajczyk <piotr.mikolajczyk@qt.io>2020-12-18 10:51:30 +0100
committerVille Voutilainen <ville.voutilainen@qt.io>2021-03-05 07:57:14 +0000
commit5c6b10c3cee5737dbc041d0463220898c8120807 (patch)
treeaec06989da84711fa432899f84cd0adba9323e82 /src/plugins/platforms/android
parent9fb81fc28774cd4aa01a8b29d59150e1a7de8fd8 (diff)
Android: Place cursor correctly on screen when editing
When editing text the cursor is not placed correctly. So this has been achieved by tricking Android into thinking that the input area is only the line where the cursor is, so it is forced to keep it on screen. Fixes: QTBUG-91073 Pick-to: 5.15 Change-Id: Icc2e8315deb76ca1a84819d3fdceaa7b027b1174 Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
Diffstat (limited to 'src/plugins/platforms/android')
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp16
-rw-r--r--src/plugins/platforms/android/androidjniinput.h4
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp44
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.h2
4 files changed, 60 insertions, 6 deletions
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp
index 1de25b2857..d720f1a317 100644
--- a/src/plugins/platforms/android/androidjniinput.cpp
+++ b/src/plugins/platforms/android/androidjniinput.cpp
@@ -79,15 +79,16 @@ namespace QtAndroidInput
candidatesEnd);
}
- void showSoftwareKeyboard(int left, int top, int width, int height, int inputHints, int enterKeyType)
+ void showSoftwareKeyboard(int left, int top, int width, int height, int editorHeight, int inputHints, int enterKeyType)
{
QJniObject::callStaticMethod<void>(applicationClass(),
"showSoftwareKeyboard",
- "(IIIIII)V",
+ "(IIIIIII)V",
left,
top,
width,
height,
+ editorHeight,
inputHints,
enterKeyType);
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
@@ -129,6 +130,17 @@ namespace QtAndroidInput
anchor.x(), anchor.y(), rtl);
}
+ void updateInputItemRectangle(int left, int top, int width, int height)
+ {
+ QJniObject::callStaticMethod<void>(applicationClass(),
+ "updateInputItemRectangle",
+ "(IIII)V",
+ left,
+ top,
+ width,
+ height);
+ }
+
static void mouseDown(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint x, jint y)
{
if (m_ignoreMouseEvents)
diff --git a/src/plugins/platforms/android/androidjniinput.h b/src/plugins/platforms/android/androidjniinput.h
index 9e75f43a83..7a93e0214c 100644
--- a/src/plugins/platforms/android/androidjniinput.h
+++ b/src/plugins/platforms/android/androidjniinput.h
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
namespace QtAndroidInput
{
// Software keyboard support
- void showSoftwareKeyboard(int top, int left, int width, int height, int inputHints, int enterKeyType);
+ void showSoftwareKeyboard(int top, int left, int width, int editorHeight, int height, int inputHints, int enterKeyType);
void resetSoftwareKeyboard();
void hideSoftwareKeyboard();
bool isSoftwareKeyboardVisible();
@@ -57,6 +57,8 @@ namespace QtAndroidInput
void updateSelection(int selStart, int selEnd, int candidatesStart, int candidatesEnd);
// Software keyboard support
+ // edit field resize
+ void updateInputItemRectangle(int left, int top, int width, int height);
// cursor/selection handles
void updateHandles(int handleCount, QPoint editMenuPos = QPoint(), uint32_t editButtons = 0,
QPoint cursor = QPoint(), QPoint anchor = QPoint(), bool rtl = false);
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index 29236667d3..378dfa03c8 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -47,6 +47,7 @@
#include "qandroideventdispatcher.h"
#include "qandroidinputcontext.h"
#include "qandroidplatformintegration.h"
+#include "private/qhighdpiscaling_p.h"
#include <QTextBoundaryFinder>
#include <QTextCharFormat>
@@ -59,7 +60,6 @@
#include <qthread.h>
#include <qwindow.h>
#include <qpa/qplatformwindow.h>
-
QT_BEGIN_NAMESPACE
namespace {
@@ -491,7 +491,7 @@ QAndroidInputContext::QAndroidInputContext()
m_androidInputContext = this;
QObject::connect(QGuiApplication::inputMethod(), &QInputMethod::cursorRectangleChanged,
- this, &QAndroidInputContext::updateSelectionHandles);
+ this, &QAndroidInputContext::updateInputItemRectangle);
QObject::connect(QGuiApplication::inputMethod(), &QInputMethod::anchorRectangleChanged,
this, &QAndroidInputContext::updateSelectionHandles);
QObject::connect(QGuiApplication::inputMethod(), &QInputMethod::inputItemClipRectangleChanged, this, [this]{
@@ -889,12 +889,50 @@ void QAndroidInputContext::showInputPanel()
else
m_updateCursorPosConnection = connect(qGuiApp->focusObject(), SIGNAL(cursorPositionChanged()), this, SLOT(updateCursorPosition()));
- QRect rect = screenInputItemRectangle();
+ QRect rect = cursorRect();
QtAndroidInput::showSoftwareKeyboard(rect.left(), rect.top(), rect.width(), rect.height(),
+ screenInputItemRectangle().height(),
query->value(Qt::ImHints).toUInt(),
query->value(Qt::ImEnterKeyType).toUInt());
}
+QRect QAndroidInputContext::cursorRect()
+{
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ // if single line, we do not want to mess with the editor's position, as we do not
+ // have to follow the cursor in vertical axis
+ if (query.isNull()
+ || (query->value(Qt::ImHints).toUInt() & Qt::ImhMultiLine) != Qt::ImhMultiLine)
+ return {};
+
+ auto im = qGuiApp->inputMethod();
+ if (!im)
+ return {};
+
+ const auto cursorRect= im->cursorRectangle().toRect();
+ QRect finalRect(inputItemRectangle().toRect());
+ const QWindow *window = qGuiApp->focusWindow();
+ const double pd = window
+ ? QHighDpiScaling::factor(window)
+ : QHighDpiScaling::factor(QtAndroid::androidPlatformIntegration()->screen());
+ finalRect.setY(cursorRect.y() * pd);
+ finalRect.setHeight(cursorRect.height() * pd);
+ //fiddle a bit with vert margins, so the tracking rectangle is not too tight.
+ finalRect += QMargins(0, cursorRect.height() / 4, 0, cursorRect.height() / 4);
+ return finalRect;
+}
+
+void QAndroidInputContext::updateInputItemRectangle()
+{
+ QRect rect = cursorRect();
+
+ if (!rect.isValid())
+ return;
+ QtAndroidInput::updateInputItemRectangle(rect.left(), rect.top(),
+ rect.width(), rect.height());
+ updateSelectionHandles();
+}
+
void QAndroidInputContext::showInputPanelLater(Qt::ApplicationState state)
{
if (state != Qt::ApplicationActive)
diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h
index e9bfb98e66..02a66c367a 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.h
+++ b/src/plugins/platforms/android/qandroidinputcontext.h
@@ -138,6 +138,7 @@ public:
public slots:
void safeCall(const std::function<void()> &func, Qt::ConnectionType conType = Qt::BlockingQueuedConnection);
void updateCursorPosition();
+ void updateInputItemRectangle();
void updateSelectionHandles();
void handleLocationChanged(int handleId, int x, int y);
void touchDown(int x, int y);
@@ -154,6 +155,7 @@ private:
bool focusObjectIsComposing() const;
void focusObjectStartComposing();
bool focusObjectStopComposing();
+ QRect cursorRect();
private:
ExtractedText m_extractedText;