Commit 256af143 authored by Adam Barth's avatar Adam Barth

Actually populate the view host proxy

Now that the engine lets us take the view host handle, we can actually
access the view host from Dart.
parent 1328562e
name: widgets
assets:
- assets/starcircle.png
- assets/ali_connors.png
material-design-icons:
- name: action/account_circle
- name: action/alarm
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
const List<String> _kKnownApps = const <String>[
'mojo:noodles_view',
'mojo:shapes_view',
];
const Size _kSmallWindowSize = const Size(400.0, 400.0);
const Size _kBigWindowSize = const Size(600.0, 600.0);
class Window extends StatefulComponent {
Window({ Key key, this.child }) : super(key: key);
final ChildViewConnection child;
_WindowState createState() => new _WindowState();
}
class _WindowState extends State<Window> {
Offset _offset = Offset.zero;
bool _isSmall = true;
void _handlePanUpdate(Offset delta) {
setState(() {
_offset += delta;
});
}
void _handleTap() {
setState(() {
_isSmall = !_isSmall;
});
}
Widget build(BuildContext context) {
Size size = _isSmall ? _kSmallWindowSize : _kBigWindowSize;
return new Positioned(
left: _offset.dx,
top: _offset.dy,
width: size.width,
height: size.height,
child: new GestureDetector(
onPanUpdate: _handlePanUpdate,
onTap: _handleTap,
child: new ChildView(child: config.child)
)
);
}
}
class WindowManager extends StatefulComponent {
_WindowManagerState createState() => new _WindowManagerState();
}
class _WindowManagerState extends State<WindowManager> {
List<ChildViewConnection> _windows = <ChildViewConnection>[];
void _handleTap() {
setState(() {
_windows.add(new ChildViewConnection(url: _kKnownApps[_windows.length % _kKnownApps.length]));
});
}
Widget build(BuildContext context) {
return new GestureDetector(
onTap: _handleTap,
child: new Container(
decoration: new BoxDecoration(
backgroundColor: Colors.blue[500]
),
child: new Stack(
children: _windows.map((ChildViewConnection child) {
return new Window(
key: new ObjectKey(child),
child: child
);
}).toList()
)
)
);
}
}
void main() {
runApp(new MaterialApp(
title: 'Mozart',
routes: <String, RouteBuilder>{ '/': (_) => new WindowManager() }
));
}
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'dart:async';
import 'dart:ui_internals' as internals;
import 'package:flutter/services.dart';
import 'package:mojo_services/mojo/gfx/composition/scene_token.mojom.dart' as mojom;
......@@ -10,20 +11,39 @@ import 'package:mojo_services/mojo/ui/layouts.mojom.dart' as mojom;
import 'package:mojo_services/mojo/ui/view_provider.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;
import 'package:mojo/mojo/service_provider.mojom.dart' as mojom;
import 'box.dart';
import 'object.dart';
// TODO(abarth): Populate the view host.
final mojom.ViewHost _viewHost = null;
mojom.ViewHostProxy _initViewHostProxy() {
int viewHost = internals.takeViewHostHandle();
assert(() {
if (viewHost == 0)
debugPrint('Child view are supported only when running in Mojo shell.');
return true;
});
return new mojom.ViewHostProxy.fromHandle(new core.MojoHandle(viewHost));
}
// TODO(abarth): The view host is a unique resource. We should structure how we
// take the handle from the engine so that multiple libraries can interact with
// the view host safely. Unfortunately, the view host has a global namespace of
// view keys, which means any scheme for sharing the view host also needs to
// provide a mechanism for coordinating about view keys.
final mojom.ViewHostProxy _viewHostProxy = _initViewHostProxy();
final mojom.ViewHost _viewHost = _viewHostProxy?.ptr;
class ChildViewConnection {
ChildViewConnection({ this.url }) {
mojom.ServiceProviderProxy incomingServices = new mojom.ServiceProviderProxy.unbound();
mojom.ServiceProviderStub outgoingServices = new mojom.ServiceProviderStub.unbound();
assert(_viewToken == null);
mojom.ViewProviderProxy viewProvider = new mojom.ViewProviderProxy.unbound();
shell.connectToService(url, viewProvider);
_unresolvedViewToken = _awaitResponse(viewProvider.ptr.createView(incomingServices, outgoingServices), viewProvider);
_connection = new ApplicationConnection(outgoingServices, incomingServices);
_unresolvedViewToken = _connectToView(incomingServices, outgoingServices);
}
final String url;
......@@ -34,14 +54,11 @@ class ChildViewConnection {
Future<mojom.ViewToken> _unresolvedViewToken;
mojom.ViewToken _viewToken;
Future<mojom.ViewToken> _connectToView(
mojom.ServiceProviderProxy incomingServices,
mojom.ServiceProviderStub outgoingServices
Future<mojom.ViewToken> _awaitResponse(
Future<mojom.ViewProviderCreateViewResponseParams> response,
mojom.ViewProviderProxy viewProvider
) async {
assert(_viewToken == null);
mojom.ViewProviderProxy viewProvider = new mojom.ViewProviderProxy.unbound();
shell.connectToService(url, proxy);
mojom.ViewToken viewToken = (await viewProvider.ptr.createView(incomingServices, outgoingServices)).viewToken;
mojom.ViewToken viewToken = (await response).viewToken;
viewProvider.close();
assert(_viewToken == null);
_viewToken = viewToken;
......@@ -125,7 +142,10 @@ class RenderChildView extends RenderBox {
RenderChildView({
ChildViewConnection child,
double scale
}) : _child = child, _scale = scale;
}) : _child = child, _scale = scale {
if (_child != null)
_awaitViewToken();
}
ChildViewConnection get child => _child;
ChildViewConnection _child;
......@@ -150,10 +170,14 @@ class RenderChildView extends RenderBox {
// repaint now (to remove any old child view), and we need to watch for
// the view token resolving before attempting layout.
markNeedsPaint();
_child._unresolvedViewToken.then(_handleViewTokenResolved);
_awaitViewToken();
}
}
void _awaitViewToken() {
_child._unresolvedViewToken.then(_handleViewTokenResolved);
}
double get scale => _scale;
double _scale;
void set scale (double value) {
......@@ -182,7 +206,7 @@ class RenderChildView extends RenderBox {
}
void performLayout() {
if (_child != null)
if (_child != null && _child._viewToken != null)
_child._layout(size: size, scale: scale).then(_handleLayoutInfoChanged);
}
......@@ -200,6 +224,8 @@ class RenderChildView extends RenderBox {
markNeedsLayout();
}
bool hitTestSelf(Point position) => true;
void paint(PaintingContext context, Offset offset) {
assert(needsCompositing);
if (_layoutInfo != null)
......
......@@ -15,6 +15,7 @@ class ChildView extends StatelessComponent {
final ChildViewConnection child;
Widget build(BuildContext context) {
assert(MediaQuery.of(context) != null);
return new _ChildViewWidget(
child: child,
scale: MediaQuery.of(context).devicePixelRatio
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment