Skip to content

Fix invalidation during removing the layer#3146

Open
Ivan Matkov (MatkovIvan) wants to merge 3 commits into
jb-mainfrom
ivan.matkov/fix-dialog-hide
Open

Fix invalidation during removing the layer#3146
Ivan Matkov (MatkovIvan) wants to merge 3 commits into
jb-mainfrom
ivan.matkov/fix-dialog-hide

Conversation

@MatkovIvan

Copy link
Copy Markdown
Collaborator

CMP-10360 Dialog hide animation hangs on the last frame

Regression after #3096, not released yet

Release Notes

N/A

invokeInvalidationCallbacks()
// Removing a layer changes the scene's composited output (e.g. it removes a dialog scrim)
// without dirtying any remaining owner, so force a draw pass to repaint without it.
invokeInvalidationCallbacks(forceDraw = true)

@igordmn Igor Demin (igordmn) Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses knowledge of the Dialog implementation details.

There are also questions arise - why not layout, why not on attach too.

Also, we violate the contract of hasPendingDraw — it should be true when there is a draw pending.

I believe that instead of forcing the redraw, we should add the hiding scrim into the invalidation. Where is it located?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses knowledge of the Dialog implementation details.

It doesn't. The dialog scrim is just one example — this affects graphics of any kind graphics by any layer. CanvasLayersComposeScene composites every layer onto its own single canvas, so removing any layer changes what the scene paints, regardless of what that layer happened to draw.

why not layout

Because there's nothing to recompute on detach — neither in Compose terms (no node needs re-measure/relayout) nor in platform-view terms. Only the composited output changes, so only a draw pass is needed.

why not on attach too

Because a layer is added to the layers list already in an invalidated state, so the regular invokeInvalidationCallbacks() already covers attach. On detach the layer is gone from the list and no remaining owner is dirty.

Also, we violate the contract of hasPendingDraw — it should be true when there is a draw pending.

Agreed.

I believe that instead of forcing the redraw, we should add the hiding scrim into the invalidation. Where is it located?

The scrim lives inside the dismissed layer and invalidating there doesn't work - it's already removed from the list and also we shouldn't rely on use-after-close pattern. The invalidation has to happen in the scene implementation: CanvasLayersComposeScene mixes multiple levels onto one surface, so it's the thing responsible for reporting its layers' invalidations and its combination as its own.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, we violate the contract of hasPendingDraw - it should be true when there is a draw pending.

Fixed

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses knowledge of the Dialog implementation details.

Rewrote the comment in a more generic way to avoid such confusion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants