hooks.dart 10.2 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
A
Adam Barth 已提交
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
// TODO(dnfield): Remove unused_import ignores when https://github.com/dart-lang/sdk/issues/35164 is resolved.

A
Adam Barth 已提交
7
part of dart.ui;
A
Adam Barth 已提交
8

9
// ignore: unused_element
10
String _decodeUTF8(ByteData message) {
11
  return message != null ? utf8.decoder.convert(message.buffer.asUint8List()) : null;
12 13
}

14
// ignore: unused_element
15
dynamic _decodeJSON(String message) {
16
  return message != null ? json.decode(message) : null;
17 18
}

C
Chris Bracken 已提交
19
@pragma('vm:entry-point')
20
// ignore: unused_element
A
Adam Barth 已提交
21 22 23
void _updateWindowMetrics(double devicePixelRatio,
                          double width,
                          double height,
24 25 26 27 28 29 30 31
                          double paddingTop,
                          double paddingRight,
                          double paddingBottom,
                          double paddingLeft,
                          double viewInsetTop,
                          double viewInsetRight,
                          double viewInsetBottom,
                          double viewInsetLeft) {
A
Adam Barth 已提交
32 33
  window
    .._devicePixelRatio = devicePixelRatio
A
Adam Barth 已提交
34
    .._physicalSize = new Size(width, height)
35
    .._padding = new WindowPadding._(
36 37 38 39
        top: paddingTop,
        right: paddingRight,
        bottom: paddingBottom,
        left: paddingLeft)
40
    .._viewInsets = new WindowPadding._(
41 42 43 44
        top: viewInsetTop,
        right: viewInsetRight,
        bottom: viewInsetBottom,
        left: viewInsetLeft);
Y
Yegor 已提交
45
  _invoke(window.onMetricsChanged, window._onMetricsChangedZone);
A
Adam Barth 已提交
46 47
}

48
typedef _LocaleClosure = String Function();
49

50 51 52 53 54 55
String _localeClosure() {
  if (window.locale == null) {
    return null;
  }
  return window.locale.toString();
}
56

C
Chris Bracken 已提交
57
@pragma('vm:entry-point')
58
// ignore: unused_element
59
_LocaleClosure _getLocaleClosure() => _localeClosure;
60

C
Chris Bracken 已提交
61
@pragma('vm:entry-point')
62
// ignore: unused_element
63 64 65 66 67
void _updateLocales(List<String> locales) {
  const int stringsPerLocale = 4;
  final int numLocales = locales.length ~/ stringsPerLocale;
  window._locales = new List<Locale>(numLocales);
  for (int localeIndex = 0; localeIndex < numLocales; localeIndex++) {
68 69 70 71 72 73 74 75
    final String countryCode = locales[localeIndex * stringsPerLocale + 1];
    final String scriptCode = locales[localeIndex * stringsPerLocale + 2];

    window._locales[localeIndex] = new Locale.fromSubtags(
      languageCode: locales[localeIndex * stringsPerLocale],
      countryCode: countryCode.isEmpty ? null : countryCode,
      scriptCode: scriptCode.isEmpty ? null : scriptCode,
    );
76
  }
Y
Yegor 已提交
77
  _invoke(window.onLocaleChanged, window._onLocaleChangedZone);
78 79
}

C
Chris Bracken 已提交
80
@pragma('vm:entry-point')
81
// ignore: unused_element
82 83
void _updateUserSettingsData(String jsonData) {
  final Map<String, dynamic> data = json.decode(jsonData);
D
Dan Field 已提交
84 85 86
  if (data.isEmpty) {
    return;
  }
87 88
  _updateTextScaleFactor(data['textScaleFactor'].toDouble());
  _updateAlwaysUse24HourFormat(data['alwaysUse24HourFormat']);
89
  _updatePlatformBrightness(data['platformBrightness']);
90 91
}

92 93 94 95 96
void _updateTextScaleFactor(double textScaleFactor) {
  window._textScaleFactor = textScaleFactor;
  _invoke(window.onTextScaleFactorChanged, window._onTextScaleFactorChangedZone);
}

97 98 99 100
void _updateAlwaysUse24HourFormat(bool alwaysUse24HourFormat) {
  window._alwaysUse24HourFormat = alwaysUse24HourFormat;
}

101 102 103 104 105
void _updatePlatformBrightness(String brightnessName) {
  window._platformBrightness = brightnessName == 'dark' ? Brightness.dark : Brightness.light;
  _invoke(window.onPlatformBrightnessChanged, window._onPlatformBrightnessChangedZone);
}

C
Chris Bracken 已提交
106
@pragma('vm:entry-point')
107
// ignore: unused_element
108 109
void _updateSemanticsEnabled(bool enabled) {
  window._semanticsEnabled = enabled;
Y
Yegor 已提交
110
  _invoke(window.onSemanticsEnabledChanged, window._onSemanticsEnabledChangedZone);
111 112
}

C
Chris Bracken 已提交
113
@pragma('vm:entry-point')
114
// ignore: unused_element
115 116 117 118 119 120
void _updateAccessibilityFeatures(int values) {
  final AccessibilityFeatures newFeatures = new AccessibilityFeatures._(values);
  if (newFeatures == window._accessibilityFeatures)
    return;
  window._accessibilityFeatures = newFeatures;
  _invoke(window.onAccessibilityFeaturesChanged, window._onAccessibilityFlagsChangedZone);
121 122
}

C
Chris Bracken 已提交
123
@pragma('vm:entry-point')
A
Adam Barth 已提交
124 125
void _dispatchPlatformMessage(String name, ByteData data, int responseId) {
  if (window.onPlatformMessage != null) {
Y
Yegor 已提交
126 127 128 129 130 131 132 133 134
    _invoke3<String, ByteData, PlatformMessageResponseCallback>(
      window.onPlatformMessage,
      window._onPlatformMessageZone,
      name,
      data,
      (ByteData responseData) {
        window._respondToPlatformMessage(responseId, responseData);
      },
    );
A
Adam Barth 已提交
135 136 137 138 139
  } else {
    window._respondToPlatformMessage(responseId, null);
  }
}

C
Chris Bracken 已提交
140
@pragma('vm:entry-point')
141
// ignore: unused_element
142 143
void _dispatchPointerDataPacket(ByteData packet) {
  if (window.onPointerDataPacket != null)
Y
Yegor 已提交
144
    _invoke1<PointerDataPacket>(window.onPointerDataPacket, window._onPointerDataPacketZone, _unpackPointerDataPacket(packet));
145 146
}

C
Chris Bracken 已提交
147
@pragma('vm:entry-point')
148
// ignore: unused_element
149 150
void _dispatchSemanticsAction(int id, int action, ByteData args) {
  _invoke3<int, SemanticsAction, ByteData>(
Y
Yegor 已提交
151 152 153 154
    window.onSemanticsAction,
    window._onSemanticsActionZone,
    id,
    SemanticsAction.values[action],
155
    args,
Y
Yegor 已提交
156
  );
157 158
}

C
Chris Bracken 已提交
159
@pragma('vm:entry-point')
160
// ignore: unused_element
A
Adam Barth 已提交
161
void _beginFrame(int microseconds) {
Y
Yegor 已提交
162
  _invoke1<Duration>(window.onBeginFrame, window._onBeginFrameZone, new Duration(microseconds: microseconds));
A
Adam Barth 已提交
163
}
164

C
Chris Bracken 已提交
165
@pragma('vm:entry-point')
166
// ignore: unused_element
167
void _drawFrame() {
Y
Yegor 已提交
168 169 170
  _invoke(window.onDrawFrame, window._onDrawFrameZone);
}

171 172 173 174 175
// ignore: always_declare_return_types, prefer_generic_function_type_aliases
typedef _UnaryFunction(Null args);
// ignore: always_declare_return_types, prefer_generic_function_type_aliases
typedef _BinaryFunction(Null args, Null message);

C
Chris Bracken 已提交
176
@pragma('vm:entry-point')
177 178 179 180
// ignore: unused_element
void _runMainZoned(Function startMainIsolateFunction, Function userMainFunction) {
  startMainIsolateFunction((){
    runZoned<Future<void>>(() {
181 182 183 184 185 186 187 188 189 190
      const List<String> empty_args = <String>[];
      if (userMainFunction is _BinaryFunction) {
        // This seems to be undocumented but supported by the command line VM.
        // Let's do the same in case old entry-points are ported to Flutter.
        (userMainFunction as dynamic)(empty_args, '');
      } else if (userMainFunction is _UnaryFunction) {
        (userMainFunction as dynamic)(empty_args);
      } else {
        userMainFunction();
      }
191 192 193 194 195 196 197 198
    }, onError: (Object error, StackTrace stackTrace) {
      _reportUnhandledException(error.toString(), stackTrace.toString());
    });
  }, null);
}

