[web] Fix incorrect physical size due to visualviewport api on iOS (flutter/engine#25895)

This commit is contained in:
Ferhat
2021-05-06 21:02:08 -07:00
committed by GitHub
parent 4d71fc5b8b
commit d9c668cf82
2 changed files with 31 additions and 11 deletions

View File

@@ -480,11 +480,11 @@ flt-glass-pane * {
setElementAttribute(_sceneHostElement!, 'aria-hidden', 'true');
if (html.window.visualViewport == null && isWebKit) {
// Safari sometimes gives us bogus innerWidth/innerHeight values when the
// page loads. When it changes the values to correct ones it does not
// notify of the change via `onResize`. As a workaround, we set up a
// temporary periodic timer that polls innerWidth and triggers the
// resizeListener so that the framework can react to the change.
// Older Safari versions sometimes give us bogus innerWidth/innerHeight
// values when the page loads. When it changes the values to correct ones
// it does not notify of the change via `onResize`. As a workaround, we
// set up a temporary periodic timer that polls innerWidth and triggers
// the resizeListener so that the framework can react to the change.
//
// Safari 13 has implemented visualViewport API so it doesn't need this
// timer.
@@ -606,12 +606,12 @@ flt-glass-pane * {
void _metricsDidChange(html.Event? event) {
updateSemanticsScreenProperties();
if (isMobile && !window.isRotation() && textEditing.isEditing) {
window.computeOnScreenKeyboardInsets();
window.computeOnScreenKeyboardInsets(true);
EnginePlatformDispatcher.instance.invokeOnMetricsChanged();
} else {
window._computePhysicalSize();
// When physical size changes this value has to be recalculated.
window.computeOnScreenKeyboardInsets();
window.computeOnScreenKeyboardInsets(false);
EnginePlatformDispatcher.instance.invokeOnMetricsChanged();
}
}

View File

@@ -181,9 +181,25 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow {
double windowInnerWidth;
double windowInnerHeight;
final html.VisualViewport? viewport = html.window.visualViewport;
if (viewport != null) {
windowInnerWidth = viewport.width!.toDouble() * devicePixelRatio;
windowInnerHeight = viewport.height!.toDouble() * devicePixelRatio;
if (operatingSystem == OperatingSystem.iOs) {
/// Chrome on iOS reports incorrect viewport.height when app
/// starts in portrait orientation and the phone is rotated to
/// landscape.
///
/// We instead use documentElement clientWidth/Height to read
/// accurate physical size. VisualViewport api is only used during
/// text editing to make sure inset is correctly reported to
/// framework.
final double docWidth = html.document.documentElement!.clientWidth.toDouble();
final double docHeight = html.document.documentElement!.clientHeight.toDouble();
windowInnerWidth = docWidth * devicePixelRatio;
windowInnerHeight = docHeight * devicePixelRatio;
} else {
windowInnerWidth = viewport.width!.toDouble() * devicePixelRatio;
windowInnerHeight = viewport.height!.toDouble() * devicePixelRatio;
}
} else {
windowInnerWidth = html.window.innerWidth! * devicePixelRatio;
windowInnerHeight = html.window.innerHeight! * devicePixelRatio;
@@ -195,11 +211,15 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow {
}
}
void computeOnScreenKeyboardInsets() {
void computeOnScreenKeyboardInsets(bool isEditingOnMobile) {
double windowInnerHeight;
final html.VisualViewport? viewport = html.window.visualViewport;
if (viewport != null) {
windowInnerHeight = viewport.height!.toDouble() * devicePixelRatio;
if (operatingSystem == OperatingSystem.iOs && !isEditingOnMobile) {
windowInnerHeight = html.document.documentElement!.clientHeight * devicePixelRatio;
} else {
windowInnerHeight = viewport.height!.toDouble() * devicePixelRatio;
}
} else {
windowInnerHeight = html.window.innerHeight! * devicePixelRatio;
}