diff options
Diffstat (limited to 'Source/WebKit/chromium/src/WebViewImpl.cpp')
-rw-r--r-- | Source/WebKit/chromium/src/WebViewImpl.cpp | 589 |
1 files changed, 354 insertions, 235 deletions
diff --git a/Source/WebKit/chromium/src/WebViewImpl.cpp b/Source/WebKit/chromium/src/WebViewImpl.cpp index 52a022ce9..4318dc79d 100644 --- a/Source/WebKit/chromium/src/WebViewImpl.cpp +++ b/Source/WebKit/chromium/src/WebViewImpl.cpp @@ -31,13 +31,14 @@ #include "config.h" #include "WebViewImpl.h" -#include "AutofillPopupMenuClient.h" #include "AXObjectCache.h" +#include "ActivePlatformGestureAnimation.h" +#include "AutofillPopupMenuClient.h" #include "BackForwardListChromium.h" -#include "cc/CCProxy.h" -#include "CSSStyleSelector.h" +#include "BatteryClientImpl.h" #include "CSSValueKeywords.h" #include "Chrome.h" +#include "Color.h" #include "ColorSpace.h" #include "CompositionUnderlineVectorBuilder.h" #include "ContextMenu.h" @@ -63,6 +64,7 @@ #include "FrameTree.h" #include "FrameView.h" #include "GeolocationClientProxy.h" +#include "GeolocationController.h" #include "GraphicsContext.h" #include "GraphicsContext3D.h" #include "GraphicsContext3DPrivate.h" @@ -85,6 +87,8 @@ #include "Page.h" #include "PageGroup.h" #include "PageGroupLoadDeferrer.h" +#include "PagePopupClient.h" +#include "PageWidgetDelegate.h" #include "Pasteboard.h" #include "PlatformContextSkia.h" #include "PlatformKeyboardEvent.h" @@ -106,46 +110,55 @@ #include "Settings.h" #include "SharedGraphicsContext3D.h" #include "SpeechInputClientImpl.h" +#include "SpeechRecognitionClientProxy.h" +#include "StyleResolver.h" +#include "TextFieldDecoratorImpl.h" #include "TextIterator.h" #include "Timer.h" +#include "TouchpadFlingPlatformGestureCurve.h" #include "TraceEvent.h" -#include "TypingCommand.h" #include "UserGestureIndicator.h" -#include "Vector.h" #include "WebAccessibilityObject.h" +#include "WebActiveWheelFlingParameters.h" #include "WebAutofillClient.h" #include "WebCompositorImpl.h" #include "WebDevToolsAgentImpl.h" #include "WebDevToolsAgentPrivate.h" -#include "platform/WebDragData.h" #include "WebFrameImpl.h" -#include "platform/WebGraphicsContext3D.h" -#include "platform/WebImage.h" #include "WebInputElement.h" #include "WebInputEvent.h" #include "WebInputEventConversion.h" #include "WebKit.h" -#include "platform/WebKitPlatformSupport.h" -#include "platform/WebLayer.h" -#include "platform/WebLayerTreeView.h" #include "WebMediaPlayerAction.h" #include "WebNode.h" +#include "WebPagePopupImpl.h" #include "WebPlugin.h" #include "WebPluginAction.h" #include "WebPluginContainerImpl.h" -#include "platform/WebPoint.h" #include "WebPopupMenuImpl.h" #include "WebRange.h" -#include "platform/WebRect.h" #include "WebRuntimeFeatures.h" #include "WebSettingsImpl.h" +#include "WebViewClient.h" +#include "WheelEvent.h" +#include "cc/CCProxy.h" +#include "painting/GraphicsContextBuilder.h" +#include "platform/WebDragData.h" +#include "platform/WebImage.h" +#include "platform/WebKitPlatformSupport.h" #include "platform/WebString.h" #include "platform/WebVector.h" -#include "WebViewClient.h" -#include <wtf/ByteArray.h> +#include <public/Platform.h> +#include <public/WebFloatPoint.h> +#include <public/WebGraphicsContext3D.h> +#include <public/WebLayer.h> +#include <public/WebLayerTreeView.h> +#include <public/WebPoint.h> +#include <public/WebRect.h> #include <wtf/CurrentTime.h> #include <wtf/MainThread.h> #include <wtf/RefPtr.h> +#include <wtf/Uint8ClampedArray.h> #if ENABLE(GESTURE_EVENTS) #include "PlatformGestureEvent.h" @@ -176,7 +189,7 @@ using namespace std; // (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 minScaleDifference = 0.01f; static const float doubleTapZoomContentDefaultMargin = 5; static const float doubleTapZoomContentMinimumMargin = 2; @@ -313,6 +326,18 @@ void WebViewImpl::setSpellCheckClient(WebSpellCheckClient* spellCheckClient) m_spellCheckClient = spellCheckClient; } +void WebViewImpl::addTextFieldDecoratorClient(WebTextFieldDecoratorClient* client) +{ + ASSERT(client); + // We limit the number of decorators because it affects performance of text + // field creation. If you'd like to add more decorators, consider moving + // your decorator or existing decorators to WebCore. + const unsigned maximumNumberOfDecorators = 8; + if (m_textFieldDecorators.size() >= maximumNumberOfDecorators) + CRASH(); + m_textFieldDecorators.append(TextFieldDecoratorImpl::create(client)); +} + WebViewImpl::WebViewImpl(WebViewClient* client) : m_client(client) , m_autofillClient(0) @@ -349,20 +374,30 @@ WebViewImpl::WebViewImpl(WebViewClient* client) , m_isTransparent(false) , m_tabsToLinks(false) , m_dragScrollTimer(adoptPtr(new DragScrollTimer)) + , m_isCancelingFullScreen(false) #if USE(ACCELERATED_COMPOSITING) , m_rootGraphicsLayer(0) , m_isAcceleratedCompositingActive(false) , m_compositorCreationFailed(false) , m_recreatingGraphicsContext(false) + , m_compositorSurfaceReady(false) #endif #if ENABLE(INPUT_SPEECH) , m_speechInputClient(SpeechInputClientImpl::create(client)) #endif +#if ENABLE(SCRIPTED_SPEECH) + , m_speechRecognitionClient(SpeechRecognitionClientProxy::create(client ? client->speechRecognizer() : 0)) +#endif , m_deviceOrientationClientProxy(adoptPtr(new DeviceOrientationClientProxy(client ? client->deviceOrientationClient() : 0))) , m_geolocationClientProxy(adoptPtr(new GeolocationClientProxy(client ? client->geolocationClient() : 0))) +#if ENABLE(BATTERY_STATUS) + , m_batteryClient(adoptPtr(new BatteryClientImpl(client ? client->batteryStatusClient() : 0))) +#endif + , m_emulatedTextZoomFactor(1) #if ENABLE(MEDIA_STREAM) , m_userMediaClientImpl(this) #endif + , m_flingModifier(0) { // WebKit/win/WebView.cpp does the same thing, except they call the // KJS specific wrapper around this method. We need to have threading @@ -370,16 +405,12 @@ WebViewImpl::WebViewImpl(WebViewClient* client) WTF::initializeThreading(); WTF::initializeMainThread(); - // set to impossible point so we always get the first mouse pos - m_lastMousePosition = WebPoint(-1, -1); - Page::PageClients pageClients; pageClients.chromeClient = &m_chromeClientImpl; pageClients.contextMenuClient = &m_contextMenuClientImpl; pageClients.editorClient = &m_editorClientImpl; pageClients.dragClient = &m_dragClientImpl; pageClients.inspectorClient = &m_inspectorClientImpl; - pageClients.geolocationClient = m_geolocationClientProxy.get(); pageClients.backForwardClient = BackForwardListChromium::create(this); m_page = adoptPtr(new Page(pageClients)); @@ -389,13 +420,21 @@ WebViewImpl::WebViewImpl(WebViewClient* client) #if ENABLE(INPUT_SPEECH) provideSpeechInputTo(m_page.get(), m_speechInputClient.get()); #endif -#if ENABLE(NOTIFICATIONS) +#if ENABLE(SCRIPTED_SPEECH) + provideSpeechRecognitionTo(m_page.get(), m_speechRecognitionClient.get()); +#endif +#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) provideNotification(m_page.get(), notificationPresenterImpl()); #endif provideDeviceOrientationTo(m_page.get(), m_deviceOrientationClientProxy.get()); - m_geolocationClientProxy->setController(m_page->geolocationController()); + provideGeolocationTo(m_page.get(), m_geolocationClientProxy.get()); + m_geolocationClientProxy->setController(GeolocationController::from(m_page.get())); +#if ENABLE(BATTERY_STATUS) + provideBatteryTo(m_page.get(), m_batteryClient.get()); +#endif + m_page->setGroupName(pageGroupName); #if ENABLE(PAGE_VISIBILITY_API) @@ -433,38 +472,14 @@ void WebViewImpl::setTabKeyCyclesThroughElements(bool value) m_page->setTabKeyCyclesThroughElements(value); } -void WebViewImpl::mouseMove(const WebMouseEvent& event) +void WebViewImpl::handleMouseLeave(Frame& mainFrame, const WebMouseEvent& event) { - if (!mainFrameImpl() || !mainFrameImpl()->frameView()) - return; - - m_lastMousePosition = WebPoint(event.x, event.y); - - // We call mouseMoved here instead of handleMouseMovedEvent because we need - // our ChromeClientImpl to receive changes to the mouse position and - // tooltip text, and mouseMoved handles all of that. - mainFrameImpl()->frame()->eventHandler()->mouseMoved( - PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event)); -} - -void WebViewImpl::mouseLeave(const WebMouseEvent& event) -{ - // This event gets sent as the main frame is closing. In that case, just - // ignore it. - if (!mainFrameImpl() || !mainFrameImpl()->frameView()) - return; - m_client->setMouseOverURL(WebURL()); - - mainFrameImpl()->frame()->eventHandler()->handleMouseMoveEvent( - PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event)); + PageWidgetEventHandler::handleMouseLeave(mainFrame, event); } -void WebViewImpl::mouseDown(const WebMouseEvent& event) +void WebViewImpl::handleMouseDown(Frame& mainFrame, const WebMouseEvent& event) { - if (!mainFrameImpl() || !mainFrameImpl()->frameView()) - return; - // If there is a select popup open, close it as the user is clicking on // the page (outside of the popup). We also save it so we can prevent a // click on the select element from immediately reopening the popup. @@ -488,8 +503,7 @@ void WebViewImpl::mouseDown(const WebMouseEvent& event) m_mouseCaptureNode = hitNode; } - mainFrameImpl()->frame()->eventHandler()->handleMousePressEvent( - PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event)); + PageWidgetEventHandler::handleMouseDown(mainFrame, event); if (m_selectPopup && m_selectPopup == selectPopup) { // That click triggered a select popup which is the same as the one that @@ -540,11 +554,8 @@ void WebViewImpl::mouseContextMenu(const WebMouseEvent& event) // implementation... } -void WebViewImpl::mouseUp(const WebMouseEvent& event) +void WebViewImpl::handleMouseUp(Frame& mainFrame, const WebMouseEvent& event) { - if (!mainFrameImpl() || !mainFrameImpl()->frameView()) - return; - #if OS(UNIX) && !OS(DARWIN) // If the event was a middle click, attempt to copy text into the focused // frame. We execute this before we let the page have a go at the event @@ -582,8 +593,7 @@ void WebViewImpl::mouseUp(const WebMouseEvent& event) } #endif - mainFrameImpl()->frame()->eventHandler()->handleMouseReleaseEvent( - PlatformMouseEventBuilder(mainFrameImpl()->frameView(), event)); + PageWidgetEventHandler::handleMouseUp(mainFrame, event); #if OS(WINDOWS) // Dispatch the contextmenu event regardless of if the click was swallowed. @@ -593,17 +603,89 @@ void WebViewImpl::mouseUp(const WebMouseEvent& event) #endif } -bool WebViewImpl::mouseWheel(const WebMouseWheelEvent& event) +void WebViewImpl::scrollBy(const WebCore::IntPoint& delta) { - PlatformWheelEventBuilder platformEvent(mainFrameImpl()->frameView(), event); - return mainFrameImpl()->frame()->eventHandler()->handleWheelEvent(platformEvent); + WebMouseWheelEvent syntheticWheel; + const float tickDivisor = WebCore::WheelEvent::tickMultiplier; + + syntheticWheel.deltaX = delta.x(); + syntheticWheel.deltaY = delta.y(); + syntheticWheel.wheelTicksX = delta.x() / tickDivisor; + syntheticWheel.wheelTicksY = delta.y() / tickDivisor; + syntheticWheel.hasPreciseScrollingDeltas = true; + syntheticWheel.x = m_lastWheelPosition.x; + syntheticWheel.y = m_lastWheelPosition.y; + syntheticWheel.globalX = m_lastWheelGlobalPosition.x; + syntheticWheel.globalY = m_lastWheelGlobalPosition.y; + syntheticWheel.modifiers = m_flingModifier; + + if (m_page && m_page->mainFrame() && m_page->mainFrame()->view()) + handleMouseWheel(*m_page->mainFrame(), syntheticWheel); } #if ENABLE(GESTURE_EVENTS) -bool WebViewImpl::gestureEvent(const WebGestureEvent& event) +bool WebViewImpl::handleGestureEvent(const WebGestureEvent& event) +{ + switch (event.type) { + case WebInputEvent::GestureFlingStart: { + m_lastWheelPosition = WebPoint(event.x, event.y); + m_lastWheelGlobalPosition = WebPoint(event.globalX, event.globalY); + m_flingModifier = event.modifiers; + // FIXME: Make the curve parametrizable from the browser. + m_gestureAnimation = ActivePlatformGestureAnimation::create(TouchpadFlingPlatformGestureCurve::create(FloatPoint(event.deltaX, event.deltaY)), this); + scheduleAnimation(); + return true; + } + case WebInputEvent::GestureFlingCancel: + if (m_gestureAnimation) { + m_gestureAnimation.clear(); + return true; + } + return false; + case WebInputEvent::GestureTap: { + PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event); + RefPtr<WebCore::PopupContainer> selectPopup; + selectPopup = m_selectPopup; + hideSelectPopup(); + ASSERT(!m_selectPopup); + bool gestureHandled = mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent); + if (m_selectPopup && m_selectPopup == selectPopup) { + // That tap triggered a select popup which is the same as the one that + // was showing before the tap. It means the user tapped the select + // while the popup was showing, and as a result we first closed then + // immediately reopened the select popup. It needs to be closed. + hideSelectPopup(); + } + return gestureHandled; + } + case WebInputEvent::GestureScrollBegin: + case WebInputEvent::GestureScrollEnd: + case WebInputEvent::GestureScrollUpdate: + case WebInputEvent::GestureTapDown: + case WebInputEvent::GestureDoubleTap: + case WebInputEvent::GestureLongPress: + case WebInputEvent::GesturePinchBegin: + case WebInputEvent::GesturePinchEnd: + case WebInputEvent::GesturePinchUpdate: { + PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event); + return mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent); + } + default: + ASSERT_NOT_REACHED(); + } + return false; +} + +void WebViewImpl::transferActiveWheelFlingAnimation(const WebActiveWheelFlingParameters& parameters) { - PlatformGestureEventBuilder platformEvent(mainFrameImpl()->frameView(), event); - return mainFrameImpl()->frame()->eventHandler()->handleGestureEvent(platformEvent); + TRACE_EVENT0("webkit", "WebViewImpl::transferActiveWheelFlingAnimation"); + ASSERT(!m_gestureAnimation); + m_lastWheelPosition = parameters.point; + m_lastWheelGlobalPosition = parameters.globalPoint; + m_flingModifier = parameters.modifiers; + OwnPtr<PlatformGestureCurve> curve = TouchpadFlingPlatformGestureCurve::create(parameters.delta, IntPoint(parameters.cumulativeScroll)); + m_gestureAnimation = ActivePlatformGestureAnimation::create(curve.release(), this, parameters.startTime); + scheduleAnimation(); } void WebViewImpl::startPageScaleAnimation(const IntPoint& scroll, bool useAnchor, float newScale, double durationSec) @@ -613,12 +695,16 @@ void WebViewImpl::startPageScaleAnimation(const IntPoint& scroll, bool useAnchor } #endif -bool WebViewImpl::keyEvent(const WebKeyboardEvent& event) +bool WebViewImpl::handleKeyEvent(const WebKeyboardEvent& event) { ASSERT((event.type == WebInputEvent::RawKeyDown) || (event.type == WebInputEvent::KeyDown) || (event.type == WebInputEvent::KeyUp)); + // Halt an in-progress fling on a key event. + if (m_gestureAnimation) + m_gestureAnimation.clear(); + // Please refer to the comments explaining the m_suppressNextKeypressEvent // member. // The m_suppressNextKeypressEvent is set if the KeyDown is handled by @@ -631,6 +717,16 @@ bool WebViewImpl::keyEvent(const WebKeyboardEvent& event) // not the page. if (m_selectPopup) return m_selectPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event)); +#if ENABLE(PAGE_POPUP) + if (m_pagePopup) { + m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event)); + // We need to ignore the next Char event after this otherwise pressing + // enter when selecting an item in the popup will go to the page. + if (WebInputEvent::RawKeyDown == event.type) + m_suppressNextKeypressEvent = true; + return true; + } +#endif // Give Autocomplete a chance to consume the key events it is interested in. if (autocompleteHandleKeyEvent(event)) @@ -727,7 +823,7 @@ bool WebViewImpl::autocompleteHandleKeyEvent(const WebKeyboardEvent& event) return false; } -bool WebViewImpl::charEvent(const WebKeyboardEvent& event) +bool WebViewImpl::handleCharEvent(const WebKeyboardEvent& event) { ASSERT(event.type == WebInputEvent::Char); @@ -743,6 +839,10 @@ bool WebViewImpl::charEvent(const WebKeyboardEvent& event) // not the page. if (m_selectPopup) return m_selectPopup->handleKeyEvent(PlatformKeyboardEventBuilder(event)); +#if ENABLE(PAGE_POPUP) + if (m_pagePopup) + return m_pagePopup->handleKeyEvent(PlatformKeyboardEventBuilder(event)); +#endif Frame* frame = focusedWebCoreFrame(); if (!frame) @@ -773,18 +873,6 @@ bool WebViewImpl::charEvent(const WebKeyboardEvent& event) return true; } -#if ENABLE(TOUCH_EVENTS) -bool WebViewImpl::touchEvent(const WebTouchEvent& event) -{ - if (!mainFrameImpl() || !mainFrameImpl()->frameView()) - return false; - - PlatformTouchEventBuilder touchEventBuilder(mainFrameImpl()->frameView(), event); - bool defaultPrevented = mainFrameImpl()->frame()->eventHandler()->handleTouchEvent(touchEventBuilder); - return defaultPrevented; -} -#endif - #if ENABLE(GESTURE_EVENTS) WebRect WebViewImpl::computeBlockBounds(const WebRect& rect, AutoZoomType zoomType) { @@ -807,7 +895,7 @@ WebRect WebViewImpl::computeBlockBounds(const WebRect& rect, AutoZoomType zoomTy // Return the bounding box in the window coordinate system. if (node) { - IntRect rect = node->Node::getRect(); + IntRect rect = node->Node::getPixelSnappedRect(); Frame* frame = node->document()->frame(); return frame->view()->contentsToWindow(rect); } @@ -1105,6 +1193,42 @@ void WebViewImpl::popupClosed(WebCore::PopupContainer* popupContainer) } } +#if ENABLE(PAGE_POPUP) +PagePopup* WebViewImpl::openPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView) +{ + ASSERT(client); + if (hasOpenedPopup()) + hidePopups(); + ASSERT(!m_pagePopup); + + WebWidget* popupWidget = m_client->createPopupMenu(WebPopupTypePage); + ASSERT(popupWidget); + m_pagePopup = static_cast<WebPagePopupImpl*>(popupWidget); + if (!m_pagePopup->init(this, client, originBoundsInRootView)) { + m_pagePopup->closePopup(); + m_pagePopup = 0; + } + + if (Frame* frame = focusedWebCoreFrame()) + frame->selection()->setCaretVisible(false); + return m_pagePopup.get(); +} + +void WebViewImpl::closePagePopup(PagePopup* popup) +{ + ASSERT(popup); + WebPagePopupImpl* popupImpl = static_cast<WebPagePopupImpl*>(popup); + ASSERT(m_pagePopup.get() == popupImpl); + if (m_pagePopup.get() != popupImpl) + return; + m_pagePopup->closePopup(); + m_pagePopup = 0; + + if (Frame* frame = focusedWebCoreFrame()) + frame->selection()->pageActivationChanged(); +} +#endif + void WebViewImpl::hideAutofillPopup() { if (m_autofillPopupShowing) { @@ -1171,8 +1295,14 @@ void WebViewImpl::resize(const WebSize& newSize) return; m_size = newSize; - if (mainFrameImpl()->frameView()) - mainFrameImpl()->frameView()->resize(m_size.width, m_size.height); + WebDevToolsAgentPrivate* agentPrivate = devToolsAgentPrivate(); + if (agentPrivate && agentPrivate->metricsOverridden()) + agentPrivate->webViewResized(); + else { + WebFrameImpl* webFrame = mainFrameImpl(); + if (webFrame->frameView()) + webFrame->frameView()->resize(newSize.width, newSize.height); + } sendResizeEventAndRepaint(); } @@ -1224,8 +1354,14 @@ void WebViewImpl::willExitFullScreen() return; if (Document* doc = m_fullScreenFrame->document()) { - if (doc->webkitIsFullScreen()) + if (doc->webkitIsFullScreen()) { + // When the client exits from full screen we have to call webkitCancelFullScreen to + // notify the document. While doing that, suppress notifications back to the client. + m_isCancelingFullScreen = true; + doc->webkitCancelFullScreen(); + m_isCancelingFullScreen = false; doc->webkitWillExitFullScreenForElement(0); + } } #endif } @@ -1250,61 +1386,71 @@ void WebViewImpl::instrumentBeginFrame() InspectorInstrumentation::didBeginFrame(m_page.get()); } -void WebViewImpl::animate(double frameBeginTime) +void WebViewImpl::instrumentCancelFrame() +{ + InspectorInstrumentation::didCancelFrame(m_page.get()); +} + +#if ENABLE(BATTERY_STATUS) +void WebViewImpl::updateBatteryStatus(const WebBatteryStatus& status) +{ + m_batteryClient->updateBatteryStatus(status); +} +#endif + +void WebViewImpl::setCompositorSurfaceReady() +{ + m_compositorSurfaceReady = true; + if (!m_layerTreeView.isNull()) + m_layerTreeView.setSurfaceReady(); +} + +void WebViewImpl::animate(double) { #if ENABLE(REQUEST_ANIMATION_FRAME) - // FIXME: remove this zero-check once render_widget has been modified to - // pass in a frameBeginTime. - if (!frameBeginTime) - frameBeginTime = currentTime(); + double monotonicFrameBeginTime = monotonicallyIncreasingTime(); #if USE(ACCELERATED_COMPOSITING) // In composited mode, we always go through the compositor so it can apply // appropriate flow-control mechanisms. if (isAcceleratedCompositingActive()) - m_layerTreeView.updateAnimations(frameBeginTime); + m_layerTreeView.updateAnimations(monotonicFrameBeginTime); else #endif - updateAnimations(frameBeginTime); + updateAnimations(monotonicFrameBeginTime); #endif } -void WebViewImpl::updateAnimations(double frameBeginTime) +void WebViewImpl::willBeginFrame() +{ + instrumentBeginFrame(); + m_client->willBeginCompositorFrame(); +} + +void WebViewImpl::updateAnimations(double monotonicFrameBeginTime) { #if ENABLE(REQUEST_ANIMATION_FRAME) TRACE_EVENT("WebViewImpl::updateAnimations", this, 0); - WebFrameImpl* webframe = mainFrameImpl(); - if (!webframe) - return; - FrameView* view = webframe->frameView(); - if (!view) + // Create synthetic wheel events as necessary for fling. + if (m_gestureAnimation) { + if (m_gestureAnimation->animate(monotonicFrameBeginTime)) + scheduleAnimation(); + else + m_gestureAnimation.clear(); + } + + if (!m_page) return; - view->serviceScriptedAnimations(convertSecondsToDOMTimeStamp(frameBeginTime)); + + PageWidgetDelegate::animate(m_page.get(), monotonicFrameBeginTime); #endif } void WebViewImpl::layout() { TRACE_EVENT("WebViewImpl::layout", this, 0); - - WebFrameImpl* webframe = mainFrameImpl(); - if (webframe) { - // In order for our child HWNDs (NativeWindowWidgets) to update properly, - // they need to be told that we are updating the screen. The problem is - // that the native widgets need to recalculate their clip region and not - // overlap any of our non-native widgets. To force the resizing, call - // setFrameRect(). This will be a quick operation for most frames, but - // the NativeWindowWidgets will update a proper clipping region. - FrameView* view = webframe->frameView(); - if (view) - view->setFrameRect(view->frameRect()); - - // setFrameRect may have the side-effect of causing existing page - // layout to be invalidated, so layout needs to be called last. - - webframe->layout(); - } + PageWidgetDelegate::layout(m_page.get()); } #if USE(ACCELERATED_COMPOSITING) @@ -1327,7 +1473,7 @@ void WebViewImpl::doPixelReadbackToCanvas(WebCanvas* canvas, const IntRect& rect IntRect invertRect(rect.x(), bitmapHeight - rect.maxY(), rect.width(), rect.height()); OwnPtr<ImageBuffer> imageBuffer(ImageBuffer::create(rect.size())); - RefPtr<ByteArray> pixelArray(ByteArray::create(rect.width() * rect.height() * 4)); + RefPtr<Uint8ClampedArray> pixelArray(Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4)); if (imageBuffer && pixelArray) { m_layerTreeView.compositeAndReadback(pixelArray->data(), invertRect); imageBuffer->putByteArray(Premultiplied, pixelArray.get(), rect.size(), IntRect(IntPoint(), rect.size()), IntPoint()); @@ -1357,13 +1503,11 @@ void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect) #endif } else { double paintStart = currentTime(); - WebFrameImpl* webframe = mainFrameImpl(); - if (webframe) - webframe->paint(canvas, rect); + PageWidgetDelegate::paint(m_page.get(), pageOverlays(), canvas, rect); double paintEnd = currentTime(); double pixelsPerSec = (rect.width * rect.height) / (paintEnd - paintStart); - PlatformSupport::histogramCustomCounts("Renderer4.SoftwarePaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30); - PlatformSupport::histogramCustomCounts("Renderer4.SoftwarePaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.SoftwarePaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30); } } @@ -1403,6 +1547,15 @@ void WebViewImpl::setNeedsRedraw() #endif } +bool WebViewImpl::isInputThrottled() const +{ +#if USE(ACCELERATED_COMPOSITING) + if (!m_layerTreeView.isNull() && isAcceleratedCompositingActive()) + return m_layerTreeView.commitRequested(); +#endif + return false; +} + void WebViewImpl::loseCompositorContext(int numTimes) { #if USE(ACCELERATED_COMPOSITING) @@ -1427,6 +1580,15 @@ void WebViewImpl::enterFullScreenForElement(WebCore::Element* element) return; } +#if USE(NATIVE_FULLSCREEN_VIDEO) + if (element && element->isMediaElement()) { + HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(element); + if (mediaElement->player() && mediaElement->player()->enterFullscreen()) + m_provisionalFullScreenElement = element; + return; + } +#endif + // We need to transition to fullscreen mode. if (m_client && m_client->enterFullScreen()) m_provisionalFullScreenElement = element; @@ -1434,6 +1596,17 @@ void WebViewImpl::enterFullScreenForElement(WebCore::Element* element) void WebViewImpl::exitFullScreenForElement(WebCore::Element* element) { + // The client is exiting full screen, so don't send a notification. + if (m_isCancelingFullScreen) + return; +#if USE(NATIVE_FULLSCREEN_VIDEO) + if (element && element->isMediaElement()) { + HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(element); + if (mediaElement->player()) + mediaElement->player()->exitFullscreen(); + return; + } +#endif if (m_client) m_client->exitFullScreen(); } @@ -1504,79 +1677,8 @@ bool WebViewImpl::handleInputEvent(const WebInputEvent& inputEvent) return true; } - bool handled = true; - - // FIXME: WebKit seems to always return false on mouse events processing - // methods. For now we'll assume it has processed them (as we are only - // interested in whether keyboard events are processed). - switch (inputEvent.type) { - case WebInputEvent::MouseMove: - mouseMove(*static_cast<const WebMouseEvent*>(&inputEvent)); - break; - - case WebInputEvent::MouseLeave: - mouseLeave(*static_cast<const WebMouseEvent*>(&inputEvent)); - break; - - case WebInputEvent::MouseWheel: - handled = mouseWheel(*static_cast<const WebMouseWheelEvent*>(&inputEvent)); - break; - - case WebInputEvent::MouseDown: - mouseDown(*static_cast<const WebMouseEvent*>(&inputEvent)); - break; - - case WebInputEvent::MouseUp: - mouseUp(*static_cast<const WebMouseEvent*>(&inputEvent)); - break; - - case WebInputEvent::RawKeyDown: - case WebInputEvent::KeyDown: - case WebInputEvent::KeyUp: - handled = keyEvent(*static_cast<const WebKeyboardEvent*>(&inputEvent)); - break; - - case WebInputEvent::Char: - handled = charEvent(*static_cast<const WebKeyboardEvent*>(&inputEvent)); - break; - -#if ENABLE(GESTURE_EVENTS) - case WebInputEvent::GestureScrollBegin: - case WebInputEvent::GestureScrollEnd: - case WebInputEvent::GestureScrollUpdate: - case WebInputEvent::GestureFlingStart: - case WebInputEvent::GestureFlingCancel: - case WebInputEvent::GestureTap: - case WebInputEvent::GestureTapDown: - case WebInputEvent::GestureDoubleTap: - handled = gestureEvent(*static_cast<const WebGestureEvent*>(&inputEvent)); - break; -#endif - -#if ENABLE(TOUCH_EVENTS) - case WebInputEvent::TouchStart: - case WebInputEvent::TouchMove: - case WebInputEvent::TouchEnd: - case WebInputEvent::TouchCancel: - handled = touchEvent(*static_cast<const WebTouchEvent*>(&inputEvent)); - break; -#endif - -#if ENABLE(GESTURE_EVENTS) - case WebInputEvent::GesturePinchBegin: - case WebInputEvent::GesturePinchEnd: - case WebInputEvent::GesturePinchUpdate: - // FIXME: Once PlatformGestureEvent is updated to support pinch, this should call handleGestureEvent, just like it currently does for gesture scroll. - handled = false; - break; -#endif - - default: - handled = false; - } - + bool handled = PageWidgetDelegate::handleInputEvent(m_page.get(), *this, inputEvent); m_currentInputEvent = 0; - return handled; } @@ -1615,8 +1717,7 @@ void WebViewImpl::setFocus(bool enable) } m_imeAcceptEvents = true; } else { - hideAutofillPopup(); - hideSelectPopup(); + hidePopups(); // Clear focus on the currently focused frame if any. if (!m_page) @@ -2103,9 +2204,9 @@ double WebViewImpl::setZoomLevel(bool textOnly, double zoomLevel) else { float zoomFactor = static_cast<float>(zoomLevelToZoomFactor(m_zoomLevel)); if (textOnly) - frame->setPageAndTextZoomFactors(1, zoomFactor); + frame->setPageAndTextZoomFactors(1, zoomFactor * m_emulatedTextZoomFactor); else - frame->setPageAndTextZoomFactors(zoomFactor, 1); + frame->setPageAndTextZoomFactors(zoomFactor, m_emulatedTextZoomFactor); } return m_zoomLevel; } @@ -2263,14 +2364,6 @@ void WebViewImpl::disableAutoResizeMode() configureAutoResizeMode(); } -void WebViewImpl::enableAutoResizeMode(bool enable, const WebSize& minSize, const WebSize& maxSize) -{ - if (enable) - enableAutoResizeMode(minSize, maxSize); - else - disableAutoResizeMode(); -} - void WebViewImpl::setPageScaleFactorLimits(float minPageScale, float maxPageScale) { m_pageDefinedMinimumPageScaleFactor = minPageScale; @@ -2658,12 +2751,11 @@ void WebViewImpl::applyAutofillSuggestions( const WebVector<WebString>& names, const WebVector<WebString>& labels, const WebVector<WebString>& icons, - const WebVector<int>& uniqueIDs, + const WebVector<int>& itemIDs, int separatorIndex) { ASSERT(names.size() == labels.size()); - ASSERT(names.size() == uniqueIDs.size()); - ASSERT(separatorIndex < static_cast<int>(names.size())); + ASSERT(names.size() == itemIDs.size()); if (names.isEmpty()) { hideAutofillPopup(); @@ -2688,19 +2780,24 @@ void WebViewImpl::applyAutofillSuggestions( m_autofillPopupClient = adoptPtr(new AutofillPopupMenuClient); m_autofillPopupClient->initialize( - inputElem, names, labels, icons, uniqueIDs, separatorIndex); + inputElem, names, labels, icons, itemIDs, separatorIndex); if (!m_autofillPopup) { + PopupContainerSettings popupSettings = autofillPopupSettings; + popupSettings.defaultDeviceScaleFactor = + m_page->settings()->defaultDeviceScaleFactor(); + if (!popupSettings.defaultDeviceScaleFactor) + popupSettings.defaultDeviceScaleFactor = 1; m_autofillPopup = PopupContainer::create(m_autofillPopupClient.get(), PopupContainer::Suggestion, - autofillPopupSettings); + popupSettings); } if (m_autofillPopupShowing) { refreshAutofillPopup(); } else { - m_autofillPopup->showInRect(focusedNode->getRect(), focusedNode->ownerDocument()->view(), 0); m_autofillPopupShowing = true; + m_autofillPopup->showInRect(focusedNode->getPixelSnappedRect(), focusedNode->ownerDocument()->view(), 0); } } @@ -2708,6 +2805,10 @@ void WebViewImpl::hidePopups() { hideSelectPopup(); hideAutofillPopup(); +#if ENABLE(PAGE_POPUP) + if (m_pagePopup) + closePagePopup(m_pagePopup.get()); +#endif } void WebViewImpl::performCustomContextMenuAction(unsigned action) @@ -2837,6 +2938,8 @@ void WebViewImpl::didCommitLoad(bool* isNewNavigation, bool isNavigationWithinPa m_observedNewNavigation = false; if (!isNavigationWithinPage) m_pageScaleFactorIsSet = false; + + m_gestureAnimation.clear(); } void WebViewImpl::layoutUpdated(WebFrameImpl* webframe) @@ -2876,6 +2979,14 @@ bool WebViewImpl::useExternalPopupMenus() return shouldUseExternalPopupMenus; } +void WebViewImpl::setEmulatedTextZoomFactor(float textZoomFactor) +{ + m_emulatedTextZoomFactor = textZoomFactor; + Frame* frame = mainFrameImpl()->frame(); + if (frame) + frame->setPageAndTextZoomFactors(frame->pageZoomFactor(), m_emulatedTextZoomFactor); +} + bool WebViewImpl::navigationPolicyFromMouseEvent(unsigned short button, bool ctrl, bool shift, bool alt, bool meta, @@ -2952,7 +3063,7 @@ void WebViewImpl::setOverlayLayer(WebCore::GraphicsLayer* layer) } } -#if ENABLE(NOTIFICATIONS) +#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) NotificationPresenterImpl* WebViewImpl::notificationPresenterImpl() { if (!m_notificationPresenter.isInitialized() && m_client) @@ -2971,16 +3082,11 @@ void WebViewImpl::refreshAutofillPopup() return; } - IntRect oldBounds = m_autofillPopup->frameRect(); - m_autofillPopup->refresh(focusedWebCoreNode()->getRect()); - IntRect newBounds = m_autofillPopup->frameRect(); + WebRect newWidgetRect = m_autofillPopup->refresh(focusedWebCoreNode()->getPixelSnappedRect()); // Let's resize the backing window if necessary. - if (oldBounds != newBounds) { - WebPopupMenuImpl* popupMenu = - static_cast<WebPopupMenuImpl*>(m_autofillPopup->client()); - if (popupMenu) - popupMenu->client()->setWindowRect(m_chromeClientImpl.rootViewToScreen(newBounds)); - } + WebPopupMenuImpl* popupMenu = static_cast<WebPopupMenuImpl*>(m_autofillPopup->client()); + if (popupMenu && popupMenu->client()->windowRect() != newWidgetRect) + popupMenu->client()->setWindowRect(newWidgetRect); } Node* WebViewImpl::focusedWebCoreNode() @@ -3089,6 +3195,14 @@ NonCompositedContentHost* WebViewImpl::nonCompositedContentHost() return m_nonCompositedContentHost.get(); } +void WebViewImpl::setBackgroundColor(const WebCore::Color& color) +{ + WebCore::Color documentBackgroundColor = color.isValid() ? color : WebCore::Color::white; + WebColor webDocumentBackgroundColor = documentBackgroundColor.rgb(); + m_nonCompositedContentHost->setBackgroundColor(documentBackgroundColor); + m_layerTreeView.setBackgroundColor(webDocumentBackgroundColor); +} + #if ENABLE(REQUEST_ANIMATION_FRAME) void WebViewImpl::scheduleAnimation() { @@ -3121,11 +3235,10 @@ public: view->paintContents(&context, contentRect); double paintEnd = currentTime(); double pixelsPerSec = (contentRect.width() * contentRect.height()) / (paintEnd - paintStart); - PlatformSupport::histogramCustomCounts("Renderer4.AccelRootPaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30); - PlatformSupport::histogramCustomCounts("Renderer4.AccelRootPaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30); - - m_webViewImpl->nonCompositedContentHost()->setBackgroundColor(view->documentBackgroundColor()); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelRootPaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30); + WebKit::Platform::current()->histogramCustomCounts("Renderer4.AccelRootPaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30); + m_webViewImpl->setBackgroundColor(view->documentBackgroundColor()); } private: @@ -3139,7 +3252,7 @@ private: void WebViewImpl::setIsAcceleratedCompositingActive(bool active) { - PlatformSupport::histogramEnumeration("GPU.setIsAcceleratedCompositingActive", active * 2 + m_isAcceleratedCompositingActive, 4); + WebKit::Platform::current()->histogramEnumeration("GPU.setIsAcceleratedCompositingActive", active * 2 + m_isAcceleratedCompositingActive, 4); if (m_isAcceleratedCompositingActive == active) return; @@ -3161,7 +3274,6 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active) WebLayerTreeView::Settings layerTreeViewSettings; layerTreeViewSettings.acceleratePainting = page()->settings()->acceleratedDrawingEnabled(); - layerTreeViewSettings.compositeOffscreen = settings()->compositeToTextureEnabled(); layerTreeViewSettings.showFPSCounter = settings()->showFPSCounter(); layerTreeViewSettings.showPlatformLayerTree = settings()->showPlatformLayerTree(); @@ -3172,12 +3284,11 @@ void WebViewImpl::setIsAcceleratedCompositingActive(bool active) m_nonCompositedContentHost = NonCompositedContentHost::create(WebViewImplContentPainter::create(this)); m_nonCompositedContentHost->setShowDebugBorders(page()->settings()->showDebugBorders()); - if (page() && page()->mainFrame()->view()) - m_nonCompositedContentHost->setBackgroundColor(page()->mainFrame()->view()->documentBackgroundColor()); - m_layerTreeView.initialize(this, m_rootLayer, layerTreeViewSettings); if (!m_layerTreeView.isNull()) { m_layerTreeView.setPageScaleFactorAndLimits(pageScaleFactor(), m_minimumPageScaleFactor, m_maximumPageScaleFactor); + if (m_compositorSurfaceReady) + m_layerTreeView.setSurfaceReady(); updateLayerTreeViewport(); m_client->didActivateCompositor(m_layerTreeView.compositorIdentifier()); m_isAcceleratedCompositingActive = true; @@ -3239,9 +3350,10 @@ void WebViewImpl::applyScrollAndScale(const WebSize& scrollDelta, float pageScal if (!mainFrameImpl() || !mainFrameImpl()->frameView()) return; - if (pageScaleDelta == 1) + if (pageScaleDelta == 1) { + TRACE_EVENT_INSTANT2("webkit", "WebViewImpl::applyScrollAndScale::scrollBy", "x", scrollDelta.width, "y", scrollDelta.height); mainFrameImpl()->frameView()->scrollBy(scrollDelta); - else { + } else { // The page scale changed, so apply a scale and scroll in a single // operation. The old scroll offset (and passed-in delta) are // in the old coordinate space, so we first need to multiply them @@ -3255,6 +3367,12 @@ void WebViewImpl::applyScrollAndScale(const WebSize& scrollDelta, float pageScal } } +void WebViewImpl::didCommit() +{ + if (m_client) + m_client->didBecomeReadyForAdditionalInput(); +} + void WebViewImpl::didCommitAndDrawFrame() { if (m_client) @@ -3310,7 +3428,7 @@ void WebViewImpl::updateLayerTreeViewport() layerAdjustX = -view->contentsSize().width() + view->visibleContentRect(false).width(); } m_nonCompositedContentHost->setViewport(visibleRect.size(), view->contentsSize(), scroll, pageScaleFactor(), layerAdjustX); - m_layerTreeView.setViewportSize(visibleRect.size()); + m_layerTreeView.setViewportSize(size()); m_layerTreeView.setPageScaleFactorAndLimits(pageScaleFactor(), m_minimumPageScaleFactor, m_maximumPageScaleFactor); } @@ -3343,7 +3461,7 @@ WebGraphicsContext3D* WebViewImpl::sharedGraphicsContext3D() if (!m_page->settings()->acceleratedCompositingEnabled() || !allowsAcceleratedCompositing()) return 0; - return GraphicsContext3DPrivate::extractWebGraphicsContext3D(SharedGraphicsContext3D::get()); + return GraphicsContext3DPrivate::extractWebGraphicsContext3D(SharedGraphicsContext3D::get().get()); } void WebViewImpl::setVisibilityState(WebPageVisibilityState visibilityState, @@ -3354,14 +3472,15 @@ void WebViewImpl::setVisibilityState(WebPageVisibilityState visibilityState, #if ENABLE(PAGE_VISIBILITY_API) ASSERT(visibilityState == WebPageVisibilityStateVisible || visibilityState == WebPageVisibilityStateHidden - || visibilityState == WebPageVisibilityStatePrerender); + || visibilityState == WebPageVisibilityStatePrerender + || visibilityState == WebPageVisibilityStatePreview); m_page->setVisibilityState(static_cast<PageVisibilityState>(static_cast<int>(visibilityState)), isInitialState); #endif #if USE(ACCELERATED_COMPOSITING) - if (isAcceleratedCompositingActive()) { + if (!m_layerTreeView.isNull()) { bool visible = visibilityState == WebPageVisibilityStateVisible; - if (!visible) + if (!visible && isAcceleratedCompositingActive()) m_nonCompositedContentHost->protectVisibleTileTextures(); m_layerTreeView.setVisible(visible); } |