Skip to content

Commit

Permalink
Cherry-pick 1b857d6. rdar://121898126
Browse files Browse the repository at this point in the history
    [iOS] Pinch zooming then fullscreening causes fullscreen presentation to be zoomed unexpectedly
    https://bugs.webkit.org/show_bug.cgi?id=269195
    rdar://121898126

    Reviewed by Andy Estes.

    The intent of the fullscreen presentation on iOS is to disable zooming & lock the zoom level to an
    extent to which the entire contents of the fulscreen element are visible in the viewport. However,
    the web page itself can change the minimum and maximum zoom levels (and even the current zoom
    level). When this happens, it breaks the expected behavior of fullscreen mode, which is to show the
    entire contents of the fullscreen element in the viewport.

    The previous implementation attempted to save and restore the min, max, and current zoom levels when
    entering and exiting fullscreen, assuming those levels would not be re-set during fullscreen mode.
    This assumption was not met. Instead, add an IPI to override zoom levels sent by the page during
    rendering, and a matching IPI to remove that override. Only the current zoom level is saved and restored.

    * Source/WebKit/UIProcess/API/Cocoa/WKWebViewInternal.h:
    * Source/WebKit/UIProcess/API/ios/WKWebViewIOS.h:
    * Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm:
    (-[WKWebView _updateScrollViewForTransaction:]):
    (-[WKWebView _overrideZoomScaleParametersWithMinimumZoomScale:maximumZoomScale:allowUserScaling:]):
    (-[WKWebView _clearOverrideZoomScaleParameters]):
    * Source/WebKit/UIProcess/ios/fullscreen/WKFullScreenWindowControllerIOS.mm:
    (WebKit::WKWebViewState::applyTo):
    (WebKit::WKWebViewState::store):
    (-[WKFullScreenWindowController enterFullScreen:]):
    (-[WKFullScreenWindowController _reinsertWebViewUnderPlaceholder]):

    Canonical link: https://commits.webkit.org/274503@main

Identifier: 272448.608@safari-7618-branch
  • Loading branch information
jernoble authored and MyahCobbs committed Feb 23, 2024
1 parent 266e0b3 commit 1ae7cde
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 9 deletions.
7 changes: 7 additions & 0 deletions Source/WebKit/UIProcess/API/Cocoa/WKWebViewInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ struct OverriddenLayoutParameters {
CGSize maximumUnobscuredSize { CGSizeZero };
};

struct OverriddenZoomScaleParameters {
CGFloat minimumZoomScale { 1 };
CGFloat maximumZoomScale { 1 };
BOOL allowUserScaling { YES };
};

