Add a persistent, fixed scale factor to make it easy to scale down WK(Web)Views
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Apr 2015 00:27:39 +0000 (00:27 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Apr 2015 00:27:39 +0000 (00:27 +0000)
https://bugs.webkit.org/show_bug.cgi?id=143560
<rdar://problem/16302047>

Reviewed by Darin Adler.

Add a new "view" scale factor to WKView and WKWebView.

Unlike page scale (or "magnification" in the API), view scale:
    - persists between page loads
    - persists between Web process crashes
    - is not user adjustable
    - can reliably be < 1

The page scale and view scale are multiplied together whenever we push
a new page scale down into WebCore, so the implementation of view scale
is transparent to WebCore, and acts effectively as a constant multiplier
for the (user-adjustable) page scale factor.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::scaleView):
Add scaleView, which updates our cached viewScaleFactor and pushes it to the Web process.

(WebKit::WebPageProxy::creationParameters):
Plumb viewScaleFactor through the page creation parameters.

* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::viewScaleFactor): Added.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::WebPage):
If the viewScaleFactor is not 1 at creation time, call scalePage with a page scale of 1.
Internally, scalePage will multiply in the viewScaleFactor and push it all to the Web process.

(WebKit::WebPage::scalePage):
Multiply the page scale factor by the view scale factor before passing it to WebCore.

(WebKit::WebPage::scalePageInViewCoordinates):
Early returns need to check the total scale, not just the new page scale.

(WebKit::WebPage::totalScaleFactor):
The scale that we get back from WebCore::Page::pageScaleFactor is the product
of WebKit2's view and page scales. So, here we'll call that the totalScaleFactor.
(Might need a different name because it seems like "total" should include deviceScale too).

(WebKit::WebPage::pageScaleFactor):
WebKit2's notion of the pageScaleFactor does not include the view scale, so
divide it out of WebCore's page scale.

(WebKit::WebPage::scaleView):
Apply a new view scale, maintaining the current scroll position.

* WebProcess/WebPage/WebPage.h:
(WebKit::WebPage::viewScaleFactor):
* WebProcess/WebPage/WebPage.messages.in:

* Shared/WebPageCreationParameters.cpp:
(WebKit::WebPageCreationParameters::encode):
(WebKit::WebPageCreationParameters::decode):
* Shared/WebPageCreationParameters.h:
Plumb viewScaleFactor through the page creation parameters.

* UIProcess/API/Cocoa/WKViewPrivate.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _viewScale]):
(-[WKWebView _setViewScale:]):
* UIProcess/API/mac/WKView.mm:
(-[WKView _viewScale]):
(-[WKView _setViewScale:]):
Push the new view scale to WebPage.

* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _setAutomaticallyComputesFixedLayoutSizeFromViewScale:]):
(-[WKWebView _automaticallyComputesFixedLayoutSizeFromViewScale]):
* UIProcess/API/mac/WKView.mm:
(-[WKView setFrameSize:]):
(-[WKView _updateAutomaticallyComputedFixedLayoutSize]):
(-[WKView _setAutomaticallyComputesFixedLayoutSizeFromViewScale:]):
(-[WKView _automaticallyComputesFixedLayoutSizeFromViewScale]):
* UIProcess/API/mac/WKViewInternal.h:
Add a new layout mode, "DynamicSizeComputedFromViewScale",
which turns on fixed layout size mode, and sets the fixed layout size
based on the view's frame and view scale. The fixed layout size is maintained
as the frame of the view scaled by the inverse of the view scale. This
makes it very easy to maintain a WK(Web)View that is scaled down by
a constant amount, but is laid out as if it were not.

* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::adjustTransientZoom):
(WebKit::TiledCoreAnimationDrawingArea::commitTransientZoom):
(WebKit::TiledCoreAnimationDrawingArea::applyTransientZoomToPage):
Because the transient zoom mechanism touches layers that WebCore owns,
it mostly need to operate with totalScaleFactor, because that is what WebCore sees.

* MiniBrowser/mac/BrowserWindowController.h:
* MiniBrowser/mac/MainMenu.xib:
* MiniBrowser/mac/WK1BrowserWindowController.m:
(-[WK1BrowserWindowController setScale:]):
* MiniBrowser/mac/WK2BrowserWindowController.m:
(viewScaleForMenuItemTag):
(-[WK2BrowserWindowController setScale:]):
(-[WK2BrowserWindowController validateMenuItem:]):
Add a submenu with four view scale options: 100%, 75%, 50%, and 25%.
When in use, we resize the window so that the view fits correctly, and
use automaticallyComputesFixedlayoutSizeFromViewScale so that the page's
layout size will not change when scaling down (but will update appropriately
when the view is resized).

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

