mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Reland #19396 with a fix for improper scale that was affecting internal tests Tested: Ran all unittests, ran internal tests, and ran workstation on Fuchsia BUG: 53062, 53063
420 lines
12 KiB
Dart
420 lines
12 KiB
Dart
// 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.
|
|
|
|
// @dart = 2.10
|
|
|
|
// HACK: pretend to be dart.ui in order to access its internals
|
|
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';
|
|
|
|
|
|
// 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() {
|
|
VoidCallback? originalOnMetricsChanged;
|
|
VoidCallback? originalOnLocaleChanged;
|
|
FrameCallback? originalOnBeginFrame;
|
|
VoidCallback? originalOnDrawFrame;
|
|
TimingsCallback? originalOnReportTimings;
|
|
PointerDataPacketCallback? originalOnPointerDataPacket;
|
|
VoidCallback? originalOnSemanticsEnabledChanged;
|
|
SemanticsActionCallback? originalOnSemanticsAction;
|
|
PlatformMessageCallback? originalOnPlatformMessage;
|
|
VoidCallback? originalOnTextScaleFactorChanged;
|
|
|
|
double? oldDPR;
|
|
Size? oldSize;
|
|
WindowPadding? oldPadding;
|
|
WindowPadding? oldInsets;
|
|
WindowPadding? oldSystemGestureInsets;
|
|
|
|
void setUp() {
|
|
oldDPR = window.devicePixelRatio;
|
|
oldSize = window.physicalSize;
|
|
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;
|
|
}
|
|
|
|
void tearDown() {
|
|
_updateWindowMetrics(
|
|
oldDPR!, // DPR
|
|
oldSize!.width, // width
|
|
oldSize!.height, // height
|
|
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;
|
|
}
|
|
|
|
void test(String description, void Function() testFunction) {
|
|
print(description);
|
|
setUp();
|
|
testFunction();
|
|
tearDown();
|
|
}
|
|
|
|
void expectEquals(dynamic actual, dynamic expected) {
|
|
if (actual != expected) {
|
|
throw Exception('Equality check failed:\n Expected: $expected\n Actual: $actual');
|
|
}
|
|
}
|
|
|
|
void expectIterablesEqual(Iterable<dynamic> actual, Iterable<dynamic> expected) {
|
|
expectEquals(actual.length, expected.length);
|
|
final Iterator<dynamic> actualIter = actual.iterator;
|
|
final Iterator<dynamic> expectedIter = expected.iterator;
|
|
while (expectedIter.moveNext()) {
|
|
expectEquals(actualIter.moveNext(), true);
|
|
expectEquals(actualIter.current, expectedIter.current);
|
|
}
|
|
expectEquals(actualIter.moveNext(), false);
|
|
}
|
|
|
|
void expectNotEquals(dynamic actual, dynamic expected) {
|
|
if (actual == expected) {
|
|
throw Exception('Inequality check failed:\n Expected: $expected\n Actual: $actual');
|
|
}
|
|
}
|
|
|
|
void expectIdentical(dynamic actual, dynamic expected) {
|
|
if (!identical(actual, expected)) {
|
|
throw Exception('Identity check failed:\n Expected: $expected\n Actual: $actual');
|
|
}
|
|
}
|
|
|
|
test('updateUserSettings can handle an empty object', () {
|
|
// this should not throw.
|
|
_updateUserSettingsData('{}');
|
|
});
|
|
|
|
test('onMetricsChanged preserves callback zone', () {
|
|
late Zone innerZone;
|
|
late Zone runZone;
|
|
late 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, // 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
|
|
);
|
|
expectNotEquals(runZone, null);
|
|
expectIdentical(runZone, innerZone);
|
|
expectEquals(devicePixelRatio, 0.1234);
|
|
});
|
|
|
|
test('onLocaleChanged preserves callback zone', () {
|
|
late Zone innerZone;
|
|
late Zone runZone;
|
|
Locale? locale;
|
|
|
|
runZoned(() {
|
|
innerZone = Zone.current;
|
|
window.onLocaleChanged = () {
|
|
runZone = Zone.current;
|
|
locale = window.locale;
|
|
};
|
|
});
|
|
|
|
_updateLocales(<String>['en', 'US', '', '']);
|
|
expectNotEquals(runZone, null);
|
|
expectIdentical(runZone, innerZone);
|
|
expectEquals(locale, const Locale('en', 'US'));
|
|
});
|
|
|
|
test('onBeginFrame preserves callback zone', () {
|
|
late Zone innerZone;
|
|
late Zone runZone;
|
|
late Duration start;
|
|
|
|
runZoned(() {
|
|
innerZone = Zone.current;
|
|
window.onBeginFrame = (Duration value) {
|
|
runZone = Zone.current;
|
|
start = value;
|
|
};
|
|
});
|
|
|
|
_beginFrame(1234);
|
|
expectNotEquals(runZone, null);
|
|
expectIdentical(runZone, innerZone);
|
|
expectEquals(start, const Duration(microseconds: 1234));
|
|
});
|
|
|
|
test('onDrawFrame preserves callback zone', () {
|
|
late Zone innerZone;
|
|
late Zone runZone;
|
|
|
|
runZoned(() {
|
|
innerZone = Zone.current;
|
|
window.onDrawFrame = () {
|
|
runZone = Zone.current;
|
|
};
|
|
});
|
|
|
|
_drawFrame();
|
|
expectNotEquals(runZone, null);
|
|
expectIdentical(runZone, innerZone);
|
|
});
|
|
|
|
test('onReportTimings preserves callback zone', () {
|
|
late Zone innerZone;
|
|
late Zone runZone;
|
|
|
|
window._setNeedsReportTimings = (bool _) {};
|
|
|
|
runZoned(() {
|
|
innerZone = Zone.current;
|
|
window.onReportTimings = (List<FrameTiming> timings) {
|
|
runZone = Zone.current;
|
|
};
|
|
});
|
|
|
|
_reportTimings(<int>[]);
|
|
expectNotEquals(runZone, null);
|
|
expectIdentical(runZone, innerZone);
|
|
});
|
|
|
|
test('onPointerDataPacket preserves callback zone', () {
|
|
late Zone innerZone;
|
|
late Zone runZone;
|
|
late 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);
|
|
expectNotEquals(runZone, null);
|
|
expectIdentical(runZone, innerZone);
|
|
expectIterablesEqual(data.data, _unpackPointerDataPacket(testData).data);
|
|
});
|
|
|
|
test('onSemanticsEnabledChanged preserves callback zone', () {
|
|
late Zone innerZone;
|
|
late Zone runZone;
|
|
late bool enabled;
|
|
|
|
runZoned(() {
|
|
innerZone = Zone.current;
|
|
window.onSemanticsEnabledChanged = () {
|
|
runZone = Zone.current;
|
|
enabled = window.semanticsEnabled;
|
|
};
|
|
});
|
|
|
|
_updateSemanticsEnabled(window._semanticsEnabled);
|
|
expectNotEquals(runZone, null);
|
|
expectIdentical(runZone, innerZone);
|
|
expectNotEquals(enabled, null);
|
|
expectEquals(enabled, window._semanticsEnabled);
|
|
});
|
|
|
|
test('onSemanticsAction preserves callback zone', () {
|
|
late Zone innerZone;
|
|
late Zone runZone;
|
|
late int id;
|
|
late 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);
|
|
expectNotEquals(runZone, null);
|
|
expectIdentical(runZone, innerZone);
|
|
expectEquals(id, 1234);
|
|
expectEquals(action, 4);
|
|
});
|
|
|
|
test('onPlatformMessage preserves callback zone', () {
|
|
late Zone innerZone;
|
|
late Zone runZone;
|
|
late String name;
|
|
|
|
runZoned(() {
|
|
innerZone = Zone.current;
|
|
window.onPlatformMessage = (String value, _, __) {
|
|
runZone = Zone.current;
|
|
name = value;
|
|
};
|
|
});
|
|
|
|
_dispatchPlatformMessage('testName', null, 123456789);
|
|
expectNotEquals(runZone, null);
|
|
expectIdentical(runZone, innerZone);
|
|
expectEquals(name, 'testName');
|
|
});
|
|
|
|
test('onTextScaleFactorChanged preserves callback zone', () {
|
|
late Zone innerZone;
|
|
late Zone runZone;
|
|
late double textScaleFactor;
|
|
|
|
runZoned(() {
|
|
innerZone = Zone.current;
|
|
window.onTextScaleFactorChanged = () {
|
|
runZone = Zone.current;
|
|
textScaleFactor = window.textScaleFactor;
|
|
};
|
|
});
|
|
|
|
window.onTextScaleFactorChanged!();
|
|
_updateTextScaleFactor(0.5);
|
|
expectNotEquals(runZone, null);
|
|
expectIdentical(runZone, innerZone);
|
|
expectEquals(textScaleFactor, 0.5);
|
|
});
|
|
|
|
test('onThemeBrightnessMode preserves callback zone', () {
|
|
late Zone innerZone;
|
|
late Zone runZone;
|
|
late Brightness platformBrightness;
|
|
|
|
runZoned(() {
|
|
innerZone = Zone.current;
|
|
window.onPlatformBrightnessChanged = () {
|
|
runZone = Zone.current;
|
|
platformBrightness = window.platformBrightness;
|
|
};
|
|
});
|
|
|
|
window.onPlatformBrightnessChanged!();
|
|
_updatePlatformBrightness('dark');
|
|
expectNotEquals(runZone, null);
|
|
expectIdentical(runZone, innerZone);
|
|
expectEquals(platformBrightness, Brightness.dark);
|
|
});
|
|
|
|
test('Window padding/insets/viewPadding/systemGestureInsets', () {
|
|
_updateWindowMetrics(
|
|
1.0, // DPR
|
|
800.0, // width
|
|
600.0, // height
|
|
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
|
|
);
|
|
|
|
expectEquals(window.viewInsets.bottom, 0.0);
|
|
expectEquals(window.viewPadding.bottom, 40.0);
|
|
expectEquals(window.padding.bottom, 40.0);
|
|
expectEquals(window.systemGestureInsets.bottom, 0.0);
|
|
|
|
_updateWindowMetrics(
|
|
1.0, // DPR
|
|
800.0, // width
|
|
600.0, // height
|
|
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
|
|
);
|
|
|
|
expectEquals(window.viewInsets.bottom, 400.0);
|
|
expectEquals(window.viewPadding.bottom, 40.0);
|
|
expectEquals(window.padding.bottom, 0.0);
|
|
expectEquals(window.systemGestureInsets.bottom, 44.0);
|
|
});
|
|
}
|