From 7e4b10677fe5a46cbeb478dedf0e4d3ca638adef Mon Sep 17 00:00:00 2001 From: Rami Potinkara Date: Thu, 17 Oct 2024 20:50:10 +0300 Subject: [PATCH] Android: Do not hide keyboard when opening It takes some time to display the keyboard. For this reason, in case the keyboard was not displayed yet - we could wrongly assume that the keyboard is hiding. To avoid this situation, there is a new check. In case the keyboard has just been opened and it is not displayed yet, the execution of HideKeyboardRunnable is postponed to give time for the keyboard to be displayed. Fixes: QTBUG-130000 Change-Id: Iee1310c777ebbb807990bf3cec39e6d07481dfad Reviewed-by: Assam Boudjelthia (cherry picked from commit 4de9b94042dd173c6db31a4641a1513a9b319a79) Reviewed-by: Qt Cherry-pick Bot --- .../qt/android/QtInputConnection.java | 14 ++++++++- .../qtproject/qt/android/QtInputDelegate.java | 31 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java index 79d58029da7..2fbbd5ae1b5 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java @@ -66,12 +66,15 @@ class QtInputConnection extends BaseInputConnection private static final int ID_COPY_URL = android.R.id.copyUrl; private static final int ID_SWITCH_INPUT_METHOD = android.R.id.switchInputMethod; private static final int ID_ADD_TO_DICTIONARY = android.R.id.addToDictionary; + private static final int KEYBOARD_CHECK_DELAY_MS = 100; private static final String QtTAG = "QtInputConnection"; private final QtInputConnectionListener m_qtInputConnectionListener; class HideKeyboardRunnable implements Runnable { + private int m_numberOfAttempts = 10; + @Override public void run() { // Check that the keyboard is really no longer there. @@ -79,6 +82,14 @@ class QtInputConnection extends BaseInputConnection Log.w(QtTAG, "HideKeyboardRunnable: QtInputConnectionListener is null"); return; } + + if (m_qtInputConnectionListener.keyboardTransitionInProgress() + && m_numberOfAttempts > 0) { + --m_numberOfAttempts; + m_view.postDelayed(this, KEYBOARD_CHECK_DELAY_MS); + return; + } + if (m_qtInputConnectionListener.isKeyboardHidden()) m_qtInputConnectionListener.onHideKeyboardRunnableDone(false, System.nanoTime()); } @@ -89,6 +100,7 @@ class QtInputConnection extends BaseInputConnection void onHideKeyboardRunnableDone(boolean visibility, long hideTimeStamp); void onSendKeyEventDefaultCase(); void onEditTextChanged(QtEditText editText); + boolean keyboardTransitionInProgress(); boolean isKeyboardHidden(); } @@ -98,7 +110,7 @@ class QtInputConnection extends BaseInputConnection private void setClosing(boolean closing) { if (closing) - m_view.postDelayed(new HideKeyboardRunnable(), 100); + m_view.postDelayed(new HideKeyboardRunnable(), KEYBOARD_CHECK_DELAY_MS); else if (m_qtInputConnectionListener != null) m_qtInputConnectionListener.onSetClosing(false); } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java index b544a2c9625..89f2529ab87 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java @@ -20,6 +20,7 @@ import android.view.MotionEvent; import android.view.WindowInsets; import android.view.WindowInsets.Type; import android.view.WindowManager; +import android.view.ViewTreeObserver; import android.view.inputmethod.InputMethodManager; import org.qtproject.qt.android.QtInputConnection.QtInputConnectionListener; @@ -52,6 +53,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt // That is why we assume that the keyboard should be higher than 0.15 of the screen. private static final float KEYBOARD_TO_SCREEN_RATIO = 0.15f; + private boolean m_keyboardTransitionInProgress = false; private boolean m_keyboardIsVisible = false; private boolean m_isKeyboardHidingAnimationOngoing = false; private long m_showHideTimeStamp = System.nanoTime(); @@ -91,6 +93,28 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt Log.w(TAG, "getSystemService() returned a null InputMethodManager instance"); } + private final ViewTreeObserver.OnGlobalLayoutListener keyboardListener = + new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + if (!isKeyboardHidden()) + setKeyboardTransitionInProgress(false); + } + }; + + private void setKeyboardTransitionInProgress(boolean state) + { + if (m_keyboardTransitionInProgress == state || m_currentEditText == null) + return; + + m_keyboardTransitionInProgress= state; + ViewTreeObserver observer = m_currentEditText.getViewTreeObserver(); + if (state) + observer.addOnGlobalLayoutListener(keyboardListener); + else + observer.removeOnGlobalLayoutListener(keyboardListener); + } + // QtInputInterface implementation begin @Override public void updateSelection(final int selStart, final int selEnd, @@ -234,6 +258,11 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt // QtInputInterface implementation end // QtInputConnectionListener methods + @Override + public boolean keyboardTransitionInProgress() { + return m_keyboardTransitionInProgress; + } + @Override public boolean isKeyboardHidden() { Activity activity = QtNative.activity(); @@ -313,6 +342,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt return; m_keyboardIsVisible = visibility; keyboardVisibilityUpdated(m_keyboardIsVisible); + setKeyboardTransitionInProgress(visibility); if (!visibility) { // Hiding the keyboard clears the immersive mode, so we need to set it again. @@ -324,6 +354,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt void setFocusedView(QtEditText currentEditText) { + setKeyboardTransitionInProgress(false); m_currentEditText = currentEditText; }