21 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/WebPageCreationParameters.cpp
Source/WebKit2/Shared/WebPageCreationParameters.h
Source/WebKit2/UIProcess/API/C/WKLayoutMode.h
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/Cocoa/_WKLayoutMode.h
Source/WebKit2/UIProcess/API/mac/WKView.mm
Source/WebKit2/UIProcess/API/mac/WKViewInternal.h
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/WebPage.h
Source/WebKit2/WebProcess/WebPage/WebPage.messages.in
Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm
Tools/ChangeLog
Tools/MiniBrowser/mac/BrowserWindowController.h
Tools/MiniBrowser/mac/MainMenu.xib
Tools/MiniBrowser/mac/WK1BrowserWindowController.m
Tools/MiniBrowser/mac/WK2BrowserWindowController.m

index 152f520..86e1dc1 100644 (file)
@@ -1,3 +1,100 @@
+2015-04-13  Tim Horton  <timothy_horton@apple.com>
+
+        Add a persistent, fixed scale factor to make it easy to scale down WK(Web)Views
+        https://bugs.webkit.org/show_bug.cgi?id=143560
+        <rdar://problem/16302047>
+
+        Reviewed by Darin Adler.
+
+        Add a new "view" scale factor to WKView and WKWebView.
+
+        Unlike page scale (or "magnification" in the API), view scale:
+            - persists between page loads
+            - persists between Web process crashes
+            - is not user adjustable
+            - can reliably be < 1
+
+        The page scale and view scale are multiplied together whenever we push
+        a new page scale down into WebCore, so the implementation of view scale
+        is transparent to WebCore, and acts effectively as a constant multiplier
+        for the (user-adjustable) page scale factor.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::scaleView):
+        Add scaleView, which updates our cached viewScaleFactor and pushes it to the Web process.
+
+        (WebKit::WebPageProxy::creationParameters):
+        Plumb viewScaleFactor through the page creation parameters.
+
+        * UIProcess/WebPageProxy.h:
+        (WebKit::WebPageProxy::viewScaleFactor): Added.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::WebPage):
+        If the viewScaleFactor is not 1 at creation time, call scalePage with a page scale of 1.
+        Internally, scalePage will multiply in the viewScaleFactor and push it all to the Web process.
+
+        (WebKit::WebPage::scalePage):
+        Multiply the page scale factor by the view scale factor before passing it to WebCore.
+
+        (WebKit::WebPage::scalePageInViewCoordinates):
+        Early returns need to check the total scale, not just the new page scale.
+
+        (WebKit::WebPage::totalScaleFactor):
+        The scale that we get back from WebCore::Page::pageScaleFactor is the product
+        of WebKit2's view and page scales. So, here we'll call that the totalScaleFactor.
+        (Might need a different name because it seems like "total" should include deviceScale too).
+
+        (WebKit::WebPage::pageScaleFactor):
+        WebKit2's notion of the pageScaleFactor does not include the view scale, so
+        divide it out of WebCore's page scale.
+
+        (WebKit::WebPage::scaleView):
+        Apply a new view scale, maintaining the current scroll position.
+
+        * WebProcess/WebPage/WebPage.h:
+        (WebKit::WebPage::viewScaleFactor):
+        * WebProcess/WebPage/WebPage.messages.in:
+
+        * Shared/WebPageCreationParameters.cpp:
+        (WebKit::WebPageCreationParameters::encode):
+        (WebKit::WebPageCreationParameters::decode):
+        * Shared/WebPageCreationParameters.h:
+        Plumb viewScaleFactor through the page creation parameters.
+
+        * UIProcess/API/Cocoa/WKViewPrivate.h:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _viewScale]):
+        (-[WKWebView _setViewScale:]):
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView _viewScale]):
+        (-[WKView _setViewScale:]):
+        Push the new view scale to WebPage.
+
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _setAutomaticallyComputesFixedLayoutSizeFromViewScale:]):
+        (-[WKWebView _automaticallyComputesFixedLayoutSizeFromViewScale]):
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView setFrameSize:]):
+        (-[WKView _updateAutomaticallyComputedFixedLayoutSize]):
+        (-[WKView _setAutomaticallyComputesFixedLayoutSizeFromViewScale:]):
+        (-[WKView _automaticallyComputesFixedLayoutSizeFromViewScale]):
+        * UIProcess/API/mac/WKViewInternal.h:
+        Add a new layout mode, "DynamicSizeComputedFromViewScale",
+        which turns on fixed layout size mode, and sets the fixed layout size
+        based on the view's frame and view scale. The fixed layout size is maintained
+        as the frame of the view scaled by the inverse of the view scale. This
+        makes it very easy to maintain a WK(Web)View that is scaled down by
+        a constant amount, but is laid out as if it were not.
+        
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
+        (WebKit::TiledCoreAnimationDrawingArea::adjustTransientZoom):
+        (WebKit::TiledCoreAnimationDrawingArea::commitTransientZoom):
+        (WebKit::TiledCoreAnimationDrawingArea::applyTransientZoomToPage):
+        Because the transient zoom mechanism touches layers that WebCore owns,
+        it mostly need to operate with totalScaleFactor, because that is what WebCore sees.
+
 2015-04-10  Brent Fulgham  <bfulgham@apple.com>
 
         Expand test infrastructure to support scrolling tests
