Closed jahorton closed 1 year ago
Test specification and instructions
Somehow, it's about that line -
keyman.alignInputs
- so far as I can tell.
So it sounds like window.innerWidth
is internally invalidated, but refresh of the value is delayed. My suspicion is that the code in keyman.alignInputs
is forcing a DOM layout or reflow, which internally also ends up validating window.innerWidth
.
If this is the case, then when alignInputs
goes away with #3030, we'll need to re-fix this. We should be able to do that by forcing a reflow using one of the triggers in the aforementioned link.
(Technically, this could be classed as a bug in Chrome I guess -- reading window.innerWidth
should force a layout reflow post-rotation? Building a minimal repro might be painful though.)
BTW, that link above is a hugely worthwhile resource to wrap your brain around -- in terms of performance of the OSK in web in particular. Some of the notes may be slightly out of date but mostly very solid as far as I can tell.
change(web): updates mobile screen-dim detection code ⬅️
I didn't understand this PR title for a long time... what does this have to with screen dimming?
I find it helpful when approaching a new PR to have a short summary at the start of the initial comment stating what the purpose of the PR is. Just one or two sentences is good, introducing the purpose and approach. Something along the lines of "change the screen dimension calculations to use x.y.z instead of a.b.c, because a.b.c appears to be unreliable."
Somehow, it's about that line -
keyman.alignInputs
- so far as I can tell.So it sounds like
window.innerWidth
is internally invalidated, but refresh of the value is delayed. My suspicion is that the code inkeyman.alignInputs
is forcing a DOM layout or reflow, which internally also ends up validatingwindow.innerWidth
.
It most likely is; in my memory, alignInputs
checks for the current layout properties of the base elements for any touch-aliased elements KMW has produced and "re-aligns" those aliases to properly cover their bases in case the elements shifted. That'd definitely trigger some DOM layout calculations.
If this is the case, then when
alignInputs
goes away with #3030, we'll need to re-fix this. We should be able to do that by forcing a reflow using one of the triggers in the aforementioned link.(Technically, this could be classed as a bug in Chrome I guess -- reading
window.innerWidth
should force a layout reflow post-rotation? Building a minimal repro might be painful though.)
And Safari. The same user test failed for both Android (Chrome) and iOS (Safari). It's also mentioned as one of the reflow triggers in that document. So, technically, aren't we already triggering layout reflow with that method?
So, technically, aren't we already triggering layout reflow with that method?
Yes. The async part is the problem I guess :grin:
What about this: https://stackoverflow.com/a/49383279/1836776?
orientationchange
is apparently deprecated: https://developer.mozilla.org/en-US/docs/Web/API/Window/orientationchange_eventSee also:
* https://developer.mozilla.org/en-US/docs/Web/API/ScreenOrientation * https://bugs.webkit.org/show_bug.cgi?id=170595 * https://github.com/gajus/orientationchangeend
And the suggested replacement... isn't even implemented on Safari yet. I'll take the one that's fully cross-platform.
And the suggested replacement... isn't even implemented on Safari yet. I'll take the one that's fully cross-platform.
First draft of that spec was published 2012-05-22. Only 10 years ago. Given this is working around what is effectively a bug, we may have better results with multiple solutions to the issue. I'm not opposed to a big comment saying "do this for Safari which doesn't have the Orientation API" -- and using feature detection to get us an answer.
SUITE_ROTATION:
GROUP_ANDROID_5: - run tests against Android API 21 if possible (Android 5.0)
Huh. that's odd. Haven't we run tests against the TeamCity-hosted Web test page artifacts before on emulated Android 5.0? I wonder why it's giving us errors this time; it's clearly a TC thing (that, or an emulated-Android thing) not due to this PR's changes.
What about this: https://stackoverflow.com/a/49383279/1836776?
We already do that.
This block also happens to be where we'd set the potential screenOrientation.onchange
event handler. I guess it'd come first in the Android-block's if
-else
chain? I mean, I can add it if we care that strongly about it at the moment.
A bit of an aside, but...
change(web): updates mobile screen-dim detection code ⬅️
I didn't understand this PR title for a long time... what does this have to with screen dimming?
So, that angle never even occurred to me. My mind went "screen dimension" - eh, just shorten it, it'll be obvious. It took me a moment or two to figure out where the confusion came from!
Tested on Samsung Galaxy Tab A7 running Android 12, One UI Core 4.1.
SUITE_ROTATION:
GROUP_ANDROID_5: - run tests against Android API 21 if possible (Android 5.0)
TEST_OSK_PORTRAIT_LOAD (BLOCKED): I also experience this same thing.
Re blocked tests @bharanidharanj, can we try against Android 6 or 7? (I am investigating options for supporting Android 5, but it looks like it is too old to work with new websites)
Re blocked tests @bharanidharanj, can we try against Android 6 or 7? (I am investigating options for supporting Android 5, but it looks like it is too old to work with new websites)
That does sound like the best approach we can take for the moment with our current testing setup.
Re blocked tests @bharanidharanj, can we try against Android 6 or 7? (I am investigating options for supporting Android 5, but it looks like it is too old to work with new websites)
@mcdurdin @jahorton That's sounds good. I will try it in Android 6 emulator and will post my comment. Thanks.
@mcdurdin @jahorton I am getting the same issue in Android 6.0 emulator. But, it is working fine in Android 7.0 emulator.
So, Shall we use Android 7.0 emulator for future testing?
@mcdurdin @jahorton I am getting the same issue in Android 6.0 emulator. But, it is working fine in Android 7.0 emulator.
So, Shall we use Android 7.0 emulator for future testing?
Here's what I think we should do:
@keymanapp-test-bot retest SUITE_ROTATION GROUP_ANDROID_5 TEST_OSK_PORTRAIT_LOAD TEST_OSK_LANDSCAPE_LOAD TEST_BROWSER_ROTATE_P-TO-L TEST_BROWSER_ROTATE_L-TO-P
OSK_Portrait:
OSK_Landscape:
before rotation:
after rotation:
before rotation:
after rotation:
TEST_OSK_PORTRAIT_LOAD (PASSED): Tested this as per the instructions in API 24 / Android 7.0 emulator and it is working as expected.
TEST_OSK_LANDSCAPE_LOAD (PASSED): Tested this as per the instructions in API 24 / Android 7.0 emulator and it is working as expected.
TEST_BROWSER_ROTATE_P-TO-L (PASSED): Tested this as per the instructions in API 24 / Android 7.0 emulator and it is working as expected.
before rotation:
after rotation:
before rotation:
after rotation:
before rotation:
after rotation:
before rotation:
after rotation:
TEST_OSK_PORTRAIT_LOAD (PASSED): Tested this as per instructions in iOS 15.5 / iPad Pro (9.7 inch) Simulator and it is working as expected.
TEST_OSK_LANDSCAPE_LOAD (PASSED): Tested this as per instructions in iOS 15.5 / iPad Pro (9.7 inch) Simulator and it is working as expected.
TEST_BROWSER_ROTATE_P-TO-L (PASSED): Tested this as per instructions in iOS 15.5 / iPad Pro (9.7 inch) Simulator and it is working as expected.
before rotation:
after rotation:
before rotation:
after rotation:
TEST_OSK_PORTRAIT_LOAD (PASSED): Tested this as per the instructions in iOS 13.7 / iPhone 11 Pro Max and it is working as expected.
TEST_OSK_LANDSCAPE_LOAD (PASSED): TTested this as per the instructions in iOS 13.7 / iPhone 11 Pro Max and it is working as expected.
TEST_BROWSER_ROTATE_P-TO-L (PASSED): Tested this as per the instructions in iOS 13.7 / iPhone 11 Pro Max and it is working as expected.
before rotation:
after rotation:
before rotation:
after rotation:
TEST_OSK_PORTRAIT_LOAD (PASSED): Tested this as per the instructions in my Android Mobile device / Version 11.0 and it is working as expected.
TEST_OSK_LANDSCAPE_LOAD (PASSED): Tested this as per the instructions in my Android Mobile device / Version 11.0 and it is working as expected.
TEST_BROWSER_ROTATE_P-TO-L (PASSED): Tested this as per the instructions in my Android Mobile device / Version 11.0 and it is working as expected.
before rotation:
after rotation:
before rotation:
after rotation:
@keymanapp-test-bot retest SUITE_ROTATION GROUP_ANDROID_TABLET TEST_BROWSER_ROTATE_P-TO-L TEST_BROWSER_ROTATE_L-TO-P
I've observed that the OSK only stays visible when tested on an actual device. It quickly disappears when tested with an emulator, API 30.
Changes in this pull request will be available for download in Keyman version 16.0.43-alpha
Based on #6787, as its user test issues motivated development of this PR.
So, it turns out there there are some very strange issues with how
window.innerWidth
updates on mobile devices, and these issues were behind the failed user tests. It appears that the best approach for detecting screen width (what the mobile-form OSK uses) is actuallydocument.documentElement.clientWidth
. (Minor reference: https://stackoverflow.com/a/54812656)Relying upon that, along with some other shifts to how the mobile-form OSK computes its preferred height, appear to stabilize the base PR's issues. That said, these are some notable shifts to how the calculations are done, and there may be noteworthy history behind why things were the way that they were, so I expect some scrunity in the review & in the user-test suite.
Alternatively, adding a 50ms timeout halfway during the rotation adjustments seems to be enough to remedy the issue. There's some very odd behavior that I noticed when stepping through this function via debugger:
https://github.com/keymanapp/keyman/blob/16643d7479b2dc751b4e8ccaa3f5627bc2570bda/web/source/kmwrotation.ts#L44-L67
Before
keyman.alignInputs()
is called,window.innerWidth
is consistently "wrong" - it's notably larger than the value we'd expect it to hold. After it's called, when stepping through,window.innerWidth
changes. Unfortunately, that appears to be asynchronous, and a very short timeout isn't enough to alleviate the issue. And there's nothing in that function that should directly affect the browser's management ofwindow.innerWidth
.So, that "halfway during" note seen above would involve setting a 50ms timeout to run lines 47-60. Possible to do, but that feels more "hacky" than the approach I decided to run with. That may just be my perception, though.
By the way, setting the rotation "resolve" timer to a longer period (i.e. further delaying the whole function shown above) does not remedy the issue. Somehow, it's about that line -
keyman.alignInputs
- so far as I can tell.User Testing
SUITE_ROTATION
Test environments
Tests
TEST_OSK_PORTRAIT_LOAD:
TEST_OSK_LANDSCAPE_LOAD:
TEST_BROWSER_ROTATE_P-TO-L:
TEST_BROWSER_ROTATE_L-TO-P: