binding.dart 6.39 KB
Newer Older
1 2 3 4
// 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.

5
import 'dart:ui' as ui show window;
6

7
import 'package:flutter/foundation.dart';
8
import 'package:flutter/gestures.dart';
9
import 'package:flutter/scheduler.dart';
Ian Hickson's avatar
Ian Hickson committed
10
import 'package:flutter/services.dart';
11
import 'package:mojo/core.dart' as core;
Hixie's avatar
Hixie committed
12
import 'package:sky_services/semantics/semantics.mojom.dart' as mojom;
13 14

import 'box.dart';
15
import 'debug.dart';
16 17
import 'object.dart';
import 'view.dart';
Hixie's avatar
Hixie committed
18
import 'semantics.dart';
19

Ian Hickson's avatar
Ian Hickson committed
20
export 'package:flutter/gestures.dart' show HitTestResult;
21

Florian Loitsch's avatar
Florian Loitsch committed
22
/// The glue between the render tree and the Flutter engine.
23
abstract class RendererBinding extends BindingBase implements SchedulerBinding, ServicesBinding, HitTestable {
24
  @override
Ian Hickson's avatar
Ian Hickson committed
25 26
  void initInstances() {
    super.initInstances();
27
    _instance = this;
Ian Hickson's avatar
Ian Hickson committed
28 29
    ui.window.onMetricsChanged = handleMetricsChanged;
    initRenderView();
30
    initSemantics();
31
    assert(renderView != null);
32 33 34
    addPersistentFrameCallback(_handlePersistentFrameCallback);
  }

35 36 37
  /// The current [RendererBinding], if one has been created.
  static RendererBinding get instance => _instance;
  static RendererBinding _instance;
38 39 40 41

  @override
  void initServiceExtensions() {
    super.initServiceExtensions();
42

43
    assert(() {
44 45
      // this service extension only works in checked mode
      registerBoolServiceExtension(
46
        name: 'debugPaint',
47 48 49 50 51
        getter: () => debugPaintSizeEnabled,
        setter: (bool value) {
          if (debugPaintSizeEnabled == value)
            return;
          debugPaintSizeEnabled = value;
52
          _forceRepaint();
53 54
        }
      );
55 56
      return true;
    });
57

58 59 60 61 62 63
    assert(() {
      // this service extension only works in checked mode
      registerBoolServiceExtension(
        name: 'repaintRainbow',
        getter: () => debugRepaintRainbowEnabled,
        setter: (bool value) {
64
          bool repaint = debugRepaintRainbowEnabled && !value;
65
          debugRepaintRainbowEnabled = value;
66 67
          if (repaint)
            _forceRepaint();
68 69 70 71 72
        }
      );
      return true;
    });
  }
73

74 75 76 77 78 79
  /// Creates a [RenderView] object to be the root of the
  /// [RenderObject] rendering tree, and initializes it so that it
  /// will be rendered when the engine is next ready to display a
  /// frame.
  ///
  /// Called automatically when the binding is created.
Ian Hickson's avatar
Ian Hickson committed
80 81 82 83
  void initRenderView() {
    if (renderView == null) {
      renderView = new RenderView();
      renderView.scheduleInitialFrame();
84
    }
85
    handleMetricsChanged(); // configures renderView's metrics
86 87
  }

88 89 90 91
  /// The render tree's owner, which maintains dirty state for layout,
  /// composite, paint, and accessibility semantics
  final PipelineOwner pipelineOwner = new PipelineOwner();

Florian Loitsch's avatar
Florian Loitsch committed
92
  /// The render tree that's attached to the output surface.
93
  RenderView get renderView => _renderView;
94
  RenderView _renderView;
95 96
  /// Sets the given [RenderView] object (which must not be null), and its tree, to
  /// be the new render tree to display. The previous tree, if any, is detached.
97
  set renderView(RenderView value) {
98
    assert(value != null);
Ian Hickson's avatar
Ian Hickson committed
99 100 101 102 103
    if (_renderView == value)
      return;
    if (_renderView != null)
      _renderView.detach();
    _renderView = value;
104
    _renderView.attach(pipelineOwner);
105 106
  }

107 108 109
  /// Invoked when the system metrics change.
  ///
  /// See [ui.window.onMetricsChanged].
Ian Hickson's avatar
Ian Hickson committed
110
  void handleMetricsChanged() {
111
    assert(renderView != null);
112
    renderView.configuration = new ViewConfiguration(size: ui.window.size);
113 114
  }

115 116 117
  /// Prepares the rendering library to handle semantics requests from the engine.
  ///
  /// Called automatically when the binding is created.
118 119
  void initSemantics() {
    SemanticsNode.onSemanticsEnabled = renderView.scheduleInitialSemantics;
120
    shell.provideService(mojom.SemanticsServer.serviceName, (core.MojoMessagePipeEndpoint endpoint) {
121 122
      mojom.SemanticsServerStub server = new mojom.SemanticsServerStub.fromEndpoint(endpoint);
      server.impl = new SemanticsServer();
123
    });
Hixie's avatar
Hixie committed
124 125
  }

126 127 128 129
  void _handlePersistentFrameCallback(Duration timeStamp) {
    beginFrame();
  }

Ian Hickson's avatar
Ian Hickson committed
130
  /// Pump the rendering pipeline to generate a frame.
131 132
  ///
  /// Called automatically by the engine when it is time to lay out and paint a frame.
133
  void beginFrame() {
134
    assert(renderView != null);
135 136 137
    pipelineOwner.flushLayout();
    pipelineOwner.flushCompositingBits();
    pipelineOwner.flushPaint();
Hixie's avatar
Hixie committed
138
    renderView.compositeFrame(); // this sends the bits to the GPU
139
    if (SemanticsNode.hasListeners) {
140
      pipelineOwner.flushSemantics();
141
      SemanticsNode.sendSemanticsTree();
Hixie's avatar
Hixie committed
142
    }
143 144
  }

145 146 147 148 149 150
  @override
  void reassembleApplication() {
    super.reassembleApplication();
    pipelineOwner.reassemble(renderView);
  }

151
  @override
Ian Hickson's avatar
Ian Hickson committed
152
  void hitTest(HitTestResult result, Point position) {
153 154
    assert(renderView != null);
    renderView.hitTest(result, position: position);
Ian Hickson's avatar
Ian Hickson committed
155
    super.hitTest(result, position);
156
  }
157 158 159 160 161 162 163 164 165

  void _forceRepaint() {
    RenderObjectVisitor visitor;
    visitor = (RenderObject child) {
      child.markNeedsPaint();
      child.visitChildren(visitor);
    };
    instance?.renderView?.visitChildren(visitor);
  }
166
}
167

Florian Loitsch's avatar
Florian Loitsch committed
168
/// Prints a textual representation of the entire render tree.
169
void debugDumpRenderTree() {
170
  debugPrint(RendererBinding.instance?.renderView?.toStringDeep());
171
}
172

Florian Loitsch's avatar
Florian Loitsch committed
173
/// Prints a textual representation of the entire layer tree.
174
void debugDumpLayerTree() {
175
  debugPrint(RendererBinding.instance?.renderView?.layer?.toStringDeep());
Ian Hickson's avatar
Ian Hickson committed
176 177
}

Hixie's avatar
Hixie committed
178 179 180 181
/// Prints a textual representation of the entire semantics tree.
/// This will only work if there is a semantics client attached.
/// Otherwise, the tree is empty and this will print "null".
void debugDumpSemanticsTree() {
182
  debugPrint(RendererBinding.instance?.renderView?.debugSemantics?.toStringDeep() ?? 'Semantics not collected.');
Hixie's avatar
Hixie committed
183 184
}

Ian Hickson's avatar
Ian Hickson committed
185 186
/// A concrete binding for applications that use the Rendering framework
/// directly. This is the glue that binds the framework to the Flutter engine.
187 188 189 190 191 192 193
///
/// You would only use this binding if you are writing to the
/// rendering layer directly. If you are writing to a higher-level
/// library, such as the Flutter Widgets library, then you would use
/// that layer's binding.
///
/// See also [BindingBase].
194
class RenderingFlutterBinding extends BindingBase with SchedulerBinding, GestureBinding, ServicesBinding, RendererBinding {
Ian Hickson's avatar
Ian Hickson committed
195
  RenderingFlutterBinding({ RenderBox root }) {
196
    assert(renderView != null);
Ian Hickson's avatar
Ian Hickson committed
197 198
    renderView.child = root;
  }
199
}