Skip to content

Commit

Permalink
Merge branch 'master' into fix/pageController_get_value_error
Browse files Browse the repository at this point in the history
* master: (23 commits)
  Roll pub packages (flutter#150810)
  Remove reference to `MaterialApp` and `showCupertinoModalPopup` from `CupertinoAlertDialog` (flutter#150725)
  Read `AndroidManifest.xml` and emit `manifest-impeller-(enabled|disabled)` analytics (flutter#150791)
  [flutter_tools] Shut down Chromium cleanly using a command sent through the debug protocol (flutter#150645)
  Reland fix inputDecorator hint color on M3 (flutter#150278)
  Roll Flutter Engine from 62e0b5f9c340 to 94023d711db3 (7 revisions) (flutter#150797)
  Fix collapsed InputDecorator minimum height (flutter#150770)
  Add more warm up frame docs (flutter#150464)
  Roll pub packages (flutter#150739)
  Add `focusNode`, `focusColor`, `onFocusChange`, `autofocus` to `CupertinoButton` (flutter#150721)
  Document RenderObject._relayoutBoundary and its invariant; small refactors (flutter#150527)
  Roll Flutter Engine from 6313b1e5afd7 to 62e0b5f9c340 (1 revision) (flutter#150790)
  fix a typo (flutter#150682)
  Fix link in RenderObjectWidget doc comment (flutter#150600)
  Roll Flutter Engine from fbd92055f3a6 to 6313b1e5afd7 (1 revision) (flutter#150781)
  [tool] make `ErrorHandlingFileSystem.deleteIfExists` catch error code 3 (`ERROR_PATH_NOT_FOUND` on Windows) (flutter#150741)
  Roll Packages from 711b4ac2794e to 03f5f6d5660c (21 revisions) (flutter#150779)
  Roll Flutter Engine from afa7ce19bca8 to fbd92055f3a6 (1 revision) (flutter#150777)
  Reland Add tests for form_text_field.1.dart (flutter#150481) (flutter#150696) (flutter#150750)
  Add an example for CupertinoPopupSurface (flutter#150357)
  ...
  • Loading branch information
hello-coder-xu committed Jun 26, 2024
2 parents 993c6bd + 1a445b9 commit 5a85c2d
Show file tree
Hide file tree
Showing 34 changed files with 1,276 additions and 304 deletions.
2 changes: 1 addition & 1 deletion bin/internal/engine.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
be7db94196fee940e319363f7ed0c486a780ae50
94023d711db3f950a235fd84a80a3dde4dd86338
2 changes: 1 addition & 1 deletion bin/internal/flutter_packages.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
711b4ac2794e299e8d8926a269f672b1eba56640
03f5f6d5660cf1dd77586d207845971ce2bebb93
2 changes: 1 addition & 1 deletion bin/internal/fuchsia-linux.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
iU-B6rJxy0wUYSmmp1O7ykcFNnD26n1wW_i9UZ8fT4kC
WUN7NQK04NjF9fRmfM16ILdIhytQAHB7O1631G4HsIEC
1 change: 0 additions & 1 deletion dev/bots/check_code_samples.dart
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,6 @@ final Set<String> _knownMissingTests = <String>{
'examples/api/test/material/flexible_space_bar/flexible_space_bar.0_test.dart',
'examples/api/test/material/chip/deletable_chip_attributes.on_deleted.0_test.dart',
'examples/api/test/material/expansion_panel/expansion_panel_list.expansion_panel_list_radio.0_test.dart',
'examples/api/test/material/text_form_field/text_form_field.1_test.dart',
'examples/api/test/material/scrollbar/scrollbar.1_test.dart',
'examples/api/test/material/search_anchor/search_anchor.0_test.dart',
'examples/api/test/material/search_anchor/search_anchor.1_test.dart',
Expand Down
4 changes: 2 additions & 2 deletions dev/tools/gen_defaults/lib/input_decorator_template.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ class _${blockName}DefaultsM3 extends InputDecorationTheme {
@override
TextStyle? get hintStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return TextStyle(color: Theme.of(context).disabledColor);
return TextStyle(color: ${componentColor('md.comp.filled-text-field.disabled.supporting-text')});
}
return TextStyle(color: Theme.of(context).hintColor);
return TextStyle(color: ${componentColor('md.comp.filled-text-field.supporting-text')});
});
@override
Expand Down
26 changes: 25 additions & 1 deletion docs/engine/Life-of-a-Flutter-Frame.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ Flutter does some minimal housekeeping when a frame is requested, primarily to i

Once a frame is scheduled, Flutter [waits for a vsync][vsyncWaiter] from the operating system to proceed.


## Building the frame

At the heart of Flutter's graphics workflow is the frame [pipeline][pipeline]. The pipeline is responsible for coordinating work between the UI thread, where the application code runs, and the Raster thread, where rasterization and compositing is performed. See the [threading section][engineArchThreading] of the Engine Architecture wiki for more details on threading in the engine.
Expand All @@ -41,6 +40,28 @@ Once a surface is acquired, the [LayerTree][layerTree] is rasterized to the surf

The above process is repeated until the pipeline is empty.

## Warm-up frame

Normally, the Flutter framework begins producing a frame when it receives
a vsync event from the operating system. However, this may not happen for
several milliseconds after the app starts (or after a hot reload). To make
use of the time between when the widget tree is first configured and when
the engine requests an update, the framework schedules a _warm-up frame_
using [PlatformDispatcher.scheduleWarmUpFrame][scheduleWarmUpFrame].

A warm-up frame may never actually render (as it invokes
[FlutterView.render][flutterViewRender] outside of the scope of
[PlatformDispatcher.onBeginFrame][onBeginFrame] or
[PlatformDispatcher.onDrawFrame][onDrawFrame]), but it will cause the framework
to go through the steps of building, laying out, and painting, which can
together take several milliseconds. Thus, when the engine requests a real frame,
much of the work will already have been completed, and the framework can
generate the frame with minimal additional effort.

At startup, a warm-up frame can be produced before the Flutter engine has reported the
initial view metrics using [PlatformDispatcher.onMetricsChanged][onMetricsChanged].
As a result, the first frame can be produced with a size of zero.

## Cleaning up frame resources

TODO(cbracken): write this up using [this patch](https://github.com/flutter/engine/pull/38038) as a reminder.
Expand All @@ -53,10 +74,13 @@ TODO(cbracken): write this up using [this patch](https://github.com/flutter/engi
[handleBeginFrame]: https://api.flutter.dev/flutter/scheduler/SchedulerBinding/handleBeginFrame.html
[layerTree]: https://github.com/flutter/engine/blob/main/flow/layers/layer_tree.h
[onBeginFrame]: https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/onBeginFrame.html
[onDrawFrame]: https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/onDrawFrame.html
[onMetricsChanged]: https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/onMetricsChanged.html
[pipeline]: https://github.com/flutter/engine/blob/main/shell/common/pipeline.h
[rasterizer]: https://github.com/flutter/engine/blob/main/shell/common/rasterizer.h
[renderingPipelineTalk]: https://www.youtube.com/watch?v=UUfXWzp0-DU
[scene]: https://api.flutter.dev/flutter/dart-ui/Scene-class.html
[scheduleWarmUpFrame]: https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/scheduleWarmUpFrame.html
[surface]: https://github.com/flutter/engine/blob/main/flow/surface.h
[scheduleFrame]: https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/scheduleFrame.html
[vsyncWaiter]: https://github.com/flutter/engine/blob/main/shell/common/vsync_waiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ class AlertDialogApp extends StatelessWidget {
class AlertDialogExample extends StatelessWidget {
const AlertDialogExample({super.key});

// This shows a CupertinoModalPopup which hosts a CupertinoAlertDialog.
void _showAlertDialog(BuildContext context) {
showCupertinoModalPopup<void>(
showCupertinoDialog<void>(
context: context,
builder: (BuildContext context) => CupertinoAlertDialog(
title: const Text('Alert'),
Expand Down
105 changes: 105 additions & 0 deletions examples/api/lib/cupertino/dialog/cupertino_popup_surface.0.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// 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 'package:flutter/cupertino.dart';

/// Flutter code sample for [CupertinoPopupSurface].
void main() => runApp(const PopupSurfaceApp());

class PopupSurfaceApp extends StatelessWidget {
const PopupSurfaceApp({super.key});

@override
Widget build(BuildContext context) {
return const CupertinoApp(
home: PopupSurfaceExample(),
);
}
}

class PopupSurfaceExample extends StatefulWidget {
const PopupSurfaceExample({super.key});

@override
State<PopupSurfaceExample> createState() => _PopupSurfaceExampleState();
}

class _PopupSurfaceExampleState extends State<PopupSurfaceExample> {
bool _shouldPaintSurface = true;

@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
const Text('Paint surface'),
const SizedBox(width: 16.0),
CupertinoSwitch(
value: _shouldPaintSurface,
onChanged: (bool value) => setState(() => _shouldPaintSurface = value),
),
],
),
CupertinoButton(
onPressed: () => _showPopupSurface(context),
child: const Text('Show popup'),
),
],
),
),
);
}

void _showPopupSurface(BuildContext context) {
showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) {
return CupertinoPopupSurface(
isSurfacePainted: _shouldPaintSurface,
child: Container(
height: 240,
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Expanded(
child: Container(
alignment: Alignment.center,
decoration: _shouldPaintSurface
? null
: BoxDecoration(
color: CupertinoTheme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(8.0),
),
child: const Text('This is a popup surface.'),
),
),
const SizedBox(height: 8.0),
SizedBox(
width: double.infinity,
child: CupertinoButton(
color: _shouldPaintSurface
? null
: CupertinoTheme.of(context).scaffoldBackgroundColor,
onPressed: () => Navigator.pop(context),
child: const Text(
'Close',
style: TextStyle(color: CupertinoColors.systemBlue),
),
),
),
],
),
),
);
},
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// 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 'package:flutter/cupertino.dart';
import 'package:flutter_api_samples/cupertino/dialog/cupertino_popup_surface.0.dart'
as example;
import 'package:flutter_test/flutter_test.dart';

void main() {
testWidgets('CupertinoPopupSurface displays expected widgets in init state',
(WidgetTester tester) async {
await tester.pumpWidget(const example.PopupSurfaceApp());

final Finder cupertinoButton = find.byType(CupertinoButton);
expect(cupertinoButton, findsOneWidget);

final Finder cupertinoSwitch = find.byType(CupertinoSwitch);
expect(cupertinoSwitch, findsOneWidget);
});

testWidgets('CupertinoPopupSurface is displayed with painted surface',
(WidgetTester tester) async {
await tester.pumpWidget(const example.PopupSurfaceApp());

// CupertinoSwitch is toggled on by default.
expect(tester.widget<CupertinoSwitch>(find.byType(CupertinoSwitch)).value, isTrue);

// Tap on the CupertinoButton to show the CupertinoPopupSurface.
await tester.tap(find.byType(CupertinoButton));
await tester.pumpAndSettle();

// Make sure CupertinoPopupSurface is showing.
final Finder cupertinoPopupSurface = find.byType(CupertinoPopupSurface);
expect(cupertinoPopupSurface, findsOneWidget);

// Confirm that CupertinoPopupSurface is painted with a ColoredBox.
final Finder coloredBox = find.descendant(
of: cupertinoPopupSurface,
matching: find.byType(ColoredBox),
);
expect(coloredBox, findsOneWidget);
});

testWidgets('CupertinoPopupSurface is displayed without painted surface',
(WidgetTester tester) async {
await tester.pumpWidget(const example.PopupSurfaceApp());

// Toggling off CupertinoSwitch and confirm its state.
final Finder cupertinoSwitch = find.byType(CupertinoSwitch);
await tester.tap(cupertinoSwitch);
await tester.pumpAndSettle();
expect(tester.widget<CupertinoSwitch>(cupertinoSwitch).value, isFalse);

// Tap on the CupertinoButton to show the CupertinoPopupSurface.
await tester.tap(find.byType(CupertinoButton));
await tester.pumpAndSettle();

// Make sure CupertinoPopupSurface is showing.
final Finder cupertinoPopupSurface = find.byType(CupertinoPopupSurface);
expect(cupertinoPopupSurface, findsOneWidget);

// Confirm that CupertinoPopupSurface is not painted with a ColoredBox.
final Finder coloredBox = find.descendant(
of: cupertinoPopupSurface,
matching: find.byType(ColoredBox),
);
expect(coloredBox, findsNothing);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// 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 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_api_samples/material/text_form_field/text_form_field.1.dart' as example;
import 'package:flutter_test/flutter_test.dart';

void main() {
testWidgets('Pressing space should focus the next field', (WidgetTester tester) async {
await tester.pumpWidget(const example.TextFormFieldExampleApp());
final Finder textFormField = find.byType(TextFormField);

expect(textFormField, findsExactly(5));

final Finder editableText = find.byType(EditableText);
expect(editableText, findsExactly(5));

List<bool> getFocuses() {
return editableText.evaluate()
.map((Element finderResult) => (finderResult.widget as EditableText).focusNode.hasFocus)
.toList();
}

expect(getFocuses(), const <bool>[false, false, false, false, false]);

await tester.tap(textFormField.first);
await tester.pump();

expect(getFocuses(), const <bool>[true, false, false, false, false]);

await tester.sendKeyEvent(LogicalKeyboardKey.space);
await tester.pump();

expect(getFocuses(), const <bool>[false, true, false, false, false]);

await tester.sendKeyEvent(LogicalKeyboardKey.space);
await tester.pump();

expect(getFocuses(), const <bool>[false, false, true, false, false]);

await tester.sendKeyEvent(LogicalKeyboardKey.space);
await tester.pump();

expect(getFocuses(), const <bool>[false, false, false, true, false]);

await tester.sendKeyEvent(LogicalKeyboardKey.space);
await tester.pump();

expect(getFocuses(), const <bool>[false, false, false, false, true]);

await tester.sendKeyEvent(LogicalKeyboardKey.space);
await tester.pump();

expect(getFocuses(), const <bool>[true, false, false, false, false]);
});
}
Loading

0 comments on commit 5a85c2d

Please sign in to comment.