diff options
9 files changed, 101 insertions, 14 deletions
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java index 4cae9465ba..c473c1f78b 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java @@ -280,7 +280,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; @@ -302,7 +302,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); @@ -419,12 +419,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 { @@ -575,6 +575,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/qt/android/QtNative.java b/src/android/jar/src/org/qtproject/qt/android/QtNative.java index 001e6a7970..cb2a78b403 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtNative.java @@ -883,10 +883,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) { @@ -894,7 +909,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/qt/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java index a4e6df058d..553c9dffdd 100644 --- a/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java +++ b/src/android/java/src/org/qtproject/qt/android/bindings/QtActivity.java @@ -1074,6 +1074,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 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; diff --git a/tests/auto/corelib/global/qglobalstatic/CMakeLists.txt b/tests/auto/corelib/global/qglobalstatic/CMakeLists.txt index 959b2b25b0..6f8a784a0d 100644 --- a/tests/auto/corelib/global/qglobalstatic/CMakeLists.txt +++ b/tests/auto/corelib/global/qglobalstatic/CMakeLists.txt @@ -12,4 +12,5 @@ qt_internal_add_test(tst_qglobalstatic SRCDIR=\\\"${CMAKE_CURRENT_SOURCE_DIR}/\\\" PUBLIC_LIBRARIES Qt::CorePrivate + Qt::TestPrivate ) diff --git a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp index dfc62ce163..190df2a555 100644 --- a/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp +++ b/tests/auto/corelib/global/qglobalstatic/tst_qglobalstatic.cpp @@ -35,6 +35,8 @@ #include <sys/resource.h> #endif +#include <QtTest/private/qemulationdetector_p.h> + class tst_QGlobalStatic : public QObject { Q_OBJECT @@ -179,6 +181,9 @@ Q_GLOBAL_STATIC_WITH_ARGS(ThrowingType, threadStressTestGS, (threadStressTestCon void tst_QGlobalStatic::threadStressTest() { + if (QTestPrivate::isRunningArmOnX86()) + QSKIP("Frequently hangs on QEMU, QTBUG-91423"); + class ThreadStressTestThread: public QThread { public: |