Title: [160923] trunk/Source
Revision
160923
Author
timothy_hor...@apple.com
Date
2013-12-20 14:01:27 -0800 (Fri, 20 Dec 2013)

Log Message

WebKit2 View Gestures: Implement smartMagnifyWithEvent: and make it work
https://bugs.webkit.org/show_bug.cgi?id=125752
<rdar://problem/15664245>

Reviewed by Anders Carlsson.

Implement "smart magnify", which is the double-tap-to-zoom gesture on OS X.

* UIProcess/API/mac/WKView.mm:
(-[WKView smartMagnifyWithEvent:]):
Forward smartMagnifyWithEvent to ViewGestureController.

* UIProcess/mac/ViewGestureController.cpp:
(WebKit::ViewGestureController::handleMagnificationGesture):
Drive-by repair a comment.

(WebKit::ViewGestureController::handleSmartMagnificationGesture):
Added. Immediately dispatch a message to the web process to retrieve
the rendered rect of the element under the gesture.

(WebKit::maximumRectangleComponentDelta):
Return the absolute maximum delta between corresponding components of two rects.

(WebKit::ViewGestureController::didCollectGeometryForSmartMagnificationGesture):
Once the WebProcess has replied with the relevant geometry, use it to
determine our target rectangle (the element's rect, with some padding)
and target magnification (attempting to keep replaced elements
fully in-view, and otherwise zooming in as far as possible to fit the
element's width).

If this gesture occurs after the page is already magnified, and targets
a similar region to the previous smart magnification gesture, zoom out
instead of panning across the page.

Begin a transient zoom with the current magnification, and immediately
commit it at our target magnification and offset, so that the drawing
area will animate to the new parameters.

(WebKit::ViewGestureController::endActiveGesture):
* UIProcess/mac/ViewGestureController.h:
* UIProcess/mac/ViewGestureController.messages.in:
* WebProcess/WebPage/ViewGestureGeometryCollector.cpp:
(WebKit::ViewGestureGeometryCollector::collectGeometryForSmartMagnificationGesture):
Hit-test the document to determine the node under the smart magnification
gesture, and return it to the UI process along with various other bits of data.

* WebProcess/WebPage/ViewGestureGeometryCollector.h:
* WebProcess/WebPage/ViewGestureGeometryCollector.messages.in:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea):
(WebKit::TiledCoreAnimationDrawingArea::adjustTransientZoom):
(WebKit::TiledCoreAnimationDrawingArea::commitTransientZoom):
(WebKit::TiledCoreAnimationDrawingArea::applyTransientZoomToPage):
Instead of short-circuiting the animation if we didn't have to constrain
the origin, short-circuit if we're already *at* the right origin,
like the comment said. This prevents jarring jumps when double-tap-panning
between elements when zoomed all the way in.

* WebCore.exp.in:
Add some exports.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (160922 => 160923)


--- trunk/Source/WebCore/ChangeLog	2013-12-20 21:00:46 UTC (rev 160922)
+++ trunk/Source/WebCore/ChangeLog	2013-12-20 22:01:27 UTC (rev 160923)
@@ -1,3 +1,14 @@
+2013-12-20  Tim Horton  <timothy_hor...@apple.com>
+
+        WebKit2 View Gestures: Implement smartMagnifyWithEvent: and make it work
+        https://bugs.webkit.org/show_bug.cgi?id=125752
+        <rdar://problem/15664245>
+
+        Reviewed by Anders Carlsson.
+
+        * WebCore.exp.in:
+        Add some exports.
+
 2013-12-20  Antti Koivisto  <an...@apple.com>
 
         http/tests/misc/object-image-error.html asserts

Modified: trunk/Source/WebCore/WebCore.exp.in (160922 => 160923)


--- trunk/Source/WebCore/WebCore.exp.in	2013-12-20 21:00:46 UTC (rev 160922)
+++ trunk/Source/WebCore/WebCore.exp.in	2013-12-20 22:01:27 UTC (rev 160923)
@@ -283,6 +283,7 @@
 __ZN7WebCore13HTTPHeaderMapD1Ev
 __ZN7WebCore13HitTestResultC1ERKNS_11LayoutPointE
 __ZN7WebCore13HitTestResultC1ERKNS_11LayoutPointEjjjj
+__ZN7WebCore13HitTestResultC1ERKNS_15HitTestLocationE
 __ZN7WebCore13HitTestResultC1ERKS0_
 __ZN7WebCore13HitTestResultD1Ev
 __ZN7WebCore13IdentifierRep3getEPKc
@@ -576,6 +577,8 @@
 __ZN7WebCore15GraphicsLayerCAD2Ev
 __ZN7WebCore15GraphicsLayerCA19setCustomAppearanceENS_13GraphicsLayer16CustomAppearanceE
 __ZN7WebCore15HitTestLocation12rectForPointERKNS_11LayoutPointEjjjj
+__ZN7WebCore15HitTestLocationC1ERKNS_10FloatPointE
+__ZN7WebCore15HitTestLocationD1Ev
 __ZN7WebCore15JSDOMWindowBase8commonVMEv
 __ZN7WebCore15PasteboardImageC1Ev
 __ZN7WebCore15PasteboardImageD1Ev

Modified: trunk/Source/WebKit2/ChangeLog (160922 => 160923)


--- trunk/Source/WebKit2/ChangeLog	2013-12-20 21:00:46 UTC (rev 160922)
+++ trunk/Source/WebKit2/ChangeLog	2013-12-20 22:01:27 UTC (rev 160923)
@@ -1,3 +1,64 @@
+2013-12-20  Tim Horton  <timothy_hor...@apple.com>
+
+        WebKit2 View Gestures: Implement smartMagnifyWithEvent: and make it work
+        https://bugs.webkit.org/show_bug.cgi?id=125752
+        <rdar://problem/15664245>
+
+        Reviewed by Anders Carlsson.
+
+        Implement "smart magnify", which is the double-tap-to-zoom gesture on OS X.
+
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView smartMagnifyWithEvent:]):
+        Forward smartMagnifyWithEvent to ViewGestureController.
+
+        * UIProcess/mac/ViewGestureController.cpp:
+        (WebKit::ViewGestureController::handleMagnificationGesture):
+        Drive-by repair a comment.
+
+        (WebKit::ViewGestureController::handleSmartMagnificationGesture):
+        Added. Immediately dispatch a message to the web process to retrieve
+        the rendered rect of the element under the gesture.
+
+        (WebKit::maximumRectangleComponentDelta):
+        Return the absolute maximum delta between corresponding components of two rects.
+
+        (WebKit::ViewGestureController::didCollectGeometryForSmartMagnificationGesture):
+        Once the WebProcess has replied with the relevant geometry, use it to
+        determine our target rectangle (the element's rect, with some padding)
+        and target magnification (attempting to keep replaced elements
+        fully in-view, and otherwise zooming in as far as possible to fit the
+        element's width).
+
+        If this gesture occurs after the page is already magnified, and targets
+        a similar region to the previous smart magnification gesture, zoom out
+        instead of panning across the page.
+
+        Begin a transient zoom with the current magnification, and immediately
+        commit it at our target magnification and offset, so that the drawing
+        area will animate to the new parameters.
+
+        (WebKit::ViewGestureController::endActiveGesture):
+        * UIProcess/mac/ViewGestureController.h:
+        * UIProcess/mac/ViewGestureController.messages.in:
+        * WebProcess/WebPage/ViewGestureGeometryCollector.cpp:
+        (WebKit::ViewGestureGeometryCollector::collectGeometryForSmartMagnificationGesture):
+        Hit-test the document to determine the node under the smart magnification
+        gesture, and return it to the UI process along with various other bits of data.
+
+        * WebProcess/WebPage/ViewGestureGeometryCollector.h:
+        * WebProcess/WebPage/ViewGestureGeometryCollector.messages.in:
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h:
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
+        (WebKit::TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea):
+        (WebKit::TiledCoreAnimationDrawingArea::adjustTransientZoom):
+        (WebKit::TiledCoreAnimationDrawingArea::commitTransientZoom):
+        (WebKit::TiledCoreAnimationDrawingArea::applyTransientZoomToPage):
+        Instead of short-circuiting the animation if we didn't have to constrain
+        the origin, short-circuit if we're already *at* the right origin,
+        like the comment said. This prevents jarring jumps when double-tap-panning
+        between elements when zoomed all the way in.
+
 2013-12-20  Ricky Mondello  <rmonde...@apple.com>
 
         Allow partial application of PlugInAutoStart tables based on timestamp

Modified: trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm (160922 => 160923)


--- trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm	2013-12-20 21:00:46 UTC (rev 160922)
+++ trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm	2013-12-20 22:01:27 UTC (rev 160923)
@@ -3221,6 +3221,18 @@
     _data->_gestureController->handleMagnificationGesture(event.magnification, [self convertPoint:event.locationInWindow fromView:nil]);
 }
 
+- (void)smartMagnifyWithEvent:(NSEvent *)event
+{
+    if (!_data->_allowsMagnification) {
+        [super smartMagnifyWithEvent:event];
+        return;
+    }
+
+    [self _ensureGestureController];
+
+    _data->_gestureController->handleSmartMagnificationGesture([self convertPoint:event.locationInWindow fromView:nil]);
+}
+
 -(void)endGestureWithEvent:(NSEvent *)event
 {
     if (!_data->_gestureController) {

Modified: trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.cpp (160922 => 160923)


--- trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.cpp	2013-12-20 21:00:46 UTC (rev 160922)
+++ trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.cpp	2013-12-20 22:01:27 UTC (rev 160923)
@@ -42,6 +42,9 @@
 static const double zoomOutBoost = 1.6;
 static const double zoomOutResistance = 0.10;
 
+static const float smartMagnificationElementPadding = 0.05;
+static const float smartMagnificationPanScrollThreshold = 100;
+
 namespace WebKit {
 
 ViewGestureController::ViewGestureController(WebPageProxy& webPageProxy)
@@ -104,7 +107,7 @@
         return;
     }
 
-    // We're still waiting for the DidBeginTransientZoom callback.
+    // We're still waiting for the DidCollectGeometry callback.
     if (!m_visibleContentRectIsValid)
         return;
 
@@ -128,10 +131,60 @@
     m_webPageProxy.drawingArea()->commitTransientZoom(newMagnification, scaledMagnificationOrigin(m_magnificationOrigin, newMagnification));
 }
 
+void ViewGestureController::handleSmartMagnificationGesture(FloatPoint origin)
+{
+    if (m_activeGestureType != ViewGestureType::None)
+        return;
+
+    m_webPageProxy.process().send(Messages::ViewGestureGeometryCollector::CollectGeometryForSmartMagnificationGesture(origin), m_webPageProxy.pageID());
+}
+
+static float maximumRectangleComponentDelta(FloatRect a, FloatRect b)
+{
+    return std::max(fabs(a.x() - b.x()), std::max(fabs(a.y() - b.y()), std::max(fabs(a.width() - b.width()), fabs(a.height() - b.height()))));
+}
+
+void ViewGestureController::didCollectGeometryForSmartMagnificationGesture(FloatPoint origin, FloatRect renderRect, FloatRect visibleContentRect, bool isReplacedElement)
+{
+    double currentScaleFactor = m_webPageProxy.pageScaleFactor();
+
+    FloatRect unscaledTargetRect = renderRect;
+    unscaledTargetRect.scale(1 / currentScaleFactor);
+    unscaledTargetRect.inflateX(unscaledTargetRect.width() * smartMagnificationElementPadding);
+    unscaledTargetRect.inflateY(unscaledTargetRect.height() * smartMagnificationElementPadding);
+
+    double targetMagnification = visibleContentRect.width() / unscaledTargetRect.width();
+
+    // For replaced elements like images, we want to fit the whole element
+    // in the view, so scale it down enough to make both dimensions fit if possible.
+    if (isReplacedElement)
+        targetMagnification = std::min(targetMagnification, static_cast<double>(visibleContentRect.height() / unscaledTargetRect.height()));
+
+    targetMagnification = std::min(std::max(targetMagnification, minMagnification), maxMagnification);
+
+    // Allow panning between elements via double-tap while magnified, unless the target rect is
+    // similar to the last one, in which case we'll zoom all the way out.
+    if (currentScaleFactor > 1
+        && !m_lastSmartMagnificationUnscaledTargetRect.isEmpty()
+        && maximumRectangleComponentDelta(m_lastSmartMagnificationUnscaledTargetRect, unscaledTargetRect) < smartMagnificationPanScrollThreshold)
+        targetMagnification = 1;
+
+    FloatRect targetRect(unscaledTargetRect);
+    targetRect.scale(targetMagnification);
+    FloatPoint targetOrigin(visibleContentRect.center());
+    targetOrigin.moveBy(-targetRect.center());
+
+    m_webPageProxy.drawingArea()->adjustTransientZoom(m_webPageProxy.pageScaleFactor(), scaledMagnificationOrigin(FloatPoint(), m_webPageProxy.pageScaleFactor()));
+    m_webPageProxy.drawingArea()->commitTransientZoom(targetMagnification, targetOrigin);
+
+    m_lastSmartMagnificationUnscaledTargetRect = unscaledTargetRect;
+}
+
 void ViewGestureController::endActiveGesture()
 {
     switch (m_activeGestureType) {
     case ViewGestureType::None:
+    case ViewGestureType::SmartMagnification:
         break;
     case ViewGestureType::Magnification:
         endMagnificationGesture();

Modified: trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h (160922 => 160923)


--- trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h	2013-12-20 21:00:46 UTC (rev 160922)
+++ trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.h	2013-12-20 22:01:27 UTC (rev 160923)
@@ -39,14 +39,17 @@
     ViewGestureController(WebPageProxy&);
     ~ViewGestureController();
 
-    void handleMagnificationGesture(double scale, WebCore::FloatPoint origin);
     double magnification() const;
 
+    void handleMagnificationGesture(double scale, WebCore::FloatPoint origin);
+    void handleSmartMagnificationGesture(WebCore::FloatPoint origin);
+
     void endActiveGesture();
 
     enum class ViewGestureType {
         None,
         Magnification,
+        SmartMagnification,
     };
 
 private:
@@ -55,6 +58,7 @@
 
     // Message handlers.
     void didCollectGeometryForMagnificationGesture(WebCore::FloatRect visibleContentBounds);
+    void didCollectGeometryForSmartMagnificationGesture(WebCore::FloatPoint origin, WebCore::FloatRect renderRect, WebCore::FloatRect visibleContentBounds, bool isReplacedElement);
 
     void endMagnificationGesture();
     WebCore::FloatPoint scaledMagnificationOrigin(WebCore::FloatPoint origin, double scale);
@@ -64,6 +68,8 @@
     double m_magnification;
     WebCore::FloatPoint m_magnificationOrigin;
 
+    WebCore::FloatRect m_lastSmartMagnificationUnscaledTargetRect;
+
     ViewGestureType m_activeGestureType;
 
     WebCore::FloatRect m_visibleContentRect;

Modified: trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.messages.in (160922 => 160923)


--- trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.messages.in	2013-12-20 21:00:46 UTC (rev 160922)
+++ trunk/Source/WebKit2/UIProcess/mac/ViewGestureController.messages.in	2013-12-20 22:01:27 UTC (rev 160923)
@@ -22,4 +22,5 @@
 
 messages -> ViewGestureController {
     DidCollectGeometryForMagnificationGesture(WebCore::FloatRect visibleContentBounds)
+    DidCollectGeometryForSmartMagnificationGesture(WebCore::FloatPoint origin, WebCore::FloatRect renderRect, WebCore::FloatRect visibleContentBounds, bool isReplacedElement)
 }

Modified: trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.cpp (160922 => 160923)


--- trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.cpp	2013-12-20 21:00:46 UTC (rev 160922)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.cpp	2013-12-20 22:01:27 UTC (rev 160923)
@@ -32,6 +32,8 @@
 #include "WebPage.h"
 #include "WebProcess.h"
 #include <WebCore/FrameView.h>
+#include <WebCore/HitTestResult.h>
+#include <WebCore/RenderView.h>
 
 using namespace WebCore;
 
@@ -54,4 +56,22 @@
     m_webPage.send(Messages::ViewGestureController::DidCollectGeometryForMagnificationGesture(visibleContentRect));
 }
 
+void ViewGestureGeometryCollector::collectGeometryForSmartMagnificationGesture(FloatPoint origin)
+{
+    FloatRect visibleContentRect = m_webPage.mainFrameView()->visibleContentRect(ScrollableArea::IncludeScrollbars);
+
+    FloatPoint scrolledOrigin = origin;
+    scrolledOrigin.moveBy(m_webPage.mainFrameView()->scrollPosition());
+
+    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
+    HitTestResult hitTestResult = HitTestResult(scrolledOrigin);
+    m_webPage.mainFrameView()->renderView()->hitTest(request, hitTestResult);
+
+    if (hitTestResult.innerNode()) {
+        bool isReplaced;
+        FloatRect renderRect = hitTestResult.innerNode()->renderRect(&isReplaced);
+        m_webPage.send(Messages::ViewGestureController::DidCollectGeometryForSmartMagnificationGesture(origin, renderRect, visibleContentRect, isReplaced));
+    }
+}
+
 } // namespace WebKit

Modified: trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.h (160922 => 160923)


--- trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.h	2013-12-20 21:00:46 UTC (rev 160922)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.h	2013-12-20 22:01:27 UTC (rev 160923)
@@ -28,6 +28,10 @@
 
 #include "MessageReceiver.h"
 
+namespace WebCore {
+class FloatPoint;
+}
+
 namespace WebKit {
 
 class WebPage;
@@ -43,6 +47,7 @@
 
     // Message handlers.
     void collectGeometryForMagnificationGesture();
+    void collectGeometryForSmartMagnificationGesture(WebCore::FloatPoint origin);
 
     WebPage& m_webPage;
 };

Modified: trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.messages.in (160922 => 160923)


--- trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.messages.in	2013-12-20 21:00:46 UTC (rev 160922)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.messages.in	2013-12-20 22:01:27 UTC (rev 160923)
@@ -23,5 +23,6 @@
 messages -> ViewGestureGeometryCollector {
 
 CollectGeometryForMagnificationGesture()
+CollectGeometryForSmartMagnificationGesture(WebCore::FloatPoint origin)
 
 }

Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h (160922 => 160923)


--- trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h	2013-12-20 21:00:46 UTC (rev 160922)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h	2013-12-20 22:01:27 UTC (rev 160923)
@@ -149,6 +149,7 @@
     bool m_inUpdateGeometry;
 
     double m_transientZoomScale;
+    WebCore::FloatPoint m_transientZoomOrigin;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm (160922 => 160923)


--- trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm	2013-12-20 21:00:46 UTC (rev 160922)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm	2013-12-20 22:01:27 UTC (rev 160923)
@@ -73,6 +73,7 @@
     , m_isPaintingSuspended(!(parameters.viewState & ViewState::IsVisible))
     , m_clipsToExposedRect(false)
     , m_updateIntrinsicContentSizeTimer(this, &TiledCoreAnimationDrawingArea::updateIntrinsicContentSizeTimerFired)
+    , m_transientZoomScale(1)
 {
     m_webPage->corePage()->settings().setForceCompositingMode(true);
 
@@ -729,6 +730,7 @@
     shadowLayer->setPosition(origin + shadowBounds.center());
 
     m_transientZoomScale = scale;
+    m_transientZoomOrigin = origin;
 }
 
 static RetainPtr<CABasicAnimation> transientZoomSnapAnimationForKeyPath(String keyPath)
@@ -765,7 +767,7 @@
     constrainedOrigin.moveBy(-visibleContentRect.location());
     constrainedOrigin = -constrainedOrigin;
 
-    if (m_transientZoomScale == scale && roundedIntPoint(origin) == roundedIntPoint(constrainedOrigin)) {
+    if (m_transientZoomScale == scale && roundedIntPoint(m_transientZoomOrigin) == roundedIntPoint(constrainedOrigin)) {
         // We're already at the right scale and position, so we don't need to animate.
         applyTransientZoomToPage(scale, origin);
         return;
@@ -829,6 +831,8 @@
     unscrolledOrigin.moveBy(-visibleContentRect.location());
     m_webPage->scalePage(scale, roundedIntPoint(-unscrolledOrigin));
     flushLayers();
+
+    m_transientZoomScale = 1;
 }
 
 } // namespace WebKit
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to