[Cocoa][Mac] WKWebView should automatically set topContentInset when beneath a toolbar
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 1 Jul 2014 21:16:14 +0000 (21:16 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 1 Jul 2014 21:16:14 +0000 (21:16 +0000)
<rdar://problem/17523159>
https://bugs.webkit.org/show_bug.cgi?id=134496

Reviewed by Beth Dakin.

Source/WebKit2:
- Adds _automaticallyAdjustsContentInsets SPI to both WKView and WKWebView.
- Defaults _automaticallyAdjustsContentInsets to NO for WKView to keep legacy clients working.
- Defaults _automaticallyAdjustsContentInsets to YES for WKWebView.

* UIProcess/API/Cocoa/WKViewPrivate.h:
Add _automaticallyAdjustsContentInsets SPI.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView initWithFrame:configuration:]):
Default _automaticallyAdjustsContentInsets to YES for WKWebView.

(-[WKWebView _setTopContentInset:]):
(-[WKWebView _topContentInset]):
Change to forward to the WKView, since we now do coalescing and caching there.

(-[WKWebView _setAutomaticallyAdjustsContentInsets:]):
(-[WKWebView _automaticallyAdjustsContentInsets]):
Forward to the WKView.

* UIProcess/API/Cocoa/WKWebViewPrivate.h:
Add _automaticallyAdjustsContentInsets SPI.

* UIProcess/API/mac/WKView.mm:
(-[WKView renewGState]):
Ensure the contentInset is updated when the view changes, as its relative location to the toolbar may have changed.

(-[WKView addWindowObserversForWindow:]):
(-[WKView removeWindowObservers]):
(-[WKView observeValueForKeyPath:ofObject:change:context:]):
Add observers for the contentLayoutRect and titlebarAppearsTransparent properties on the window. If either of them
change, we need to recalculate the content inset.

(-[WKView _updateContentInsetsIfAutomatic]):
If _automaticallyAdjustsContentInsets is YES, follow the same rules as AppKit in setting the top content inset. Like
AppKit this is only done when:
    - The window's style mask has the NSFullSizeContentViewWindowMask bit.
    - The window does not have titlebarAppearsTransparent set.
    - And we are not in an enclosing NSScrollView.

(-[WKView _setTopContentInset:]):
(-[WKView _topContentInset]):
Coalesce setting the topContentInset to avoid a visual lag when resizing the window that was caused by us sending
multiple topContentInsets to the WebContentProcess per runloop cycle. The reason for the lag was that at the time
we observe the contentLayoutRect changing, our view may not yet be in its final position yet, so the inset will be
temporarily wrong. When the view is finally positioned correctly, we will get a renewGState, at which point we will
again calculate the inset, which now will be correct. Since these both happen in the same runloop iteration, we can
just defer sending the inset to the WebContentProcess.

(-[WKView _setAutomaticallyAdjustsContentInsets:]):
(-[WKView _automaticallyAdjustsContentInsets]):
Add the new SPI.

Tools:
* MiniBrowser/mac/BrowserWindowController.m:
(-[BrowserWindowController windowDidLoad]):
Use the NSFullSizeContentViewWindowMask bit on Yosemite and later to enable toolbar blurring.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@170667 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/Cocoa/WKViewPrivate.h
Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h
Source/WebKit2/UIProcess/API/mac/WKView.mm
Tools/ChangeLog
Tools/MiniBrowser/mac/BrowserWindowController.m

index 89665d3..afa3f06 100644 (file)
@@ -1,3 +1,63 @@
+2014-07-01  Sam Weinig  <sam@webkit.org>
+
+        [Cocoa][Mac] WKWebView should automatically set topContentInset when beneath a toolbar
+        <rdar://problem/17523159>
+        https://bugs.webkit.org/show_bug.cgi?id=134496
+
+        Reviewed by Beth Dakin.
+
+        - Adds _automaticallyAdjustsContentInsets SPI to both WKView and WKWebView.
+        - Defaults _automaticallyAdjustsContentInsets to NO for WKView to keep legacy clients working.
+        - Defaults _automaticallyAdjustsContentInsets to YES for WKWebView.
+
+        * UIProcess/API/Cocoa/WKViewPrivate.h:
+        Add _automaticallyAdjustsContentInsets SPI.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView initWithFrame:configuration:]):
+        Default _automaticallyAdjustsContentInsets to YES for WKWebView.
+
+        (-[WKWebView _setTopContentInset:]):
+        (-[WKWebView _topContentInset]):
+        Change to forward to the WKView, since we now do coalescing and caching there.
+
+        (-[WKWebView _setAutomaticallyAdjustsContentInsets:]):
+        (-[WKWebView _automaticallyAdjustsContentInsets]):
+        Forward to the WKView.
+
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        Add _automaticallyAdjustsContentInsets SPI.
+
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView renewGState]):
+        Ensure the contentInset is updated when the view changes, as its relative location to the toolbar may have changed.
+
+        (-[WKView addWindowObserversForWindow:]):
+        (-[WKView removeWindowObservers]):
+        (-[WKView observeValueForKeyPath:ofObject:change:context:]):
+        Add observers for the contentLayoutRect and titlebarAppearsTransparent properties on the window. If either of them
+        change, we need to recalculate the content inset.
+
+        (-[WKView _updateContentInsetsIfAutomatic]):
+        If _automaticallyAdjustsContentInsets is YES, follow the same rules as AppKit in setting the top content inset. Like
+        AppKit this is only done when:
+            - The window's style mask has the NSFullSizeContentViewWindowMask bit.
+            - The window does not have titlebarAppearsTransparent set.
+            - And we are not in an enclosing NSScrollView.
+
+        (-[WKView _setTopContentInset:]):
+        (-[WKView _topContentInset]):
+        Coalesce setting the topContentInset to avoid a visual lag when resizing the window that was caused by us sending
+        multiple topContentInsets to the WebContentProcess per runloop cycle. The reason for the lag was that at the time
+        we observe the contentLayoutRect changing, our view may not yet be in its final position yet, so the inset will be
+        temporarily wrong. When the view is finally positioned correctly, we will get a renewGState, at which point we will
+        again calculate the inset, which now will be correct. Since these both happen in the same runloop iteration, we can
+        just defer sending the inset to the WebContentProcess.
+
+        (-[WKView _setAutomaticallyAdjustsContentInsets:]):
+        (-[WKView _automaticallyAdjustsContentInsets]):
+        Add the new SPI.
+
 2014-07-01  Anders Carlsson  <andersca@apple.com>
 
         Add a function for restoring page state given a SessionState object
