Skip to content

Commit 235ac2c

Browse files
Fix Dimensions not changing when orientation changes (#51978)
This fixes the bug where Dimensions (width and height) are not changing when the orientation changes.
1 parent ea6abb6 commit 235ac2c

File tree

1 file changed

+50
-20
lines changed

1 file changed

+50
-20
lines changed

packages/react-native/React/CoreModules/RCTDeviceInfo.mm

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@
1414
#import <React/RCTEventDispatcherProtocol.h>
1515
#import <React/RCTInitializing.h>
1616
#import <React/RCTInvalidating.h>
17-
#import <React/RCTKeyWindowValuesProxy.h>
1817
#import <React/RCTUtils.h>
19-
#import <React/RCTWindowSafeAreaProxy.h>
2018
#import <atomic>
2119

2220
#import "CoreModulesPlugins.h"
@@ -31,23 +29,40 @@ @implementation RCTDeviceInfo {
3129
NSDictionary *_currentInterfaceDimensions;
3230
BOOL _isFullscreen;
3331
std::atomic<BOOL> _invalidated;
32+
NSDictionary *_constants;
33+
34+
__weak UIWindow *_applicationWindow;
3435
}
3536

37+
static NSString *const kFrameKeyPath = @"frame";
38+
3639
@synthesize moduleRegistry = _moduleRegistry;
3740

3841
RCT_EXPORT_MODULE()
3942

4043
- (instancetype)init
4144
{
4245
if (self = [super init]) {
43-
[[RCTKeyWindowValuesProxy sharedInstance] startObservingWindowSizeIfNecessary];
46+
_applicationWindow = RCTKeyWindow();
47+
[_applicationWindow addObserver:self forKeyPath:kFrameKeyPath options:NSKeyValueObservingOptionNew context:nil];
4448
}
4549
return self;
4650
}
4751

52+
- (void)observeValueForKeyPath:(NSString *)keyPath
53+
ofObject:(id)object
54+
change:(NSDictionary *)change
55+
context:(void *)context
56+
{
57+
if ([keyPath isEqualToString:kFrameKeyPath]) {
58+
[self interfaceFrameDidChange];
59+
[[NSNotificationCenter defaultCenter] postNotificationName:RCTWindowFrameDidChangeNotification object:self];
60+
}
61+
}
62+
4863
+ (BOOL)requiresMainQueueSetup
4964
{
50-
return NO;
65+
return YES;
5166
}
5267

5368
- (dispatch_queue_t)methodQueue
@@ -81,7 +96,7 @@ - (void)initialize
8196

8297
#if TARGET_OS_IOS
8398

84-
_currentInterfaceOrientation = [RCTKeyWindowValuesProxy sharedInstance].currentInterfaceOrientation;
99+
_currentInterfaceOrientation = RCTKeyWindow().windowScene.interfaceOrientation;
85100

86101
[[NSNotificationCenter defaultCenter] addObserver:self
87102
selector:@selector(interfaceFrameDidChange)
@@ -98,6 +113,15 @@ - (void)initialize
98113
selector:@selector(invalidate)
99114
name:RCTBridgeWillInvalidateModulesNotification
100115
object:nil];
116+
117+
_constants = @{
118+
@"Dimensions" : [self _exportedDimensions],
119+
// Note:
120+
// This prop is deprecated and will be removed in a future release.
121+
// Please use this only for a quick and temporary solution.
122+
// Use <SafeAreaView> instead.
123+
@"isIPhoneX_deprecated" : @(RCTIsIPhoneNotched()),
124+
};
101125
}
102126

103127
- (void)invalidate
@@ -120,6 +144,8 @@ - (void)_cleanupObservers
120144

121145
[[NSNotificationCenter defaultCenter] removeObserver:self name:RCTBridgeWillInvalidateModulesNotification object:nil];
122146

147+
[_applicationWindow removeObserver:self forKeyPath:kFrameKeyPath];
148+
123149
#if TARGET_OS_IOS
124150
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
125151
#endif
@@ -132,8 +158,13 @@ static BOOL RCTIsIPhoneNotched()
132158

