[Cocoa][Mac] WKWebView should automatically set topContentInset when beneath a toolbar
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / mac / WKView.mm
index 0e1d94b..5ce9528 100644 (file)
@@ -241,6 +241,13 @@ struct WKViewInterpretKeyEventsParameters {
 
     RetainPtr<CALayer> _rootLayer;
 
+    BOOL _didScheduleSetTopContentInset;
+    CGFloat _topContentInset;
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+    BOOL _automaticallyAdjustsContentInsets;
+#endif
+
 #if WK_API_ENABLED
     _WKThumbnailView *_thumbnailView;
 #endif
@@ -481,6 +488,10 @@ struct WKViewInterpretKeyEventsParameters {
     if ([self window])
         [self _updateWindowAndViewFrames];
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+    [self _updateContentInsetsIfAutomatic];
+#endif
+
     [super renewGState];
 }
 
@@ -2402,6 +2413,10 @@ static void createSandboxExtensionsForFileUpload(NSPasteboard *pasteboard, Sandb
     return NSMouseInRect(localPoint, visibleThumbRect, [self isFlipped]);
 }
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+static void* keyValueObservingContext = &keyValueObservingContext;
+#endif
+
 - (void)addWindowObserversForWindow:(NSWindow *)window
 {
     if (window) {
@@ -2431,6 +2446,10 @@ static void createSandboxExtensionsForFileUpload(NSPasteboard *pasteboard, Sandb
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_windowDidChangeOcclusionState:)
                                                      name:NSWindowDidChangeOcclusionStateNotification object:window];
 #endif
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+        [window addObserver:self forKeyPath:@"contentLayoutRect" options:NSKeyValueObservingOptionInitial context:keyValueObservingContext];
+        [window addObserver:self forKeyPath:@"titlebarAppearsTransparent" options:NSKeyValueObservingOptionInitial context:keyValueObservingContext];
+#endif
     }
 }
 
@@ -2455,6 +2474,10 @@ static void createSandboxExtensionsForFileUpload(NSPasteboard *pasteboard, Sandb
 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
     [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidChangeOcclusionStateNotification object:window];
 #endif
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+    [window removeObserver:self forKeyPath:@"contentLayoutRect" context:keyValueObservingContext];
+    [window removeObserver:self forKeyPath:@"titlebarAppearsTransparent" context:keyValueObservingContext];
+#endif
 }
 
 - (void)viewWillMoveToWindow:(NSWindow *)window
@@ -3550,6 +3573,35 @@ static NSString *pathWithUniqueFilenameForPath(NSString *path)
 }
 #endif // WK_API_ENABLED
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+
+- (void)_updateContentInsetsIfAutomatic
+{
+    if (!self._automaticallyAdjustsContentInsets)
+        return;
+
+    if ((self.window.styleMask & NSFullSizeContentViewWindowMask) && !self.window.titlebarAppearsTransparent && ![self enclosingScrollView]) {
+        NSRect contentLayoutRect = [self convertRect:self.window.contentLayoutRect fromView:nil];
+        CGFloat newTopContentInset = NSMaxY(contentLayoutRect) - NSHeight(contentLayoutRect);
+        if (self._topContentInset != newTopContentInset)
+            self._topContentInset = newTopContentInset;
+    } else
+        self._topContentInset = 0;
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+    if (context == keyValueObservingContext) {
+        if ([keyPath isEqualToString:@"contentLayoutRect"] || [keyPath isEqualToString:@"titlebarAppearsTransparent"])
+            [self _updateContentInsetsIfAutomatic];
+        return;
+    }
+
+    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+}
+
+#endif
+
 @end
 
 @implementation WKView (Private)
@@ -3835,12 +3887,23 @@ static NSString *pathWithUniqueFilenameForPath(NSString *path)
 
 - (void)_setTopContentInset:(CGFloat)contentInset
 {
-    _data->_page->setTopContentInset(contentInset);
+    _data->_topContentInset = contentInset;
+
+    if (_data->_didScheduleSetTopContentInset)
+        return;
+
+    _data->_didScheduleSetTopContentInset = YES;
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        _data->_didScheduleSetTopContentInset = NO;
+
+        _data->_page->setTopContentInset(_data->_topContentInset);
+    });
 }
 
 - (CGFloat)_topContentInset
 {
-    return _data->_page->topContentInset();
+    return _data->_topContentInset;
 }
 
 - (NSColor *)_pageExtendedBackgroundColor
@@ -3988,6 +4051,21 @@ static NSString *pathWithUniqueFilenameForPath(NSString *path)
     return handledEvent;
 }
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+
+- (void)_setAutomaticallyAdjustsContentInsets:(BOOL)automaticallyAdjustsContentInsets
+{
+    _data->_automaticallyAdjustsContentInsets = automaticallyAdjustsContentInsets;
+    [self _updateContentInsetsIfAutomatic];
+}
+
+- (BOOL)_automaticallyAdjustsContentInsets
+{
+    return _data->_automaticallyAdjustsContentInsets;
+}
+
+#endif
+
 @end
 
 @implementation WKResponderChainSink