If the OSK had a non-integer width or height stored in the OSK cookie,
then the width and height would be parsed incorrectly and the OSK would
fail to be sized correctly on first load; this also caused a script
error and made the OSK impossible to interact with.
This makes two corrections:
1. Removed an obsolete test for screen size based on dpi, which is
unreliable, meant that we had been treating many Android tablets as
phones (domManager.ts).
2. Font scale for Android tablets had some incorrect assumptions around
keyboard height and devicePixelRatio, which I was able to simplify
into a fixed ratio, and was much better across all devices I
tested (however, all emulated in Chrome).
Summary of these changes:
Two targeted improvements; more optimization is possible but IMO this is
a significant enough improvement to go through test:
1. In oskView.ts, avoid calling `VisualKeyboard.refreshLayout` twice
from `OSKView.refreshLayout`. This roughly halves the time spent in
`VisualKeyboard.refreshLayout` for a keyboard switch.
2. In modelManager.ts, we avoid a very expensive `unloadModel` /
`loadModel` sequence from `registerModel` by checking to see if the
model spec we are passed is already registered. This avoids an
expensive callback to Keyman for Android which causes the banner to
'bounce'.
Longer notes:
So `VisualKeyboard.refreshLayout` is called 20+ times during a keyboard
switch. It is a very expensive call. It is the bulk of the time spent
when you press the globe key in Keyman for Android. This seems ripe for
optimization; see the following functions in keyboard.html:
* `setKeymanLanguage` -> `setActiveKeyboard` -> 6 calls
* `enableSuggestions` -> `registerModel` -> 8 calls
* `stateChange` -> 6+ calls
`OSKView.refreshLayout` always seems to call
`VisualKeyboard.refreshLayout` twice: first with `setSize`, and then
again itself.
Keyman for Android and KeymanWeb seem to fight over who is responsible
for selecting models (KMW first calls `loadModel`, then Keyman for
Android calls `unloadModel`, `loadModel`, through `enableSuggestions`).
The fix for rotation (`correctOSKTextSize()`), as called from
`stateChange()`, is expensive as well, because it rebuilds the entire
keyboard from scratch.
Along with that, we have the size of the webview changing as the model
is unloaded and reloaded and lots of back-and-forth between the
KeymanWeb and KMEA which seems unnecessary.
Shouldn't KeymanWeb be responsible for loading and unloading models,
once they are all registered? We should only need to register the models
once at page load time (when config changes, do we just reload the
page?).
Fixes#5907.
The state machine for the Hide transition for the OSK was very complex,
and had some peculiarities which caused it to sometimes fail to
correctly hide. Once I simplified the state machine, it seems that those
edge cases have gone away, and the keyboard always hides correctly.
There is an unrelated issue with focus timeout which can be confusing
when testing this; see #5909.
Fixes#5779.
Fixes#5731 (I believe mitigation is sufficient to close this issue).
A variety of interrelated font and font size display issues resolved:
1. KVK font was not applied early enough for size calculations, which
meant that we were calculating font scaling per key based on a
default font when transforming from the KVK data for desktop devices
(defaultLayout.ts)
2. Font scaling for non-default layers was calculated when elements were
not visible and had no size information, giving incorrect values. To
resolve this, font scaling is now calculated when a layer is made
visible, which had performance impacts; resolved by reducing
unnecessary `layer.refreshLayout()` calls; see performance point 1
below (oskView.ts:layerChangeHandler())
3. `getViewportScale()` would return an incorrect scaled value when
emulating touch devices on a desktop browser (kmwutils.ts)
4. After switching keyboards, the device-specific scaling factor was not
maintained (oskView.ts:refreshLayout())
Related performance improvements:
1. Multiple calls to `layer.refreshLayout()` in `refreshLayout()` have
been eliminated, and only the currently visible layer is now
refreshed. This dramatically reduces the number of calls to
`getIdealFontSize()` which was the primary concern of #5731.
(visualKeyboards.ts)
2. Unnecessary use of `innerHTML` replaced with `innerText`
(oskBaseKey.ts)
Minor Keyman Developer performance improvement:
1. The web debugger no longer recalculates the OSK twice (test.js)