133159
#if TARGET_OS_IOS
134160
dispatch_once(&onceToken, ^{
161+
RCTAssertMainQueue();
162+
135163
// 20pt is the top safeArea value in non-notched devices
136-
isIPhoneNotched = [RCTWindowSafeAreaProxy sharedInstance].currentSafeAreaInsets.top > 20;
164+
UIWindow *keyWindow = RCTKeyWindow();
165+
if (keyWindow) {
166+
isIPhoneNotched = keyWindow.safeAreaInsets.top > 20;
167+
}
137168
});
138169
#endif
139170

@@ -142,11 +173,13 @@ static BOOL RCTIsIPhoneNotched()
142173

143174
static NSDictionary *RCTExportedDimensions(CGFloat fontScale)
144175
{
176+
RCTAssertMainQueue();
145177
UIScreen *mainScreen = UIScreen.mainScreen;
146178
CGSize screenSize = mainScreen.bounds.size;
179+
UIView *mainWindow = RCTKeyWindow();
147180

148181
// We fallback to screen size if a key window is not found.
149-
CGSize windowSize = [RCTKeyWindowValuesProxy sharedInstance].windowSize;
182+
CGSize windowSize = mainWindow ? mainWindow.bounds.size : screenSize;
150183

151184
NSDictionary<NSString *, NSNumber *> *dimsWindow = @{
152185
@"width" : @(windowSize.width),
@@ -170,7 +203,10 @@ - (NSDictionary *)_exportedDimensions
170203
RCTAssert(_moduleRegistry, @"Failed to get exported dimensions: RCTModuleRegistry is nil");
171204
RCTAccessibilityManager *accessibilityManager =
172205
(RCTAccessibilityManager *)[_moduleRegistry moduleForName:"AccessibilityManager"];
173-
RCTAssert(accessibilityManager, @"Failed to get exported dimensions: AccessibilityManager is nil");
206+
// TOOD(T225745315): For some reason, accessibilityManager is nil in some cases.
207+
// We default the fontScale to 1.0 in this case. This should be okay: if we assume
208+
// that accessibilityManager will eventually become available, js will eventually
209+
// be updated with the correct fontScale.
174210
CGFloat fontScale = accessibilityManager ? accessibilityManager.multiplier : 1.0;
175211
return RCTExportedDimensions(fontScale);
176212
}
@@ -182,14 +218,7 @@ - (NSDictionary *)_exportedDimensions
182218

183219
- (NSDictionary<NSString *, id> *)getConstants
184220
{
185-
return @{
186-
@"Dimensions" : [self _exportedDimensions],
187-
// Note:
188-
// This prop is deprecated and will be removed in a future release.
189-
// Please use this only for a quick and temporary solution.
190-
// Use <SafeAreaView> instead.
191-
@"isIPhoneX_deprecated" : @(RCTIsIPhoneNotched()),
192-
};
221+
return _constants;
193222
}
194223

195224
- (void)didReceiveNewContentSizeMultiplier
@@ -209,10 +238,11 @@ - (void)didReceiveNewContentSizeMultiplier
209238
- (void)interfaceOrientationDidChange
210239
{
211240
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
212-
UIWindow *keyWindow = RCTKeyWindow();
213-
UIInterfaceOrientation nextOrientation = keyWindow.windowScene.interfaceOrientation;
241+
UIApplication *application = RCTSharedApplication();
242+
UIInterfaceOrientation nextOrientation = RCTKeyWindow().windowScene.interfaceOrientation;
214243

215-
BOOL isRunningInFullScreen = CGRectEqualToRect(keyWindow.frame, keyWindow.screen.bounds);
244+
BOOL isRunningInFullScreen =
245+
CGRectEqualToRect(application.delegate.window.frame, application.delegate.window.screen.bounds);
216246
// We are catching here two situations for multitasking view:
217247
// a) The app is in Split View and the container gets resized -> !isRunningInFullScreen
218248
// b) The app changes to/from fullscreen example: App runs in slide over mode and goes into fullscreen->
@@ -275,4 +305,4 @@ - (void)_interfaceFrameDidChange
275305
Class RCTDeviceInfoCls(void)
276306
{
277307
return RCTDeviceInfo.class;
278-
}
308+
}

0 commit comments

Comments
 (0)