index 6af91ae..1edb365 100644 (file)
@@ -58,6 +58,7 @@ void WebPageCreationParameters::encode(IPC::ArgumentEncoder& encoder) const
     encoder << canRunBeforeUnloadConfirmPanel;
     encoder << canRunModal;
     encoder << deviceScaleFactor;
+    encoder << viewScaleFactor;
     encoder << topContentInset;
     encoder << mediaVolume;
     encoder << muted;
@@ -135,6 +136,8 @@ bool WebPageCreationParameters::decode(IPC::ArgumentDecoder& decoder, WebPageCre
         return false;
     if (!decoder.decode(parameters.deviceScaleFactor))
         return false;
+    if (!decoder.decode(parameters.viewScaleFactor))
+        return false;
     if (!decoder.decode(parameters.topContentInset))
         return false;
     if (!decoder.decode(parameters.mediaVolume))
index bc12897..c923095 100644 (file)
@@ -93,6 +93,7 @@ struct WebPageCreationParameters {
     bool canRunModal;
 
     float deviceScaleFactor;
+    float viewScaleFactor;
 
     float topContentInset;
     
index f4a4f17..6d66a8a 100644 (file)
@@ -35,6 +35,7 @@ extern "C" {
 enum {
     kWKLayoutModeViewSize,
     kWKLayoutModeFixedSize,
+    kWKLayoutModeDynamicSizeComputedFromViewScale
 };
 typedef uint32_t WKLayoutMode;
 
index 417d12c..833ce3f 100644 (file)
@@ -94,6 +94,8 @@
 @property (nonatomic, setter=_setLayoutMode:) WKLayoutMode _layoutMode;
 @property (nonatomic, setter=_setFixedLayoutSize:) CGSize _fixedLayoutSize;
 
+@property (nonatomic, setter=_setViewScale:) CGFloat _viewScale;
+
 @property (nonatomic, setter=_setOverrideDeviceScaleFactor:) CGFloat _overrideDeviceScaleFactor WK_AVAILABLE(WK_MAC_TBA, NA);
 
 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
index ded9963..450365b 100644 (file)
@@ -2269,12 +2269,23 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
 
 - (_WKLayoutMode)_layoutMode
 {
-    return _page->useFixedLayout() ? _WKLayoutModeFixedSize : _WKLayoutModeViewSize;
+    if (_page->useFixedLayout()) {
+#if PLATFORM(MAC)
+        if ([_wkView _automaticallyComputesFixedLayoutSizeFromViewScale])
+            return _WKLayoutModeDynamicSizeComputedFromViewScale;
+#endif
+        return _WKLayoutModeFixedSize;
+    }
+    return _WKLayoutModeViewSize;
 }
 
 - (void)_setLayoutMode:(_WKLayoutMode)layoutMode
 {
-    _page->setUseFixedLayout(layoutMode == _WKLayoutModeFixedSize);
+    _page->setUseFixedLayout(layoutMode == _WKLayoutModeFixedSize || layoutMode == _WKLayoutModeDynamicSizeComputedFromViewScale);
+
+#if PLATFORM(MAC)
+    [_wkView _setAutomaticallyComputesFixedLayoutSizeFromViewScale:(layoutMode == _WKLayoutModeDynamicSizeComputedFromViewScale)];
+#endif
 }
 
 - (CGSize)_fixedLayoutSize
@@ -2287,6 +2298,24 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
     _page->setFixedLayoutSize(WebCore::expandedIntSize(WebCore::FloatSize(fixedLayoutSize)));
 }
 
+- (CGFloat)_viewScale
+{
+    return _page->viewScaleFactor();
+}
+
+- (void)_setViewScale:(CGFloat)viewScale
+{
+    if (viewScale <= 0 || isnan(viewScale) || isinf(viewScale))
+        [NSException raise:NSInvalidArgumentException format:@"View scale should be a positive number"];
+
+    _page->scaleView(viewScale);
+
+#if PLATFORM(MAC)
+    if ([_wkView _automaticallyComputesFixedLayoutSizeFromViewScale])
+        [_wkView _updateAutomaticallyComputedFixedLayoutSize];
+#endif
+}
+
 #pragma mark scrollperf methods
 
 - (void)_setScrollPerformanceDataCollectionEnabled:(BOOL)enabled
@@ -2302,8 +2331,8 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
 - (NSArray *)_scrollPerformanceData
 {
 #if PLATFORM(IOS)
-    if (WebKit::RemoteLayerTreeScrollingPerformanceData* scrollPefData = _page->scrollingPerformanceData())
-        return scrollPefData->data();
+    if (WebKit::RemoteLayerTreeScrollingPerformanceData* scrollPerfData = _page->scrollingPerformanceData())
+        return scrollPerfData->data();
 #endif
     return nil;
 }
index 3650442..121fbd0 100644 (file)
@@ -95,6 +95,8 @@ typedef NS_ENUM(NSInteger, _WKPaginationMode) {
 @property (nonatomic, setter=_setLayoutMode:) _WKLayoutMode _layoutMode;
 @property (nonatomic, setter=_setFixedLayoutSize:) CGSize _fixedLayoutSize;
 
+@property (nonatomic, setter=_setViewScale:) CGFloat _viewScale;
+
 #if TARGET_OS_IPHONE
 // DERECATED: The setters of the three following function are deprecated, please use overrideLayoutParameters.
 // Define the smallest size a page take with a regular viewport.
index 077dac1..eec6aba 100644 (file)
@@ -30,6 +30,7 @@
 typedef NS_ENUM(NSUInteger, _WKLayoutMode) {
     _WKLayoutModeViewSize,
     _WKLayoutModeFixedSize,
+    _WKLayoutModeDynamicSizeComputedFromViewScale
 } WK_ENUM_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA);
 
 #endif
index 178620e..503ac23 100644 (file)
@@ -268,6 +268,7 @@ struct WKViewInterpretKeyEventsParameters {
     BOOL _ignoresNonWheelEvents;
     BOOL _ignoresAllEvents;
     BOOL _allowsBackForwardNavigationGestures;
+    BOOL _automaticallyComputesFixedLayoutSizeFromViewScale;
 
     RetainPtr<CALayer> _rootLayer;
 
@@ -557,9 +558,18 @@ struct WKViewInterpretKeyEventsParameters {
         if (_data->_clipsToVisibleRect)
             [self _updateViewExposedRect];
         [self _setDrawingAreaSize:size];
+        if (_data->_automaticallyComputesFixedLayoutSizeFromViewScale)
+            [self _updateAutomaticallyComputedFixedLayoutSize];
     }
 }
 
+- (void)_updateAutomaticallyComputedFixedLayoutSize
+{
+    ASSERT(_data->_automaticallyComputesFixedLayoutSizeFromViewScale);
+    CGFloat inverseScale = 1 / _data->_page->viewScaleFactor();
+    [self _setFixedLayoutSize:NSMakeSize(self.frame.size.width * inverseScale, self.frame.size.height * inverseScale)];
+}
+
 - (void)_updateWindowAndViewFrames
 {
     if (_data->_clipsToVisibleRect)
@@ -4353,12 +4363,23 @@ static NSString *pathWithUniqueFilenameForPath(NSString *path)
 
 - (WKLayoutMode)_layoutMode
 {
-    return _data->_page->useFixedLayout() ? kWKLayoutModeFixedSize : kWKLayoutModeViewSize;
+    if (_data->_page->useFixedLayout()) {
+#if PLATFORM(MAC)
+        if (self._automaticallyComputesFixedLayoutSizeFromViewScale)
+            return kWKLayoutModeDynamicSizeComputedFromViewScale;
+#endif
+        return kWKLayoutModeFixedSize;
+    }
+    return kWKLayoutModeViewSize;
 }
 
 - (void)_setLayoutMode:(WKLayoutMode)layoutMode
 {
-    _data->_page->setUseFixedLayout(layoutMode == kWKLayoutModeFixedSize);
+    _data->_page->setUseFixedLayout(layoutMode == kWKLayoutModeFixedSize || layoutMode == kWKLayoutModeDynamicSizeComputedFromViewScale);
+
+#if PLATFORM(MAC)
+    self._automaticallyComputesFixedLayoutSizeFromViewScale = (layoutMode == kWKLayoutModeDynamicSizeComputedFromViewScale);
+#endif
 }
 
 - (CGSize)_fixedLayoutSize
@@ -4371,6 +4392,20 @@ static NSString *pathWithUniqueFilenameForPath(NSString *path)
     _data->_page->setFixedLayoutSize(expandedIntSize(FloatSize(fixedLayoutSize)));
 }
 
+- (CGFloat)_viewScale
+{
+    return _data->_page->viewScaleFactor();
+}
+
+- (void)_setViewScale:(CGFloat)viewScale
+{
+    if (viewScale <= 0 || isnan(viewScale) || isinf(viewScale))
+        [NSException raise:NSInvalidArgumentException format:@"View scale should be a positive number"];
+
+    _data->_page->scaleView(viewScale);
+    [self _updateAutomaticallyComputedFixedLayoutSize];
+}
+
 - (void)_dispatchSetTopContentInset
 {
     if (!_data->_didScheduleSetTopContentInset)
@@ -4497,6 +4532,9 @@ static NSString *pathWithUniqueFilenameForPath(NSString *path)
 
 - (void)setMagnification:(double)magnification centeredAtPoint:(NSPoint)point
 {
+    if (magnification <= 0 || isnan(magnification) || isinf(magnification))
+        [NSException raise:NSInvalidArgumentException format:@"Magnification should be a positive number"];
+
     [self _dismissContentRelativeChildWindows];
 
     _data->_page->scalePageInViewCoordinates(magnification, roundedIntPoint(point));
@@ -4504,6 +4542,9 @@ static NSString *pathWithUniqueFilenameForPath(NSString *path)
 
 - (void)setMagnification:(double)magnification
 {
+    if (magnification <= 0 || isnan(magnification) || isinf(magnification))
+        [NSException raise:NSInvalidArgumentException format:@"Magnification should be a positive number"];
+
     [self _dismissContentRelativeChildWindows];
 
     FloatPoint viewCenter(NSMidX([self bounds]), NSMidY([self bounds]));
@@ -4637,6 +4678,24 @@ static NSString *pathWithUniqueFilenameForPath(NSString *path)
 
 #endif
 
+- (void)_setAutomaticallyComputesFixedLayoutSizeFromViewScale:(BOOL)automaticallyComputesFixedLayoutSizeFromViewScale
+{
+    if (_data->_automaticallyComputesFixedLayoutSizeFromViewScale == automaticallyComputesFixedLayoutSizeFromViewScale)
+        return;
+
+    _data->_automaticallyComputesFixedLayoutSizeFromViewScale = automaticallyComputesFixedLayoutSizeFromViewScale;
+
+    if (!_data->_automaticallyComputesFixedLayoutSizeFromViewScale)
+        return;
+
+    [self _updateAutomaticallyComputedFixedLayoutSize];
+}
+
+- (BOOL)_automaticallyComputesFixedLayoutSizeFromViewScale
+{
+    return _data->_automaticallyComputesFixedLayoutSizeFromViewScale;
+}
+
 @end
 
 @implementation WKResponderChainSink
index 3bf7107..9e2a6cd 100644 (file)
@@ -146,4 +146,7 @@ struct WebPageConfiguration;
 
 @property (readonly) NSWindow *_targetWindowForMovePreparation;
 
+@property (nonatomic, setter=_setAutomaticallyComputesFixedLayoutSizeFromViewScale:) BOOL _automaticallyComputesFixedLayoutSizeFromViewScale;
+- (void)_updateAutomaticallyComputedFixedLayoutSize;
+
 @end
index 8a60174..b25b1c9 100644 (file)
@@ -2216,6 +2216,8 @@ double WebPageProxy::pageScaleFactor() const
 
 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
 {
+    ASSERT(scale > 0);
+
     if (!isValid())
         return;
 
@@ -2225,6 +2227,8 @@ void WebPageProxy::scalePage(double scale, const IntPoint& origin)
 
 void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& centerInViewCoordinates)
 {
+    ASSERT(scale > 0);
+
     if (!isValid())
         return;
 
@@ -2232,6 +2236,17 @@ void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& cent
     m_process->send(Messages::WebPage::ScalePageInViewCoordinates(scale, centerInViewCoordinates), m_pageID);
 }
 
+void WebPageProxy::scaleView(double scale)
+{
+    ASSERT(scale > 0);
+
+    if (!isValid())
+        return;
+
+    m_viewScaleFactor = scale;
+    m_process->send(Messages::WebPage::ScaleView(scale), m_pageID);
+}
+
 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
 {
     if (m_intrinsicDeviceScaleFactor == scaleFactor)
@@ -4901,6 +4916,7 @@ WebPageCreationParameters WebPageProxy::creationParameters()
     parameters.canRunBeforeUnloadConfirmPanel = m_uiClient->canRunBeforeUnloadConfirmPanel();
     parameters.canRunModal = m_canRunModal;
     parameters.deviceScaleFactor = deviceScaleFactor();
+    parameters.viewScaleFactor = m_viewScaleFactor;
     parameters.topContentInset = m_topContentInset;
     parameters.mediaVolume = m_mediaVolume;
     parameters.muted = m_muted;
index 42b217e..fade601 100644 (file)
@@ -639,6 +639,8 @@ public:
     void scalePage(double scale, const WebCore::IntPoint& origin);
     void scalePageInViewCoordinates(double scale, const WebCore::IntPoint& centerInViewCoordinates);
     double pageScaleFactor() const;
+    double viewScaleFactor() const { return m_viewScaleFactor; }
+    void scaleView(double scale);
 
     float deviceScaleFactor() const;
     void setIntrinsicDeviceScaleFactor(float);
@@ -1535,6 +1537,7 @@ private:
     double m_pageScaleFactor;
     double m_pluginZoomFactor;
     double m_pluginScaleFactor;
+    double m_viewScaleFactor { 1 };
     float m_intrinsicDeviceScaleFactor;
     float m_customDeviceScaleFactor;
     float m_topContentInset;
index 5e1a63e..0cca892 100644 (file)
@@ -338,6 +338,7 @@ WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
     , m_processSuppressionEnabled(true)
     , m_userActivity("Process suppression disabled for page.")
     , m_pendingNavigationID(0)
+    , m_viewScaleFactor(parameters.viewScaleFactor)
 #if ENABLE(WEBGL)
     , m_systemWebGLPolicy(WebGLAllowCreation)
 #endif
@@ -504,6 +505,9 @@ WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
         m_page->settings().setMediaKeysStorageDirectory(manager->mediaKeyStorageDirectory());
 #endif
     m_page->settings().setAppleMailPaginationQuirkEnabled(parameters.appleMailPaginationQuirkEnabled);
+
+    if (m_viewScaleFactor != 1)
+        scalePage(1, IntPoint());
 }
 
 void WebPage::reinitializeWebPage(const WebPageCreationParameters& parameters)
@@ -1367,7 +1371,8 @@ void WebPage::windowScreenDidChange(uint32_t displayID)
 
 void WebPage::scalePage(double scale, const IntPoint& origin)
 {
-    bool willChangeScaleFactor = scale != pageScaleFactor();
+    double totalScale = scale * m_viewScaleFactor;
+    bool willChangeScaleFactor = totalScale != totalScaleFactor();
 
 #if PLATFORM(IOS)
     if (willChangeScaleFactor) {
@@ -1378,11 +1383,11 @@ void WebPage::scalePage(double scale, const IntPoint& origin)
 #endif
     PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame());
     if (pluginView && pluginView->handlesPageScaleFactor()) {
-        pluginView->setPageScaleFactor(scale, origin);
+        pluginView->setPageScaleFactor(totalScale, origin);
         return;
     }
 
-    m_page->setPageScaleFactor(scale, origin);
+    m_page->setPageScaleFactor(totalScale, origin);
 
     // We can't early return before setPageScaleFactor because the origin might be different.
     if (!willChangeScaleFactor)
@@ -1399,7 +1404,8 @@ void WebPage::scalePage(double scale, const IntPoint& origin)
 
 void WebPage::scalePageInViewCoordinates(double scale, IntPoint centerInViewCoordinates)
 {
-    if (scale == pageScaleFactor())
+    double totalScale = scale * m_viewScaleFactor;
+    if (totalScale == totalScaleFactor())
         return;
 
     IntPoint scrollPositionAtNewScale = mainFrameView()->rootViewToContents(-centerInViewCoordinates);
@@ -1408,7 +1414,7 @@ void WebPage::scalePageInViewCoordinates(double scale, IntPoint centerInViewCoor
     scalePage(scale, scrollPositionAtNewScale);
 }
 
-double WebPage::pageScaleFactor() const
+double WebPage::totalScaleFactor() const
 {
     PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame());
     if (pluginView && pluginView->handlesPageScaleFactor())
@@ -1417,6 +1423,27 @@ double WebPage::pageScaleFactor() const
     return m_page->pageScaleFactor();
 }
 
+double WebPage::pageScaleFactor() const
+{
+    return totalScaleFactor() / m_viewScaleFactor;
+}
+
+void WebPage::scaleView(double scale)
+{
+    float pageScale = pageScaleFactor();
+
+    double scaleRatio = scale / m_viewScaleFactor;
+
+    IntPoint scrollPositionAtNewScale;
+    if (FrameView* mainFrameView = m_page->mainFrame().view()) {
+        scrollPositionAtNewScale = mainFrameView->scrollPosition();
+        scrollPositionAtNewScale.scale(scaleRatio, scaleRatio);
+    }
+
+    m_viewScaleFactor = scale;
+    scalePage(pageScale, scrollPositionAtNewScale);
+}
+
 void WebPage::setDeviceScaleFactor(float scaleFactor)
 {
     if (scaleFactor == m_page->deviceScaleFactor())
index 9bc33f7..ce438d2 100644 (file)
@@ -357,6 +357,9 @@ public:
     void scalePage(double scale, const WebCore::IntPoint& origin);
     void scalePageInViewCoordinates(double scale, WebCore::IntPoint centerInViewCoordinates);
     double pageScaleFactor() const;
+    double totalScaleFactor() const;
+    double viewScaleFactor() const { return m_viewScaleFactor; }
+    void scaleView(double scale);
 
     void setUseFixedLayout(bool);
     bool useFixedLayout() const { return m_useFixedLayout; }
@@ -1342,6 +1345,8 @@ private:
 
     uint64_t m_pendingNavigationID;
 
+    double m_viewScaleFactor { 1 };
+
 #if ENABLE(WEBGL)
     WebCore::WebGLLoadPolicy m_systemWebGLPolicy;
 #endif
index 49a24e1..8fdd68d 100644 (file)
@@ -196,6 +196,7 @@ messages -> WebPage LegacyReceiver {
 
     ScalePage(double scale, WebCore::IntPoint origin)
     ScalePageInViewCoordinates(double scale, WebCore::IntPoint centerInViewCoordinates)
+    ScaleView(double scale)
 
     SetUseFixedLayout(bool fixed)
     SetFixedLayoutSize(WebCore::IntSize size)
index f0759f2..d73104f 100644 (file)
@@ -616,9 +616,11 @@ void TiledCoreAnimationDrawingArea::applyTransientZoomToLayers(double scale, Flo
 
 void TiledCoreAnimationDrawingArea::adjustTransientZoom(double scale, FloatPoint origin)
 {
+    scale *= m_webPage.viewScaleFactor();
+
     applyTransientZoomToLayers(scale, origin);
 
-    double currentPageScale = m_webPage.pageScaleFactor();
+    double currentPageScale = m_webPage.totalScaleFactor();
     if (scale > currentPageScale)
         return;
 
@@ -644,6 +646,8 @@ static RetainPtr<CABasicAnimation> transientZoomSnapAnimationForKeyPath(String k
 
 void TiledCoreAnimationDrawingArea::commitTransientZoom(double scale, FloatPoint origin)
 {
+    scale *= m_webPage.viewScaleFactor();
+
     FrameView& frameView = *m_webPage.mainFrameView();
     FloatRect visibleContentRect = frameView.visibleContentRectIncludingScrollbars();
 
@@ -651,7 +655,7 @@ void TiledCoreAnimationDrawingArea::commitTransientZoom(double scale, FloatPoint
     constrainedOrigin.moveBy(-origin);
 
     IntSize scaledTotalContentsSize = frameView.totalContentsSize();
-    scaledTotalContentsSize.scale(scale / m_webPage.pageScaleFactor());
+    scaledTotalContentsSize.scale(scale / m_webPage.totalScaleFactor());
 
     // Scaling may have exposed the overhang area, so we need to constrain the final
     // layer position exactly like scrolling will once it's committed, to ensure that
@@ -730,7 +734,7 @@ void TiledCoreAnimationDrawingArea::applyTransientZoomToPage(double scale, Float
     FloatPoint unscrolledOrigin(origin);
     FloatRect unobscuredContentRect = frameView.unobscuredContentRectIncludingScrollbars();
     unscrolledOrigin.moveBy(-unobscuredContentRect.location());
-    m_webPage.scalePage(scale, roundedIntPoint(-unscrolledOrigin));
+    m_webPage.scalePage(scale / m_webPage.viewScaleFactor(), roundedIntPoint(-unscrolledOrigin));
     m_transientZoomScale = 1;
     flushLayers();
 }
index 03cc54c..b884445 100644 (file)
@@ -1,3 +1,25 @@
+2015-04-13  Tim Horton  <timothy_horton@apple.com>
+
+        Add a persistent, fixed scale factor to make it easy to scale down WK(Web)Views
+        https://bugs.webkit.org/show_bug.cgi?id=143560
+        <rdar://problem/16302047>
+
+        Reviewed by Darin Adler.
+
+        * MiniBrowser/mac/BrowserWindowController.h:
+        * MiniBrowser/mac/MainMenu.xib:
+        * MiniBrowser/mac/WK1BrowserWindowController.m:
+        (-[WK1BrowserWindowController setScale:]):
+        * MiniBrowser/mac/WK2BrowserWindowController.m:
+        (viewScaleForMenuItemTag):
+        (-[WK2BrowserWindowController setScale:]):
+        (-[WK2BrowserWindowController validateMenuItem:]):
+        Add a submenu with four view scale options: 100%, 75%, 50%, and 25%.
+        When in use, we resize the window so that the view fits correctly, and
+        use automaticallyComputesFixedlayoutSizeFromViewScale so that the page's
+        layout size will not change when scaling down (but will update appropriately
+        when the view is resized).
+
 2015-04-13  Alexey Proskuryakov  <ap@apple.com>
 
         build.webkit.org/dashboard shows obsolete results when builds are substantially out of order
index 1d8ad76..4bcde80 100644 (file)
@@ -45,6 +45,8 @@
 
 - (IBAction)toggleZoomMode:(id)sender;
 
+- (IBAction)setScale:(id)sender;
+
 - (IBAction)dumpSourceToConsole:(id)sender;
 - (IBAction)find:(id)sender;
 
index 6e837b0..c329c85 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7504.2" systemVersion="14D89" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="8040.1" systemVersion="14D106" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
     <dependencies>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7504.2"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="8040.1"/>
     </dependencies>
     <objects>
         <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
                                     <action selector="toggleZoomMode:" target="-1" id="564"/>
                                 </connections>
                             </menuItem>
+                            <menuItem title="View Scale" id="8UY-Pj-H13">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <menu key="submenu" title="View Scale" id="Ml8-mk-ffu">
+                                    <items>
+                                        <menuItem title="100%" state="on" tag="1" keyEquivalent="1" id="EAm-Xn-VrC">
+                                            <connections>
+                                                <action selector="setScale:" target="-1" id="aaW-VE-lxu"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="75%" tag="2" keyEquivalent="2" id="jcA-I1-Cbq">
+                                            <connections>
+                                                <action selector="setScale:" target="-1" id="voc-3W-ppg"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="50%" tag="3" keyEquivalent="3" id="BRM-D5-YNO">
+                                            <connections>
+                                                <action selector="setScale:" target="-1" id="sfY-6N-EeS"/>
+                                            </connections>
+                                        </menuItem>
+                                        <menuItem title="25%" tag="4" keyEquivalent="4" id="gzk-YK-x0W">
+                                            <connections>
+                                                <action selector="setScale:" target="-1" id="WPq-Rm-CVA"/>
+                                            </connections>
+                                        </menuItem>
+                                    </items>
+                                </menu>
+                            </menuItem>
                             <menuItem isSeparatorItem="YES" id="581"/>
                             <menuItem title="Reload Page" keyEquivalent="r" id="579">
                                 <connections>
index 23f53c4..9f06f66 100644 (file)
     }
 }
 
+- (IBAction)setScale:(id)sender
+{
+    
+}
+
 - (IBAction)reload:(id)sender
 {
     [_webView reload:sender];
index 08504eb..8b52c38 100644 (file)
@@ -33,7 +33,6 @@
 #import <WebKit/WKNavigationDelegate.h>
 #import <WebKit/WKPreferencesPrivate.h>
 #import <WebKit/WKUIDelegate.h>
-#import <WebKit/WKWebView.h>
 #import <WebKit/WKWebViewConfigurationPrivate.h>
 #import <WebKit/WKWebViewPrivate.h>
 #import <WebKit/WebNSURLExtras.h>
@@ -124,6 +123,37 @@ static void* keyValueObservingContext = &keyValueObservingContext;
     }
 }
 
+static CGFloat viewScaleForMenuItemTag(NSInteger tag)
+{
+    if (tag == 1)
+        return 1;
+    if (tag == 2)
+        return 0.75;
+    if (tag == 3)
+        return 0.5;
+    if (tag == 4)
+        return 0.25;
+
+    return 1;
+}
+
+- (IBAction)setScale:(id)sender
+{
+    CGFloat scale = viewScaleForMenuItemTag([sender tag]);
+    CGFloat oldScale = [_webView _viewScale];
+
+    if (scale == oldScale)
+        return;
+
+    [_webView _setLayoutMode:_WKLayoutModeDynamicSizeComputedFromViewScale];
+
+    NSRect oldFrame = self.window.frame;
+    NSSize newFrameSize = NSMakeSize(oldFrame.size.width * (scale / oldScale), oldFrame.size.height * (scale / oldScale));
+    [self.window setFrame:NSMakeRect(oldFrame.origin.x, oldFrame.origin.y - (newFrameSize.height - oldFrame.size.height), newFrameSize.width, newFrameSize.height) display:NO animate:NO];
+
+    [_webView _setViewScale:scale];
+}
+
 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
 {
     SEL action = [menuItem action];
@@ -148,6 +178,9 @@ static void* keyValueObservingContext = &keyValueObservingContext;
     else if (action == @selector(toggleZoomMode:))
         [menuItem setState:_zoomTextOnly ? NSOnState : NSOffState];
 
+    if (action == @selector(setScale:))
+        [menuItem setState:[_webView _viewScale] == viewScaleForMenuItemTag([menuItem tag])];
+
     return YES;
 }