Unverified Commit cb9a3f69 authored by Todd Volkert's avatar Todd Volkert Committed by GitHub

Add timeline events for post frame callbacks (#136435)

Before this change, long-running post-frame callbacks wouldn't show up in the timeline at all.  This adds a timeline event for post-frame callbacks, with a debug flag that will add timeline events for each individual callback.

#testexempt -- we have no way to test calls to the timeline.
parent 024e0da4
......@@ -585,7 +585,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
_lastOverlayEntry?.dispose();
_lastOverlayEntry = null;
_openController.reset();
});
}, debugLabel: 'removeContextMenuDecoy');
case AnimationStatus.forward:
case AnimationStatus.reverse:
......@@ -1009,7 +1009,7 @@ class _ContextMenuRoute<T> extends PopupRoute<T> {
_updateTweenRects();
_internalOffstage = false;
_setOffstageInternally();
});
}, debugLabel: 'renderContextMenuRouteOffstage');
return super.didPush();
}
......
......@@ -1007,7 +1007,7 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {
final int position = minCheck ? positionDouble.ceil() : positionDouble.floor();
_animateColumnControllerToItem(minuteController, position);
}
});
}, debugLabel: 'DatePicker.scrollToDate');
}
@override
......@@ -1401,7 +1401,7 @@ class _CupertinoDatePickerDateState extends State<CupertinoDatePicker> {
if (selectedDay != newDate.day) {
_animateColumnControllerToItem(dayController, newDate.day - 1);
}
});
}, debugLabel: 'DatePicker.scrollToDate');
}
@override
......@@ -1725,7 +1725,7 @@ class _CupertinoDatePickerMonthYearState extends State<CupertinoDatePicker> {
if (selectedMonth != newDate.month) {
_animateColumnControllerToItem(monthController, newDate.month - 1);
}
});
}, debugLabel: 'DatePicker.scrollToDate');
}
@override
......
......@@ -461,7 +461,7 @@ class _CupertinoSliverRefreshControlState extends State<CupertinoSliverRefreshCo
} else {
SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
setState(() => hasSliverLayoutExtent = false);
});
}, debugLabel: 'Refresh.goToDone');
}
}
......@@ -497,7 +497,7 @@ class _CupertinoSliverRefreshControlState extends State<CupertinoSliverRefreshCo
}
});
setState(() => hasSliverLayoutExtent = true);
});
}, debugLabel: 'Refresh.transition');
}
return RefreshIndicatorMode.armed;
}
......
......@@ -130,7 +130,7 @@ class CupertinoSpellCheckSuggestionsToolbar extends StatelessWidget {
if (editableTextState.mounted) {
editableTextState.bringIntoView(editableTextState.textEditingValue.selection.extent);
}
});
}, debugLabel: 'SpellCheckSuggestions.bringIntoView');
editableTextState.hideToolbar();
}
......
......@@ -175,7 +175,7 @@ class _Resampler {
_timer = Timer.periodic(_samplingInterval, (_) => _onSampleTimeChanged());
// Trigger an immediate sample time change.
_onSampleTimeChanged();
});
}, debugLabel: 'Resampler.startTimer');
}
}
......
......@@ -201,7 +201,7 @@ class _AutocompleteOptions<T extends Object> extends StatelessWidget {
if (highlight) {
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
Scrollable.ensureVisible(context, alignment: 0.5);
});
}, debugLabel: 'AutocompleteOptions.ensureVisible');
}
return Container(
color: highlight ? Theme.of(context).focusColor : null,
......
......@@ -423,7 +423,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
setState(() {
leadingPadding = getWidth(_leadingKey);
});
});
}, debugLabel: 'DropdownMenu.refreshLeadingPadding');
}
void scrollToHighlight() {
......@@ -432,7 +432,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
if (highlightContext != null) {
Scrollable.ensureVisible(highlightContext);
}
});
}, debugLabel: 'DropdownMenu.scrollToHighlight');
}
double? getWidth(GlobalKey key) {
......
......@@ -174,7 +174,7 @@ class _InputDatePickerFormFieldState extends State<InputDatePickerFormField> {
_selectedDate = widget.initialDate;
_updateValueForSelectedDate();
});
});
}, debugLabel: 'InputDatePickerFormField.update');
}
}
......
......@@ -583,7 +583,7 @@ _MenuAnchorState? get _previousFocusableSibling {
} else if (!inDispose) {
SchedulerBinding.instance.addPostFrameCallback((_) {
_overlayController.hide();
});
}, debugLabel: 'MenuAnchor.hide');
}
if (!inDispose) {
// Notify that _childIsOpen changed state, but only if not
......@@ -1150,7 +1150,7 @@ class _MenuItemButtonState extends State<MenuItemButton> {
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
FocusManager.instance.applyFocusChangesIfNeeded();
widget.onPressed?.call();
});
}, debugLabel: 'MenuAnchor.onPressed');
}
void _createInternalFocusNodeIfNeeded() {
......@@ -1902,7 +1902,7 @@ class _SubmenuButtonState extends State<SubmenuButton> {
SchedulerBinding.instance.addPostFrameCallback((_) {
_menuController._anchor?._focusButton();
_waitingToFocusMenu = false;
});
}, debugLabel: 'MenuAnchor.focus');
_waitingToFocusMenu = true;
}
setState(() { /* Rebuild with updated controller.isOpen value */ });
......
......@@ -142,7 +142,7 @@ class SpellCheckSuggestionsToolbar extends StatelessWidget {
if (editableTextState.mounted) {
editableTextState.bringIntoView(editableTextState.textEditingValue.selection.extent);
}
});
}, debugLabel: 'SpellCheckerSuggestionsToolbar.bringIntoView');
editableTextState.hideToolbar();
}
......
......@@ -1507,7 +1507,7 @@ class _TabBarState extends State<TabBar> {
}
return true;
}());
});
}, debugLabel: 'TabBar.tabsCountCheck');
_debugHasScheduledValidTabsCountCheck = true;
return true;
}
......@@ -2024,7 +2024,7 @@ class _TabBarViewState extends State<TabBarView> {
}
return true;
}());
});
}, debugLabel: 'TabBarView.validChildrenCountCheck');
_debugHasScheduledValidChildrenCountCheck = true;
return true;
}
......
......@@ -655,7 +655,7 @@ void paintImage({
},
);
_pendingImageSizeInfo = <String, ImageSizeInfo>{};
});
}, debugLabel: 'paintImage.recordImageSizes');
}
}
......
......@@ -621,7 +621,7 @@ abstract class _CachedImageBase {
assert(handle != null);
handle?.dispose();
handle = null;
});
}, debugLabel: 'CachedImage.disposeHandle');
}
}
......
......@@ -46,7 +46,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
addPersistentFrameCallback(_handlePersistentFrameCallback);
initMouseTracker();
if (kIsWeb) {
addPostFrameCallback(_handleWebFirstFrame);
addPostFrameCallback(_handleWebFirstFrame, debugLabel: 'RendererBinding.webFirstFrame');
}
rootPipelineOwner.attach(_manifold);
}
......@@ -463,7 +463,7 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture
return true;
}());
_mouseTracker!.updateAllDevices();
});
}, debugLabel: 'RendererBinding.mouseTrackerUpdate');
}
int _firstFrameDeferredCount = 0;
......
......@@ -2337,7 +2337,7 @@ class LayerLink {
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
_debugLeaderCheckScheduled = false;
assert(_debugPreviousLeaders!.isEmpty);
});
}, debugLabel: 'LayerLink.leadersCleanUpCheck');
return true;
}());
}
......
......@@ -202,7 +202,7 @@ class RenderAndroidView extends PlatformViewRenderBox {
// Schedule a new post frame callback.
_setOffset();
}
});
}, debugLabel: 'RenderAndroidView.setOffset');
}
@override
......
......@@ -765,6 +765,13 @@ mixin SchedulerBinding on BindingBase {
///
/// Post-frame callbacks cannot be unregistered. They are called exactly once.
///
/// In debug mode, if [debugTracePostFrameCallbacks] is set to true, then the
/// registered callback will show up in the timeline events chart, which can
/// be viewed in [DevTools](https://docs.flutter.dev/tools/devtools/overview).
/// In that case, the `debugLabel` argument specifies the name of the callback
/// as it will appear in the timeline. In profile and release builds,
/// post-frame are never traced, and the `debugLabel` argument is ignored.
///
/// See also:
///
/// * [scheduleFrameCallback], which registers a callback for the start of
......@@ -772,7 +779,21 @@ mixin SchedulerBinding on BindingBase {
/// * [WidgetsBinding.drawFrame], which explains the phases of each frame
/// for those apps that use Flutter widgets (and where post frame
/// callbacks fit into those phases).
void addPostFrameCallback(FrameCallback callback) {
void addPostFrameCallback(FrameCallback callback, {String debugLabel = 'callback'}) {
assert(() {
if (debugTracePostFrameCallbacks) {
final FrameCallback originalCallback = callback;
callback = (Duration timeStamp) {
Timeline.startSync(debugLabel);
try {
originalCallback(timeStamp);
} finally {
Timeline.finishSync();
}
};
}
return true;
}());
_postFrameCallbacks.add(callback);
}
......@@ -796,7 +817,7 @@ mixin SchedulerBinding on BindingBase {
addPostFrameCallback((Duration timeStamp) {
_nextFrameCompleter!.complete();
_nextFrameCompleter = null;
});
}, debugLabel: 'SchedulerBinding.completeFrame');
}
return _nextFrameCompleter!.future;
}
......@@ -1127,7 +1148,7 @@ mixin SchedulerBinding on BindingBase {
// still be true here and cause us to skip scheduling an engine frame.
_hasScheduledFrame = false;
scheduleFrame();
});
}, debugLabel: 'SchedulerBinding.scheduleFrame');
return;
}
handleDrawFrame();
......@@ -1280,8 +1301,13 @@ mixin SchedulerBinding on BindingBase {
final List<FrameCallback> localPostFrameCallbacks =
List<FrameCallback>.of(_postFrameCallbacks);
_postFrameCallbacks.clear();
for (final FrameCallback callback in localPostFrameCallbacks) {
_invokeFrameCallback(callback, _currentFrameTimeStamp!);
Timeline.startSync('POST_FRAME');
try {
for (final FrameCallback callback in localPostFrameCallbacks) {
_invokeFrameCallback(callback, _currentFrameTimeStamp!);
}
} finally {
Timeline.finishSync();
}
} finally {
_schedulerPhase = SchedulerPhase.idle;
......
......@@ -48,6 +48,20 @@ bool debugPrintEndFrameBanner = false;
/// [debugPrintScheduleBuildForStacks].
bool debugPrintScheduleFrameStacks = false;
/// Record timeline trace events for post-frame callbacks.
///
/// When this flag is set to false (the default), the developer timeline
/// records when post-frame callbacks are running, but it does not tell you any
/// information about how that time is spent within specific callbacks:
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/scheduler/debug_trace_post_frame_callbacks_off.png)
///
/// When this flag is set to true, timeline events will be recorded for each
/// post-frame callback that runs, like so:
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/scheduler/debug_trace_post_frame_callbacks_on.png)
bool debugTracePostFrameCallbacks = false;
/// Returns true if none of the scheduler library debug variables have been changed.
///
/// This function is used by the test framework to ensure that debug variables
......
......@@ -268,7 +268,7 @@ class RestorationManager extends ChangeNotifier {
if (_isReplacing) {
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
_isReplacing = false;
});
}, debugLabel: 'RestorationManager.resetIsReplacing');
}
final RestorationBucket? oldRoot = _rootBucket;
......@@ -349,7 +349,10 @@ class RestorationManager extends ChangeNotifier {
_bucketsNeedingSerialization.add(bucket);
if (!_serializationScheduled) {
_serializationScheduled = true;
SchedulerBinding.instance.addPostFrameCallback((Duration _) => _doSerialization());
SchedulerBinding.instance.addPostFrameCallback(
(Duration _) => _doSerialization(),
debugLabel: 'RestorationManager.doSerialization'
);
}
}
......
......@@ -1231,7 +1231,7 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
_updateHighlightMode(FocusManager.instance.highlightMode);
});
}, debugLabel: 'FocusableActionDetector.updateHighlightMode');
FocusManager.instance.addHighlightModeListener(_handleFocusHighlightModeChange);
}
......@@ -1339,7 +1339,7 @@ class _FocusableActionDetectorState extends State<FocusableActionDetector> {
if (widget.enabled != oldWidget.enabled) {
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
_mayTriggerCallback(oldWidget: oldWidget);
});
}, debugLabel: 'FocusableActionDetector.mayTriggerCallback');
}
}
......
......@@ -440,7 +440,7 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>>
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
_floatingOptionsUpdateScheduled = false;
_updateOverlay();
});
}, debugLabel: 'RawAutoComplete.updateOverlay');
}
return;
}
......
......@@ -99,7 +99,7 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
final ParentDataElement<KeepAliveParentDataMixin>? childElement = _getChildElement();
assert(childElement != null);
_updateParentDataOfChild(childElement!);
});
}, debugLabel: 'AutomaticKeepAlive.updateParentData');
}
}
return false;
......
......@@ -763,7 +763,7 @@ class _DraggableScrollableSheetState extends State<DraggableScrollableSheet> {
_scrollController.positions.elementAt(index) as _DraggableScrollableSheetScrollPosition;
position.goBallistic(0);
}
});
}, debugLabel: 'DraggableScrollableSheet.snap');
}
}
......
......@@ -2390,7 +2390,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
if (mounted) {
bringIntoView(textEditingValue.selection.extent);
}
});
}, debugLabel: 'EditableText.bringSelectionIntoView');
hideToolbar();
}
clipboardStatus.update();
......@@ -2430,7 +2430,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
if (mounted) {
bringIntoView(textEditingValue.selection.extent);
}
});
}, debugLabel: 'EditableText.bringSelectionIntoView');
hideToolbar();
}
}
......@@ -2818,7 +2818,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
_flagInternalFocus();
FocusScope.of(context).autofocus(widget.focusNode);
}
});
}, debugLabel: 'EditableText.autofocus');
}
// Restart or stop the blinking cursor when TickerMode changes.
......@@ -2889,7 +2889,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
// See https://github.com/flutter/flutter/issues/126312
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
_openInputConnection();
});
}, debugLabel: 'EditableText.openInputConnection');
}
if (kIsWeb && _hasInputConnection) {
......@@ -3721,7 +3721,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
rect: caretPadding.inflateRect(rectToReveal),
);
}
});
}, debugLabel: 'EditableText.showCaret');
}
late double _lastBottomViewInset;
......@@ -3735,7 +3735,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
if (_lastBottomViewInset != view.viewInsets.bottom) {
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
_selectionOverlay?.updateForScroll();
});
}, debugLabel: 'EditableText.updateForScroll');
if (_lastBottomViewInset < view.viewInsets.bottom) {
// Because the metrics change signal from engine will come here every frame
// (on both iOS and Android). So we don't need to show caret with animation.
......@@ -4038,7 +4038,10 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
_updateSelectionRects();
_updateComposingRectIfNeeded();
_updateCaretRectIfNeeded();
SchedulerBinding.instance.addPostFrameCallback(_schedulePeriodicPostFrameCallbacks);
SchedulerBinding.instance.addPostFrameCallback(
_schedulePeriodicPostFrameCallbacks,
debugLabel: 'EditableText.postFrameCallbacks'
);
}
_ScribbleCacheKey? _scribbleCacheKey;
......
......@@ -902,7 +902,7 @@ class HeroController extends NavigatorObserver {
return;
}
_startHeroTransition(from, to, flightType, isUserGestureTransition);
});
}, debugLabel: 'HeroController.startTransition');
}
}
......
......@@ -124,7 +124,7 @@ Future<void> precacheImage(
// See ImageCache._liveImages
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
stream.removeListener(listener!);
});
}, debugLabel: 'precacheImage.removeListener');
},
onError: (Object exception, StackTrace? stackTrace) {
if (!completer.isCompleted) {
......@@ -1164,7 +1164,10 @@ class _ImageState extends State<Image> with WidgetsBindingObserver {
void _replaceImage({required ImageInfo? info}) {
final ImageInfo? oldImageInfo = _imageInfo;
SchedulerBinding.instance.addPostFrameCallback((_) => oldImageInfo?.dispose());
SchedulerBinding.instance.addPostFrameCallback(
(_) => oldImageInfo?.dispose(),
debugLabel: 'Image.disposeOldInfo'
);
_imageInfo = info;
}
......
......@@ -3509,7 +3509,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
return;
}
notification.dispatch(context);
});
}, debugLabel: 'Navigator.dispatchNotification');
}
}
......@@ -3716,7 +3716,7 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin, Res
);
}
}
});
}, debugLabel: 'Navigator.checkHeroControllerOwnership');
}
return true;
}());
......
......@@ -1183,11 +1183,9 @@ class _NestedScrollController extends ScrollController {
// the position change notifications because those happen synchronously
// during a frame, at a time where it's too late to call setState. Since the
// result is usually animated, the lag incurred is no big deal.
SchedulerBinding.instance.addPostFrameCallback(
(Duration timeStamp) {
coordinator.updateShadow();
},
);
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
coordinator.updateShadow();
}, debugLabel: 'NestedScrollController.updateShadow');
}
Iterable<_NestedScrollPosition> get nestedPositions {
......
......@@ -177,7 +177,7 @@ class OverlayEntry implements Listenable {
if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) {
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
overlay._markDirty();
});
}, debugLabel: 'OverlayEntry.markDirty');
} else {
overlay._markDirty();
}
......
......@@ -1301,7 +1301,7 @@ class _PlatformViewPlaceholderBox extends RenderConstrainedBox {
// A call to `localToGlobal` requires waiting for a frame to render first.
SchedulerBinding.instance.addPostFrameCallback((_) {
onLayout(size, localToGlobal(Offset.zero));
});
}, debugLabel: 'PlatformViewPlaceholderBox.onLayout');
}
}
......@@ -1333,6 +1333,6 @@ extension on PlatformViewController {
void disposePostFrame() {
SchedulerBinding.instance.addPostFrameCallback((_) {
dispose();
});
}, debugLabel: 'PlatformViewController.dispose');
}
}
......@@ -753,7 +753,7 @@ class SliverReorderableListState extends State<SliverReorderableList> with Ticke
_dragStartTransitionComplete = false;
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
_dragStartTransitionComplete = true;
});
}, debugLabel: 'SliverReorderableList.completeDragStartTransition');
_insertIndex = item.index;
_dragInfo = _DragInfo(
......
......@@ -628,7 +628,10 @@ class _RouterState<T> extends State<Router<T>> with RestorationMixin {
}
assert(_currentIntentionToReport != null);
_routeInformationReportingTaskScheduled = true;
SchedulerBinding.instance.addPostFrameCallback(_reportRouteInformation);
SchedulerBinding.instance.addPostFrameCallback(
_reportRouteInformation,
debugLabel: 'Router.reportRouteInfo',
);
}
void _reportRouteInformation(Duration timestamp) {
......
......@@ -710,7 +710,7 @@ mixin LocalHistoryRoute<T> on Route<T> {
if (isActive) {
changedInternalState();
}
});
}, debugLabel: 'LocalHistoryRoute.changedInternalState');
} else {
changedInternalState();
}
......@@ -1672,7 +1672,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
return;
}
notification.dispatch(subtreeContext);
});
}, debugLabel: 'ModalRoute.dispatchNotification');
}
}
......
......@@ -468,7 +468,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
notifyListeners();
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
_impliedVelocity = 0;
});
}, debugLabel: 'ScrollPosition.resetVelocity');
}
/// Called whenever scrolling ends, to store the current scroll offset in a
......
......@@ -1167,7 +1167,7 @@ class _ScrollableSelectionContainerDelegate extends MultiSelectableSelectionCont
}
_scheduledLayoutChange = false;
layoutDidChange();
});
}, debugLabel: 'ScrollableSelectionContainer.layoutDidChange');
}
/// Stores the scroll offset when a scrollable receives the last
......
......@@ -1413,7 +1413,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
}
WidgetsBinding.instance.addPostFrameCallback((Duration duration) {
assert(_debugCheckHasValidScrollPosition());
});
}, debugLabel: 'RawScrollbar.checkScrollPosition');
return true;
}
......
......@@ -677,7 +677,7 @@ class SelectableRegionState extends State<SelectableRegion> with TextSelectionDe
}
_scheduledSelectionEndEdgeUpdate = false;
_triggerSelectionEndEdgeUpdate(textGranularity: textGranularity);
});
}, debugLabel: 'SelectableRegion.endEdgeUpdate');
return;
}
}
......@@ -731,7 +731,7 @@ class SelectableRegionState extends State<SelectableRegion> with TextSelectionDe
}
_scheduledSelectionStartEdgeUpdate = false;
_triggerSelectionStartEdgeUpdate(textGranularity: textGranularity);
});
}, debugLabel: 'SelectableRegion.startEdgeUpdate');
return;
}
}
......@@ -1716,7 +1716,10 @@ abstract class MultiSelectableSelectionContainerDelegate extends SelectionContai
// safely updated in the same frame in this case.
scheduleMicrotask(runScheduledTask);
} else {
SchedulerBinding.instance.addPostFrameCallback(runScheduledTask);
SchedulerBinding.instance.addPostFrameCallback(
runScheduledTask,
debugLabel: 'SelectionContainer.runScheduledTask',
);
}
}
}
......
......@@ -94,7 +94,7 @@ class _SemanticsDebuggerState extends State<SemanticsDebugger> with WidgetsBindi
// The generation of the _SemanticsDebuggerListener has changed.
});
}
});
}, debugLabel: 'SemanticsDebugger.update');
}
Offset? _lastPointerDownLocation;
......
......@@ -1276,7 +1276,7 @@ class ShortcutRegistry with ChangeNotifier {
if (!_disposed) {
notifyListeners();
}
});
}, debugLabel: 'ShortcutRegistry.notifyListeners');
_notificationScheduled = true;
}
}
......
......@@ -1454,7 +1454,7 @@ class SelectionOverlay {
} else if (_spellCheckToolbarController.isShown) {
_spellCheckToolbarController.markNeedsBuild();
}
});
}, debugLabel: 'SelectionOverlay.markNeedsBuild');
} else {
if (_handles != null) {
_handles!.start.markNeedsBuild();
......
......@@ -2371,7 +2371,7 @@ mixin WidgetInspectorService {
void _onFrameStart(Duration timeStamp) {
_frameStart = timeStamp;
SchedulerBinding.instance.addPostFrameCallback(_onFrameEnd);
SchedulerBinding.instance.addPostFrameCallback(_onFrameEnd, debugLabel: 'WidgetInspector.onFrameStart');
}
void _onFrameEnd(Duration timeStamp) {
......
......@@ -33,7 +33,7 @@ class TestResampleEventFlutterBinding extends BindingBase with GestureBinding, S
}
@override
int addPostFrameCallback(FrameCallback callback) {
int addPostFrameCallback(FrameCallback callback, {String debugLabel = 'callback'}) {
postFrameCallback = callback;
return 0;
}
......
......@@ -70,7 +70,7 @@ class TestMouseTrackerFlutterBinding extends BindingBase
// Proxy post-frame callbacks.
@override
void addPostFrameCallback(void Function(Duration) callback) {
void addPostFrameCallback(void Function(Duration) callback, {String debugLabel = 'callback'}) {
postFrameCallbacks.add(callback);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment