Merge pull request #2824 from abarth/update_mojo

Update ChildView after Mojo roll
This commit is contained in:
Adam Barth 2016-03-23 11:59:32 -07:00
commit a8c108dea5
4 changed files with 107 additions and 49 deletions

View file

@ -1 +1 @@
56bca69d7a9112af22e6873599b57b5b2fe90395
b7419de14af49f61b67b290a2b66a3416f94cb62

View file

@ -3,12 +3,15 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:collection';
import 'dart:ui' as ui;
import 'package:flutter/services.dart';
import 'package:mojo_services/mojo/gfx/composition/scene_token.mojom.dart' as mojom;
import 'package:mojo_services/mojo/ui/layouts.mojom.dart' as mojom;
import 'package:mojo_services/mojo/ui/view_containers.mojom.dart' as mojom;
import 'package:mojo_services/mojo/ui/view_provider.mojom.dart' as mojom;
import 'package:mojo_services/mojo/ui/view_token.mojom.dart' as mojom;
import 'package:mojo_services/mojo/ui/views.mojom.dart' as mojom;
import 'package:mojo/application.dart';
import 'package:mojo/core.dart' as core;
@ -32,6 +35,37 @@ mojom.ViewProxy _initViewProxy() {
final mojom.ViewProxy _viewProxy = _initViewProxy();
final mojom.View _view = _viewProxy?.ptr;
mojom.ViewContainer _initViewContainer() {
mojom.ViewContainerProxy viewContainerProxy = new mojom.ViewContainerProxy.unbound();
_view.getContainer(viewContainerProxy);
viewContainerProxy.ptr.setListener(new mojom.ViewContainerListenerStub.unbound()..impl = _ViewContainerListenerImpl.instance);
return viewContainerProxy.ptr;
}
final mojom.ViewContainer _viewContainer = _initViewContainer();
typedef dynamic _ResponseFactory();
class _ViewContainerListenerImpl extends mojom.ViewContainerListener {
static final _ViewContainerListenerImpl instance = new _ViewContainerListenerImpl();
@override
dynamic onChildAttached(int childKey, mojom.ViewInfo childViewInfo, [_ResponseFactory responseFactory = null]) {
ChildViewConnection connection = _connections[childKey];
connection?._onAttachedToContainer(childViewInfo);
return responseFactory();
}
@override
dynamic onChildUnavailable(int childKey, [_ResponseFactory responseFactory = null]) {
ChildViewConnection connection = _connections[childKey];
connection?._onUnavailable();
return responseFactory();
}
final Map<int, ChildViewConnection> _connections = new HashMap<int, ChildViewConnection>();
}
/// (mojo-only) A connection with a child view.
///
/// Used with the [ChildView] widget to display a child view.
@ -66,22 +100,42 @@ class ChildViewConnection {
static int _nextViewKey = 1;
int _viewKey;
VoidCallback _onViewInfoAvailable;
mojom.ViewInfo _viewInfo;
void _onAttachedToContainer(mojom.ViewInfo viewInfo) {
assert(_viewInfo == null);
_viewInfo = viewInfo;
if (_onViewInfoAvailable != null)
_onViewInfoAvailable();
}
void _onUnavailable() {
_viewInfo = null;
}
void _addChildToViewHost() {
assert(_attached);
assert(_viewOwner != null);
assert(_viewKey == null);
_viewKey = _nextViewKey++;
_view?.addChild(_viewKey, _viewOwner.impl);
_viewInfo = null;
_viewContainer?.addChild(_viewKey, _viewOwner.impl);
_viewOwner = null;
assert(!_ViewContainerListenerImpl.instance._connections.containsKey(_viewKey));
_ViewContainerListenerImpl.instance._connections[_viewKey] = this;
}
void _removeChildFromViewHost() {
assert(!_attached);
assert(_viewOwner == null);
assert(_viewKey != null);
assert(_ViewContainerListenerImpl.instance._connections[_viewKey] == this);
_ViewContainerListenerImpl.instance._connections.remove(_viewKey);
_viewOwner = new mojom.ViewOwnerProxy.unbound();
_view?.removeChild(_viewKey, _viewOwner);
_viewContainer?.removeChild(_viewKey, _viewOwner);
_viewKey = null;
_viewInfo = null;
}
// The number of render objects attached to this view. In between frames, we
@ -110,26 +164,24 @@ class ChildViewConnection {
_removeChildFromViewHost();
}
Future<mojom.ViewLayoutInfo> _layout({ Size size, double scale }) async {
void _layout({ int physicalWidth, int physicalHeight, double devicePixelRatio }) {
assert(_attached);
assert(_attachments == 1);
assert(_viewKey != null);
if (_view == null)
return new Future<mojom.ViewLayoutInfo>.value(null);
int width = (size.width * scale).round();
int height = (size.height * scale).round();
return;
// TODO(abarth): Ideally we would propagate our actual constraints to be
// able to support rich cross-app layout. For now, we give the child tight
// constraints for simplicity.
mojom.BoxConstraints childConstraints = new mojom.BoxConstraints()
..minWidth = width
..maxWidth = width
..minHeight = height
..maxHeight = height;
..minWidth = physicalWidth
..maxWidth = physicalWidth
..minHeight = physicalHeight
..maxHeight = physicalHeight;
mojom.ViewLayoutParams layoutParams = new mojom.ViewLayoutParams()
..constraints = childConstraints
..devicePixelRatio = scale;
return (await _view.layoutChild(_viewKey, layoutParams)).info;
..devicePixelRatio = devicePixelRatio;
_viewContainer.layoutChild(_viewKey, layoutParams);
}
}
@ -138,7 +190,9 @@ class RenderChildView extends RenderBox {
RenderChildView({
ChildViewConnection child,
double scale
}) : _child = child, _scale = scale;
}) : _scale = scale {
this.child = child;
}
/// The child to display.
ChildViewConnection get child => _child;
@ -146,12 +200,17 @@ class RenderChildView extends RenderBox {
void set child (ChildViewConnection value) {
if (value == _child)
return;
if (attached)
_child?._detach();
if (attached && _child != null) {
_child._detach();
assert(_child._onViewInfoAvailable != null);
_child._onViewInfoAvailable = null;
}
_child = value;
_layoutInfo = null;
if (attached)
_child?._attach();
if (attached && _child != null) {
_child._attach();
assert(_child._onViewInfoAvailable == null);
_child._onViewInfoAvailable = markNeedsPaint;
}
if (_child == null) {
markNeedsPaint();
} else {
@ -185,20 +244,18 @@ class RenderChildView extends RenderBox {
@override
bool get alwaysNeedsCompositing => true;
@override
bool get sizedByParent => true;
@override
void performResize() {
size = constraints.biggest;
}
TextPainter _debugErrorMessage;
int _physicalWidth;
int _physicalHeight;
@override
void performLayout() {
size = constraints.biggest;
if (_child != null) {
_child._layout(size: size, scale: scale).then(_handleLayoutInfoChanged);
_physicalWidth = (size.width * scale).round();
_physicalHeight = (size.height * scale).round();
_child._layout(physicalWidth: _physicalWidth, physicalHeight: _physicalHeight, devicePixelRatio: scale);
assert(() {
if (_view == null) {
_debugErrorMessage ??= new TextPainter()
@ -215,21 +272,14 @@ class RenderChildView extends RenderBox {
}
}
mojom.ViewLayoutInfo _layoutInfo;
void _handleLayoutInfoChanged(mojom.ViewLayoutInfo layoutInfo) {
_layoutInfo = layoutInfo;
markNeedsPaint();
}
@override
bool hitTestSelf(Point position) => true;
@override
void paint(PaintingContext context, Offset offset) {
assert(needsCompositing);
if (_layoutInfo != null)
context.pushChildScene(offset, scale, _layoutInfo);
if (_child?._viewInfo != null)
context.pushChildScene(offset, scale, _physicalWidth, _physicalHeight, _child._viewInfo.sceneToken);
assert(() {
if (_view == null) {
context.canvas.drawRect(offset & size, new Paint()..color = const Color(0xFF0000FF));

View file

@ -7,7 +7,7 @@ import 'dart:ui' show Offset;
import 'package:flutter/painting.dart';
import 'package:vector_math/vector_math_64.dart';
import 'package:mojo_services/mojo/ui/layouts.mojom.dart' as mojom;
import 'package:mojo_services/mojo/gfx/composition/scene_token.mojom.dart' as mojom;
import 'debug.dart';
@ -110,20 +110,22 @@ class PictureLayer extends Layer {
}
class ChildSceneLayer extends Layer {
ChildSceneLayer({ this.offset, this.devicePixelRatio, this.layoutInfo });
ChildSceneLayer({ this.offset, this.devicePixelRatio, this.physicalWidth, this.physicalHeight, this.sceneToken });
Offset offset;
double devicePixelRatio;
mojom.ViewLayoutInfo layoutInfo;
int physicalWidth;
int physicalHeight;
mojom.SceneToken sceneToken;
@override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
builder.addChildScene(
offset + layerOffset,
devicePixelRatio,
layoutInfo.size.width,
layoutInfo.size.height,
layoutInfo.sceneToken.value
physicalWidth,
physicalHeight,
sceneToken.value
);
}
@ -131,9 +133,9 @@ class ChildSceneLayer extends Layer {
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('offset: $offset');
description.add('physicalWidth: ${layoutInfo.size.width}');
description.add('physicalHeight: ${layoutInfo.size.height}');
description.add('sceneToken.value: ${layoutInfo.sceneToken.value}');
description.add('physicalWidth: $physicalWidth');
description.add('physicalHeight: $physicalHeight');
description.add('sceneToken.value: ${sceneToken.value}');
}
}

View file

@ -9,7 +9,7 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:mojo_services/mojo/ui/layouts.mojom.dart' as mojom;
import 'package:mojo_services/mojo/gfx/composition/scene_token.mojom.dart' as mojom;
import 'package:vector_math/vector_math_64.dart';
import 'debug.dart';
@ -201,9 +201,15 @@ class PaintingContext {
));
}
void pushChildScene(Offset offset, double devicePixelRatio, mojom.ViewLayoutInfo layoutInfo) {
void pushChildScene(Offset offset, double devicePixelRatio, int physicalWidth, int physicalHeight, mojom.SceneToken sceneToken) {
_stopRecordingIfNeeded();
_appendLayer(new ChildSceneLayer(offset: offset, devicePixelRatio: devicePixelRatio, layoutInfo: layoutInfo));
_appendLayer(new ChildSceneLayer(
offset: offset,
devicePixelRatio: devicePixelRatio,
physicalWidth: physicalWidth,
physicalHeight: physicalHeight,
sceneToken: sceneToken
));
}
/// Push a rectangular clip rect.