flutter/dev/integration_tests/windows_startup_test/lib/main.dart
Michael Goderbauer 5491c8c146
Auto-format Framework (#160545)
This auto-formats all *.dart files in the repository outside of the
`engine` subdirectory and enforces that these files stay formatted with
a presubmit check.

**Reviewers:** Please carefully review all the commits except for the
one titled "formatted". The "formatted" commit was auto-generated by
running `dev/tools/format.sh -a -f`. The other commits were hand-crafted
to prepare the repo for the formatting change. I recommend reviewing the
commits one-by-one via the "Commits" tab and avoiding Github's "Files
changed" tab as it will likely slow down your browser because of the
size of this PR.

---------

Co-authored-by: Kate Lovett <katelovett@google.com>
Co-authored-by: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com>
2024-12-19 20:06:21 +00:00

130 lines
4.8 KiB
Dart

// Copyright 2014 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.
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter_driver/driver_extension.dart';
import 'windows.dart';
void drawHelloWorld(ui.FlutterView view) {
final ui.ParagraphStyle style = ui.ParagraphStyle();
final ui.ParagraphBuilder paragraphBuilder = ui.ParagraphBuilder(style)..addText('Hello world');
final ui.Paragraph paragraph = paragraphBuilder.build();
paragraph.layout(const ui.ParagraphConstraints(width: 100.0));
final ui.PictureRecorder recorder = ui.PictureRecorder();
final ui.Canvas canvas = ui.Canvas(recorder);
canvas.drawParagraph(paragraph, ui.Offset.zero);
final ui.Picture picture = recorder.endRecording();
final ui.SceneBuilder sceneBuilder =
ui.SceneBuilder()
..addPicture(ui.Offset.zero, picture)
..pop();
view.render(sceneBuilder.build());
}
Future<void> _waitUntilWindowVisible() async {
while (!await isWindowVisible()) {
await Future<void>.delayed(const Duration(milliseconds: 100));
}
}
void _expectVisible(bool current, bool expect, Completer<String> completer, int frameCount) {
if (current != expect) {
try {
throw 'Window should be ${expect ? 'visible' : 'hidden'} on frame $frameCount';
} catch (e) {
if (!completer.isCompleted) {
completer.completeError(e);
}
rethrow;
}
}
}
void main() async {
// TODO(goderbauer): Create a window if embedder doesn't provide an implicit view to draw into.
assert(ui.PlatformDispatcher.instance.implicitView != null);
final ui.FlutterView view = ui.PlatformDispatcher.instance.implicitView!;
// Create a completer to send the window visibility result back to the
// integration test.
final Completer<String> visibilityCompleter = Completer<String>();
enableFlutterDriverExtension(
handler: (String? message) async {
if (message == 'verifyWindowVisibility') {
return visibilityCompleter.future;
} else if (message == 'verifyTheme') {
final bool app = await isAppDarkModeEnabled();
final bool system = await isSystemDarkModeEnabled();
return (app == system)
? 'success'
: 'error: app dark mode ($app) does not match system dark mode ($system)';
} else if (message == 'verifyStringConversion') {
// Use a test string that contains code points that fit in both 8 and 16 bits.
// The code points are passed a list of integers through the method channel,
// which will use the UTF16 to UTF8 utility function to convert them to a
// std::string, which should equate to the original expected string.
const String expected = 'ABCℵ';
final Int32List codePoints = Int32List.fromList(expected.codeUnits);
final String converted = await testStringConversion(codePoints);
return (converted == expected)
? 'success'
: 'error: conversion of UTF16 string to UTF8 failed, expected "${expected.codeUnits}" but got "${converted.codeUnits}"';
}
throw 'Unrecognized message: $message';
},
);
try {
if (await isWindowVisible()) {
throw 'Window should be hidden at startup';
}
int frameCount = 0;
ui.PlatformDispatcher.instance.onBeginFrame = (Duration duration) {
// Our goal is to verify that it's `drawHelloWorld` that makes the window
// appear, not anything else. This requires checking the visibility right
// before drawing, but since `isWindowVisible` has to be async, and
// `FlutterView.render` (in `drawHelloWorld`) forbids async before it,
// this can not be done during a single onBeginFrame. However, we can
// verify in separate frames to indirectly prove it, by ensuring that
// no other mechanism can affect isWindowVisible in the first frame at all.
frameCount += 1;
switch (frameCount) {
// The 1st frame: render nothing, just verify that the window is hidden.
case 1:
isWindowVisible().then((bool visible) {
_expectVisible(visible, false, visibilityCompleter, frameCount);
ui.PlatformDispatcher.instance.scheduleFrame();
});
// The 2nd frame: render, which makes the window appear.
case 2:
drawHelloWorld(view);
_waitUntilWindowVisible().then((_) {
if (!visibilityCompleter.isCompleted) {
visibilityCompleter.complete('success');
}
});
// Others, in case requested to render.
default:
drawHelloWorld(view);
}
};
} catch (e) {
visibilityCompleter.completeError(e);
rethrow;
}
ui.PlatformDispatcher.instance.scheduleFrame();
}