Skip to content

Commit

Permalink
Schedule new frame in markNeedsPaint
Browse files Browse the repository at this point in the history
  • Loading branch information
angelosilvestre committed Oct 12, 2023
1 parent c28dd5f commit ceafa68
Showing 1 changed file with 26 additions and 27 deletions.
53 changes: 26 additions & 27 deletions lib/src/follower.dart
Original file line number Diff line number Diff line change
Expand Up @@ -305,15 +305,28 @@ class RenderFollower extends RenderProxyBox {
void attach(PipelineOwner owner) {
super.attach(owner);

_link.addFollowerLayerTransformChangeListener(_followerLayerTransformChanged);
// We repaint whenever the `FollowerLayer` changes its transform. This is why.
//
// We had a bug where the initial layout of an iOS toolbar wasn't positioning
// its arrow in the expected place. It was found that the `FollowerLayer` was
// running `_establishTransform()` after this `RenderFollower` was done with
// layout and paint. The `FollowerLayer` wasn't settling on its final transform
// until after this `RenderFollower` was done doing all of its work, which meant
// that content within a `Follower` never got a chance to react to the final
// `Follower` offset, leading to the wrong arrow position.
//
// By running another paint pass whenever the `FollowerLayer` changes its
// transform, `Follower`s like the iOS toolbar can correctly position its
// content at least within 1 frame of the desired moment.
_link.addFollowerLayerTransformChangeListener(markNeedsPaint);
if (repaintWhenLeaderChanges) {
_link.addListener(_onLinkChange);
}
}

@override
void detach() {
_link.removeFollowerLayerTransformChangeListener(_followerLayerTransformChanged);
_link.removeFollowerLayerTransformChangeListener(markNeedsPaint);
if (repaintWhenLeaderChanges) {
_link.removeListener(_onLinkChange);
}
Expand All @@ -334,14 +347,14 @@ class RenderFollower extends RenderProxyBox {

FtlLogs.follower.fine("Setting new link - $value");

_link.removeFollowerLayerTransformChangeListener(_followerLayerTransformChanged);
_link.removeFollowerLayerTransformChangeListener(markNeedsPaint);
if (repaintWhenLeaderChanges) {
_link.removeListener(_onLinkChange);
}

_link = value;

_link.addFollowerLayerTransformChangeListener(_followerLayerTransformChanged);
_link.addFollowerLayerTransformChangeListener(markNeedsPaint);
if (repaintWhenLeaderChanges) {
_link.addListener(_onLinkChange);
}
Expand Down Expand Up @@ -574,6 +587,15 @@ class RenderFollower extends RenderProxyBox {
}
}

@override
void markNeedsPaint() {
super.markNeedsPaint();

// Immediately schedule a new frame to avoid being in a dirty in the cases
// where markNeedsPaint and there are no other frames scheduled.
WidgetsBinding.instance.scheduleFrame();
}

void _paintDebugVisuals(PaintingContext context) {
if (!showDebugPaint) {
return;
Expand Down Expand Up @@ -749,29 +771,6 @@ class RenderFollower extends RenderProxyBox {
properties.add(DiagnosticsProperty<bool>('showWhenUnlinked', showWhenUnlinked));
properties.add(TransformProperty('current transform matrix', _getCurrentTransform()));
}

void _followerLayerTransformChanged() {
// We repaint whenever the `FollowerLayer` changes its transform. This is why.
//
// We had a bug where the initial layout of an iOS toolbar wasn't positioning
// its arrow in the expected place. It was found that the `FollowerLayer` was
// running `_establishTransform()` after this `RenderFollower` was done with
// layout and paint. The `FollowerLayer` wasn't settling on its final transform
// until after this `RenderFollower` was done doing all of its work, which meant
// that content within a `Follower` never got a chance to react to the final
// `Follower` offset, leading to the wrong arrow position.
//
// By running another paint pass whenever the `FollowerLayer` changes its
// transform, `Follower`s like the iOS toolbar can correctly position its
// content at least within 1 frame of the desired moment.
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
if (!attached) {
return;
}

markNeedsPaint();
});
}
}

/// A composited layer that applies a transformation matrix to its children such
Expand Down

0 comments on commit ceafa68

Please sign in to comment.