void _reportUnhandledException(String error, String stackTrace) native 'Window_reportUnhandledException';

Y
Yegor 已提交
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
/// Invokes [callback] inside the given [zone].
void _invoke(void callback(), Zone zone) {
  if (callback == null)
    return;

  assert(zone != null);

  if (identical(zone, Zone.current)) {
    callback();
  } else {
    zone.runGuarded(callback);
  }
}

/// Invokes [callback] inside the given [zone] passing it [arg].
void _invoke1<A>(void callback(A a), Zone zone, A arg) {
  if (callback == null)
    return;

  assert(zone != null);

  if (identical(zone, Zone.current)) {
    callback(arg);
  } else {
223
    zone.runUnaryGuarded<A>(callback, arg);
Y
Yegor 已提交
224 225 226 227
  }
}

/// Invokes [callback] inside the given [zone] passing it [arg1] and [arg2].
228
// ignore: unused_element
Y
Yegor 已提交
229 230 231 232 233 234 235 236 237
void _invoke2<A1, A2>(void callback(A1 a1, A2 a2), Zone zone, A1 arg1, A2 arg2) {
  if (callback == null)
    return;

  assert(zone != null);

  if (identical(zone, Zone.current)) {
    callback(arg1, arg2);
  } else {
238
    zone.runBinaryGuarded<A1, A2>(callback, arg1, arg2);
Y
Yegor 已提交
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
  }
}

/// Invokes [callback] inside the given [zone] passing it [arg1], [arg2] and [arg3].
void _invoke3<A1, A2, A3>(void callback(A1 a1, A2 a2, A3 a3), Zone zone, A1 arg1, A2 arg2, A3 arg3) {
  if (callback == null)
    return;

  assert(zone != null);

  if (identical(zone, Zone.current)) {
    callback(arg1, arg2, arg3);
  } else {
    zone.runGuarded(() {
      callback(arg1, arg2, arg3);
    });
  }
256 257
}

258 259 260 261
// If this value changes, update the encoding code in the following files:
//
//  * pointer_data.cc
//  * FlutterView.java
262
const int _kPointerDataFieldCount = 21;
263 264

PointerDataPacket _unpackPointerDataPacket(ByteData packet) {
265
  const int kStride = Int64List.bytesPerElement;
266 267 268
  const int kBytesPerPointerData = _kPointerDataFieldCount * kStride;
  final int length = packet.lengthInBytes ~/ kBytesPerPointerData;
  assert(length * kBytesPerPointerData == packet.lengthInBytes);
269
  final List<PointerData> data = new List<PointerData>(length);
270 271
  for (int i = 0; i < length; ++i) {
    int offset = i * _kPointerDataFieldCount;
272
    data[i] = new PointerData(
273 274 275
      timeStamp: new Duration(microseconds: packet.getInt64(kStride * offset++, _kFakeHostEndian)),
      change: PointerChange.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)],
      kind: PointerDeviceKind.values[packet.getInt64(kStride * offset++, _kFakeHostEndian)],
276
      device: packet.getInt64(kStride * offset++, _kFakeHostEndian),
277 278 279 280 281 282 283 284 285
      physicalX: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
      physicalY: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
      buttons: packet.getInt64(kStride * offset++, _kFakeHostEndian),
      obscured: packet.getInt64(kStride * offset++, _kFakeHostEndian) != 0,
      pressure: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
      pressureMin: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
      pressureMax: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
      distance: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
      distanceMax: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
286
      size: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
287 288 289 290 291
      radiusMajor: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
      radiusMinor: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
      radiusMin: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
      radiusMax: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
      orientation: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
292 293
      tilt: packet.getFloat64(kStride * offset++, _kFakeHostEndian),
      platformData: packet.getInt64(kStride * offset++, _kFakeHostEndian),
294 295 296
    );
    assert(offset == (i + 1) * _kPointerDataFieldCount);
  }
297
  return new PointerDataPacket(data: data);
298
}