- Revision
- 160685
- Author
- [email protected]
- Date
- 2013-12-16 18:12:31 -0800 (Mon, 16 Dec 2013)
Log Message
WebKit2 View Gestures: Pinching beyond the extremes doesn't animate back to the min/max
https://bugs.webkit.org/show_bug.cgi?id=125750
Reviewed by Simon Fraser.
When you let go of a pinch where you exceeded the maximum or minimum scale,
the view should animate back to the limit instead of snapping back.
* UIProcess/mac/ViewGestureController.cpp:
(WebKit::ViewGestureController::endMagnificationGesture):
Unscrolling the scaled origin here is wrong; we should send the same
value for 'origin' for commitTransientZoom that we do for adjustTransientZoom.
The drawing area can deal with transforming that however it needs to call scalePage().
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::beginTransientZoom):
Drive-by use WebPage::mainFrameView().
(WebKit::TiledCoreAnimationDrawingArea::adjustTransientZoom):
Update the shadow layer's bounds, position, and shadow path while zooming,
instead of hiding it.
(WebKit::transientZoomSnapAnimationForKeyPath):
Create a CABasicAnimation that stays applied to its target when it finishes,
lasts for a quarter second, and uses the ease-in-ease-out timing function.
(WebKit::constrainZoomOriginForFrameView):
When we land a transient zoom, there may be overhang areas (linen, in the case of Mac)
visible. During the commit animation, we should move the RenderView layer appropriately
so that the page covers the entire view and there are no overhang areas visible.
Adapt some code from ScrollableArea to constrain the zoom origin to do so.
(WebKit::TiledCoreAnimationDrawingArea::commitTransientZoom):
Animate the RenderView layer's transform, and the shadow layer's bounds, position, and path.
When they complete, apply the zoom via scalePage() and flush the layer tree (otherwise there
can be a flash between removing the animations and the next flush with the new scale).
(WebKit::TiledCoreAnimationDrawingArea::applyTransientZoomToPage):
Move the code to land the transient zoom (via scalePage) and to put the shadow back
in the state WebCore left it out into its own function, so it can be called both from the
animation completion callback and from the short-circuit in the case where we don't need to animate.
* WebCore.exp.in:
Export a few things so WebKit2 can use them.
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (160684 => 160685)
--- trunk/Source/WebCore/ChangeLog 2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebCore/ChangeLog 2013-12-17 02:12:31 UTC (rev 160685)
@@ -1,3 +1,13 @@
+2013-12-16 Tim Horton <[email protected]>
+
+ WebKit2 View Gestures: Pinching beyond the extremes doesn't animate back to the min/max
+ https://bugs.webkit.org/show_bug.cgi?id=125750
+
+ Reviewed by Simon Fraser.
+
+ * WebCore.exp.in:
+ Export a few things so WebKit2 can use them.
+
2013-12-16 Joseph Pecoraro <[email protected]>
Fix some whitespace issues in inspector code
Modified: trunk/Source/WebCore/WebCore.exp.in (160684 => 160685)
--- trunk/Source/WebCore/WebCore.exp.in 2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebCore/WebCore.exp.in 2013-12-17 02:12:31 UTC (rev 160685)
@@ -399,6 +399,7 @@
__ZN7WebCore14ScrollableArea27notifyScrollPositionChangedERKNS_8IntPointE
__ZN7WebCore14ScrollableArea28setScrollOffsetFromInternalsERKNS_8IntPointE
__ZN7WebCore14ScrollableArea30scrollToOffsetWithoutAnimationERKNS_10FloatPointE
+__ZN7WebCore14ScrollableArea34constrainScrollPositionForOverhangERKNS_7IntRectERKNS_7IntSizeERKNS_8IntPointES9_ii
__ZN7WebCore14ScrollableArea6scrollENS_15ScrollDirectionENS_17ScrollGranularityEf
__ZN7WebCore14ScrollableAreaC2Ev
__ZN7WebCore14ScrollableAreaD2Ev
@@ -437,6 +438,7 @@
__ZN7WebCore14decodeHostNameEP8NSString
__ZN7WebCore14encodeHostNameEP8NSString
__ZN7WebCore14endOfParagraphERKNS_15VisiblePositionENS_27EditingBoundaryCrossingRuleE
+__ZN7WebCore14roundedIntRectERKNS_9FloatRectE
__ZN7WebCore14setMetadataURLERN3WTF6StringERKS1_S4_
__ZN7WebCore15AffineTransform5flipYEv
__ZN7WebCore15AffineTransform5scaleEd
@@ -757,6 +759,9 @@
__ZN7WebCore19ResourceRequestBase25setDefaultTimeoutIntervalEd
__ZN7WebCore19ResourceRequestBase50setResponseContentDispositionEncodingFallbackArrayERKN3WTF6StringES4_S4_
__ZN7WebCore19ResourceRequestBase6setURLERKNS_3URLE
+__ZN7WebCore19PlatformCAAnimation6createEP19CAPropertyAnimation
+__ZN7WebCore19PlatformCAAnimation10setToValueERKNS_20TransformationMatrixE
+__ZN7WebCore19PlatformCAAnimationD1Ev
__ZN7WebCore19TextResourceDecoder5flushEv
__ZN7WebCore19TextResourceDecoder6decodeEPKcm
__ZN7WebCore19TextResourceDecoderC1ERKN3WTF6StringERKNS_12TextEncodingEb
@@ -1232,6 +1237,7 @@
__ZN7WebCore9DOMWindow30dispatchAllPendingUnloadEventsEv
__ZN7WebCore9DOMWindow36dispatchAllPendingBeforeUnloadEventsEv
__ZN7WebCore9FloatRect5scaleEff
+__ZN7WebCore9FloatRect9intersectERKS0_
__ZN7WebCore9FloatRectC1ERK6CGRect
__ZN7WebCore9FloatRectC1ERKNS_7IntRectE
__ZN7WebCore9FloatSizeC1ERK6CGSize
@@ -1393,6 +1399,7 @@
__ZNK7WebCore10RenderText9firstRunXEv
__ZNK7WebCore10RenderText9firstRunYEv
__ZNK7WebCore10RenderView12documentRectEv
+__ZNK7WebCore10RenderView20unscaledDocumentRectEv
__ZNK7WebCore10ScrollView12contentsSizeEv
__ZNK7WebCore10ScrollView12documentViewEv
__ZNK7WebCore10ScrollView14scrollbarModesERNS_13ScrollbarModeES2_
Modified: trunk/Source/WebCore/platform/KeyedCoding.h (160684 => 160685)
--- trunk/Source/WebCore/platform/KeyedCoding.h 2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebCore/platform/KeyedCoding.h 2013-12-17 02:12:31 UTC (rev 160685)
@@ -35,63 +35,7 @@
virtual ~KeyedEncoder() { }
public:
- virtual void encodeBytes(const String& key, const uint8_t*, size_t) = 0;
- virtual void encodeBool(const String& key, bool) = 0;
virtual void encodeUInt32(const String& key, uint32_t) = 0;
- virtual void encodeInt32(const String& key, int32_t) = 0;
- virtual void encodeInt64(const String& key, int64_t) = 0;
- virtual void encodeFloat(const String& key, float) = 0;
- virtual void encodeDouble(const String& key, double) = 0;
- virtual void encodeString(const String& key, const String&) = 0;
-
- template<typename T>
- void encodeEnum(const String& key, T value)
- {
- static_assert(std::is_enum<T>::value, "T must be an enum type");
-
- encodeInt64(key, static_cast<int64_t>(value));
- }
-
- template<typename T, typename F>
- void encodeObject(const String& key, const T& object, F&& function)
- {
- beginObject(key);
- function(*this, object);
- endObject();
- }
-
- template<typename T, typename F>
- void encodeConditionalObject(const String& key, const T* object, F&& function)
- {
- if (!object)
- return;
-
- encodeObject(key, *object, std::forward<F>(function));
- }
-
- template<typename T, typename F>
- void encodeObjects(const String& key, T begin, T end, F&& function)
- {
- if (begin == end)
- return;
-
- beginArray(key);
- for (T it = begin; it != end; ++it) {
- beginArrayElement();
- function(*this, *it);
- endArrayElement();
- }
- endArray();
- }
-
-private:
- virtual void beginObject(const String& key) = 0;
- virtual void endObject() = 0;
-
- virtual void beginArray(const String& key) = 0;
- virtual void beginArrayElement() = 0;
- virtual void endArrayElement() = 0;
- virtual void endArray() = 0;
};
} // namespace WebCore
Modified: trunk/Source/WebKit2/ChangeLog (160684 => 160685)
--- trunk/Source/WebKit2/ChangeLog 2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebKit2/ChangeLog 2013-12-17 02:12:31 UTC (rev 160685)
@@ -1,3 +1,48 @@
+2013-12-16 Tim Horton <[email protected]>
+
+ WebKit2 View Gestures: Pinching beyond the extremes doesn't animate back to the min/max
+ https://bugs.webkit.org/show_bug.cgi?id=125750
+
+ Reviewed by Simon Fraser.
+
+ When you let go of a pinch where you exceeded the maximum or minimum scale,
+ the view should animate back to the limit instead of snapping back.
+
+ * UIProcess/mac/ViewGestureController.cpp:
+ (WebKit::ViewGestureController::endMagnificationGesture):
+ Unscrolling the scaled origin here is wrong; we should send the same
+ value for 'origin' for commitTransientZoom that we do for adjustTransientZoom.
+ The drawing area can deal with transforming that however it needs to call scalePage().
+
+ * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
+ * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
+ (WebKit::TiledCoreAnimationDrawingArea::beginTransientZoom):
+ Drive-by use WebPage::mainFrameView().
+
+ (WebKit::TiledCoreAnimationDrawingArea::adjustTransientZoom):
+ Update the shadow layer's bounds, position, and shadow path while zooming,
+ instead of hiding it.
+
+ (WebKit::transientZoomSnapAnimationForKeyPath):
+ Create a CABasicAnimation that stays applied to its target when it finishes,
+ lasts for a quarter second, and uses the ease-in-ease-out timing function.
+
+ (WebKit::constrainZoomOriginForFrameView):
+ When we land a transient zoom, there may be overhang areas (linen, in the case of Mac)
+ visible. During the commit animation, we should move the RenderView layer appropriately
+ so that the page covers the entire view and there are no overhang areas visible.
+ Adapt some code from ScrollableArea to constrain the zoom origin to do so.
+
+ (WebKit::TiledCoreAnimationDrawingArea::commitTransientZoom):
+ Animate the RenderView layer's transform, and the shadow layer's bounds, position, and path.
+ When they complete, apply the zoom via scalePage() and flush the layer tree (otherwise there
+ can be a flash between removing the animations and the next flush with the new scale).
+
+ (WebKit::TiledCoreAnimationDrawingArea::applyTransientZoomToPage):
+ Move the code to land the transient zoom (via scalePage) and to put the shadow back
+ in the state WebCore left it out into its own function, so it can be called both from the
+ animation completion callback and from the short-circuit in the case where we don't need to animate.
+
2013-12-16 Ryuan Choi <[email protected]>
Unreviewed. Fix GTK+ build after r160653.
Modified: trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.cpp (160684 => 160685)
--- trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.cpp 2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.cpp 2013-12-17 02:12:31 UTC (rev 160685)
@@ -122,13 +122,8 @@
{
ASSERT(m_activeGestureType == ViewGestureType::Magnification);
- // FIXME: Should rubber-band back when zoomed in or out past the limit.
double newMagnification = std::min(std::max(m_magnification, minMagnification), maxMagnification);
-
- FloatPoint scaledOrigin = scaledMagnificationOrigin(m_magnificationOrigin, newMagnification);
- scaledOrigin.moveBy(-m_visibleContentRect.location());
-
- m_webPageProxy.drawingArea()->commitTransientZoom(newMagnification, -scaledOrigin);
+ m_webPageProxy.drawingArea()->commitTransientZoom(newMagnification, scaledMagnificationOrigin(m_magnificationOrigin, newMagnification));
}
void ViewGestureController::endActiveGesture()
Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h (160684 => 160685)
--- trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h 2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h 2013-12-17 02:12:31 UTC (rev 160685)
@@ -107,6 +107,7 @@
virtual void beginTransientZoom() OVERRIDE;
virtual void adjustTransientZoom(double scale, WebCore::FloatPoint origin) OVERRIDE;
virtual void commitTransientZoom(double scale, WebCore::FloatPoint origin) OVERRIDE;
+ void applyTransientZoomToPage(double scale, WebCore::FloatPoint origin);
void updateLayerHostingContext();
Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm (160684 => 160685)
--- trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm 2013-12-17 02:02:42 UTC (rev 160684)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm 2013-12-17 02:12:31 UTC (rev 160685)
@@ -47,6 +47,7 @@
#import <WebCore/RenderLayerBacking.h>
#import <WebCore/RenderLayerCompositor.h>
#import <WebCore/RenderView.h>
+#import <WebCore/ScrollbarTheme.h>
#import <WebCore/Settings.h>
#import <WebCore/TiledBacking.h>
#import <wtf/MainThread.h>
@@ -702,7 +703,7 @@
void TiledCoreAnimationDrawingArea::beginTransientZoom()
{
- FloatRect visibleContentRect = m_webPage->corePage()->mainFrame().view()->visibleContentRect(ScrollableArea::IncludeScrollbars);
+ FloatRect visibleContentRect = m_webPage->mainFrameView()->visibleContentRect(ScrollableArea::IncludeScrollbars);
m_webPage->send(Messages::ViewGestureController::DidBeginTransientZoom(visibleContentRect));
}
@@ -715,38 +716,153 @@
if (!m_rootLayer)
return;
- RenderView* renderView = m_webPage->corePage()->mainFrame().view()->renderView();
-
TransformationMatrix transform;
transform.translate(origin.x(), origin.y());
transform.scale(scale);
+ RenderView* renderView = m_webPage->mainFrameView()->renderView();
PlatformCALayer* renderViewLayer = static_cast<GraphicsLayerCA*>(renderView->layer()->backing()->graphicsLayer())->platformCALayer();
renderViewLayer->setTransform(transform);
renderViewLayer->setAnchorPoint(FloatPoint3D());
renderViewLayer->setPosition(FloatPoint3D());
- // FIXME: We should transform the shadow layer as well, instead of hiding it.
PlatformCALayer* shadowLayer = static_cast<GraphicsLayerCA*>(renderView->compositor().layerForContentShadow())->platformCALayer();
- shadowLayer->setHidden(true);
+ FloatRect shadowBounds = FloatRect(FloatPoint(), toFloatSize(renderView->layoutOverflowRect().maxXMaxYCorner()));
+ shadowBounds.scale(scale);
+
+ shadowLayer->setBounds(shadowBounds);
+ shadowLayer->setPosition(origin + shadowBounds.center());
+ shadowLayer->platformLayer().shadowPath = adoptCF(CGPathCreateWithRect(shadowBounds, NULL)).get();
+
m_transientZoomScale = scale;
}
+static RetainPtr<CABasicAnimation> transientZoomSnapAnimationForKeyPath(String keyPath)
+{
+ const float transientZoomSnapBackDuration = 0.25;
+
+ RetainPtr<CABasicAnimation> animation = [CABasicAnimation animationWithKeyPath:keyPath];
+ [animation setDuration:transientZoomSnapBackDuration];
+ [animation setFillMode:kCAFillModeForwards];
+ [animation setRemovedOnCompletion:false];
+ [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
+
+ return animation;
+}
+
+/*static FloatPoint constrainZoomOriginForFrameView(double scale, FloatPoint origin, FrameView* frameView)
+{
+ // 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
+ // scrolling doesn't make the view jump; this is borrowed from ScrollableArea.
+ FloatRect visibleContentRect = frameView->visibleContentRect(ScrollableArea::IncludeScrollbars);
+
+ FloatRect zoomContentRect = visibleContentRect;
+ zoomContentRect.moveBy(-origin);
+
+ FloatRect documentRect = frameView->renderView()->unscaledDocumentRect();
+ documentRect.scale(scale);
+ zoomContentRect.intersect(documentRect);
+
+ if (zoomContentRect.size() != visibleContentRect.size()) {
+ zoomContentRect.setSize(visibleContentRect.size());
+ zoomContentRect.intersect(documentRect);
+ if (zoomContentRect.width() < visibleContentRect.width())
+ zoomContentRect.move(-(visibleContentRect.width() - zoomContentRect.width()), 0);
+ if (zoomContentRect.height() < visibleContentRect.height())
+ zoomContentRect.move(0, -(visibleContentRect.height() - zoomContentRect.height()));
+ }
+
+ FloatPoint constrainedOrigin = zoomContentRect.location();
+ constrainedOrigin.moveBy(-visibleContentRect.location());
+
+ return -constrainedOrigin;
+}*/
+
void TiledCoreAnimationDrawingArea::commitTransientZoom(double scale, FloatPoint origin)
{
- RenderView* renderView = m_webPage->corePage()->mainFrame().view()->renderView();
+ FrameView* frameView = m_webPage->mainFrameView();
+ RenderView* renderView = frameView->renderView();
+ PlatformCALayer* renderViewLayer = static_cast<GraphicsLayerCA*>(renderView->layer()->backing()->graphicsLayer())->platformCALayer();
- // If the page scale is already the target scale, scalePage() will short-circuit
- // and not apply the transform, so we can't depend on it to do so.
+ FloatRect visibleContentRect = frameView->visibleContentRect(ScrollableArea::IncludeScrollbars);
+
+ FloatPoint constrainedOrigin = visibleContentRect.location();
+ constrainedOrigin.moveBy(-origin);
+
+ IntRect documentRect = frameView->renderView()->unscaledDocumentRect();
+ documentRect.scale(scale);
+
+ constrainedOrigin = ScrollableArea::constrainScrollPositionForOverhang(roundedIntRect(visibleContentRect), documentRect.size(), roundedIntPoint(constrainedOrigin), IntPoint(), 0, 0);
+ constrainedOrigin.moveBy(-visibleContentRect.location());
+ constrainedOrigin = -constrainedOrigin;
+
+ if (m_transientZoomScale == scale && roundedIntPoint(origin) == roundedIntPoint(constrainedOrigin)) {
+ // We're already at the right scale and position, so we don't need to animate.
+ applyTransientZoomToPage(scale, origin);
+ return;
+ }
+
TransformationMatrix transform;
+ transform.translate(constrainedOrigin.x(), constrainedOrigin.y());
transform.scale(scale);
- static_cast<GraphicsLayerCA*>(renderView->layer()->backing()->graphicsLayer())->platformCALayer()->setTransform(transform);
+ RetainPtr<CABasicAnimation> renderViewAnimationCA = transientZoomSnapAnimationForKeyPath("transform");
+ RefPtr<PlatformCAAnimation> renderViewAnimation = PlatformCAAnimation::create(renderViewAnimationCA.get());
+ renderViewAnimation->setToValue(transform);
+
+ RetainPtr<CALayer> shadowLayer = static_cast<GraphicsLayerCA*>(renderView->compositor().layerForContentShadow())->platformCALayer()->platformLayer();
+
+ FloatRect shadowBounds = FloatRect(FloatPoint(), toFloatSize(renderView->layoutOverflowRect().maxXMaxYCorner()));
+ shadowBounds.scale(scale);
+ RetainPtr<CGPathRef> shadowPath = adoptCF(CGPathCreateWithRect(shadowBounds, NULL)).get();
+
+ RetainPtr<CABasicAnimation> shadowBoundsAnimation = transientZoomSnapAnimationForKeyPath("bounds");
+ [shadowBoundsAnimation setToValue:[NSValue valueWithRect:shadowBounds]];
+ RetainPtr<CABasicAnimation> shadowPositionAnimation = transientZoomSnapAnimationForKeyPath("position");
+ [shadowBoundsAnimation setToValue:[NSValue valueWithPoint:constrainedOrigin + shadowBounds.center()]];
+ RetainPtr<CABasicAnimation> shadowPathAnimation = transientZoomSnapAnimationForKeyPath("shadowPath");
+ [shadowBoundsAnimation setToValue:(id)shadowPath.get()];
+
+ [CATransaction begin];
+ [CATransaction setCompletionBlock:^(void) {
+ renderViewLayer->removeAnimationForKey("transientZoomCommit");
+ [shadowLayer removeAllAnimations];
+ applyTransientZoomToPage(scale, origin);
+ }];
+
+ renderViewLayer->addAnimationForKey("transientZoomCommit", renderViewAnimation.get());
+ [shadowLayer addAnimation:shadowBoundsAnimation.get() forKey:@"transientZoomCommitShadowBounds"];
+ [shadowLayer addAnimation:shadowPositionAnimation.get() forKey:@"transientZoomCommitShadowPosition"];
+ [shadowLayer addAnimation:shadowPathAnimation.get() forKey:@"transientZoomCommitShadowPath"];
+
+ [CATransaction commit];
+}
+
+void TiledCoreAnimationDrawingArea::applyTransientZoomToPage(double scale, FloatPoint origin)
+{
+ RenderView* renderView = m_webPage->mainFrameView()->renderView();
+ PlatformCALayer* renderViewLayer = static_cast<GraphicsLayerCA*>(renderView->layer()->backing()->graphicsLayer())->platformCALayer();
+
+ TransformationMatrix finalTransform;
+ finalTransform.scale(scale);
+
+ // If the page scale is already the target scale, setPageScaleFactor() will short-circuit
+ // and not apply the transform, so we can't depend on it to do so.
+ renderViewLayer->setTransform(finalTransform);
+
PlatformCALayer* shadowLayer = static_cast<GraphicsLayerCA*>(renderView->compositor().layerForContentShadow())->platformCALayer();
- shadowLayer->setHidden(false);
+ IntRect overflowRect = renderView->pixelSnappedLayoutOverflowRect();
+ shadowLayer->setBounds(IntRect(IntPoint(), toIntSize(overflowRect.maxXMaxYCorner())));
+ shadowLayer->setPosition(shadowLayer->bounds().center());
+ ScrollbarTheme::theme()->setUpContentShadowLayer(renderView->compositor().layerForContentShadow());
- m_webPage->scalePage(scale, roundedIntPoint(origin));
+ FloatPoint unscrolledOrigin(origin);
+ FloatRect visibleContentRect = m_webPage->mainFrameView()->visibleContentRect(ScrollableArea::IncludeScrollbars);
+ unscrolledOrigin.moveBy(-visibleContentRect.location());
+ m_webPage->scalePage(scale, roundedIntPoint(-unscrolledOrigin));
+ flushLayers();
}
} // namespace WebKit