Skip to content

fix(android): fix keyboard size after rotation and restore via onSizeChanged, after layout#11722

Merged
jahorton merged 1 commit intomasterfrom
fix/android/split-layout-and-rescale
Jun 10, 2024
Merged

fix(android): fix keyboard size after rotation and restore via onSizeChanged, after layout#11722
jahorton merged 1 commit intomasterfrom
fix/android/split-layout-and-rescale

Conversation

@jahorton
Copy link
Copy Markdown
Contributor

@jahorton jahorton commented Jun 6, 2024

Fixes: #10054

This aims to fix the size and orientation issues we've been seeing for our touch-keyboards on Android.

Note that this PR adds to the adjustments made by ##11604. That does appear to properly ensure the correct "outer size" of the keyboard - that of the hosting WebView. The remaining issues appear to lie within the keyboard host-page inside of the WebView.

In order to properly handle this, ensuring proper layout for our WebView-internal keyboard, we split management of WebView's layout operations from the JS calls used to set the WebView-internal layout, the latter of which are based on the final size of the hosting WebView. To do so, we relocate the latter set of calls to onSizeChanged, overriding a superclass method that ought be triggered after onConfigurationChanged and its layout-update.

User Testing

TEST_KEYBOARD_REPEATED_RESTORE

  1. Install the PR build of Keyman for Android on an Android device/emulator Android 13 (SDK 33)
  2. Ensure the keyboard may be used as the system keyboard.
  3. Pick any application and start editing text via the Keyman system keyboard (without changing orientation).
  4. Dismiss the keyboard (by finishing your input and selecting something that doesn't need the keyboard).
  5. Change your device's orientation: if in 'portrait', go to 'landscape' mode and vice-versa.
  6. Re-activate the keyboard.
  7. Repeat steps 3 through 6 at least five times, verifying that the OSK always displays with the correct width for the device's orientation.

TEST_GENERAL_USE: Test the system keyboard in general use, tossing in a few orientation changes from time to time. Verify that the keyboard always displays correctly for the current orientation.

@keymanapp-test-bot keymanapp-test-bot bot added has-user-test user-test-required User tests have not been completed labels Jun 6, 2024
@keymanapp-test-bot
Copy link
Copy Markdown

keymanapp-test-bot bot commented Jun 6, 2024

User Test Results

Test specification and instructions

  • TEST_KEYBOARD_REPEATED_RESTORE (PASSED): I tested this issue with the attached "Keyman 18.0.45-alpha-test-11722" build on an Android 13(SDK 33) emulator and physical environment: Here is my observation. (notes)
  • TEST_GENERAL_USE (PASSED): I used the keyman as the system's keyboard in multiple applications. OSK always displays the correct device's orientation. It works correctly. Thank you.

Test Artifacts

Comment on lines +446 to 448
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Copy link
Copy Markdown
Contributor Author

@jahorton jahorton Jun 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What set me on this path: we're calling methods that should be automatically called by the Android OS with parameters we're managing in order to maintain WebView and host page layout. That... feels odd. It does seem to be the correct time to adjust Android View layout data, at least.

The question this left me with, though: the API for Configuration suggests that it returns the "available" width and height. The thing is... the Configuration passed in as a parameter would have been computed before we set new layout parameters in place. So... is it actually right to expect the values to be current within this method? Or, do we need to wait for layout adjustments to take place first? If we're adjusting height, that could certainly be volatile... and made worse if we're also simultaneously flipping our width and height values due to orientation change.

@mcdurdin mcdurdin self-requested a review June 7, 2024 01:20
@mcdurdin
Copy link
Copy Markdown
Member

mcdurdin commented Jun 7, 2024

I am going to install this now

Copy link
Copy Markdown
Member

@mcdurdin mcdurdin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code changes look okay.

I know this is a bug fix, and we are trying to keep changes minimal. It seems like part of the problem here is the existing spaghetti is making it very difficult to reason about the orientation state.

One simple refactor I think we should try and apply is to reduce the number of loadJavascript calls:

  • Each call is costly
  • If we have a setDimensions function which is passed an object, then we can set as many of the dimensions as are passed in, in the specific order that they should be set, and without having to bubble that ordering detail all the up into the Java code.
  • It helps us see where we are only setting width or height or vice-versa.

Comment on lines 478 to 481
loadJavascript(KMString.format("setBannerHeight(%d)", bannerHeight));
loadJavascript(KMString.format("setOskWidth(%d)", newConfig.screenWidthDp));
loadJavascript(KMString.format("setOskWidth(%d)", width));
// Must be last - it's the one that triggers a Web-engine layout refresh.
loadJavascript(KMString.format("setOskHeight(%d)", oskHeight));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This smells like it should be a single function call, setDimensions({bannerHeight:%d,oskWidth:%d,oskHeight:%d}).

This may also be relevant:

public void onResume() {
DisplayMetrics dms = context.getResources().getDisplayMetrics();
int kbWidth = (int) (dms.widthPixels / dms.density);
// Ensure window is loaded for javascript functions
loadJavascript(KMString.format(
"window.onload = function(){ setOskWidth(\"%d\");"+
"setOskHeight(\"0\"); };", kbWidth));
if (this.getShouldShowHelpBubble()) {
this.showHelpBubbleAfterDelay(2000);
}
}

Calls to these functions (on master branch):

  • Only 1 call to setBannerHeight, right here.
  • 4 calls to setOskHeight
  • 2 calls to setOskWidth

@dinakaranr
Copy link
Copy Markdown

Test Results

  • TEST_KEYBOARD_REPEATED_RESTORE (PASSED): I tested this issue with the attached "Keyman 18.0.45-alpha-test-11722" build on an Android 13(SDK 33) emulator and physical environment: Here is my observation.
  1. Installed the "Keyman 18.0.45.apk" file and gave all permissions to the application.
  2. Checked the "Enable Keyman as system-wide keyboard" and set the keyboard as the default keyboard box on the settings page.

I have followed the acceptance steps. I tried to change the view from portrait to landscape and landscape to portrait. OSK always displays the correct width and height after the device's orientation. It works correctly after repeating steps more than 10 times. It works correctly. Thank you.

  • TEST_GENERAL_USE (PASSED): I used the keyman as the system's keyboard in multiple applications. OSK always displays the correct device's orientation. It works correctly. Thank you.

@keymanapp-test-bot keymanapp-test-bot bot removed the user-test-required User tests have not been completed label Jun 7, 2024
@mcdurdin mcdurdin modified the milestones: A18S3, A18S4 Jun 7, 2024
jahorton added a commit that referenced this pull request Jun 10, 2024
Base automatically changed from fix/android/sys-keyboard-orientation to master June 10, 2024 05:15
@jahorton jahorton merged commit b8943ea into master Jun 10, 2024
@jahorton jahorton deleted the fix/android/split-layout-and-rescale branch June 10, 2024 05:15
@keyman-server
Copy link
Copy Markdown
Collaborator

Changes in this pull request will be available for download in Keyman version 18.0.53-alpha

@mcdurdin
Copy link
Copy Markdown
Member

So far the test build has worked perfectly for me. I'll move to 18.0.53-alpha on my phone today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(android): sometimes the Android keyboard pops up at wrong size

4 participants