-
Notifications
You must be signed in to change notification settings - Fork 25.1k
Ensure full layout occurs when a system scale change occurs #45047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Should the same occur for font scale changes? |
|
Might be worth contributing parts of this to https://github.com/facebook/yoga and adding a test case as well. |
| LayoutResults* layout = &node->getLayout(); | ||
|
|
||
| depth++; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These files will ultimately get synced everywhere, but we usually prefer changes against Yoga to be made against the Yoga repo (which will run some additional validation in OSS as well).
Yoga is also pretty heavily unit tested, so we would want to add a test alongside this. Unit tests are run automatically against the Yoga repo, but there is also a unit_tests.bat that will build and run the tests on Windows/MSVC so long as CMake is set up correctly (I think you can run from VS command shell)?
| layout->lastOwnerDirection != ownerDirection || | ||
| layout->lastScale != node->getConfig()->getPointScaleFactor(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is logic today, to try to account for pointScaleFactor when we are comparing layout constraints for cache reuse (compared to logic that has gotten chained here for dirtying all results): https://github.com/facebook/yoga/blob/baf670e261892ad4e72c5c02b6ff671537b661a7/yoga/algorithm/Cache.cpp#L64
I wouldn't be surprised if there are issues with the current interaction of layout rounding and caching, but we should probably only do this invalidation in one place (and make sure we have tests that it works, if we don't right now).
|
|
||
| if (layoutConstraints != getConcreteProps().layoutConstraints) { | ||
| if (layoutConstraints != getConcreteProps().layoutConstraints || | ||
| layoutContext.pointScaleFactor != | ||
| getConcreteProps().layoutContext.pointScaleFactor) { | ||
| newRootShadowNode->dirtyLayout(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a down-propagation/inheritance step, during commit, once we have the full shadow-tree constructed, where we propagate pointScaleFactor to every Yoga node.
Line 462 in d8739e1
| YGConfigSetPointScaleFactor(&yogaConfig_, pointScaleFactor); |
YGNodeSetConfig will do a comparison of previous and current config to dirty node (though changing something on the actual config after-the-fact does not, which is an API bug). So this code has a defect where it is not dirtying underlying Yoga node, if pointScaleFactor changes.
We probably want to fixup the invalidation when setting pointScaleFactor (either there in RN, or in Yoga), instead of just invalidating the root node.
An aside, I know the code already does this, but this method of dirtying that Fabric uses is a smell (and Yoga's public API only allows dirtying nodes with measure functions which can be impacted by external changes). Yoga tries to manage dirtying in all other cases, when APIs are called which mutate style or config. RootShadowNode::layoutIfNeeded should normally be able to run, even if the node is not dirty, and work only happens if the passed in constraints have changed.
|
Okay, so right now we invalidate based on
I think we could replace all of this, with a single solution, that solves for the config invalidation API issue Yoga has.
I think we could potentially then remove any of the other derived pointScaleFactor comparisons, since we fully bust layout and measurement caches (of the single node) when a layout-effecting config parameter changes. |
|
@NickGerleman - Does storing the dirty bit on the yoga config work? Doesn't the API allow for the same config object to be shared across multiple nodes? |
|
@acoates-ms, you are right. Multiple nodes sharing single config would break a single dirty flag. I think the core behavior we want, is that The first extension I could imagine for fixing n:1 issue of dirty flag, could be keeping revision count on config (and associated last-config-revision on node) instead, but that might be too extreme. At the same time, implementing as config-level dirtniess is appealing to me though, just to generalize this fix to other config attributes. |
Summary: This is a continuation of the previous PR: facebook#45047 I made the change more generic for allowing any kind of config change to invalidate layout. X-link: facebook/yoga#1674 Differential Revision: D59286992 Pulled By: NickGerleman
…45259) Summary: Pull Request resolved: facebook#45259 This is a continuation of the previous PR: facebook#45047 I made the change more generic for allowing any kind of config change to invalidate layout. X-link: facebook/yoga#1674 Reviewed By: rozele Differential Revision: D59286992 Pulled By: NickGerleman
…1674) Summary: This is a continuation of the previous PR: facebook/react-native#45047 I made the change more generic for allowing any kind of config change to invalidate layout. Pull Request resolved: facebook#1674 Differential Revision: D59286992 Pulled By: NickGerleman
Summary: X-link: facebook/react-native#45259 This is a continuation of the previous PR: facebook/react-native#45047 I made the change more generic for allowing any kind of config change to invalidate layout. Changelog: [Internal] X-link: facebook/yoga#1674 Reviewed By: rozele Differential Revision: D59286992 Pulled By: NickGerleman fbshipit-source-id: f46f35b03d5d9a743b798844ee3e1a02c271ccde
Summary: Pull Request resolved: #45259 This is a continuation of the previous PR: #45047 I made the change more generic for allowing any kind of config change to invalidate layout. Changelog: [Internal] X-link: facebook/yoga#1674 Reviewed By: rozele Differential Revision: D59286992 Pulled By: NickGerleman fbshipit-source-id: f46f35b03d5d9a743b798844ee3e1a02c271ccde
Summary: X-link: facebook/react-native#45259 This is a continuation of the previous PR: facebook/react-native#45047 I made the change more generic for allowing any kind of config change to invalidate layout. Changelog: [Internal] Pull Request resolved: #1674 Reviewed By: rozele Differential Revision: D59286992 Pulled By: NickGerleman fbshipit-source-id: f46f35b03d5d9a743b798844ee3e1a02c271ccde
|
Replaced by #45259 |
Summary:
When a scale factor change occurs, RN does not fully invalidate the layout. This can cause issues with pixel alignment and means that the LayoutMetrics on native components do not reliably get the updated scale factor.
Essentially the layout caching in calculateLayoutInternal, will not recalculate layout on a scale factor change.
This likely affects desktop platforms more than mobile, since on desktop you can have the scale factor change often while running by moving windows between monitors with different scale factors. I'm not sure under what scenarios this would affect mobile.
Changelog:
[INTERNAL] [FIXED] - Recalculate layout on scale factor changes.
Test Plan:
Using this change to validate running react-native-windows fabric in environments with multiple monitors of different scale factors.