| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // HACK: pretend to be dart.ui in order to access its internals |
| // @dart = 2.6 |
| library dart.ui; |
| |
| import 'dart:async'; |
| // this needs to be imported because painting.dart expects it this way |
| import 'dart:collection' as collection; |
| import 'dart:convert'; |
| import 'dart:developer' as developer; |
| import 'dart:math' as math; |
| import 'dart:nativewrappers'; // ignore: unused_import |
| import 'dart:typed_data'; |
| |
| |
| import 'package:test/test.dart'; |
| |
| // HACK: these parts are to get access to private functions tested here. |
| part '../../lib/ui/annotations.dart'; |
| part '../../lib/ui/channel_buffers.dart'; |
| part '../../lib/ui/compositing.dart'; |
| part '../../lib/ui/geometry.dart'; |
| part '../../lib/ui/hash_codes.dart'; |
| part '../../lib/ui/hooks.dart'; |
| part '../../lib/ui/lerp.dart'; |
| part '../../lib/ui/natives.dart'; |
| part '../../lib/ui/painting.dart'; |
| part '../../lib/ui/pointer.dart'; |
| part '../../lib/ui/semantics.dart'; |
| part '../../lib/ui/text.dart'; |
| part '../../lib/ui/window.dart'; |
| |
| void main() { |
| group('window callback zones', () { |
| VoidCallback originalOnMetricsChanged; |
| VoidCallback originalOnLocaleChanged; |
| FrameCallback originalOnBeginFrame; |
| VoidCallback originalOnDrawFrame; |
| TimingsCallback originalOnReportTimings; |
| PointerDataPacketCallback originalOnPointerDataPacket; |
| VoidCallback originalOnSemanticsEnabledChanged; |
| SemanticsActionCallback originalOnSemanticsAction; |
| PlatformMessageCallback originalOnPlatformMessage; |
| VoidCallback originalOnTextScaleFactorChanged; |
| |
| double oldDPR; |
| Size oldSize; |
| double oldDepth; |
| WindowPadding oldPadding; |
| WindowPadding oldInsets; |
| WindowPadding oldSystemGestureInsets; |
| |
| setUp(() { |
| oldDPR = window.devicePixelRatio; |
| oldSize = window.physicalSize; |
| oldDepth = window.physicalDepth; |
| oldPadding = window.viewPadding; |
| oldInsets = window.viewInsets; |
| oldSystemGestureInsets = window.systemGestureInsets; |
| |
| originalOnMetricsChanged = window.onMetricsChanged; |
| originalOnLocaleChanged = window.onLocaleChanged; |
| originalOnBeginFrame = window.onBeginFrame; |
| originalOnDrawFrame = window.onDrawFrame; |
| originalOnReportTimings = window.onReportTimings; |
| originalOnPointerDataPacket = window.onPointerDataPacket; |
| originalOnSemanticsEnabledChanged = window.onSemanticsEnabledChanged; |
| originalOnSemanticsAction = window.onSemanticsAction; |
| originalOnPlatformMessage = window.onPlatformMessage; |
| originalOnTextScaleFactorChanged = window.onTextScaleFactorChanged; |
| }); |
| |
| tearDown(() { |
| _updateWindowMetrics( |
| oldDPR, // DPR |
| oldSize.width, // width |
| oldSize.height, // height |
| oldDepth, // depth |
| oldPadding.top, // padding top |
| oldPadding.right, // padding right |
| oldPadding.bottom, // padding bottom |
| oldPadding.left, // padding left |
| oldInsets.top, // inset top |
| oldInsets.right, // inset right |
| oldInsets.bottom, // inset bottom |
| oldInsets.left, // inset left |
| oldSystemGestureInsets.top, // system gesture inset top |
| oldSystemGestureInsets.right, // system gesture inset right |
| oldSystemGestureInsets.bottom, // system gesture inset bottom |
| oldSystemGestureInsets.left, // system gesture inset left |
| ); |
| window.onMetricsChanged = originalOnMetricsChanged; |
| window.onLocaleChanged = originalOnLocaleChanged; |
| window.onBeginFrame = originalOnBeginFrame; |
| window.onDrawFrame = originalOnDrawFrame; |
| window.onReportTimings = originalOnReportTimings; |
| window.onPointerDataPacket = originalOnPointerDataPacket; |
| window.onSemanticsEnabledChanged = originalOnSemanticsEnabledChanged; |
| window.onSemanticsAction = originalOnSemanticsAction; |
| window.onPlatformMessage = originalOnPlatformMessage; |
| window.onTextScaleFactorChanged = originalOnTextScaleFactorChanged; |
| }); |
| |
| test('updateUserSettings can handle an empty object', () { |
| // this should now throw. |
| _updateUserSettingsData('{}'); |
| expect(true, equals(true)); |
| }); |
| |
| test('onMetricsChanged preserves callback zone', () { |
| Zone innerZone; |
| Zone runZone; |
| double devicePixelRatio; |
| |
| runZoned(() { |
| innerZone = Zone.current; |
| window.onMetricsChanged = () { |
| runZone = Zone.current; |
| devicePixelRatio = window.devicePixelRatio; |
| }; |
| }); |
| |
| window.onMetricsChanged(); |
| _updateWindowMetrics( |
| 0.1234, // DPR |
| 0.0, // width |
| 0.0, // height |
| 0.0, // depth |
| 0.0, // padding top |
| 0.0, // padding right |
| 0.0, // padding bottom |
| 0.0, // padding left |
| 0.0, // inset top |
| 0.0, // inset right |
| 0.0, // inset bottom |
| 0.0, // inset left |
| 0.0, // system gesture inset top |
| 0.0, // system gesture inset right |
| 0.0, // system gesture inset bottom |
| 0.0, // system gesture inset left |
| ); |
| expect(runZone, isNotNull); |
| expect(runZone, same(innerZone)); |
| expect(devicePixelRatio, equals(0.1234)); |
| }); |
| |
| test('onLocaleChanged preserves callback zone', () { |
| Zone innerZone; |
| Zone runZone; |
| Locale locale; |
| |
| runZoned(() { |
| innerZone = Zone.current; |
| window.onLocaleChanged = () { |
| runZone = Zone.current; |
| locale = window.locale; |
| }; |
| }); |
| |
| _updateLocales(<String>['en', 'US', '', '']); |
| expect(runZone, isNotNull); |
| expect(runZone, same(innerZone)); |
| expect(locale, equals(const Locale('en', 'US'))); |
| }); |
| |
| test('onBeginFrame preserves callback zone', () { |
| Zone innerZone; |
| Zone runZone; |
| Duration start; |
| |
| runZoned(() { |
| innerZone = Zone.current; |
| window.onBeginFrame = (Duration value) { |
| runZone = Zone.current; |
| start = value; |
| }; |
| }); |
| |
| _beginFrame(1234); |
| expect(runZone, isNotNull); |
| expect(runZone, same(innerZone)); |
| expect(start, equals(const Duration(microseconds: 1234))); |
| }); |
| |
| test('onDrawFrame preserves callback zone', () { |
| Zone innerZone; |
| Zone runZone; |
| |
| runZoned(() { |
| innerZone = Zone.current; |
| window.onDrawFrame = () { |
| runZone = Zone.current; |
| }; |
| }); |
| |
| _drawFrame(); |
| expect(runZone, isNotNull); |
| expect(runZone, same(innerZone)); |
| }); |
| |
| test('onReportTimings preserves callback zone', () { |
| Zone innerZone; |
| Zone runZone; |
| |
| window._setNeedsReportTimings = (bool _) {}; |
| |
| runZoned(() { |
| innerZone = Zone.current; |
| window.onReportTimings = (List<FrameTiming> timings) { |
| runZone = Zone.current; |
| }; |
| }); |
| |
| _reportTimings(<int>[]); |
| expect(runZone, isNotNull); |
| expect(runZone, same(innerZone)); |
| }); |
| |
| test('onPointerDataPacket preserves callback zone', () { |
| Zone innerZone; |
| Zone runZone; |
| PointerDataPacket data; |
| |
| runZoned(() { |
| innerZone = Zone.current; |
| window.onPointerDataPacket = (PointerDataPacket value) { |
| runZone = Zone.current; |
| data = value; |
| }; |
| }); |
| |
| final ByteData testData = ByteData.view(Uint8List(0).buffer); |
| _dispatchPointerDataPacket(testData); |
| expect(runZone, isNotNull); |
| expect(runZone, same(innerZone)); |
| expect(data.data, equals(_unpackPointerDataPacket(testData).data)); |
| }); |
| |
| test('onSemanticsEnabledChanged preserves callback zone', () { |
| Zone innerZone; |
| Zone runZone; |
| bool enabled; |
| |
| runZoned(() { |
| innerZone = Zone.current; |
| window.onSemanticsEnabledChanged = () { |
| runZone = Zone.current; |
| enabled = window.semanticsEnabled; |
| }; |
| }); |
| |
| _updateSemanticsEnabled(window._semanticsEnabled); |
| expect(runZone, isNotNull); |
| expect(runZone, same(innerZone)); |
| expect(enabled, isNotNull); |
| expect(enabled, equals(window._semanticsEnabled)); |
| }); |
| |
| test('onSemanticsAction preserves callback zone', () { |
| Zone innerZone; |
| Zone runZone; |
| int id; |
| int action; |
| |
| runZoned(() { |
| innerZone = Zone.current; |
| window.onSemanticsAction = (int i, SemanticsAction a, ByteData _) { |
| runZone = Zone.current; |
| action = a.index; |
| id = i; |
| }; |
| }); |
| |
| _dispatchSemanticsAction(1234, 4, null); |
| expect(runZone, isNotNull); |
| expect(runZone, same(innerZone)); |
| expect(id, equals(1234)); |
| expect(action, equals(4)); |
| }); |
| |
| test('onPlatformMessage preserves callback zone', () { |
| Zone innerZone; |
| Zone runZone; |
| String name; |
| |
| runZoned(() { |
| innerZone = Zone.current; |
| window.onPlatformMessage = (String value, _, __) { |
| runZone = Zone.current; |
| name = value; |
| }; |
| }); |
| |
| _dispatchPlatformMessage('testName', null, null); |
| expect(runZone, isNotNull); |
| expect(runZone, same(innerZone)); |
| expect(name, equals('testName')); |
| }); |
| |
| test('onTextScaleFactorChanged preserves callback zone', () { |
| Zone innerZone; |
| Zone runZone; |
| double textScaleFactor; |
| |
| runZoned(() { |
| innerZone = Zone.current; |
| window.onTextScaleFactorChanged = () { |
| runZone = Zone.current; |
| textScaleFactor = window.textScaleFactor; |
| }; |
| }); |
| |
| window.onTextScaleFactorChanged(); |
| _updateTextScaleFactor(0.5); |
| expect(runZone, isNotNull); |
| expect(runZone, same(innerZone)); |
| expect(textScaleFactor, equals(0.5)); |
| }); |
| |
| test('onThemeBrightnessMode preserves callback zone', () { |
| Zone innerZone; |
| Zone runZone; |
| Brightness platformBrightness; |
| |
| runZoned(() { |
| innerZone = Zone.current; |
| window.onPlatformBrightnessChanged = () { |
| runZone = Zone.current; |
| platformBrightness = window.platformBrightness; |
| }; |
| }); |
| |
| window.onPlatformBrightnessChanged(); |
| _updatePlatformBrightness('dark'); |
| expect(runZone, isNotNull); |
| expect(runZone, same(innerZone)); |
| expect(platformBrightness, equals(Brightness.dark)); |
| }); |
| |
| test('Window padding/insets/viewPadding/systemGestureInsets', () { |
| _updateWindowMetrics( |
| 1.0, // DPR |
| 800.0, // width |
| 600.0, // height |
| 100.0, // depth |
| 50.0, // padding top |
| 0.0, // padding right |
| 40.0, // padding bottom |
| 0.0, // padding left |
| 0.0, // inset top |
| 0.0, // inset right |
| 0.0, // inset bottom |
| 0.0, // inset left |
| 0.0, // system gesture inset top |
| 0.0, // system gesture inset right |
| 0.0, // system gesture inset bottom |
| 0.0, // system gesture inset left |
| ); |
| |
| expect(window.viewInsets.bottom, 0.0); |
| expect(window.viewPadding.bottom, 40.0); |
| expect(window.padding.bottom, 40.0); |
| expect(window.physicalDepth, 100.0); |
| expect(window.systemGestureInsets.bottom, 0.0); |
| |
| _updateWindowMetrics( |
| 1.0, // DPR |
| 800.0, // width |
| 600.0, // height |
| 100.0, // depth |
| 50.0, // padding top |
| 0.0, // padding right |
| 40.0, // padding bottom |
| 0.0, // padding left |
| 0.0, // inset top |
| 0.0, // inset right |
| 400.0, // inset bottom |
| 0.0, // inset left |
| 0.0, // system gesture insets top |
| 0.0, // system gesture insets right |
| 44.0, // system gesture insets bottom |
| 0.0, // system gesture insets left |
| ); |
| |
| expect(window.viewInsets.bottom, 400.0); |
| expect(window.viewPadding.bottom, 40.0); |
| expect(window.padding.bottom, 0.0); |
| expect(window.physicalDepth, 100.0); |
| expect(window.systemGestureInsets.bottom, 44.0); |
| }); |
| }); |
| } |