Changeset 258821 in webkit


Ignore:
Timestamp:
Mar 22, 2020 12:29:40 PM (4 years ago)
Author:
Wenson Hsieh
Message:

Adopt -[UIWindowScene interfaceOrientation] when determining device orientation
https://bugs.webkit.org/show_bug.cgi?id=209372
<rdar://problem/60491857>

Reviewed by Darin Adler.

Currently, for WebKit clients that have adopted the UIScene lifecycle (and also do not set an interface
orientation override, like MobileSafari does), device orientation APIs will always report that the device is in
portrait mode, regardless of the actual device orientation. This is because our current mechanism for tracking
device orientation asks the shared UIApplication for its -statusBarOrientation. This is hard-coded to always
return UIInterfaceOrientationPortrait for apps that adopt the UIScene lifecycle, and will additionally trigger a
simulated crash, explaining that it is invalid for any scene-based app to call -statusBarOrientation.

To fix this, we adjust the deviceOrientation helper in WKWebViewIOS.mm to work for scene-based apps. See below
for more details.

  • Platform/spi/ios/UIKitSPI.h:
  • UIProcess/API/ios/WKWebViewIOS.h:
  • UIProcess/API/ios/WKWebViewIOS.mm:

(-[WKWebView _setupScrollAndContentViews]):

Change call sites of deviceOrientation() to be [self _deviceOrientation] instead.

(-[WKWebView _deviceOrientation]):

Replace deviceOrientation() with a _deviceOrientation helper method on WKWebView. For non-scene-based
apps, this new helper method does not change any behavior, and continues to go through UIApplication. However,
for scene-based apps, we instead ask the web view's window's UIWindowScene for its interface orientation.

Importantly, this means that if a WKWebView is not parented, it doesn't have a valid device orientation (i.e.
the orientation is UIInterfaceOrientationUnknown). As such, a newly created WKWebView that is unparented will
start out with no orientation; it's only upon moving the view into a window that it is able to determine the
device orientation. To ensure this, we add logic to -didMoveToWindow to recompute device orientation and
dispatch an update if needed.

To avoid sending unnecessary updates, if a WKWebView is unparented, we wait until it's parented again to send
the new device orientation.

(-[WKWebView didMoveToWindow]):
(-[WKWebView _windowDidRotate:]):
(deviceOrientation): Deleted.

See -[WKWebView _deviceOrientation] above.