index 1cb8ff3..f8aaf00 100644 (file)
 @property (readwrite) BOOL allowsBackForwardNavigationGestures;
 @property (nonatomic, setter=_setTopContentInset:) CGFloat _topContentInset;
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+@property (nonatomic, setter=_setAutomaticallyAdjustsContentInsets:) BOOL _automaticallyAdjustsContentInsets;
+#endif
+
 @property (readonly) NSColor *_pageExtendedBackgroundColor;
 @property(copy, nonatomic) NSColor *underlayColor;
 
index d3b6d66..aa5975f 100644 (file)
@@ -306,6 +306,10 @@ static int32_t deviceOrientation()
     _wkView = [[WKView alloc] initWithFrame:bounds context:context configuration:std::move(webPageConfiguration) webView:self];
     [self addSubview:_wkView.get()];
     _page = WebKit::toImpl([_wkView pageRef]);
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+    [_wkView _setAutomaticallyAdjustsContentInsets:YES];
+#endif
 #endif
 
     _page->setBackgroundExtendsBeyondPage(true);
@@ -2240,14 +2244,28 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
 
 - (void)_setTopContentInset:(CGFloat)contentInset
 {
-    _page->setTopContentInset(contentInset);
+    [_wkView _setTopContentInset:contentInset];
 }
 
 - (CGFloat)_topContentInset
 {
-    return _page->topContentInset();
+    return [_wkView _topContentInset];
+}
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+
+- (void)_setAutomaticallyAdjustsContentInsets:(BOOL)automaticallyAdjustsContentInsets
+{
+    [_wkView _setAutomaticallyAdjustsContentInsets:automaticallyAdjustsContentInsets];
 }
 
+- (BOOL)_automaticallyAdjustsContentInsets
+{
+    return [_wkView _automaticallyAdjustsContentInsets];
+}
+
+#endif
+
 #endif
 
 @end
index 4a86e4a..f8ede74 100644 (file)
@@ -146,6 +146,9 @@ typedef NS_OPTIONS(NSUInteger, _WKFindOptions) {
 @property (readonly) NSColor *_pageExtendedBackgroundColor;
 @property (nonatomic, setter=_setDrawsTransparentBackground:) BOOL _drawsTransparentBackground;
 @property (nonatomic, setter=_setTopContentInset:) CGFloat _topContentInset;
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+@property (nonatomic, setter=_setAutomaticallyAdjustsContentInsets:) BOOL _automaticallyAdjustsContentInsets;
+#endif
 #endif
 
 - (void)_getMainResourceDataWithCompletionHandler:(void (^)(NSData *, NSError *))completionHandler;
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
index de4fb30..4b2f4ab 100644 (file)
@@ -1,3 +1,15 @@
+2014-07-01  Sam Weinig  <sam@webkit.org>
+
+        [Cocoa][Mac] WKWebView should automatically set topContentInset when beneath a toolbar
+        <rdar://problem/17523159>
+        https://bugs.webkit.org/show_bug.cgi?id=134496
+
+        Reviewed by Beth Dakin.
+
+        * MiniBrowser/mac/BrowserWindowController.m:
+        (-[BrowserWindowController windowDidLoad]):
+        Use the NSFullSizeContentViewWindowMask bit on Yosemite and later to enable toolbar blurring.
+
 2014-07-01  Zan Dobersek  <zdobersek@igalia.com>
 
         [CMake] Add necessary support for building for the Wayland target
index 795f2a2..5e9ae86 100644 (file)
 
 - (void)windowDidLoad
 {
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+    self.window.styleMask |= NSFullSizeContentViewWindowMask;
+#endif
+
     [super windowDidLoad];
 }