bool VisualViewport::magnifyScaleAroundAnchor(float magnifyDelta, const FloatPoint& anchor) { const float oldPageScale = scale(); const float newPageScale = frameHost().chromeClient().clampPageScaleFactorToLimits(magnifyDelta * oldPageScale); if (newPageScale == oldPageScale) return false; if (!mainFrame() || !mainFrame()->view()) return false; // Keep the center-of-pinch anchor in a stable position over the course // of the magnify. FloatPoint anchorAtOldScale = anchor.scaledBy(1.f / oldPageScale); FloatPoint anchorAtNewScale = anchor.scaledBy(1.f / newPageScale); FloatSize anchorDelta = anchorAtOldScale - anchorAtNewScale; // First try to use the anchor's delta to scroll the FrameView. FloatSize anchorDeltaUnusedByScroll = anchorDelta; // Manually bubble any remaining anchor delta up to the visual viewport. FloatPoint newLocation(FloatPoint(getScrollOffset()) + anchorDeltaUnusedByScroll); setScaleAndLocation(newPageScale, newLocation); return true; }
bool VisualViewport::magnifyScaleAroundAnchor(float magnifyDelta, const FloatPoint& anchor) { const float oldPageScale = scale(); const float newPageScale = frameHost().chromeClient().clampPageScaleFactorToLimits( magnifyDelta * oldPageScale); if (newPageScale == oldPageScale) return false; if (!mainFrame() || !mainFrame()->view()) return false; // Keep the center-of-pinch anchor in a stable position over the course // of the magnify. FloatPoint anchorAtOldScale = anchor.scaledBy(1.f / oldPageScale); FloatPoint anchorAtNewScale = anchor.scaledBy(1.f / newPageScale); FloatSize anchorDelta = anchorAtOldScale - anchorAtNewScale; // First try to use the anchor's delta to scroll the FrameView. FloatSize anchorDeltaUnusedByScroll = anchorDelta; if (!frameHost().settings().invertViewportScrollOrder()) { FrameView* view = mainFrame()->view(); DoublePoint oldPosition = view->scrollPositionDouble(); view->scrollBy(DoubleSize(anchorDelta.width(), anchorDelta.height()), UserScroll); DoublePoint newPosition = view->scrollPositionDouble(); anchorDeltaUnusedByScroll -= toFloatSize(newPosition - oldPosition); } // Manually bubble any remaining anchor delta up to the visual viewport. FloatPoint newLocation(location() + anchorDeltaUnusedByScroll); setScaleAndLocation(newPageScale, newLocation); return true; }
void TouchEventManager::setAllPropertiesOfTouchInfos( HeapVector<TouchInfo>& touchInfos) { for (auto& touchInfo : touchInfos) { PlatformTouchPoint::TouchState pointState = touchInfo.point.state(); Node* touchNode = nullptr; String regionID; if (pointState == PlatformTouchPoint::TouchReleased || pointState == PlatformTouchPoint::TouchCancelled) { // The target should be the original target for this touch, so get // it from the hashmap. As it's a release or cancel we also remove // it from the map. touchNode = m_targetForTouchID.take(touchInfo.point.id()); regionID = m_regionForTouchID.take(touchInfo.point.id()); } else { // No hittest is performed on move or stationary, since the target // is not allowed to change anyway. touchNode = m_targetForTouchID.get(touchInfo.point.id()); regionID = m_regionForTouchID.get(touchInfo.point.id()); } LocalFrame* targetFrame = nullptr; bool knownTarget = false; if (touchNode) { Document& doc = touchNode->document(); // If the target node has moved to a new document while it was being touched, // we can't send events to the new document because that could leak nodes // from one document to another. See http://crbug.com/394339. if (&doc == m_touchSequenceDocument.get()) { targetFrame = doc.frame(); knownTarget = true; } } if (!knownTarget) { // If we don't have a target registered for the point it means we've // missed our opportunity to do a hit test for it (due to some // optimization that prevented blink from ever seeing the // touchstart), or that the touch started outside the active touch // sequence document. We should still include the touch in the // Touches list reported to the application (eg. so it can // differentiate between a one and two finger gesture), but we won't // actually dispatch any events for it. Set the target to the // Document so that there's some valid node here. Perhaps this // should really be LocalDOMWindow, but in all other cases the target of // a Touch is a Node so using the window could be a breaking change. // Since we know there was no handler invoked, the specific target // should be completely irrelevant to the application. touchNode = m_touchSequenceDocument; targetFrame = m_touchSequenceDocument->frame(); } ASSERT(targetFrame); // pagePoint should always be in the target element's document coordinates. FloatPoint pagePoint = targetFrame->view()->rootFrameToContents( touchInfo.point.pos()); float scaleFactor = 1.0f / targetFrame->pageZoomFactor(); touchInfo.touchNode = touchNode; touchInfo.targetFrame = targetFrame; touchInfo.contentPoint = pagePoint.scaledBy(scaleFactor); touchInfo.adjustedRadius = touchInfo.point.radius().scaledBy(scaleFactor); touchInfo.knownTarget = knownTarget; touchInfo.consumed = false; touchInfo.region = regionID; } }