Location:
trunk/Source/WebKit
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r258814 r258821  
     12020-03-22  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        Adopt -[UIWindowScene interfaceOrientation] when determining device orientation
     4        https://bugs.webkit.org/show_bug.cgi?id=209372
     5        <rdar://problem/60491857>
     6
     7        Reviewed by Darin Adler.
     8
     9        Currently, for WebKit clients that have adopted the UIScene lifecycle (and also do not set an interface
     10        orientation override, like MobileSafari does), device orientation APIs will always report that the device is in
     11        portrait mode, regardless of the actual device orientation. This is because our current mechanism for tracking
     12        device orientation asks the shared UIApplication for its -statusBarOrientation. This is hard-coded to always
     13        return UIInterfaceOrientationPortrait for apps that adopt the UIScene lifecycle, and will additionally trigger a
     14        simulated crash, explaining that it is invalid for any scene-based app to call -statusBarOrientation.
     15
     16        To fix this, we adjust the `deviceOrientation` helper in WKWebViewIOS.mm to work for scene-based apps. See below
     17        for more details.
     18
     19        * Platform/spi/ios/UIKitSPI.h:
     20        * UIProcess/API/ios/WKWebViewIOS.h:
     21        * UIProcess/API/ios/WKWebViewIOS.mm:
     22        (-[WKWebView _setupScrollAndContentViews]):
     23
     24        Change call sites of `deviceOrientation()` to be `[self _deviceOrientation]` instead.
     25
     26        (-[WKWebView _deviceOrientation]):
     27
     28        Replace `deviceOrientation()` with a `_deviceOrientation` helper method on `WKWebView`. For non-scene-based
     29        apps, this new helper method does not change any behavior, and continues to go through UIApplication. However,
     30        for scene-based apps, we instead ask the web view's window's `UIWindowScene` for its interface orientation.
     31
     32        Importantly, this means that if a WKWebView is not parented, it doesn't have a valid device orientation (i.e.
     33        the orientation is UIInterfaceOrientationUnknown). As such, a newly created WKWebView that is unparented will
     34        start out with no orientation; it's only upon moving the view into a window that it is able to determine the
     35        device orientation. To ensure this, we add logic to -didMoveToWindow to recompute device orientation and
     36        dispatch an update if needed.
     37
     38        To avoid sending unnecessary updates, if a WKWebView is unparented, we wait until it's parented again to send
     39        the new device orientation.
     40
     41        (-[WKWebView didMoveToWindow]):
     42        (-[WKWebView _windowDidRotate:]):
     43        (deviceOrientation): Deleted.
     44
     45        See -[WKWebView _deviceOrientation] above.
     46
    1472020-03-21  David Kilzer  <ddkilzer@apple.com>
    248
  • trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h

    r258767 r258821  
    195195- (void)_handleHIDEvent:(IOHIDEventRef)event;
    196196- (void)handleKeyUIEvent:(UIEvent *)event;
     197- (BOOL)_appAdoptsUISceneLifecycle;
    197198@end
    198199
  • trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.h

    r254315 r258821  
    136136@property (nonatomic, readonly) UIEdgeInsets _computedUnobscuredSafeAreaInset;
    137137@property (nonatomic, readonly, getter=_isRetainingActiveFocusedState) BOOL _retainingActiveFocusedState;
     138@property (nonatomic, readonly) int32_t _deviceOrientation;
    138139
    139140- (BOOL)_effectiveAppearanceIsDark;
     
    142143@end
    143144
    144 int32_t deviceOrientation();
    145 
    146145#endif // PLATFORM(IOS_FAMILY)
  • trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm

    r258148 r258821  
    8989}
    9090
    91 int32_t deviceOrientation()
    92 {
    93 ALLOW_DEPRECATED_DECLARATIONS_BEGIN
    94     return deviceOrientationForUIInterfaceOrientation([[UIApplication sharedApplication] statusBarOrientation]);
    95 ALLOW_DEPRECATED_DECLARATIONS_END
    96 }
    97 
    9891@interface UIView (UIViewInternal)
    9992- (UIViewController *)_viewControllerForAncestor;
     
    158151    [self addSubview:_scrollView.get()];
    159152
    160     [self _dispatchSetDeviceOrientation:deviceOrientation()];
     153    [self _dispatchSetDeviceOrientation:[self _deviceOrientation]];
    161154
    162155    [_contentView layer].anchorPoint = CGPointZero;
     
    229222    // -_decrementFocusPreservationCount after resetting the count to 0.
    230223    return _focusPreservationCount || _activeFocusedStateRetainCount;
     224}
     225
     226- (int32_t)_deviceOrientation
     227{
     228    auto orientation = UIInterfaceOrientationUnknown;
     229    auto application = UIApplication.sharedApplication;
     230ALLOW_DEPRECATED_DECLARATIONS_BEGIN
     231    if (!application._appAdoptsUISceneLifecycle)
     232        orientation = application.statusBarOrientation;
     233ALLOW_DEPRECATED_DECLARATIONS_END
     234    else if (auto windowScene = self.window.windowScene)
     235        orientation = windowScene.interfaceOrientation;
     236    return deviceOrientationForUIInterfaceOrientation(orientation);
    231237}
    232238
     
    13961402- (void)didMoveToWindow
    13971403{
     1404    if (!_overridesInterfaceOrientation)
     1405        [self _dispatchSetDeviceOrientation:[self _deviceOrientation]];
    13981406    _page->activityStateDidChange(WebCore::ActivityState::allFlags());
    13991407    _page->webViewDidMoveToWindow();
     
    22422250{
    22432251    if (!_overridesInterfaceOrientation)
    2244         [self _dispatchSetDeviceOrientation:deviceOrientation()];
     2252        [self _dispatchSetDeviceOrientation:[self _deviceOrientation]];
    22452253}
    22462254
Note: See TracChangeset for help on using the changeset viewer.