summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPiotr Mikolajczyk <piotr.mikolajczyk@qt.io>2020-12-18 10:51:30 +0100
committerPiotr Mikolajczyk <piotr.mikolajczyk@qt.io>2021-03-12 10:03:01 +0100
commit9a81a9766c56f4a99172b105d892c905278065a4 (patch)
tree539c17e37548652b11116dcd3584860fcfedfa7f /src
parent9b23b3013b4e14a74ee1188836c334a767edaee8 (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 Change-Id: Icc2e8315deb76ca1a84819d3fdceaa7b027b1174 Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io> (cherry picked from commit 5c6b10c3cee5737dbc041d0463220898c8120807)
Diffstat (limited to 'src')
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java15
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java17
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java11
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp19
-rw-r--r--src/plugins/platforms/android/androidjniinput.h4
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp43
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.h2
7 files changed, 96 insertions, 15 deletions
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index 6aa935c2b1..a15a06a302 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -263,7 +263,7 @@ public class QtActivityDelegate
}, 5);
}
- public void showSoftwareKeyboard(final int x, final int y, final int width, final int height, final int inputHints, final int enterKeyType)
+ public void showSoftwareKeyboard(final int x, final int y, final int width, final int height, final int editorHeight, final int inputHints, final int enterKeyType)
{
if (m_imm == null)
return;
@@ -285,7 +285,7 @@ public class QtActivityDelegate
if (softInputIsHidden)
return;
} else {
- if (height > visibleHeight)
+ if (editorHeight > visibleHeight)
m_activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
else
m_activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
@@ -402,12 +402,12 @@ public class QtActivityDelegate
if (metrics.widthPixels > metrics.heightPixels) { // landscape
if (m_landscapeKeyboardHeight != r.bottom) {
m_landscapeKeyboardHeight = r.bottom;
- showSoftwareKeyboard(x, y, width, height, inputHints, enterKeyType);
+ showSoftwareKeyboard(x, y, width, height, editorHeight, inputHints, enterKeyType);
}
} else {
if (m_portraitKeyboardHeight != r.bottom) {
m_portraitKeyboardHeight = r.bottom;
- showSoftwareKeyboard(x, y, width, height, inputHints, enterKeyType);
+ showSoftwareKeyboard(x, y, width, height, editorHeight, inputHints, enterKeyType);
}
}
} else {
@@ -558,6 +558,13 @@ public class QtActivityDelegate
}
}
+ public void updateInputItemRectangle(final int x, final int y, final int w, final int h)
+ {
+ if (m_layout == null || m_editText == null || !m_keyboardIsVisible)
+ return;
+ m_layout.setLayoutParams(m_editText, new QtLayout.LayoutParams(w, h, x, y), true);
+ }
+
public boolean loadApplication(Activity activity, ClassLoader classLoader, Bundle loaderParams)
{
/// check parameters integrity
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index 39f1220722..dbd356f7a5 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -878,10 +878,25 @@ public class QtNative
});
}
+ private static void updateInputItemRectangle(final int x,
+ final int y,
+ final int w,
+ final int h)
+ {
+ runAction(new Runnable() {
+ @Override
+ public void run() {
+ m_activityDelegate.updateInputItemRectangle(x, y, w, h);
+ }
+ });
+ }
+
+
private static void showSoftwareKeyboard(final int x,
final int y,
final int width,
final int height,
+ final int editorHeight,
final int inputHints,
final int enterKeyType)
{
@@ -889,7 +904,7 @@ public class QtNative
@Override
public void run() {
if (m_activityDelegate != null)
- m_activityDelegate.showSoftwareKeyboard(x, y, width, height, inputHints, enterKeyType);
+ m_activityDelegate.showSoftwareKeyboard(x, y, width, height, editorHeight, inputHints, enterKeyType);
}
});
}
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
index b257a16567..b27f03fc7d 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
@@ -1079,6 +1079,11 @@ public class QtActivity extends Activity
QtNative.activityDelegate().resetSoftwareKeyboard();
}
+ public void updateInputItemRectangle(final int x, final int y, final int w, final int h)
+ {
+ QtNative.activityDelegate().updateInputItemRectangle(x, y, w, h);
+ }
+
public boolean setKeyboardVisibility(boolean visibility, long timeStamp)
{
return QtNative.activityDelegate().setKeyboardVisibility(visibility, timeStamp);
@@ -1090,10 +1095,10 @@ public class QtActivity extends Activity
}
public void showSoftwareKeyboard(final int x, final int y, final int width,
- final int height, final int inputHints,
- final int enterKeyType)
+ final int height, final int editorHeight,
+ final int inputHints, final int enterKeyType)
{
- QtNative.activityDelegate().showSoftwareKeyboard(x, y, width, height, inputHints, enterKeyType);
+ QtNative.activityDelegate().showSoftwareKeyboard(x, y, width, height, editorHeight, inputHints, enterKeyType);
}
public boolean startApplication()
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp
index fc581b3a94..029061edc3 100644
--- a/src/plugins/platforms/android/androidjniinput.cpp
+++ b/src/plugins/platforms/android/androidjniinput.cpp
@@ -80,18 +80,18 @@ 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)
{
QJNIObjectPrivate::callStaticMethod<void>(applicationClass(),
"showSoftwareKeyboard",
- "(IIIIII)V",
+ "(IIIIIII)V",
left,
top,
width,
height,
+ editorHeight,
inputHints,
- enterKeyType
- );
+ enterKeyType);
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints << enterKeyType;
#endif
@@ -131,6 +131,17 @@ namespace QtAndroidInput
anchor.x(), anchor.y(), rtl);
}
+ void updateInputItemRectangle(int left, int top, int width, int height)
+ {
+ QJNIObjectPrivate::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 5ef57ade61..b81ae5c995 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 5dfae532f6..c7452ef0e4 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -47,6 +47,7 @@
#include "qandroideventdispatcher.h"
#include "androiddeadlockprotector.h"
#include "qandroidplatformintegration.h"
+#include <private/qhighdpiscaling_p.h>
#include <QDebug>
#include <qevent.h>
#include <qguiapplication.h>
@@ -505,7 +506,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]{
@@ -930,12 +931,50 @@ void QAndroidInputContext::showInputPanel()
else
m_updateCursorPosConnection = connect(qGuiApp->focusObject(), SIGNAL(cursorPositionChanged()), this, SLOT(updateCursorPosition()));
- QRect rect = inputItemRectangle();
+ QRect rect = cursorRect();
QtAndroidInput::showSoftwareKeyboard(rect.left(), rect.top(), rect.width(), rect.height(),
+ inputItemRectangle().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());
+ 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 11b2360e69..8b3a362343 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;