Skip to content

fix: make RCTScreenSize take horizontal orientation into account #51444

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

okwasniewski
Copy link
Contributor

Summary:

This PR improves RCTScreenSize to handle horizontal orientations. This was causing a flicker whenever opening a Modal in horizontal orientation. Currently, RCTScreenSize is used to supply initial state for ModalHostViewState:

ModalHostViewState() : screenSize(RCTModalHostViewScreenSize()) {

This works great in portrait mode, but causes onLayout the be called twice in horizontal orientation (first with screen size and then with actual size..)

Changelog:

[IOS] [FIXED] - make RCTScreenSize take horizontal orientation into account

Test Plan:

Open modal in horizontal orientation

@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Callstack Partner: Callstack Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels May 18, 2025
@facebook-github-bot
Copy link
Contributor

@rshest has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

Copy link
Contributor

@cipolleschi cipolleschi left a comment

Choose a reason for hiding this comment

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

Hi @okwasniewski, thanks for the PR. I left a comment that I'd like you to address!

@okwasniewski okwasniewski force-pushed the fix/horizontal-size branch from bd1b325 to e7a15db Compare May 19, 2025 10:09
@facebook-github-bot
Copy link
Contributor

@rshest has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

Comment on lines 393 to 406
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
RCTUnsafeExecuteOnMainQueueSync(^{
size = [UIScreen mainScreen].bounds.size;
});
});

return size;

UIDeviceOrientation orientation = RCTDeviceOrientation();

BOOL isLandscape = orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight;

if (isLandscape) {
return CGSizeMake(size.height, size.width);
} else {
return CGSizeMake(size.width, size.height);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not really sure whether this block of code works fine in all the situations.

When the app is opened in landscape mode, the dispatch_once will run immediately, and we are going to get a height < width... 🤔

But we are returning a cg size that says that the width of the CGSize is the height of the screen, so the width of the CGSize is the small side... I'm not sure that's correct...

Copy link
Contributor Author

@okwasniewski okwasniewski May 19, 2025

Choose a reason for hiding this comment

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

Ah.. yea that's true, what do you think about getting "absolute" value in the RCTUnsafeExecuteOnMainQueueSync so if it's not portrait we reverse it? Or how would you approach it?

Copy link
Contributor

@cipolleschi cipolleschi May 19, 2025

Choose a reason for hiding this comment

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

Yeah, I think it makes sense.
I think that we should check for the orientation also in the RCTUnsafeExecuteOnMainQueueSync and then track what's the "long side" and what's the "short side" and then return the CGSize accordingly.

as a nit, ObjC has a method UIDeviceOrientationIsLandscape(UIDeviceOrientation orientation) we should use, instead of checking manually orientation == UIDeviceOrientationLandscapeLeft || UIDeviceOrientationLandscapeRight.

If we use it, we can probably do something like:

if (UIDeviceOrientationIsLandscape(RCTDeviceOrientation())) {

and get rid of the UIDeviceOrientation orientation variable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cipolleschi Thanks for the suggestion, I didn't know about UIDeviceOrientationIsLandscape. Pushed a fix!

@okwasniewski okwasniewski force-pushed the fix/horizontal-size branch from e7a15db to afa1b0a Compare May 19, 2025 20:44
@NickGerleman
Copy link
Contributor

@RSNara were you looking at a replacement for this to avoid the UI thread dispatch?

return size;

if (UIDeviceOrientationIsLandscape(RCTDeviceOrientation())) {
return CGSizeMake(portraitSize.height, portraitSize.width);
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought we were dispatching sync to avoid calling functions that required being on the UI thread? Is this safe?

Comment on lines -388 to -390
// FIXME: this caches whatever the bounds were when it was first called, and then
// doesn't update when the device is rotated. We need to find another thread-
// safe way to get the screen size.
Copy link
Contributor

Choose a reason for hiding this comment

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

Does screen size change if we have something insetting the window? Like, a keyboard open, or if a window on an iPad is resized?

I agree with the comment, that this is pretty sketchy 😀

@facebook-github-bot
Copy link
Contributor

@rshest has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Callstack Partner: Callstack Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants