From 2aae64c041e81f7c982b3d3a72fc78ea7ce00a5a Mon Sep 17 00:00:00 2001 From: Bartlomiej Moskal Date: Tue, 8 Apr 2025 14:36:56 +0200 Subject: [PATCH] Android-Keyboard: Use new show() / hide() methods for keyboard control Starting with API level 30, Android introduced new [0]WindowInsetsController.show(int) and [1]hide(int) methods for controlling the keyboard visibility. This commit updates the code to use these methods on devices running API 30 and above. [0]https://developer.android.com/reference/android/view/WindowInsetsController#show(int) [1]https://developer.android.com/reference/android/view/WindowInsetsController#hide(int) Task-number: QTBUG-98984 Pick-to: 6.8 Change-Id: Icfcad3430cd269353572f66f72114238045f7756 Reviewed-by: Assam Boudjelthia (cherry picked from commit 3823d99a688813d2692eb0d4b99939a65bb6ee6a) Reviewed-by: Qt Cherry-pick Bot (cherry picked from commit 75e575e18f0fbfa8571d9044beea3cf3939881ab) --- .../qtproject/qt/android/QtInputDelegate.java | 133 ++++++++++++------ 1 file changed, 93 insertions(+), 40 deletions(-) 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 41ad3f5ff16..8dfe9c5312d 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java @@ -19,6 +19,8 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.WindowInsets; import android.view.WindowInsets.Type; +import android.view.WindowInsetsAnimationController; +import android.view.WindowInsetsAnimationControlListener; import android.view.WindowManager; import android.view.ViewTreeObserver; import android.view.inputmethod.InputMethodManager; @@ -127,6 +129,58 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt } } + private void showKeyboard(Activity activity, + final int x, final int y, final int width, final int height, + final int inputHints, final int enterKeyType) + { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + activity.getWindow().getInsetsController().controlWindowInsetsAnimation( + WindowInsets.Type.ime(), -1, null, null, + new WindowInsetsAnimationControlListener() { + @Override + public void onCancelled(WindowInsetsAnimationController controller) { } + + @Override + public void onReady(WindowInsetsAnimationController controller, int types) { } + + @Override + public void onFinished(WindowInsetsAnimationController controller) { + QtNativeInputConnection.updateCursorPosition(); + setKeyboardVisibility(true, System.nanoTime()); + if (m_softInputMode == 0) + probeForKeyboardHeight(activity, x, y, width, height, + inputHints, enterKeyType); + } + }); + activity.getWindow().getInsetsController().show(Type.ime()); + } else { + if (m_imm == null) + return; + m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler()) { + @Override + @SuppressWarnings("fallthrough") + protected void onReceiveResult(int resultCode, Bundle resultData) { + switch (resultCode) { + case InputMethodManager.RESULT_SHOWN: + QtNativeInputConnection.updateCursorPosition(); + //FALLTHROUGH + case InputMethodManager.RESULT_UNCHANGED_SHOWN: + setKeyboardVisibility(true, System.nanoTime()); + if (m_softInputMode == 0) { + probeForKeyboardHeight(activity, + x, y, width, height, inputHints, enterKeyType); + } + break; + case InputMethodManager.RESULT_HIDDEN: + case InputMethodManager.RESULT_UNCHANGED_HIDDEN: + setKeyboardVisibility(false, System.nanoTime()); + break; + } + } + }); + } + } + @Override public void showSoftwareKeyboard(Activity activity, final int x, final int y, final int width, final int height, @@ -146,30 +200,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt m_currentEditText.setLayoutParams(new QtLayout.LayoutParams(width, height, x, y)); m_currentEditText.requestFocus(); m_currentEditText.postDelayed(() -> { - if (m_imm == null) - return; - m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler()) { - @Override - @SuppressWarnings("fallthrough") - protected void onReceiveResult(int resultCode, Bundle resultData) { - switch (resultCode) { - case InputMethodManager.RESULT_SHOWN: - QtNativeInputConnection.updateCursorPosition(); - //FALLTHROUGH - case InputMethodManager.RESULT_UNCHANGED_SHOWN: - setKeyboardVisibility(true, System.nanoTime()); - if (m_softInputMode == 0) { - probeForKeyboardHeight(activity, - x, y, width, height, inputHints, enterKeyType); - } - break; - case InputMethodManager.RESULT_HIDDEN: - case InputMethodManager.RESULT_UNCHANGED_HIDDEN: - setKeyboardVisibility(false, System.nanoTime()); - break; - } - } - }); + showKeyboard(activity, x, y, width, height, inputHints, enterKeyType); if (m_currentEditText.m_optionsChanged) { m_imm.restartInput(m_currentEditText); m_currentEditText.m_optionsChanged = false; @@ -228,22 +259,44 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt if (m_imm == null || m_currentEditText == null) return; - m_imm.hideSoftInputFromWindow(m_currentEditText.getWindowToken(), 0, - new ResultReceiver(new Handler()) { - @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - switch (resultCode) { - case InputMethodManager.RESULT_SHOWN: - case InputMethodManager.RESULT_UNCHANGED_SHOWN: - setKeyboardVisibility(true, System.nanoTime()); - break; - case InputMethodManager.RESULT_HIDDEN: - case InputMethodManager.RESULT_UNCHANGED_HIDDEN: - setKeyboardVisibility(false, System.nanoTime()); - break; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + Activity activity = QtNative.activity(); + if (activity == null) { + Log.w(TAG, "hideSoftwareKeyboard: The activity reference is null"); + return; + } + activity.getWindow().getInsetsController().controlWindowInsetsAnimation( + WindowInsets.Type.ime(), -1, null, null, + new WindowInsetsAnimationControlListener() { + @Override + public void onCancelled(WindowInsetsAnimationController controller) { } + @Override + public void onReady(WindowInsetsAnimationController controller, int types) { } + @Override + public void onFinished(WindowInsetsAnimationController controller) { + setKeyboardVisibility(false, System.nanoTime()); } - } - }); + + }); + activity.getWindow().getInsetsController().hide(Type.ime()); + } else { + m_imm.hideSoftInputFromWindow(m_currentEditText.getWindowToken(), 0, + new ResultReceiver(new Handler()) { + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + switch (resultCode) { + case InputMethodManager.RESULT_SHOWN: + case InputMethodManager.RESULT_UNCHANGED_SHOWN: + setKeyboardVisibility(true, System.nanoTime()); + break; + case InputMethodManager.RESULT_HIDDEN: + case InputMethodManager.RESULT_UNCHANGED_HIDDEN: + setKeyboardVisibility(false, System.nanoTime()); + break; + } + } + }); + } }); } @@ -271,7 +324,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt boolean isKeyboardHidden = true; - if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { Rect r = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r); DisplayMetrics metrics = new DisplayMetrics();