From 4de9b94042dd173c6db31a4641a1513a9b319a79 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 Pick-to: 6.8 Change-Id: Iee1310c777ebbb807990bf3cec39e6d07481dfad Reviewed-by: Assam Boudjelthia --- .../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 ada5ed79c86..0eafcb7f6c9 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 4e05d57c519..358e838a9bd 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; class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, QtInputInterface @@ -49,6 +50,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(); @@ -88,6 +90,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, @@ -232,6 +256,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(); @@ -311,6 +340,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. @@ -322,6 +352,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt void setFocusedView(QtEditText currentEditText) { + setKeyboardTransitionInProgress(false); m_currentEditText = currentEditText; }