summaryrefslogtreecommitdiff
path: root/Source/WebKit/chromium/src/WebViewImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit/chromium/src/WebViewImpl.cpp')
-rw-r--r--Source/WebKit/chromium/src/WebViewImpl.cpp266
1 files changed, 217 insertions, 49 deletions
diff --git a/Source/WebKit/chromium/src/WebViewImpl.cpp b/Source/WebKit/chromium/src/WebViewImpl.cpp
index a05e98920..55a2052a4 100644
--- a/Source/WebKit/chromium/src/WebViewImpl.cpp
+++ b/Source/WebKit/chromium/src/WebViewImpl.cpp
@@ -99,7 +99,6 @@
#include "RenderWidget.h"
#include "ResourceHandle.h"
#include "SchemeRegistry.h"
-#include "ScrollAnimator.h"
#include "SecurityOrigin.h"
#include "SecurityPolicy.h"
#include "Settings.h"
@@ -171,7 +170,7 @@ using namespace std;
namespace {
-GraphicsContext3D::Attributes getCompositorContextAttributes()
+WebKit::WebGraphicsContext3D::Attributes getCompositorContextAttributes(bool threaded)
{
// Explicitly disable antialiasing for the compositor. As of the time of
// this writing, the only platform that supported antialiasing for the
@@ -183,12 +182,21 @@ GraphicsContext3D::Attributes getCompositorContextAttributes()
// be optimized to resolve directly into the IOSurface shared between the
// GPU and browser processes. For these reasons and to avoid platform
// disparities we explicitly disable antialiasing.
- GraphicsContext3D::Attributes attributes;
+ WebKit::WebGraphicsContext3D::Attributes attributes;
attributes.antialias = false;
attributes.shareResources = true;
+ attributes.forUseOnAnotherThread = threaded;
return attributes;
}
+// The following constants control parameters for automated scaling of webpages
+// (such as due to a double tap gesture or find in page etc.). These are
+// experimentally determined.
+static const int touchPointPadding = 32;
+static const float minScaleDifference = 0.01;
+static const float doubleTapZoomContentDefaultMargin = 5;
+static const float doubleTapZoomContentMinimumMargin = 2;
+
} // anonymous namespace
namespace WebKit {
@@ -390,21 +398,21 @@ WebViewImpl::WebViewImpl(WebViewClient* client)
pageClients.editorClient = &m_editorClientImpl;
pageClients.dragClient = &m_dragClientImpl;
pageClients.inspectorClient = &m_inspectorClientImpl;
-#if ENABLE(INPUT_SPEECH)
- pageClients.speechInputClient = m_speechInputClient.get();
-#endif
- pageClients.deviceOrientationClient = m_deviceOrientationClientProxy.get();
pageClients.geolocationClient = m_geolocationClientProxy.get();
-#if ENABLE(NOTIFICATIONS)
- pageClients.notificationClient = notificationPresenterImpl();
-#endif
pageClients.backForwardClient = BackForwardListChromium::create(this);
-#if ENABLE(MEDIA_STREAM)
- pageClients.userMediaClient = &m_userMediaClientImpl;
-#endif
m_page = adoptPtr(new Page(pageClients));
+#if ENABLE(MEDIA_STREAM)
+ provideUserMediaTo(m_page.get(), &m_userMediaClientImpl);
+#endif
+#if ENABLE(INPUT_SPEECH)
+ provideSpeechInputTo(m_page.get(), m_speechInputClient.get());
+#endif
+#if ENABLE(NOTIFICATIONS)
+ provideNotification(m_page.get(), notificationPresenterImpl());
+#endif
+ provideDeviceOrientationTo(m_page.get(), m_deviceOrientationClientProxy.get());
m_geolocationClientProxy->setController(m_page->geolocationController());
m_page->setGroupName(pageGroupName);
@@ -614,14 +622,13 @@ bool WebViewImpl::mouseWheel(const WebMouseWheelEvent& event)
bool WebViewImpl::gestureEvent(const WebGestureEvent& event)
{
PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event);
- bool handled = mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent);
-
- Frame* frame = mainFrameImpl()->frame();
- WebPluginContainerImpl* pluginContainer = WebFrameImpl::pluginContainerFromFrame(frame);
- if (pluginContainer)
- handled |= pluginContainer->handleGestureEvent(platformEvent);
+ return mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent);
+}
- return handled;
+void WebViewImpl::startPageScaleAnimation(const IntPoint& scroll, bool useAnchor, float newScale, double durationSec)
+{
+ if (m_layerTreeHost)
+ m_layerTreeHost->startPageScaleAnimation(IntSize(scroll.x(), scroll.y()), useAnchor, newScale, durationSec);
}
#endif
@@ -797,15 +804,159 @@ bool WebViewImpl::touchEvent(const WebTouchEvent& event)
}
#endif
+#if ENABLE(GESTURE_EVENTS)
+WebRect WebViewImpl::computeBlockBounds(const WebRect& rect, AutoZoomType zoomType)
+{
+ if (!mainFrameImpl())
+ return WebRect();
+
+ // Use the rect-based hit test to find the node.
+ IntPoint point = mainFrameImpl()->frameView()->windowToContents(IntPoint(rect.x, rect.y));
+ HitTestResult result = mainFrameImpl()->frame()->eventHandler()->hitTestResultAtPoint(point,
+ false, zoomType == FindInPage, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly,
+ IntSize(rect.width, rect.height));
+
+ Node* node = result.innerNonSharedNode();
+ if (!node)
+ return WebRect();
+
+ // Find the block type node based on the hit node.
+ while (node && (!node->renderer() || node->renderer()->isInline()))
+ node = node->parentNode();
+
+ // Return the bounding box in the window coordinate system.
+ if (node) {
+ IntRect rect = node->Node::getRect();
+ Frame* frame = node->document()->frame();
+ return frame->view()->contentsToWindow(rect);
+ }
+ return WebRect();
+}
+
+WebRect WebViewImpl::widenRectWithinPageBounds(const WebRect& source, int targetMargin, int minimumMargin)
+{
+ WebSize maxSize;
+ if (mainFrame())
+ maxSize = mainFrame()->contentsSize();
+ IntSize scrollOffset;
+ if (mainFrame())
+ scrollOffset = mainFrame()->scrollOffset();
+ int leftMargin = targetMargin;
+ int rightMargin = targetMargin;
+
+ const int absoluteSourceX = source.x + scrollOffset.width();
+ if (leftMargin > absoluteSourceX) {
+ leftMargin = absoluteSourceX;
+ rightMargin = max(leftMargin, minimumMargin);
+ }
+
+ const int maximumRightMargin = maxSize.width - (source.width + absoluteSourceX);
+ if (rightMargin > maximumRightMargin) {
+ rightMargin = maximumRightMargin;
+ leftMargin = min(leftMargin, max(rightMargin, minimumMargin));
+ }
+
+ const int newWidth = source.width + leftMargin + rightMargin;
+ const int newX = source.x - leftMargin;
+
+ ASSERT(newWidth >= 0);
+ ASSERT(scrollOffset.width() + newX + newWidth <= maxSize.width);
+
+ return WebRect(newX, source.y, newWidth, source.height);
+}
+
+void WebViewImpl::computeScaleAndScrollForHitRect(const WebRect& hitRect, AutoZoomType zoomType, float& scale, WebPoint& scroll)
+{
+ scale = pageScaleFactor();
+ scroll.x = scroll.y = 0;
+ WebRect targetRect = hitRect;
+ if (targetRect.isEmpty())
+ targetRect.width = targetRect.height = touchPointPadding;
+
+ WebRect rect = computeBlockBounds(targetRect, zoomType);
+
+ const float overviewScale = m_minimumPageScaleFactor;
+ bool scaleUnchanged = true;
+ if (!rect.isEmpty()) {
+ // Pages should be as legible as on desktop when at dpi scale, so no
+ // need to zoom in further when automatically determining zoom level
+ // (after double tap, find in page, etc), though the user should still
+ // be allowed to manually pinch zoom in further if they desire.
+ const float maxScale = deviceScaleFactor();
+
+ const float defaultMargin = doubleTapZoomContentDefaultMargin * deviceScaleFactor();
+ const float minimumMargin = doubleTapZoomContentMinimumMargin * deviceScaleFactor();
+ // We want the margins to have the same physical size, which means we
+ // need to express them in post-scale size. To do that we'd need to know
+ // the scale we're scaling to, but that depends on the margins. Instead
+ // we express them as a fraction of the target rectangle: this will be
+ // correct if we end up fully zooming to it, and won't matter if we
+ // don't.
+ rect = widenRectWithinPageBounds(rect,
+ static_cast<int>(defaultMargin * rect.width / m_size.width),
+ static_cast<int>(minimumMargin * rect.width / m_size.width));
+
+ // Fit block to screen, respecting limits.
+ scale *= static_cast<float>(m_size.width) / rect.width;
+ scale = min(scale, maxScale);
+ scale = clampPageScaleFactorToLimits(scale);
+
+ scaleUnchanged = fabs(pageScaleFactor() - scale) < minScaleDifference;
+ }
+
+ if (zoomType == DoubleTap) {
+ if (rect.isEmpty() || scaleUnchanged) {
+ // Zoom out to overview mode.
+ if (overviewScale)
+ scale = overviewScale;
+ return;
+ }
+ } else if (rect.isEmpty()) {
+ // Keep current scale (no need to scroll as x,y will normally already
+ // be visible). FIXME: Revisit this if it isn't always true.
+ return;
+ }
+
+ // FIXME: If this is being called for auto zoom during find in page,
+ // then if the user manually zooms in it'd be nice to preserve the relative
+ // increase in zoom they caused (if they zoom out then it's ok to zoom
+ // them back in again). This isn't compatible with our current double-tap
+ // zoom strategy (fitting the containing block to the screen) though.
+
+ float screenHeight = m_size.height / scale * pageScaleFactor();
+ float screenWidth = m_size.width / scale * pageScaleFactor();
+
+ // Scroll to vertically align the block.
+ if (rect.height < screenHeight) {
+ // Vertically center short blocks.
+ rect.y -= 0.5 * (screenHeight - rect.height);
+ } else {
+ // Ensure position we're zooming to (+ padding) isn't off the bottom of
+ // the screen.
+ rect.y = max<float>(rect.y, hitRect.y + touchPointPadding - screenHeight);
+ } // Otherwise top align the block.
+
+ // Do the same thing for horizontal alignment.
+ if (rect.width < screenWidth)
+ rect.x -= 0.5 * (screenWidth - rect.width);
+ else
+ rect.x = max<float>(rect.x, hitRect.x + touchPointPadding - screenWidth);
+
+ scroll.x = rect.x;
+ scroll.y = rect.y;
+}
+#endif
+
void WebViewImpl::numberOfWheelEventHandlersChanged(unsigned numberOfWheelHandlers)
{
- m_haveWheelEventHandlers = numberOfWheelHandlers > 0;
if (m_client)
m_client->numberOfWheelEventHandlersChanged(numberOfWheelHandlers);
-#if USE(ACCELERATED_COMPOSITING)
- if (m_layerTreeHost)
- m_layerTreeHost->setHaveWheelEventHandlers(m_haveWheelEventHandlers);
-#endif
+}
+
+void WebViewImpl::numberOfTouchEventHandlersChanged(unsigned numberOfTouchHandlers)
+{
+ if (m_client)
+ m_client->numberOfTouchEventHandlersChanged(numberOfTouchHandlers);
}
#if !OS(DARWIN)
@@ -1257,6 +1408,14 @@ void WebViewImpl::composite(bool)
#endif
}
+void WebViewImpl::setNeedsRedraw()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_layerTreeHost && isAcceleratedCompositingActive())
+ m_layerTreeHost->setNeedsRedraw();
+#endif
+}
+
void WebViewImpl::loseCompositorContext(int numTimes)
{
#if USE(ACCELERATED_COMPOSITING)
@@ -2140,12 +2299,12 @@ bool WebViewImpl::computePageScaleFactorLimits()
m_maximumPageScaleFactor = max(m_minimumPageScaleFactor, m_maximumPageScaleFactor);
}
ASSERT(m_minimumPageScaleFactor <= m_maximumPageScaleFactor);
+
+ float clampedScale = clampPageScaleFactorToLimits(pageScaleFactor());
#if USE(ACCELERATED_COMPOSITING)
if (m_layerTreeHost)
- m_layerTreeHost->setPageScaleFactorLimits(m_minimumPageScaleFactor, m_maximumPageScaleFactor);
+ m_layerTreeHost->setPageScaleFactorAndLimits(clampedScale, m_minimumPageScaleFactor, m_maximumPageScaleFactor);
#endif
-
- float clampedScale = clampPageScaleFactorToLimits(pageScaleFactor());
if (clampedScale != pageScaleFactor()) {
setPageScaleFactorPreservingScrollOffset(clampedScale);
return true;
@@ -3005,6 +3164,7 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active)
ccSettings.perTilePainting = page()->settings()->perTileDrawingEnabled();
ccSettings.partialSwapEnabled = page()->settings()->partialSwapEnabled();
+ ccSettings.threadedAnimationEnabled = page()->settings()->threadedAnimationEnabled();
m_nonCompositedContentHost = NonCompositedContentHost::create(WebViewImplContentPainter::create(this));
m_nonCompositedContentHost->setShowDebugBorders(page()->settings()->showDebugBorders());
@@ -3014,8 +3174,7 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active)
m_layerTreeHost = CCLayerTreeHost::create(this, ccSettings);
if (m_layerTreeHost) {
- m_layerTreeHost->setHaveWheelEventHandlers(m_haveWheelEventHandlers);
- m_layerTreeHost->setPageScaleFactorLimits(m_minimumPageScaleFactor, m_maximumPageScaleFactor);
+ m_layerTreeHost->setPageScaleFactorAndLimits(pageScaleFactor(), m_minimumPageScaleFactor, m_maximumPageScaleFactor);
updateLayerTreeViewport();
m_client->didActivateCompositor(m_layerTreeHost->compositorIdentifier());
m_isAcceleratedCompositingActive = true;
@@ -3036,15 +3195,25 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active)
#endif
+PassRefPtr<GraphicsContext3D> WebViewImpl::createCompositorGraphicsContext3D()
+{
+ WebKit::WebGraphicsContext3D::Attributes attributes = getCompositorContextAttributes(CCProxy::hasImplThread());
+ OwnPtr<WebGraphicsContext3D> webContext = adoptPtr(client()->createGraphicsContext3D(attributes, true /* renderDirectlyToHostWindow */));
+ if (!webContext)
+ return 0;
+
+ return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(webContext.release(), GraphicsContext3D::RenderDirectlyToHostWindow);
+}
+
PassRefPtr<GraphicsContext3D> WebViewImpl::createLayerTreeHostContext3D()
{
- RefPtr<GraphicsContext3D> context = m_temporaryOnscreenGraphicsContext3D.release();
- if (!context) {
- if (CCProxy::hasImplThread())
- context = GraphicsContext3DPrivate::createGraphicsContextForAnotherThread(getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow);
- else
- context = GraphicsContext3D::create(getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow);
- }
+ RefPtr<GraphicsContext3D> context;
+
+ // If we've already created an onscreen context for this view, return that.
+ if (m_temporaryOnscreenGraphicsContext3D)
+ context = m_temporaryOnscreenGraphicsContext3D.release();
+ else // Otherwise make a new one.
+ context = createCompositorGraphicsContext3D();
return context;
}
@@ -3125,7 +3294,7 @@ void WebViewImpl::updateLayerTreeViewport()
}
m_nonCompositedContentHost->setViewport(visibleRect.size(), view->contentsSize(), scroll, pageScaleFactor(), layerAdjustX);
m_layerTreeHost->setViewportSize(visibleRect.size());
- m_layerTreeHost->setPageScale(pageScaleFactor());
+ m_layerTreeHost->setPageScaleFactorAndLimits(pageScaleFactor(), m_minimumPageScaleFactor, m_maximumPageScaleFactor);
}
WebGraphicsContext3D* WebViewImpl::graphicsContext3D()
@@ -3137,17 +3306,16 @@ WebGraphicsContext3D* WebViewImpl::graphicsContext3D()
if (webContext && !webContext->isContextLost())
return webContext;
}
- if (m_temporaryOnscreenGraphicsContext3D) {
- WebGraphicsContext3D* webContext = GraphicsContext3DPrivate::extractWebGraphicsContext3D(m_temporaryOnscreenGraphicsContext3D.get());
- if (webContext && !webContext->isContextLost())
- return webContext;
- }
- if (CCProxy::hasImplThread())
- m_temporaryOnscreenGraphicsContext3D = GraphicsContext3DPrivate::createGraphicsContextForAnotherThread(getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow);
- else
- m_temporaryOnscreenGraphicsContext3D = GraphicsContext3D::create(getCompositorContextAttributes(), m_page->chrome(), GraphicsContext3D::RenderDirectlyToHostWindow);
-
- return GraphicsContext3DPrivate::extractWebGraphicsContext3D(m_temporaryOnscreenGraphicsContext3D.get());
+ // If we get here it means that some system needs access to the context the compositor will use but the compositor itself
+ // hasn't requested a context or it was unable to successfully instantiate a context.
+ // We need to return the context that the compositor will later use so we allocate a new context (if needed) and stash it
+ // until the compositor requests and takes ownership of the context via createLayerTreeHost3D().
+ if (!m_temporaryOnscreenGraphicsContext3D)
+ m_temporaryOnscreenGraphicsContext3D = createCompositorGraphicsContext3D();
+
+ WebGraphicsContext3D* webContext = GraphicsContext3DPrivate::extractWebGraphicsContext3D(m_temporaryOnscreenGraphicsContext3D.get());
+ if (webContext && !webContext->isContextLost())
+ return webContext;
}
#endif
return 0;