// This holds state that should be reset when the web process exits.
struct PerWebProcessState {
CGFloat viewportMetaTagWidth { WebCore::ViewportArguments::ValueAuto };
Expand Down Expand Up @@ -248,6 +254,7 @@ struct PerWebProcessState {
PerWebProcessState _perProcessState;

std::optional<OverriddenLayoutParameters> _overriddenLayoutParameters;
std::optional<OverriddenZoomScaleParameters> _overriddenZoomScaleParameters;
CGRect _inputViewBoundsInWindow;

BOOL _fastClickingIsDisabled;
Expand Down
2 changes: 2 additions & 0 deletions Source/WebKit/UIProcess/API/ios/WKWebViewIOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ enum class TapHandlingResult : uint8_t;
- (void)_resetUnobscuredSafeAreaInsets;
- (void)_resetObscuredInsets;

- (void)_overrideZoomScaleParametersWithMinimumZoomScale:(CGFloat)minimumZoomScale maximumZoomScale:(CGFloat)maximumZoomScale allowUserScaling:(BOOL)allowUserScaling;
- (void)_clearOverrideZoomScaleParameters;
@end

_WKTapHandlingResult wkTapHandlingResult(WebKit::TapHandlingResult);
Expand Down
28 changes: 25 additions & 3 deletions Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm
Original file line number Diff line number Diff line change
Expand Up @@ -950,9 +950,19 @@ - (void)_updateScrollViewForTransaction:(const WebKit::RemoteLayerTreeTransactio
CGSize newContentSize = roundScrollViewContentSize(*_page, [_contentView frame].size);
[_scrollView _setContentSizePreservingContentOffsetDuringRubberband:newContentSize];

[_scrollView setMinimumZoomScale:layerTreeTransaction.minimumScaleFactor()];
[_scrollView setMaximumZoomScale:layerTreeTransaction.maximumScaleFactor()];
[_scrollView _setZoomEnabledInternal:layerTreeTransaction.allowsUserScaling()];
CGFloat minimumScaleFactor = layerTreeTransaction.minimumScaleFactor();
CGFloat maximumScaleFactor = layerTreeTransaction.maximumScaleFactor();
BOOL allowsUserScaling = layerTreeTransaction.allowsUserScaling();

if (_overriddenZoomScaleParameters) {
minimumScaleFactor = _overriddenZoomScaleParameters->minimumZoomScale;
maximumScaleFactor = _overriddenZoomScaleParameters->maximumZoomScale;
allowsUserScaling = _overriddenZoomScaleParameters->allowUserScaling;
}

[_scrollView setMinimumZoomScale:minimumScaleFactor];
[_scrollView setMaximumZoomScale:maximumScaleFactor];
[_scrollView _setZoomEnabledInternal:allowsUserScaling];

auto horizontalOverscrollBehavior = _page->scrollingCoordinatorProxy()->mainFrameHorizontalOverscrollBehavior();
auto verticalOverscrollBehavior = _page->scrollingCoordinatorProxy()->mainFrameVerticalOverscrollBehavior();
Expand Down Expand Up @@ -3483,6 +3493,18 @@ - (UIAxis)axesToPreventScrollingForPanGestureInScrollView:(WKBaseScrollView *)sc
return axesToPrevent;
}

- (void)_overrideZoomScaleParametersWithMinimumZoomScale:(CGFloat)minimumZoomScale maximumZoomScale:(CGFloat)maximumZoomScale allowUserScaling:(BOOL)allowUserScaling
{
_overriddenZoomScaleParameters = { minimumZoomScale, maximumZoomScale, allowUserScaling };
[_scrollView setMinimumZoomScale:minimumZoomScale];
[_scrollView setMaximumZoomScale:maximumZoomScale];
[_scrollView _setZoomEnabledInternal:allowUserScaling];
}

- (void)_clearOverrideZoomScaleParameters
{
_overriddenZoomScaleParameters = std::nullopt;
}
@end

@implementation WKWebView (WKPrivateIOS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,6 @@ static void resizeScene(UIWindowScene *scene, CGSize size, CompletionHandler<voi
#endif
UIScrollViewContentInsetAdjustmentBehavior _savedContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAutomatic;
CGPoint _savedContentOffset = CGPointZero;
CGFloat _savedMinimumZoomScale = 1;
CGFloat _savedMaximumZoomScale = 1;
BOOL _savedBouncesZoom = NO;
BOOL _savedForceAlwaysUserScalable = NO;
CGFloat _savedMinimumEffectiveDeviceWidth = 0;
Expand Down Expand Up @@ -207,8 +205,6 @@ void applyTo(WKWebView* webView)
}
[webView _setViewScale:_savedViewScale];
scrollView.zoomScale = _savedZoomScale;
scrollView.minimumZoomScale = _savedMinimumZoomScale;
scrollView.maximumZoomScale = _savedMaximumZoomScale;
scrollView.bouncesZoom = _savedBouncesZoom;
webView._minimumEffectiveDeviceWidth = _savedMinimumEffectiveDeviceWidth;
}
Expand Down Expand Up @@ -236,8 +232,6 @@ void store(WKWebView* webView)
_savedViewScale = webView._viewScale;
_savedZoomScale = scrollView.zoomScale;
_savedContentZoomScale = webView._contentZoomScale;
_savedMinimumZoomScale = scrollView.minimumZoomScale;
_savedMaximumZoomScale = scrollView.maximumZoomScale;
_savedBouncesZoom = scrollView.bouncesZoom;
_savedMinimumEffectiveDeviceWidth = webView._minimumEffectiveDeviceWidth;
_savedHaveSetUnobscuredSafeAreaInsets = webView._haveSetUnobscuredSafeAreaInsets;
Expand Down Expand Up @@ -960,6 +954,7 @@ - (void)enterFullScreen:(CGSize)videoDimensions
[webView _setMinimumEffectiveDeviceWidth:0];
[webView _setViewScale:1.f];
WebKit::WKWebViewState().applyTo(webView.get());
[webView _overrideZoomScaleParametersWithMinimumZoomScale:1 maximumZoomScale:1 allowUserScaling:NO];
[webView _resetContentOffset];
[_window insertSubview:webView.get() atIndex:0];
[webView setNeedsLayout];
Expand Down Expand Up @@ -1225,6 +1220,7 @@ - (void)_reinsertWebViewUnderPlaceholder
[[webView window] makeKeyAndVisible];
[webView becomeFirstResponder];

[webView _clearOverrideZoomScaleParameters];
_viewState.applyTo(webView.get());
if (auto page = [webView _page])
page->setOverrideViewportArguments(std::nullopt);
Expand Down

0 comments on commit 1ae7cde

Please sign in to comment.