Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Unified Diff: Source/web/WebFrameWidgetImpl.cpp

Issue 638003004: Introduce WebFrameWidget to Blink (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: More review updates Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/web/WebFrameWidgetImpl.cpp
diff --git a/Source/web/WebFrameWidgetImpl.cpp b/Source/web/WebFrameWidgetImpl.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bb61fcec0befd1a9c8b53141e69bf2029d44d85d
--- /dev/null
+++ b/Source/web/WebFrameWidgetImpl.cpp
@@ -0,0 +1,1053 @@
+/*
+ * Copyright (C) 2014 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "web/WebFrameWidgetImpl.h"
+
+#include "core/editing/Editor.h"
+#include "core/editing/FrameSelection.h"
+#include "core/editing/InputMethodController.h"
+#include "core/editing/PlainTextRange.h"
+#include "core/frame/FrameHost.h"
+#include "core/frame/FrameView.h"
+#include "core/frame/RemoteFrame.h"
+#include "core/frame/Settings.h"
+#include "core/page/EventHandler.h"
+#include "core/page/FocusController.h"
+#include "core/page/Page.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/compositing/RenderLayerCompositor.h"
+#include "platform/KeyboardCodes.h"
+#include "platform/NotImplemented.h"
+#include "platform/TraceEvent.h"
+#include "public/web/WebAXObject.h"
+#include "public/web/WebActiveWheelFlingParameters.h"
+#include "public/web/WebAutofillClient.h"
+#include "public/web/WebBeginFrameArgs.h"
+#include "public/web/WebFrameClient.h"
+#include "public/web/WebHitTestResult.h"
+#include "public/web/WebInputElement.h"
+#include "public/web/WebMediaPlayerAction.h"
+#include "public/web/WebNode.h"
+#include "public/web/WebPlugin.h"
+#include "public/web/WebPluginAction.h"
+#include "public/web/WebRange.h"
+#include "public/web/WebTextInputInfo.h"
+#include "public/web/WebViewClient.h"
+#include "public/web/WebWindowFeatures.h"
+#include "web/CompositionUnderlineVectorBuilder.h"
+#include "web/ContextFeaturesClientImpl.h"
+#include "web/DatabaseClientImpl.h"
+#include "web/FullscreenController.h"
+#include "web/GraphicsLayerFactoryChromium.h"
+#include "web/LinkHighlight.h"
+#include "web/NavigatorContentUtilsClientImpl.h"
+#include "web/PrerendererClientImpl.h"
+#include "web/SpeechRecognitionClientProxy.h"
+#include "web/StorageQuotaClientImpl.h"
+#include "web/ValidationMessageClientImpl.h"
+#include "web/ViewportAnchor.h"
+#include "web/WebDevToolsAgentImpl.h"
+#include "web/WebDevToolsAgentPrivate.h"
+#include "web/WebInputEventConversion.h"
+#include "web/WebLocalFrameImpl.h"
+#include "web/WebPluginContainerImpl.h"
+#include "web/WebRemoteFrameImpl.h"
+#include "web/WebSettingsImpl.h"
+#include "web/WebViewImpl.h"
+#include "web/WorkerGlobalScopeProxyProviderImpl.h"
+#include "web/painting/ContinuousPainter.h"
+#include "wtf/CurrentTime.h"
+#include "wtf/RefPtr.h"
+#include "wtf/TemporaryChange.h"
+
+namespace blink {
+
+// WebFrameWidget ----------------------------------------------------------------
+
+WebFrameWidget* WebFrameWidget::create(WebWidgetClient* client, WebView* webView)
+{
+ // Pass the WebFrameWidget's self-reference to the caller.
+ return WebFrameWidgetImpl::create(client, webView);
+}
+
+WebFrameWidgetImpl* WebFrameWidgetImpl::create(WebWidgetClient* client, WebView* webView)
+{
+ // Pass the WebFrameWidgetImpl's self-reference to the caller.
+ return adoptRef(new WebFrameWidgetImpl(client, webView)).leakRef();
+}
+
+void WebFrameWidgetImpl::setLocalRoot(WebLocalFrame* frame)
+{
+ m_localRoot = toWebLocalFrameImpl(frame);
+ m_localRoot->setFrameWidget(this);
+}
+
+WebFrameWidgetImpl::WebFrameWidgetImpl(WebWidgetClient* client, WebView* webView)
+ : m_client(client)
+ , m_localRoot(nullptr)
+ , m_layerTreeView(nullptr)
+ , m_rootLayer(nullptr)
+ , m_rootGraphicsLayer(nullptr)
+ , m_isAcceleratedCompositingActive(false)
+ , m_layerTreeViewClosed(false)
+ , m_page(toWebViewImpl(webView)->page())
+ , m_webView(toWebViewImpl(webView))
+ , m_suppressNextKeypressEvent(false)
+ , m_ignoreInputEvents(false)
+{
+ initializeLayerTreeView();
+}
+
+WebFrameWidgetImpl::~WebFrameWidgetImpl()
+{
+}
+
+// WebWidget ------------------------------------------------------------------
+
+void WebFrameWidgetImpl::close()
+{
+ // Reset the delegate to prevent notifications being sent as we're being
+ // deleted.
+ m_client = 0;
+
+ deref(); // Balances ref() acquired in WebFrameWidget::create
+}
+
+WebSize WebFrameWidgetImpl::size()
+{
+ return m_size;
+}
+
+void WebFrameWidgetImpl::willStartLiveResize()
+{
+ if (m_localRoot->frameView())
+ m_localRoot->frameView()->willStartLiveResize();
+
+ LocalFrame* frame = m_localRoot->frame();
+ WebPluginContainerImpl* pluginContainer = WebLocalFrameImpl::pluginContainerFromFrame(frame);
+ if (pluginContainer)
+ pluginContainer->willStartLiveResize();
+}
+
+void WebFrameWidgetImpl::resize(const WebSize& newSize)
+{
+ if (m_size == newSize)
+ return;
+
+ FrameView* view = m_localRoot->frameView();
+ if (!view)
+ return;
+
+ m_size = newSize;
+
+ updateMainFrameLayoutSize();
+
+ view->resize(m_size);
+
+ // FIXME: In WebViewImpl this layout was a precursor to setting the minimum scale limit.
+ // It is not clear if this is necessary for frame-level widget resize.
+ if (view->needsLayout())
+ view->layout();
+
+ // FIXME: Investigate whether this is needed; comment from eseidel suggests that this function
+ // is flawed.
+ sendResizeEventAndRepaint();
+}
+
+void WebFrameWidgetImpl::sendResizeEventAndRepaint()
+{
+ // FIXME: This is wrong. The FrameView is responsible sending a resizeEvent
+ // as part of layout. Layout is also responsible for sending invalidations
+ // to the embedder. This method and all callers may be wrong. -- eseidel.
+ if (m_localRoot->frameView()) {
+ // Enqueues the resize event.
+ m_localRoot->frame()->document()->enqueueResizeEvent();
+ }
+
+ if (m_client) {
+ if (isAcceleratedCompositingActive()) {
+ updateLayerTreeViewport();
+ } else {
+ WebRect damagedRect(0, 0, m_size.width, m_size.height);
+ m_client->didInvalidateRect(damagedRect);
+ }
+ }
+}
+
+void WebFrameWidgetImpl::resizePinchViewport(const WebSize& newSize)
+{
+ // TODO: Implement pinch viewport for out-of-process iframes.
+}
+
+void WebFrameWidgetImpl::updateMainFrameLayoutSize()
+{
+ if (!m_localRoot)
+ return;
+
+ RefPtr<FrameView> view = m_localRoot->frameView();
+ if (!view)
+ return;
+
+ WebSize layoutSize = m_size;
+
+ view->setLayoutSize(layoutSize);
+}
+
+void WebFrameWidgetImpl::willEndLiveResize()
+{
+ if (m_localRoot->frameView())
+ m_localRoot->frameView()->willEndLiveResize();
+
+ LocalFrame* frame = m_localRoot->frame();
+ WebPluginContainerImpl* pluginContainer = WebLocalFrameImpl::pluginContainerFromFrame(frame);
+ if (pluginContainer)
+ pluginContainer->willEndLiveResize();
+}
+
+void WebFrameWidgetImpl::willEnterFullScreen()
+{
+ // FIXME: Implement full screen for out-of-process iframes.
+}
+
+void WebFrameWidgetImpl::didEnterFullScreen()
+{
+ // FIXME: Implement full screen for out-of-process iframes.
+}
+
+void WebFrameWidgetImpl::willExitFullScreen()
+{
+ // FIXME: Implement full screen for out-of-process iframes.
+}
+
+void WebFrameWidgetImpl::didExitFullScreen()
+{
+ // FIXME: Implement full screen for out-of-process iframes.
+}
+
+void WebFrameWidgetImpl::beginFrame(const WebBeginFrameArgs& frameTime)
+{
+ TRACE_EVENT0("blink", "WebFrameWidgetImpl::beginFrame");
+
+ WebBeginFrameArgs validFrameTime(frameTime);
+ if (!validFrameTime.lastFrameTimeMonotonic)
+ validFrameTime.lastFrameTimeMonotonic = monotonicallyIncreasingTime();
+
+ PageWidgetDelegate::animate(*m_page, validFrameTime.lastFrameTimeMonotonic, *m_localRoot->frame());
+}
+
+void WebFrameWidgetImpl::layout()
+{
+ TRACE_EVENT0("blink", "WebFrameWidgetImpl::layout");
+ if (!m_localRoot)
+ return;
+
+ PageWidgetDelegate::layout(*m_page, *m_localRoot->frame());
+ updateLayerTreeBackgroundColor();
+}
+
+void WebFrameWidgetImpl::paint(WebCanvas* canvas, const WebRect& rect)
+{
+ // Out-of-process iframes require compositing.
+ ASSERT_NOT_REACHED();
+}
+
+
+void WebFrameWidgetImpl::updateLayerTreeViewport()
+{
+ if (!page() || !m_layerTreeView)
+ return;
+
+ // FIXME: We need access to page scale information from the WebView.
+ m_layerTreeView->setPageScaleFactorAndLimits(1, 1, 1);
+}
+
+void WebFrameWidgetImpl::updateLayerTreeBackgroundColor()
+{
+ if (!m_layerTreeView)
+ return;
+
+ m_layerTreeView->setBackgroundColor(alphaChannel(m_webView->backgroundColorOverride()) ? m_webView->backgroundColorOverride() : m_webView->backgroundColor());
+}
+
+void WebFrameWidgetImpl::updateLayerTreeDeviceScaleFactor()
+{
+ ASSERT(page());
+ ASSERT(m_layerTreeView);
+
+ float deviceScaleFactor = page()->deviceScaleFactor();
+ m_layerTreeView->setDeviceScaleFactor(deviceScaleFactor);
+}
+
+bool WebFrameWidgetImpl::isTransparent() const
+{
+ // FIXME: This might need to proxy to the WebView's isTransparent().
+ return false;
+}
+
+void WebFrameWidgetImpl::compositeAndReadbackAsync(WebCompositeAndReadbackAsyncCallback* callback)
+{
+ m_layerTreeView->compositeAndReadbackAsync(callback);
+}
+
+bool WebFrameWidgetImpl::isTrackingRepaints() const
+{
+ return m_localRoot->frameView()->isTrackingPaintInvalidations();
+}
+
+void WebFrameWidgetImpl::themeChanged()
+{
+ FrameView* view = m_localRoot->frameView();
+
+ WebRect damagedRect(0, 0, m_size.width, m_size.height);
+ view->invalidateRect(damagedRect);
+}
+
+const WebInputEvent* WebFrameWidgetImpl::m_currentInputEvent = 0;
+
+// FIXME: autogenerate this kind of code, and use it throughout Blink rather than
+// the one-offs for subsets of these values.
+static String inputTypeToName(WebInputEvent::Type type)
+{
+ switch (type) {
+ case WebInputEvent::MouseDown:
+ return EventTypeNames::mousedown;
+ case WebInputEvent::MouseUp:
+ return EventTypeNames::mouseup;
+ case WebInputEvent::MouseMove:
+ return EventTypeNames::mousemove;
+ case WebInputEvent::MouseEnter:
+ return EventTypeNames::mouseenter;
+ case WebInputEvent::MouseLeave:
+ return EventTypeNames::mouseleave;
+ case WebInputEvent::ContextMenu:
+ return EventTypeNames::contextmenu;
+ case WebInputEvent::MouseWheel:
+ return EventTypeNames::mousewheel;
+ case WebInputEvent::KeyDown:
+ return EventTypeNames::keydown;
+ case WebInputEvent::KeyUp:
+ return EventTypeNames::keyup;
+ case WebInputEvent::GestureScrollBegin:
+ return EventTypeNames::gesturescrollstart;
+ case WebInputEvent::GestureScrollEnd:
+ return EventTypeNames::gesturescrollend;
+ case WebInputEvent::GestureScrollUpdate:
+ return EventTypeNames::gesturescrollupdate;
+ case WebInputEvent::GestureTapDown:
+ return EventTypeNames::gesturetapdown;
+ case WebInputEvent::GestureShowPress:
+ return EventTypeNames::gestureshowpress;
+ case WebInputEvent::GestureTap:
+ return EventTypeNames::gesturetap;
+ case WebInputEvent::GestureTapUnconfirmed:
+ return EventTypeNames::gesturetapunconfirmed;
+ case WebInputEvent::TouchStart:
+ return EventTypeNames::touchstart;
+ case WebInputEvent::TouchMove:
+ return EventTypeNames::touchmove;
+ case WebInputEvent::TouchEnd:
+ return EventTypeNames::touchend;
+ case WebInputEvent::TouchCancel:
+ return EventTypeNames::touchcancel;
+ default:
+ return String("unknown");
+ }
+}
+
+bool WebFrameWidgetImpl::handleInputEvent(const WebInputEvent& inputEvent)
+{
+
+ TRACE_EVENT1("input", "WebFrameWidgetImpl::handleInputEvent", "type", inputTypeToName(inputEvent.type).ascii());
+
+ // Report the event to be NOT processed by WebKit, so that the browser can handle it appropriately.
+ if (m_ignoreInputEvents)
+ return false;
+
+ TemporaryChange<const WebInputEvent*> currentEventChange(m_currentInputEvent, &inputEvent);
+
+ if (m_mouseCaptureNode && WebInputEvent::isMouseEventType(inputEvent.type)) {
+ TRACE_EVENT1("input", "captured mouse event", "type", inputEvent.type);
+ // Save m_mouseCaptureNode since mouseCaptureLost() will clear it.
+ RefPtrWillBeRawPtr<Node> node = m_mouseCaptureNode;
+
+ // Not all platforms call mouseCaptureLost() directly.
+ if (inputEvent.type == WebInputEvent::MouseUp)
+ mouseCaptureLost();
+
+ OwnPtr<UserGestureIndicator> gestureIndicator;
+
+ AtomicString eventType;
+ switch (inputEvent.type) {
+ case WebInputEvent::MouseMove:
+ eventType = EventTypeNames::mousemove;
+ break;
+ case WebInputEvent::MouseLeave:
+ eventType = EventTypeNames::mouseout;
+ break;
+ case WebInputEvent::MouseDown:
+ eventType = EventTypeNames::mousedown;
+ gestureIndicator = adoptPtr(new UserGestureIndicator(DefinitelyProcessingNewUserGesture));
+ m_mouseCaptureGestureToken = gestureIndicator->currentToken();
+ break;
+ case WebInputEvent::MouseUp:
+ eventType = EventTypeNames::mouseup;
+ gestureIndicator = adoptPtr(new UserGestureIndicator(m_mouseCaptureGestureToken.release()));
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ node->dispatchMouseEvent(
+ PlatformMouseEventBuilder(m_localRoot->frameView(), static_cast<const WebMouseEvent&>(inputEvent)),
+ eventType, static_cast<const WebMouseEvent&>(inputEvent).clickCount);
+ return true;
+ }
+
+ return PageWidgetDelegate::handleInputEvent(*this, inputEvent, m_localRoot->frame());
+}
+
+void WebFrameWidgetImpl::setCursorVisibilityState(bool isVisible)
+{
+ if (m_page)
dcheng 2014/12/16 20:13:06 Why might page be null here and not elsewhere? Do
kenrb 2014/12/16 22:04:12 I reproduced the checks in WebViewImpl, even thoug
dcheng 2014/12/16 23:20:20 Well, we don't currently ever null out the page. S
kenrb 2014/12/17 14:52:31 Sounds good.
+ m_page->setIsCursorVisible(isVisible);
+}
+
+void WebFrameWidgetImpl::hasTouchEventHandlers(bool hasTouchHandlers)
+{
+ if (m_client)
+ m_client->hasTouchEventHandlers(hasTouchHandlers);
+}
+
+bool WebFrameWidgetImpl::hasTouchEventHandlersAt(const WebPoint& point)
+{
+ // FIXME: Implement this. Note that the point must be divided by pageScaleFactor.
+ return true;
+}
+
+void WebFrameWidgetImpl::scheduleAnimation()
+{
+ if (m_layerTreeView) {
+ m_layerTreeView->setNeedsAnimate();
+ return;
+ }
+ if (m_client)
+ m_client->scheduleAnimation();
+}
+
+void WebFrameWidgetImpl::applyViewportDeltas(
+ const WebSize& pinchViewportDelta,
+ const WebSize& mainFrameDelta,
+ float pageScaleDelta,
+ float topControlsDelta)
+{
+ // FIXME: To be implemented.
+}
+
+void WebFrameWidgetImpl::applyViewportDeltas(const WebSize& scrollDelta, float pageScaleDelta, float topControlsDelta)
+{
+ // FIXME: To be implemented.
+}
+
+void WebFrameWidgetImpl::mouseCaptureLost()
+{
+ TRACE_EVENT_ASYNC_END0("input", "capturing mouse", this);
+ m_mouseCaptureNode = nullptr;
+}
+
+void WebFrameWidgetImpl::setFocus(bool enable)
+{
+ m_page->focusController().setFocused(enable);
+ if (enable) {
+ m_page->focusController().setActive(true);
+ RefPtr<Frame> focusedFrame = m_page->focusController().focusedFrame();
+ if (focusedFrame && focusedFrame->isLocalFrame()) {
+ LocalFrame* localFrame = toLocalFrame(focusedFrame.get());
+ Element* element = localFrame->document()->focusedElement();
+ if (element && localFrame->selection().selection().isNone()) {
+ // If the selection was cleared while the WebView was not
+ // focused, then the focus element shows with a focus ring but
+ // no caret and does respond to keyboard inputs.
+ if (element->isTextFormControl()) {
+ element->updateFocusAppearance(true);
+ } else if (element->isContentEditable()) {
+ // updateFocusAppearance() selects all the text of
+ // contentseditable DIVs. So we set the selection explicitly
+ // instead. Note that this has the side effect of moving the
+ // caret back to the beginning of the text.
+ Position position(element, 0, Position::PositionIsOffsetInAnchor);
+ localFrame->selection().setSelection(VisibleSelection(position, SEL_DEFAULT_AFFINITY));
+ }
+ }
+ }
+ }
+}
+
+bool WebFrameWidgetImpl::setComposition(
+ const WebString& text,
+ const WebVector<WebCompositionUnderline>& underlines,
+ int selectionStart,
+ int selectionEnd)
+{
+ // FIXME: To be implemented.
+ return false;
+}
+
+bool WebFrameWidgetImpl::confirmComposition()
+{
+ // FIXME: To be implemented.
+ return false;
+}
+
+bool WebFrameWidgetImpl::confirmComposition(ConfirmCompositionBehavior selectionBehavior)
+{
+ // FIXME: To be implemented.
+ return false;
+}
+
+bool WebFrameWidgetImpl::confirmComposition(const WebString& text)
+{
+ // FIXME: To be implemented.
+ return false;
+}
+
+bool WebFrameWidgetImpl::compositionRange(size_t* location, size_t* length)
+{
+ // FIXME: To be implemented.
+ return false;
+}
+
+WebTextInputInfo WebFrameWidgetImpl::textInputInfo()
+{
+ WebTextInputInfo info;
+ // FIXME: To be implemented.
+ return info;
+}
+
+WebColor WebFrameWidgetImpl::backgroundColor() const
+{
+ if (isTransparent())
+ return Color::transparent;
+ if (!m_localRoot->frameView())
+ return m_webView->backgroundColor();
+ FrameView* view = m_localRoot->frameView();
+ return view->documentBackgroundColor().rgb();
+}
+
+bool WebFrameWidgetImpl::selectionBounds(WebRect& anchor, WebRect& focus) const
+{
+ const Frame* frame = focusedCoreFrame();
+ if (!frame || !frame->isLocalFrame())
+ return false;
+
+ const LocalFrame* localFrame = toLocalFrame(frame);
+ if (!localFrame)
+ return false;
+ FrameSelection& selection = localFrame->selection();
+
+ if (selection.isCaret()) {
+ anchor = focus = selection.absoluteCaretBounds();
+ } else {
+ RefPtrWillBeRawPtr<Range> selectedRange = selection.toNormalizedRange();
+ if (!selectedRange)
+ return false;
+
+ RefPtrWillBeRawPtr<Range> range(Range::create(selectedRange->startContainer()->document(),
+ selectedRange->startContainer(),
+ selectedRange->startOffset(),
+ selectedRange->startContainer(),
+ selectedRange->startOffset()));
+ anchor = localFrame->editor().firstRectForRange(range.get());
+
+ range = Range::create(selectedRange->endContainer()->document(),
+ selectedRange->endContainer(),
+ selectedRange->endOffset(),
+ selectedRange->endContainer(),
+ selectedRange->endOffset());
+ focus = localFrame->editor().firstRectForRange(range.get());
+ }
+
+ IntRect scaledAnchor(localFrame->view()->contentsToWindow(anchor));
+ IntRect scaledFocus(localFrame->view()->contentsToWindow(focus));
+
+ anchor = scaledAnchor;
+ focus = scaledFocus;
+
+ if (!selection.selection().isBaseFirst())
+ std::swap(anchor, focus);
+ return true;
+}
+
+bool WebFrameWidgetImpl::selectionTextDirection(WebTextDirection& start, WebTextDirection& end) const
+{
+ if (!focusedCoreFrame()->isLocalFrame())
+ return false;
+ const LocalFrame* frame = toLocalFrame(focusedCoreFrame());
+ if (!frame)
+ return false;
+ FrameSelection& selection = frame->selection();
+ if (!selection.toNormalizedRange())
+ return false;
+ start = toWebTextDirection(selection.start().primaryDirection());
+ end = toWebTextDirection(selection.end().primaryDirection());
+ return true;
+}
+
+bool WebFrameWidgetImpl::isSelectionAnchorFirst() const
+{
+ if (!focusedCoreFrame()->isLocalFrame())
+ return false;
+ if (const LocalFrame* frame = toLocalFrame(focusedCoreFrame()))
+ return frame->selection().selection().isBaseFirst();
+ return false;
+}
+
+bool WebFrameWidgetImpl::caretOrSelectionRange(size_t* location, size_t* length)
+{
+ if (!focusedCoreFrame()->isLocalFrame())
+ return false;
+ const LocalFrame* focused = toLocalFrame(focusedCoreFrame());
+ if (!focused)
+ return false;
+
+ PlainTextRange selectionOffsets = focused->inputMethodController().getSelectionOffsets();
+ if (selectionOffsets.isNull())
+ return false;
+
+ *location = selectionOffsets.start();
+ *length = selectionOffsets.length();
+ return true;
+}
+
+void WebFrameWidgetImpl::setTextDirection(WebTextDirection direction)
+{
+ // The Editor::setBaseWritingDirection() function checks if we can change
+ // the text direction of the selected node and updates its DOM "dir"
+ // attribute and its CSS "direction" property.
+ // So, we just call the function as Safari does.
+ if (!focusedCoreFrame()->isLocalFrame())
+ return;
+ const LocalFrame* focused = toLocalFrame(focusedCoreFrame());
+ if (!focused)
+ return;
+
+ Editor& editor = focused->editor();
+ if (!editor.canEdit())
+ return;
+
+ switch (direction) {
+ case WebTextDirectionDefault:
+ editor.setBaseWritingDirection(NaturalWritingDirection);
+ break;
+
+ case WebTextDirectionLeftToRight:
+ editor.setBaseWritingDirection(LeftToRightWritingDirection);
+ break;
+
+ case WebTextDirectionRightToLeft:
+ editor.setBaseWritingDirection(RightToLeftWritingDirection);
+ break;
+
+ default:
+ notImplemented();
+ break;
+ }
+}
+
+bool WebFrameWidgetImpl::isAcceleratedCompositingActive() const
+{
+ return m_isAcceleratedCompositingActive;
+}
+
+void WebFrameWidgetImpl::willCloseLayerTreeView()
+{
+ setIsAcceleratedCompositingActive(false);
+ m_layerTreeView = 0;
+ m_layerTreeViewClosed = true;
+}
+
+void WebFrameWidgetImpl::didChangeWindowResizerRect()
+{
+ if (m_localRoot->frameView())
+ m_localRoot->frameView()->windowResizerRectChanged();
+}
+
+void WebFrameWidgetImpl::handleMouseLeave(LocalFrame& mainFrame, const WebMouseEvent& event)
+{
+ // FIXME: WebWidget doesn't have the method below.
+ // m_client->setMouseOverURL(WebURL());
+ PageWidgetEventHandler::handleMouseLeave(mainFrame, event);
+}
+
+void WebFrameWidgetImpl::handleMouseDown(LocalFrame& mainFrame, const WebMouseEvent& event)
+{
+ // Take capture on a mouse down on a plugin so we can send it mouse events.
+ // If the hit node is a plugin but a scrollbar is over it don't start mouse
+ // capture because it will interfere with the scrollbar receiving events.
+ IntPoint point(event.x, event.y);
+ if (event.button == WebMouseEvent::ButtonLeft) {
+ point = m_localRoot->frameView()->windowToContents(point);
+ HitTestResult result(m_localRoot->frame()->eventHandler().hitTestResultAtPoint(point));
+ result.setToShadowHostIfInUserAgentShadowRoot();
+ Node* hitNode = result.innerNonSharedNode();
+
+ if (!result.scrollbar() && hitNode && hitNode->renderer() && hitNode->renderer()->isEmbeddedObject()) {
+ m_mouseCaptureNode = hitNode;
+ TRACE_EVENT_ASYNC_BEGIN0("input", "capturing mouse", this);
+ }
+ }
+
+ PageWidgetEventHandler::handleMouseDown(mainFrame, event);
+
+ if (event.button == WebMouseEvent::ButtonLeft && m_mouseCaptureNode)
+ m_mouseCaptureGestureToken = mainFrame.eventHandler().takeLastMouseDownGestureToken();
+
+ // FIXME: Add context menu support.
+}
+
+void WebFrameWidgetImpl::handleMouseUp(LocalFrame& mainFrame, const WebMouseEvent& event)
+{
+ PageWidgetEventHandler::handleMouseUp(mainFrame, event);
+
+ // FIXME: Add context menu support (Windows).
+}
+
+bool WebFrameWidgetImpl::handleMouseWheel(LocalFrame& mainFrame, const WebMouseWheelEvent& event)
+{
+ return PageWidgetEventHandler::handleMouseWheel(mainFrame, event);
+}
+
+bool WebFrameWidgetImpl::handleGestureEvent(const WebGestureEvent& event)
+{
+ // FIXME: Add gesture support.
+ return false;
+}
+
+bool WebFrameWidgetImpl::handleKeyEvent(const WebKeyboardEvent& event)
+{
+ ASSERT((event.type == WebInputEvent::RawKeyDown)
+ || (event.type == WebInputEvent::KeyDown)
+ || (event.type == WebInputEvent::KeyUp));
+
+ // Please refer to the comments explaining the m_suppressNextKeypressEvent
+ // member.
+ // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
+ // Webkit. A keyDown event is typically associated with a keyPress(char)
+ // event and a keyUp event. We reset this flag here as this is a new keyDown
+ // event.
+ m_suppressNextKeypressEvent = false;
+
+ RefPtr<Frame> focusedFrame = focusedCoreFrame();
+ if (focusedFrame && focusedFrame->isRemoteFrame()) {
+ WebRemoteFrameImpl* webFrame = WebRemoteFrameImpl::fromFrame(*toRemoteFrame(focusedFrame.get()));
+ webFrame->client()->forwardInputEvent(&event);
+ return true;
+ }
+
+ if (!focusedFrame || !focusedFrame->isLocalFrame())
+ return false;
+
+ RefPtr<LocalFrame> frame = toLocalFrame(focusedFrame.get());
+
+ PlatformKeyboardEventBuilder evt(event);
+
+ if (frame->eventHandler().keyEvent(evt)) {
+ if (WebInputEvent::RawKeyDown == event.type) {
+ // Suppress the next keypress event unless the focused node is a plug-in node.
+ // (Flash needs these keypress events to handle non-US keyboards.)
+ Element* element = focusedElement();
+ if (!element || !element->renderer() || !element->renderer()->isEmbeddedObject())
+ m_suppressNextKeypressEvent = true;
+ }
+ return true;
+ }
+
+ return keyEventDefault(event);
+}
+
+bool WebFrameWidgetImpl::handleCharEvent(const WebKeyboardEvent& event)
+{
+ ASSERT(event.type == WebInputEvent::Char);
+
+ // Please refer to the comments explaining the m_suppressNextKeypressEvent
+ // member. The m_suppressNextKeypressEvent is set if the KeyDown is
+ // handled by Webkit. A keyDown event is typically associated with a
+ // keyPress(char) event and a keyUp event. We reset this flag here as it
+ // only applies to the current keyPress event.
+ bool suppress = m_suppressNextKeypressEvent;
+ m_suppressNextKeypressEvent = false;
+
+ LocalFrame* frame = toLocalFrame(focusedCoreFrame());
+ if (!frame)
+ return suppress;
+
+ EventHandler& handler = frame->eventHandler();
+
+ PlatformKeyboardEventBuilder evt(event);
+ if (!evt.isCharacterKey())
+ return true;
+
+ // Accesskeys are triggered by char events and can't be suppressed.
+ if (handler.handleAccessKey(evt))
+ return true;
+
+ // Safari 3.1 does not pass off windows system key messages (WM_SYSCHAR) to
+ // the eventHandler::keyEvent. We mimic this behavior on all platforms since
+ // for now we are converting other platform's key events to windows key
+ // events.
+ if (evt.isSystemKey())
+ return false;
+
+ if (!suppress && !handler.keyEvent(evt))
+ return keyEventDefault(event);
+
+ return true;
+}
+
+
+bool WebFrameWidgetImpl::keyEventDefault(const WebKeyboardEvent& event)
+{
+ LocalFrame* frame = toLocalFrame(focusedCoreFrame());
+ if (!frame)
+ return false;
+
+ switch (event.type) {
+ case WebInputEvent::Char:
+ if (event.windowsKeyCode == VKEY_SPACE) {
+ int keyCode = ((event.modifiers & WebInputEvent::ShiftKey) ? VKEY_PRIOR : VKEY_NEXT);
+ return scrollViewWithKeyboard(keyCode, event.modifiers);
+ }
+ break;
+ case WebInputEvent::RawKeyDown:
+ if (event.modifiers == WebInputEvent::ControlKey) {
+ switch (event.windowsKeyCode) {
+#if !OS(MACOSX)
+ case 'A':
+ WebFrame::fromFrame(focusedCoreFrame())->executeCommand(WebString::fromUTF8("SelectAll"));
+ return true;
+ case VKEY_INSERT:
+ case 'C':
+ WebFrame::fromFrame(focusedCoreFrame())->executeCommand(WebString::fromUTF8("Copy"));
+ return true;
+#endif
+ // Match FF behavior in the sense that Ctrl+home/end are the only Ctrl
+ // key combinations which affect scrolling. Safari is buggy in the
+ // sense that it scrolls the page for all Ctrl+scrolling key
+ // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
+ case VKEY_HOME:
+ case VKEY_END:
+ break;
+ default:
+ return false;
+ }
+ }
+ if (!event.isSystemKey && !(event.modifiers & WebInputEvent::ShiftKey))
+ return scrollViewWithKeyboard(event.windowsKeyCode, event.modifiers);
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool WebFrameWidgetImpl::scrollViewWithKeyboard(int keyCode, int modifiers)
+{
+ ScrollDirection scrollDirection;
+ ScrollGranularity scrollGranularity;
+#if OS(MACOSX)
+ // Control-Up/Down should be PageUp/Down on Mac.
+ if (modifiers & WebMouseEvent::ControlKey) {
+ if (keyCode == VKEY_UP)
+ keyCode = VKEY_PRIOR;
+ else if (keyCode == VKEY_DOWN)
+ keyCode = VKEY_NEXT;
+ }
+#endif
+ if (!mapKeyCodeForScroll(keyCode, &scrollDirection, &scrollGranularity))
+ return false;
+
+ if (LocalFrame* frame = toLocalFrame(focusedCoreFrame()))
+ return frame->eventHandler().bubblingScroll(scrollDirection, scrollGranularity);
+ return false;
+}
+
+bool WebFrameWidgetImpl::mapKeyCodeForScroll(
+ int keyCode,
+ ScrollDirection* scrollDirection,
+ ScrollGranularity* scrollGranularity)
+{
+ switch (keyCode) {
+ case VKEY_LEFT:
+ *scrollDirection = ScrollLeft;
+ *scrollGranularity = ScrollByLine;
+ break;
+ case VKEY_RIGHT:
+ *scrollDirection = ScrollRight;
+ *scrollGranularity = ScrollByLine;
+ break;
+ case VKEY_UP:
+ *scrollDirection = ScrollUp;
+ *scrollGranularity = ScrollByLine;
+ break;
+ case VKEY_DOWN:
+ *scrollDirection = ScrollDown;
+ *scrollGranularity = ScrollByLine;
+ break;
+ case VKEY_HOME:
+ *scrollDirection = ScrollUp;
+ *scrollGranularity = ScrollByDocument;
+ break;
+ case VKEY_END:
+ *scrollDirection = ScrollDown;
+ *scrollGranularity = ScrollByDocument;
+ break;
+ case VKEY_PRIOR: // page up
+ *scrollDirection = ScrollUp;
+ *scrollGranularity = ScrollByPage;
+ break;
+ case VKEY_NEXT: // page down
+ *scrollDirection = ScrollDown;
+ *scrollGranularity = ScrollByPage;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+Frame* WebFrameWidgetImpl::focusedCoreFrame() const
+{
+ return m_page ? m_page->focusController().focusedOrMainFrame() : 0;
+}
+
+Element* WebFrameWidgetImpl::focusedElement() const
+{
+ Frame* frame = m_page->focusController().focusedFrame();
+ if (!frame || !frame->isLocalFrame())
+ return 0;
+
+ Document* document = toLocalFrame(frame)->document();
+ if (!document)
+ return 0;
+
+ return document->focusedElement();
+}
+
+void WebFrameWidgetImpl::initializeLayerTreeView()
+{
+ if (m_client) {
+ m_client->initializeLayerTreeView();
+ m_layerTreeView = m_client->layerTreeView();
+ }
+
+ m_page->settings().setAcceleratedCompositingEnabled(m_layerTreeView != 0);
+
+ // FIXME: only unittests, click to play, Android priting, and printing (for headers and footers)
+ // make this assert necessary. We should make them not hit this code and then delete allowsBrokenNullLayerTreeView.
+ ASSERT(m_layerTreeView || !m_client || m_client->allowsBrokenNullLayerTreeView());
+}
+
+void WebFrameWidgetImpl::setIsAcceleratedCompositingActive(bool active)
+{
+ // In the middle of shutting down; don't try to spin back up a compositor.
+ // FIXME: compositing startup/shutdown should be refactored so that it
+ // turns on explicitly rather than lazily, which causes this awkwardness.
+ if (m_layerTreeViewClosed)
+ return;
+
+ ASSERT(!active || m_layerTreeView);
+
+ if (m_isAcceleratedCompositingActive == active)
+ return;
+
+ if (!m_client)
+ return;
+
+ if (active) {
+ TRACE_EVENT0("blink", "WebViewImpl::setIsAcceleratedCompositingActive(true)");
+ m_layerTreeView->setRootLayer(*m_rootLayer);
+
+ bool visible = page()->visibilityState() == PageVisibilityStateVisible;
+ m_layerTreeView->setVisible(visible);
+ updateLayerTreeDeviceScaleFactor();
+ updateLayerTreeBackgroundColor();
+ m_layerTreeView->setHasTransparentBackground(isTransparent());
+ updateLayerTreeViewport();
+ m_isAcceleratedCompositingActive = true;
+ }
+ if (m_localRoot->frameView())
+ m_localRoot->frameView()->setClipsRepaints(!m_isAcceleratedCompositingActive);
+}
+
+RenderLayerCompositor* WebFrameWidgetImpl::compositor() const
+{
+ LocalFrame* frame = toLocalFrame(toCoreFrame(m_localRoot));
+ if (!frame || !frame->document() || !frame->document()->renderView())
+ return 0;
+
+ return frame->document()->renderView()->compositor();
+}
+
+void WebFrameWidgetImpl::suppressInvalidations(bool enable)
+{
+ if (m_client)
+ m_client->suppressCompositorScheduling(enable);
+}
+
+void WebFrameWidgetImpl::setRootGraphicsLayer(GraphicsLayer* layer)
+{
+ suppressInvalidations(true);
+
+ m_rootGraphicsLayer = layer;
+ m_rootLayer = layer ? layer->platformLayer() : 0;
+
+ setIsAcceleratedCompositingActive(layer != 0);
+
+ if (m_layerTreeView) {
+ if (m_rootLayer) {
+ m_layerTreeView->setRootLayer(*m_rootLayer);
+ // We register viewport layers here since there may not be a layer
+ // tree view prior to this point.
+ GraphicsLayer* rootScrollLayer = compositor()->scrollLayer();
+ ASSERT(rootScrollLayer);
+ WebLayer* pageScaleLayer = rootScrollLayer->parent() ? rootScrollLayer->parent()->platformLayer() : 0;
+ m_layerTreeView->registerViewportLayers(0, pageScaleLayer, rootScrollLayer->platformLayer(), 0);
+ } else {
+ m_layerTreeView->clearRootLayer();
+ m_layerTreeView->clearViewportLayers();
+ }
+ }
+
+ suppressInvalidations(false);
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698