Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 190 // (such as due to a double tap gesture or find in page etc.). These are | 190 // (such as due to a double tap gesture or find in page etc.). These are |
| 191 // experimentally determined. | 191 // experimentally determined. |
| 192 static const int touchPointPadding = 32; | 192 static const int touchPointPadding = 32; |
| 193 static const int nonUserInitiatedPointPadding = 11; | 193 static const int nonUserInitiatedPointPadding = 11; |
| 194 static const float minScaleDifference = 0.01f; | 194 static const float minScaleDifference = 0.01f; |
| 195 static const float doubleTapZoomContentDefaultMargin = 5; | 195 static const float doubleTapZoomContentDefaultMargin = 5; |
| 196 static const float doubleTapZoomContentMinimumMargin = 2; | 196 static const float doubleTapZoomContentMinimumMargin = 2; |
| 197 static const double doubleTapZoomAnimationDurationInSeconds = 0.25; | 197 static const double doubleTapZoomAnimationDurationInSeconds = 0.25; |
| 198 static const float doubleTapZoomAlreadyLegibleRatio = 1.2f; | 198 static const float doubleTapZoomAlreadyLegibleRatio = 1.2f; |
| 199 | 199 |
| 200 static const float viewportAnchorRelativeEpsilon = 0.1f; | |
| 201 static const float viewportAnchorXCoord = 0.5f; | |
| 202 static const float viewportAnchorYCoord = 0; | |
| 203 | |
| 200 // Constants for zooming in on a focused text field. | 204 // Constants for zooming in on a focused text field. |
| 201 static const double scrollAndScaleAnimationDurationInSeconds = 0.2; | 205 static const double scrollAndScaleAnimationDurationInSeconds = 0.2; |
| 202 static const int minReadableCaretHeight = 18; | 206 static const int minReadableCaretHeight = 18; |
| 203 static const float minScaleChangeToTriggerZoom = 1.05f; | 207 static const float minScaleChangeToTriggerZoom = 1.05f; |
| 204 static const float leftBoxRatio = 0.3f; | 208 static const float leftBoxRatio = 0.3f; |
| 205 static const int caretPadding = 10; | 209 static const int caretPadding = 10; |
| 206 | 210 |
| 207 namespace WebKit { | 211 namespace WebKit { |
| 208 | 212 |
| 213 #if ENABLE(VIEWPORT) | |
| 214 namespace { | |
| 215 // ViewportAnchor provides a way to anchor a viewport origin to a DOM node. | |
| 216 // In particular, the user supplies the current viewport (in CSS coordinates) | |
| 217 // and an anchor point (in view coordinates, e.g., (0, 0) == viewport origin, | |
| 218 // (0.5, 0) == viewport top center). The anchor point tracks the underlying DOM | |
| 219 // node; as the node moves or the view is resized, the viewport anchor maintains | |
| 220 // its orientation relative to the node, and the viewport origin maintains its | |
| 221 // orientation relative to the anchor. | |
| 222 class ViewportAnchor { | |
|
abarth-chromium
2013/04/12 17:33:30
This class should go in its own file. WebViewImpl
jdduke (slow)
2013/04/12 19:20:16
Done.
| |
| 223 public: | |
| 224 ViewportAnchor(EventHandler* eventHandler) | |
|
abarth-chromium
2013/04/12 17:33:30
one-argument constructors should be marked explici
jdduke (slow)
2013/04/12 19:20:16
Done.
| |
| 225 : m_eventHandler(eventHandler) { } | |
| 226 | |
| 227 void setAnchor(const IntRect& viewRect, const FloatSize& anchorInViewCoords) | |
| 228 { | |
| 229 m_viewRect = viewRect; | |
| 230 m_anchorNode.clear(); | |
| 231 m_anchorNodeBounds = LayoutRect(); | |
| 232 m_anchorInNodeCoords = FloatSize(); | |
| 233 m_anchorInViewCoords = anchorInViewCoords; | |
| 234 | |
| 235 if (viewRect.isEmpty()) | |
| 236 return; | |
| 237 | |
| 238 // Preserve origins at the absolute screen origin | |
| 239 if (viewRect.location() == IntPoint::zero()) | |
| 240 return; | |
| 241 | |
| 242 FloatSize anchorOffset = viewRect.size(); | |
| 243 anchorOffset.scale(anchorInViewCoords.width(), anchorInViewCoords.height ()); | |
| 244 const FloatPoint anchorPoint = FloatPoint(viewRect.location()) + anchorO ffset; | |
| 245 | |
| 246 Node* node = findNonEmptyAnchorNode(flooredIntPoint(anchorPoint), viewRe ct, m_eventHandler); | |
| 247 if (!node) | |
| 248 return; | |
| 249 | |
| 250 m_anchorNode = node; | |
| 251 m_anchorNodeBounds = node->boundingBox(); | |
| 252 m_anchorInNodeCoords = anchorPoint - m_anchorNodeBounds.location(); | |
| 253 m_anchorInNodeCoords.scale(1.f / m_anchorNodeBounds.width(), 1.f / m_anc horNodeBounds.height()); | |
| 254 } | |
| 255 | |
| 256 // Note: The returned point may not lie within the document bounds. | |
| 257 IntPoint computeOrigin(const IntSize& currentViewSize) const | |
| 258 { | |
| 259 if (!m_anchorNode || !m_anchorNode->inDocument()) | |
| 260 return m_viewRect.location(); | |
| 261 | |
| 262 const LayoutRect currentNodeBounds = m_anchorNode->boundingBox(); | |
| 263 if (m_anchorNodeBounds == currentNodeBounds) | |
| 264 return m_viewRect.location(); | |
| 265 | |
| 266 // Compute the new anchor point relative to the node position | |
| 267 FloatSize anchorOffsetFromNode = currentNodeBounds.size(); | |
| 268 anchorOffsetFromNode.scale(m_anchorInNodeCoords.width(), m_anchorInNodeC oords.height()); | |
| 269 FloatPoint anchorPoint = currentNodeBounds.location() + anchorOffsetFrom Node; | |
| 270 | |
| 271 // Compute the new origin point relative to the new anchor point | |
| 272 FloatSize anchorOffsetFromOrigin = currentViewSize; | |
| 273 anchorOffsetFromOrigin.scale(m_anchorInViewCoords.width(), m_anchorInVie wCoords.height()); | |
| 274 return flooredIntPoint(anchorPoint - anchorOffsetFromOrigin); | |
| 275 } | |
| 276 | |
| 277 private: | |
| 278 ViewportAnchor(); | |
| 279 | |
| 280 static Node* findNonEmptyAnchorNode(const IntPoint& point, const IntRect& vi ewRect, EventHandler* eventHandler) | |
| 281 { | |
| 282 Node* node = eventHandler->hitTestResultAtPoint(point).innerNode(); | |
| 283 | |
| 284 // If the node bounding box contains the view, make a single attempt to | |
| 285 // find a smaller node; the larger the node bounds, the greater the | |
| 286 // variability under resize. | |
| 287 if (node && node->boundingBox().contains(viewRect)) { | |
| 288 IntSize pointOffset = viewRect.size(); | |
| 289 pointOffset.scale(viewportAnchorRelativeEpsilon); | |
| 290 node = eventHandler->hitTestResultAtPoint(point + pointOffset).inner Node(); | |
| 291 } | |
| 292 | |
| 293 while (node && node->boundingBox().isEmpty()) | |
| 294 node = node->parentNode(); | |
| 295 | |
| 296 return node; | |
| 297 } | |
| 298 | |
| 299 EventHandler* m_eventHandler; | |
| 300 | |
| 301 IntRect m_viewRect; | |
| 302 | |
| 303 RefPtr<Node> m_anchorNode; | |
| 304 LayoutRect m_anchorNodeBounds; | |
| 305 | |
| 306 FloatSize m_anchorInViewCoords; | |
| 307 FloatSize m_anchorInNodeCoords; | |
| 308 }; | |
| 309 } | |
| 310 #endif // ENABLE(VIEWPORT) | |
| 311 | |
| 209 // Change the text zoom level by kTextSizeMultiplierRatio each time the user | 312 // Change the text zoom level by kTextSizeMultiplierRatio each time the user |
| 210 // zooms text in or out (ie., change by 20%). The min and max values limit | 313 // zooms text in or out (ie., change by 20%). The min and max values limit |
| 211 // text zoom to half and 3x the original text size. These three values match | 314 // text zoom to half and 3x the original text size. These three values match |
| 212 // those in Apple's port in WebKit/WebKit/WebView/WebView.mm | 315 // those in Apple's port in WebKit/WebKit/WebView/WebView.mm |
| 213 const double WebView::textSizeMultiplierRatio = 1.2; | 316 const double WebView::textSizeMultiplierRatio = 1.2; |
| 214 const double WebView::minTextSizeMultiplier = 0.5; | 317 const double WebView::minTextSizeMultiplier = 0.5; |
| 215 const double WebView::maxTextSizeMultiplier = 3.0; | 318 const double WebView::maxTextSizeMultiplier = 3.0; |
| 216 const float WebView::minPageScaleFactor = 0.25f; | 319 const float WebView::minPageScaleFactor = 0.25f; |
| 217 const float WebView::maxPageScaleFactor = 4.0f; | 320 const float WebView::maxPageScaleFactor = 4.0f; |
| 218 | 321 |
| (...skipping 1428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1647 { | 1750 { |
| 1648 if (m_shouldAutoResize || m_size == newSize) | 1751 if (m_shouldAutoResize || m_size == newSize) |
| 1649 return; | 1752 return; |
| 1650 | 1753 |
| 1651 FrameView* view = mainFrameImpl()->frameView(); | 1754 FrameView* view = mainFrameImpl()->frameView(); |
| 1652 if (!view) | 1755 if (!view) |
| 1653 return; | 1756 return; |
| 1654 | 1757 |
| 1655 WebSize oldSize = m_size; | 1758 WebSize oldSize = m_size; |
| 1656 float oldPageScaleFactor = pageScaleFactor(); | 1759 float oldPageScaleFactor = pageScaleFactor(); |
| 1657 IntSize oldScrollOffset = view->scrollOffset(); | 1760 float oldMinimumPageScaleFactor = m_minimumPageScaleFactor; |
| 1658 int oldFixedLayoutWidth = fixedLayoutSize().width; | 1761 int oldFixedLayoutWidth = fixedLayoutSize().width; |
| 1762 int oldContentsWidth = contentsSize().width(); | |
| 1659 | 1763 |
| 1660 m_size = newSize; | 1764 m_size = newSize; |
| 1661 | 1765 |
| 1662 #if ENABLE(VIEWPORT) | 1766 #if ENABLE(VIEWPORT) |
| 1767 ViewportAnchor viewportAnchor(mainFrameImpl()->frame()->eventHandler()); | |
| 1768 if (settings()->viewportEnabled()) | |
| 1769 viewportAnchor.setAnchor(view->visibleContentRect(), | |
| 1770 FloatSize(viewportAnchorXCoord, viewportAnchorY Coord)); | |
| 1771 | |
| 1663 ViewportArguments viewportArguments = mainFrameImpl()->frame()->document()-> viewportArguments(); | 1772 ViewportArguments viewportArguments = mainFrameImpl()->frame()->document()-> viewportArguments(); |
| 1664 m_page->chrome()->client()->dispatchViewportPropertiesDidChange(viewportArgu ments); | 1773 m_page->chrome()->client()->dispatchViewportPropertiesDidChange(viewportArgu ments); |
| 1665 #endif | 1774 #endif |
| 1666 | 1775 |
| 1667 WebDevToolsAgentPrivate* agentPrivate = devToolsAgentPrivate(); | 1776 WebDevToolsAgentPrivate* agentPrivate = devToolsAgentPrivate(); |
| 1668 if (agentPrivate) | 1777 if (agentPrivate) |
| 1669 agentPrivate->webViewResized(newSize); | 1778 agentPrivate->webViewResized(newSize); |
| 1670 if (!agentPrivate || !agentPrivate->metricsOverridden()) { | 1779 if (!agentPrivate || !agentPrivate->metricsOverridden()) { |
| 1671 WebFrameImpl* webFrame = mainFrameImpl(); | 1780 WebFrameImpl* webFrame = mainFrameImpl(); |
| 1672 if (webFrame->frameView()) | 1781 if (webFrame->frameView()) |
| 1673 webFrame->frameView()->resize(m_size); | 1782 webFrame->frameView()->resize(m_size); |
| 1674 } | 1783 } |
| 1675 | 1784 |
| 1676 #if ENABLE(VIEWPORT) | 1785 #if ENABLE(VIEWPORT) |
| 1677 if (settings()->viewportEnabled()) { | 1786 if (settings()->viewportEnabled()) { |
| 1678 // Relayout immediately to recalculate the minimum scale limit. | 1787 // Relayout immediately to recalculate the minimum scale limit. |
| 1679 if (view->needsLayout()) | 1788 if (view->needsLayout()) |
| 1680 view->layout(); | 1789 view->layout(); |
| 1681 | 1790 |
| 1682 // When the device rotates: | 1791 // The minimum scale limit may change as a result of layout content |
| 1683 // - If the page width is unchanged, then zoom by new width/old width | 1792 // changes; in this case, scale relative to the change in content width. |
| 1684 // such as to keep the same content horizontally onscreen. | 1793 // Otherwise scale relative to the change in layout width. |
| 1685 // - If the page width stretches proportionally to the change in | 1794 // Don't do any scaling if the old width was zero (i.e., first resize). |
| 1686 // screen width, then don't zoom at all (assuming the content has | 1795 float scalingWidthRatio = 1; |
| 1687 // scaled uniformly, then the same content will be horizontally | 1796 if (oldSize.width && oldContentsWidth && m_minimumPageScaleFactor != old MinimumPageScaleFactor) |
| 1688 // onscreen). | 1797 scalingWidthRatio = contentsSize().width() / (float) oldContentsWidt h; |
| 1689 // - If the page width partially stretches, then zoom partially to | 1798 else if (oldFixedLayoutWidth) |
| 1690 // make up the difference. | 1799 scalingWidthRatio = fixedLayoutSize().width / (float) oldFixedLayout Width; |
| 1691 // In all cases try to keep the same content at the top of the screen. | 1800 |
| 1692 float viewportWidthRatio = !oldSize.width ? 1 : newSize.width / (float) oldSize.width; | 1801 float viewportWidthRatio = !oldSize.width ? 1 : newSize.width / (float) oldSize.width; |
| 1693 float fixedLayoutWidthRatio = !oldFixedLayoutWidth ? 1 : fixedLayoutSize ().width / (float) oldFixedLayoutWidth; | 1802 float scaleMultiplier = viewportWidthRatio / scalingWidthRatio; |
| 1694 float scaleMultiplier = viewportWidthRatio / fixedLayoutWidthRatio; | 1803 |
| 1695 if (scaleMultiplier != 1) | 1804 IntSize viewportSize = view->visibleContentRect().size(); |
| 1696 setPageScaleFactor(oldPageScaleFactor * scaleMultiplier, WebPoint(ol dScrollOffset.width(), oldScrollOffset.height())); | 1805 if (scaleMultiplier != 1) { |
| 1806 float newPageScaleFactor = oldPageScaleFactor * scaleMultiplier; | |
| 1807 viewportSize.scale(pageScaleFactor() / newPageScaleFactor); | |
| 1808 IntPoint scrollOffsetAtNewScale = viewportAnchor.computeOrigin(viewp ortSize); | |
| 1809 setPageScaleFactor(newPageScaleFactor, scrollOffsetAtNewScale); | |
| 1810 } else { | |
| 1811 IntPoint scrollOffsetAtNewScale = clampOffsetAtScale(viewportAnchor. computeOrigin(viewportSize), pageScaleFactor()); | |
| 1812 updateMainFrameScrollPosition(scrollOffsetAtNewScale, false); | |
| 1813 } | |
| 1697 } | 1814 } |
| 1698 #endif | 1815 #endif |
| 1699 | 1816 |
| 1700 sendResizeEventAndRepaint(); | 1817 sendResizeEventAndRepaint(); |
| 1701 } | 1818 } |
| 1702 | 1819 |
| 1703 void WebViewImpl::willEndLiveResize() | 1820 void WebViewImpl::willEndLiveResize() |
| 1704 { | 1821 { |
| 1705 if (mainFrameImpl() && mainFrameImpl()->frameView()) | 1822 if (mainFrameImpl() && mainFrameImpl()->frameView()) |
| 1706 mainFrameImpl()->frameView()->willEndLiveResize(); | 1823 mainFrameImpl()->frameView()->willEndLiveResize(); |
| (...skipping 2485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4192 } | 4309 } |
| 4193 | 4310 |
| 4194 bool WebViewImpl::shouldDisableDesktopWorkarounds() | 4311 bool WebViewImpl::shouldDisableDesktopWorkarounds() |
| 4195 { | 4312 { |
| 4196 ViewportArguments arguments = mainFrameImpl()->frame()->document()->viewport Arguments(); | 4313 ViewportArguments arguments = mainFrameImpl()->frame()->document()->viewport Arguments(); |
| 4197 return arguments.width == ViewportArguments::ValueDeviceWidth || !arguments. userZoom | 4314 return arguments.width == ViewportArguments::ValueDeviceWidth || !arguments. userZoom |
| 4198 || (arguments.minZoom == arguments.maxZoom && arguments.minZoom != Viewp ortArguments::ValueAuto); | 4315 || (arguments.minZoom == arguments.maxZoom && arguments.minZoom != Viewp ortArguments::ValueAuto); |
| 4199 } | 4316 } |
| 4200 | 4317 |
| 4201 } // namespace WebKit | 4318 } // namespace WebKit |
| OLD | NEW |