From 35d420c21f548e5f3eb358f84f4ce561f4dc7d90 Mon Sep 17 00:00:00 2001 From: Mouad Debbar Date: Tue, 28 Nov 2023 16:57:44 -0500 Subject: [PATCH] [web] No implicit view in multi-view mode --- lib/web_ui/lib/src/engine/canvas_pool.dart | 3 +- .../lib/src/engine/canvaskit/canvas.dart | 3 +- .../src/engine/canvaskit/embedded_views.dart | 6 +-- .../lib/src/engine/canvaskit/layer_tree.dart | 3 -- .../lib/src/engine/canvaskit/rasterizer.dart | 10 ++-- .../src/engine/canvaskit/render_canvas.dart | 11 ++-- .../lib/src/engine/canvaskit/renderer.dart | 2 +- .../lib/src/engine/html/bitmap_canvas.dart | 7 ++- .../lib/src/engine/html/scene_builder.dart | 6 +-- lib/web_ui/lib/src/engine/initialization.dart | 6 ++- .../lib/src/engine/platform_dispatcher.dart | 51 ++++++++++++++----- lib/web_ui/lib/src/engine/scene_view.dart | 19 ++++--- .../src/engine/skwasm/skwasm_impl/canvas.dart | 2 +- 13 files changed, 79 insertions(+), 50 deletions(-) diff --git a/lib/web_ui/lib/src/engine/canvas_pool.dart b/lib/web_ui/lib/src/engine/canvas_pool.dart index fd1762856ea68..c5fe8378b5ba1 100644 --- a/lib/web_ui/lib/src/engine/canvas_pool.dart +++ b/lib/web_ui/lib/src/engine/canvas_pool.dart @@ -26,7 +26,6 @@ import 'safe_browser_api.dart'; import 'shadow.dart'; import 'util.dart'; import 'vector_math.dart'; -import 'window.dart'; /// Renders picture to a CanvasElement by allocating and caching 0 or more /// canvas(s) for [BitmapCanvas]. @@ -1039,7 +1038,7 @@ class ContextStateHandle { // // transformedShadowDelta = M*shadowDelta - M*origin. final Float32List tempVector = Float32List(2); - tempVector[0] = kOutsideTheBoundsOffset * window.devicePixelRatio; + tempVector[0] = kOutsideTheBoundsOffset * EngineFlutterDisplay.instance.devicePixelRatio; _canvasPool.currentTransform.transform2(tempVector); final double shadowOffsetX = tempVector[0]; final double shadowOffsetY = tempVector[1]; diff --git a/lib/web_ui/lib/src/engine/canvaskit/canvas.dart b/lib/web_ui/lib/src/engine/canvaskit/canvas.dart index 6e4fa96e543fb..26c780c6ce0bb 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/canvas.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/canvas.dart @@ -8,6 +8,7 @@ import 'dart:typed_data'; import 'package:ui/ui.dart' as ui; import '../color_filter.dart'; +import '../display.dart'; import 'canvaskit_api.dart'; import 'color_filter.dart'; import 'image.dart'; @@ -248,7 +249,7 @@ class CkCanvas { void drawShadow( CkPath path, ui.Color color, double elevation, bool transparentOccluder) { drawSkShadow(skCanvas, path, color, elevation, transparentOccluder, - ui.window.devicePixelRatio); + EngineFlutterDisplay.instance.devicePixelRatio); } void drawVertices( diff --git a/lib/web_ui/lib/src/engine/canvaskit/embedded_views.dart b/lib/web_ui/lib/src/engine/canvaskit/embedded_views.dart index 146363a482e14..f7a8dcfaa5e65 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/embedded_views.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/embedded_views.dart @@ -5,13 +5,13 @@ import 'package:ui/ui.dart' as ui; import '../../engine.dart' show PlatformViewManager; +import '../display.dart'; import '../dom.dart'; import '../html/path_to_svg_clip.dart'; import '../platform_views/slots.dart'; import '../svg.dart'; import '../util.dart'; import '../vector_math.dart'; -import '../window.dart'; import 'canvas.dart'; import 'embedded_views_diff.dart'; import 'path.dart'; @@ -68,7 +68,7 @@ class HtmlViewEmbedder { List _activeOverlayGroups = []; /// The size of the frame, in physical pixels. - ui.Size _frameSize = ui.window.physicalSize; + late ui.Size _frameSize; set frameSize(ui.Size size) { _frameSize = size; @@ -326,7 +326,7 @@ class HtmlViewEmbedder { // // HTML elements use logical (CSS) pixels, but we have been using physical // pixels, so scale down the head element to match the logical resolution. - final double scale = window.devicePixelRatio; + final double scale = EngineFlutterDisplay.instance.devicePixelRatio; final double inverseScale = 1 / scale; final Matrix4 scaleMatrix = Matrix4.diagonal3Values(inverseScale, inverseScale, 1); diff --git a/lib/web_ui/lib/src/engine/canvaskit/layer_tree.dart b/lib/web_ui/lib/src/engine/canvaskit/layer_tree.dart index d41e7daec4807..2aca00f35dd3c 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/layer_tree.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/layer_tree.dart @@ -21,9 +21,6 @@ class LayerTree { /// The root of the layer tree. final RootLayer rootLayer; - /// The size (in physical pixels) of the frame to paint this layer tree into. - final ui.Size frameSize = ui.window.physicalSize; - /// The devicePixelRatio of the frame to paint this layer tree into. double? devicePixelRatio; diff --git a/lib/web_ui/lib/src/engine/canvaskit/rasterizer.dart b/lib/web_ui/lib/src/engine/canvaskit/rasterizer.dart index 6138955d301c4..104d96109fa23 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/rasterizer.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/rasterizer.dart @@ -7,9 +7,10 @@ import 'package:ui/ui.dart' as ui; /// A class that can rasterize [LayerTree]s into a given `sceneHost` element. class Rasterizer { - Rasterizer(this.sceneHost); + Rasterizer(this.view); - final DomElement sceneHost; + final EngineFlutterView view; + DomElement get sceneHost => view.dom.sceneHost; final CompositorContext context = CompositorContext(); final RenderCanvasFactory renderCanvasFactory = RenderCanvasFactory(); late final HtmlViewEmbedder viewEmbedder = @@ -30,12 +31,13 @@ class Rasterizer { /// Creates a new frame from this rasterizer's surface, draws the given /// [LayerTree] into it, and then submits the frame. void draw(LayerTree layerTree) { - if (layerTree.frameSize.isEmpty) { + final ui.Size frameSize = view.physicalSize; + if (frameSize.isEmpty) { // Available drawing area is empty. Skip drawing. return; } - _currentFrameSize = layerTree.frameSize; + _currentFrameSize = frameSize; CanvasKitRenderer.instance.offscreenSurface.acquireFrame(_currentFrameSize); viewEmbedder.frameSize = _currentFrameSize; final CkPictureRecorder pictureRecorder = CkPictureRecorder(); diff --git a/lib/web_ui/lib/src/engine/canvaskit/render_canvas.dart b/lib/web_ui/lib/src/engine/canvaskit/render_canvas.dart index 9c444929ea431..9308c11ac6e2b 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/render_canvas.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/render_canvas.dart @@ -6,8 +6,8 @@ import 'dart:js_interop'; import 'package:ui/ui.dart' as ui; +import '../display.dart'; import '../dom.dart'; -import '../window.dart'; /// A visible (on-screen) canvas that can display bitmaps produced by CanvasKit /// in the (off-screen) SkSurface which is backed by an OffscreenCanvas. @@ -68,12 +68,13 @@ class RenderCanvas { /// match the size of the window precisely we use the most precise floating /// point value we can get. void _updateLogicalHtmlCanvasSize() { - final double logicalWidth = _pixelWidth / window.devicePixelRatio; - final double logicalHeight = _pixelHeight / window.devicePixelRatio; + final double devicePixelRatio = EngineFlutterDisplay.instance.devicePixelRatio; + final double logicalWidth = _pixelWidth / devicePixelRatio; + final double logicalHeight = _pixelHeight / devicePixelRatio; final DomCSSStyleDeclaration style = canvasElement.style; style.width = '${logicalWidth}px'; style.height = '${logicalHeight}px'; - _currentDevicePixelRatio = window.devicePixelRatio; + _currentDevicePixelRatio = devicePixelRatio; } /// Render the given [bitmap] with this [RenderCanvas]. @@ -112,7 +113,7 @@ class RenderCanvas { size.height.ceil() == _pixelHeight) { // The existing canvas doesn't need to be resized (unless the device pixel // ratio changed). - if (window.devicePixelRatio != _currentDevicePixelRatio) { + if (EngineFlutterDisplay.instance.devicePixelRatio != _currentDevicePixelRatio) { _updateLogicalHtmlCanvasSize(); } return; diff --git a/lib/web_ui/lib/src/engine/canvaskit/renderer.dart b/lib/web_ui/lib/src/engine/canvaskit/renderer.dart index ec4db4399cbfb..a948b5b55f08c 100644 --- a/lib/web_ui/lib/src/engine/canvaskit/renderer.dart +++ b/lib/web_ui/lib/src/engine/canvaskit/renderer.dart @@ -400,7 +400,7 @@ class CanvasKitRenderer implements Renderer { Rasterizer _getRasterizerForView(EngineFlutterView view) { return _rasterizers.putIfAbsent(view, () { - return Rasterizer(view.dom.sceneHost); + return Rasterizer(view); }); } diff --git a/lib/web_ui/lib/src/engine/html/bitmap_canvas.dart b/lib/web_ui/lib/src/engine/html/bitmap_canvas.dart index ef1f3015e4347..66cdc1aad2848 100644 --- a/lib/web_ui/lib/src/engine/html/bitmap_canvas.dart +++ b/lib/web_ui/lib/src/engine/html/bitmap_canvas.dart @@ -17,7 +17,6 @@ import '../html_image_codec.dart'; import '../text/canvas_paragraph.dart'; import '../util.dart'; import '../vector_math.dart'; -import '../window.dart'; import 'clip.dart'; import 'color_filter.dart'; import 'dom_canvas.dart'; @@ -1036,7 +1035,7 @@ class BitmapCanvas extends EngineCanvas { _drawPointsPaint.color = paint.color; _drawPointsPaint.maskFilter = paint.maskFilter; - final double dpr = ui.window.devicePixelRatio; + final double dpr = EngineFlutterDisplay.instance.devicePixelRatio; // Use hairline (device pixel when strokeWidth is not specified). final double strokeWidth = paint.strokeWidth == null ? 1.0 / dpr : paint.strokeWidth!; @@ -1077,7 +1076,7 @@ class BitmapCanvas extends EngineCanvas { /// viewport. ui.Rect _computeScreenBounds(Matrix4 targetTransform) { final Matrix4 inverted = targetTransform.clone()..invert(); - final double dpr = ui.window.devicePixelRatio; + final double dpr = EngineFlutterDisplay.instance.devicePixelRatio; final double width = ui.window.physicalSize.width * dpr; final double height = ui.window.physicalSize.height * dpr; final Vector3 topLeft = inverted.perspectiveTransform(x: 0, y: 0, z: 0); @@ -1457,7 +1456,7 @@ String maskFilterToCanvasFilter(ui.MaskFilter? maskFilter) { if (maskFilter != null) { // Multiply by device-pixel ratio because the canvas' pixel width and height // are larger than its CSS width and height by device-pixel ratio. - return 'blur(${maskFilter.webOnlySigma * window.devicePixelRatio}px)'; + return 'blur(${maskFilter.webOnlySigma * EngineFlutterDisplay.instance.devicePixelRatio}px)'; } else { return 'none'; } diff --git a/lib/web_ui/lib/src/engine/html/scene_builder.dart b/lib/web_ui/lib/src/engine/html/scene_builder.dart index 5f1a7c687474c..e721aa5a5576b 100644 --- a/lib/web_ui/lib/src/engine/html/scene_builder.dart +++ b/lib/web_ui/lib/src/engine/html/scene_builder.dart @@ -8,12 +8,12 @@ import 'package:ui/ui.dart' as ui; import 'package:ui/ui_web/src/ui_web.dart' as ui_web; import '../../engine.dart' show kProfileApplyFrame, kProfilePrerollFrame; +import '../display.dart'; import '../dom.dart'; import '../picture.dart'; import '../profiler.dart'; import '../util.dart'; import '../vector_math.dart'; -import '../window.dart'; import 'backdrop_filter.dart'; import 'clip.dart'; import 'color_filter.dart'; @@ -113,8 +113,8 @@ class SurfaceSceneBuilder implements ui.SceneBuilder { // scene to devicepixelratio. Use identity instead since CSS uses // logical device pixels. if (!ui_web.debugEmulateFlutterTesterEnvironment) { - assert(matrix4[0] == window.devicePixelRatio && - matrix4[5] == window.devicePixelRatio); + assert(matrix4[0] == EngineFlutterDisplay.instance.devicePixelRatio && + matrix4[5] == EngineFlutterDisplay.instance.devicePixelRatio); } matrix = Matrix4.identity().storage; } else { diff --git a/lib/web_ui/lib/src/engine/initialization.dart b/lib/web_ui/lib/src/engine/initialization.dart index 2d17adc0d4d92..c8badf914ccf5 100644 --- a/lib/web_ui/lib/src/engine/initialization.dart +++ b/lib/web_ui/lib/src/engine/initialization.dart @@ -218,8 +218,10 @@ Future initializeEngineUi() async { _initializationState = DebugEngineInitializationState.initializingUi; RawKeyboard.initialize(onMacOs: operatingSystem == OperatingSystem.macOs); - ensureImplicitViewInitialized(hostElement: configuration.hostElement); - ensureFlutterViewEmbedderInitialized(); + if (!configuration.multiViewEnabled) { + ensureImplicitViewInitialized(hostElement: configuration.hostElement); + ensureFlutterViewEmbedderInitialized(); + } _initializationState = DebugEngineInitializationState.initialized; } diff --git a/lib/web_ui/lib/src/engine/platform_dispatcher.dart b/lib/web_ui/lib/src/engine/platform_dispatcher.dart index 2f573ed08ac5b..ff0951cf1c449 100644 --- a/lib/web_ui/lib/src/engine/platform_dispatcher.dart +++ b/lib/web_ui/lib/src/engine/platform_dispatcher.dart @@ -500,10 +500,22 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher { // TODO(a-wallen): As multi-window support expands, the pop call // will need to include the view ID. Right now only one view is // supported. - implicitView!.browserHistory.exit().then((_) { + // + // TODO(mdebbar): What should we do in multi-view mode? + // https://github.com/flutter/flutter/issues/139174 + if (implicitView != null) { + implicitView!.browserHistory.exit().then((_) { + replyToPlatformMessage( + callback, + jsonCodec.encodeSuccessEnvelope(true), + ); + }); + } else { replyToPlatformMessage( - callback, jsonCodec.encodeSuccessEnvelope(true)); - }); + callback, + jsonCodec.encodeSuccessEnvelope(true), + ); + } return; case 'HapticFeedback.vibrate': final String? type = decoded.arguments as String?; @@ -588,7 +600,9 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher { decoded.arguments as Map; switch (decoded.method) { case 'activateSystemCursor': - implicitView!.mouseCursor + // TODO(mdebbar): This needs a view ID from the framework. + // https://github.com/flutter/flutter/issues/137289 + implicitView?.mouseCursor .activateSystemCursor(arguments.tryString('kind')); } return; @@ -628,14 +642,23 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher { // TODO(a-wallen): As multi-window support expands, the navigation call // will need to include the view ID. Right now only one view is // supported. - implicitView!.handleNavigationMessage(data).then((bool handled) { - if (handled) { - replyToPlatformMessage( - callback, jsonCodec.encodeSuccessEnvelope(true)); - } else { - callback?.call(null); - } - }); + // + // TODO(mdebbar): What should we do in multi-view mode? + // https://github.com/flutter/flutter/issues/139174 + if (implicitView != null) { + implicitView!.handleNavigationMessage(data).then((bool handled) { + if (handled) { + replyToPlatformMessage( + callback, + jsonCodec.encodeSuccessEnvelope(true), + ); + } else { + callback?.call(null); + } + }); + } else { + callback?.call(null); + } // As soon as Flutter starts taking control of the app navigation, we // should reset _defaultRouteName to "/" so it doesn't have any @@ -1249,7 +1272,9 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher { /// requests from the embedder. @override String get defaultRouteName { - return _defaultRouteName ??= implicitView!.browserHistory.currentPath; + // TODO(mdebbar): What should we do in multi-view mode? + // https://github.com/flutter/flutter/issues/139174 + return _defaultRouteName ??= implicitView?.browserHistory.currentPath ?? '/'; } /// Lazily initialized when the `defaultRouteName` getter is invoked. diff --git a/lib/web_ui/lib/src/engine/scene_view.dart b/lib/web_ui/lib/src/engine/scene_view.dart index 41ac3fab96cd0..61f4e48b7bb90 100644 --- a/lib/web_ui/lib/src/engine/scene_view.dart +++ b/lib/web_ui/lib/src/engine/scene_view.dart @@ -194,10 +194,11 @@ final class PictureSliceContainer extends SliceContainer { bounds.bottom.ceilToDouble() ); final DomCSSStyleDeclaration style = canvas.style; - final double logicalWidth = roundedOutBounds.width / window.devicePixelRatio; - final double logicalHeight = roundedOutBounds.height / window.devicePixelRatio; - final double logicalLeft = roundedOutBounds.left / window.devicePixelRatio; - final double logicalTop = roundedOutBounds.top / window.devicePixelRatio; + final double devicePixelRatio = EngineFlutterDisplay.instance.devicePixelRatio; + final double logicalWidth = roundedOutBounds.width / devicePixelRatio; + final double logicalHeight = roundedOutBounds.height / devicePixelRatio; + final double logicalLeft = roundedOutBounds.left / devicePixelRatio; + final double logicalTop = roundedOutBounds.top / devicePixelRatio; style.width = '${logicalWidth}px'; style.height = '${logicalHeight}px'; style.position = 'absolute'; @@ -243,21 +244,23 @@ final class PlatformViewContainer extends SliceContainer { } } + @override void updateContents() { assert(_styling != null); assert(_size != null); if (_dirty) { final DomCSSStyleDeclaration style = container.style; - final double logicalWidth = _size!.width / window.devicePixelRatio; - final double logicalHeight = _size!.height / window.devicePixelRatio; + final double devicePixelRatio = EngineFlutterDisplay.instance.devicePixelRatio; + final double logicalWidth = _size!.width / devicePixelRatio; + final double logicalHeight = _size!.height / devicePixelRatio; style.width = '${logicalWidth}px'; style.height = '${logicalHeight}px'; style.position = 'absolute'; final ui.Offset? offset = _styling!.position.offset; - final double logicalLeft = (offset?.dx ?? 0) / window.devicePixelRatio; - final double logicalTop = (offset?.dy ?? 0) / window.devicePixelRatio; + final double logicalLeft = (offset?.dx ?? 0) / devicePixelRatio; + final double logicalTop = (offset?.dy ?? 0) / devicePixelRatio; style.left = '${logicalLeft}px'; style.top = '${logicalTop}px'; diff --git a/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/canvas.dart b/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/canvas.dart index 0e331835f7f46..e33a515d281b9 100644 --- a/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/canvas.dart +++ b/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/canvas.dart @@ -375,7 +375,7 @@ class SkwasmCanvas implements SceneCanvas { _handle, path.handle, elevation, - ui.window.devicePixelRatio, + EngineFlutterDisplay.instance.devicePixelRatio, color.value, transparentOccluder); }