diff --git a/lib/web_ui/lib/src/engine/dom_renderer.dart b/lib/web_ui/lib/src/engine/dom_renderer.dart index 74d5334a269cf..302368a366301 100644 --- a/lib/web_ui/lib/src/engine/dom_renderer.dart +++ b/lib/web_ui/lib/src/engine/dom_renderer.dart @@ -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(); } } diff --git a/lib/web_ui/lib/src/engine/window.dart b/lib/web_ui/lib/src/engine/window.dart index 13f881ea50109..846d6ab89f190 100644 --- a/lib/web_ui/lib/src/engine/window.dart +++ b/lib/web_ui/lib/src/engine/window.dart @@ -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; }